{"id":28510,"date":"2022-06-28T10:19:45","date_gmt":"2022-06-28T10:19:45","guid":{"rendered":"http:\/\/create-a-fireworks-animation-in-react"},"modified":"2022-06-28T10:19:45","modified_gmt":"2022-06-28T10:19:45","slug":"create-a-fireworks-animation-in-react","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/","title":{"rendered":"Create a Fireworks Animation in React"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>With the Fourth of July right around the corner, this seems like a great time to practice building some custom animations with fireworks! Sometimes you\u2019ll work on projects that need some advanced animations, like an e-commerce or gaming site, and it can take some time to get them to function as you expect.<\/p>\n<p>That\u2019s why we\u2019re going to use <a href=\"https:\/\/animejs.com\/\"><code>anime.js<\/code><\/a> to implement a simple fireworks animation that can be customized by users. You\u2019ll see how you can create some cool animations using CSS and this package.<\/p>\n<h2>Initial setup<\/h2>\n<p>We\u2019ll need to create a new React app to get started. Run this command to bootstrap the <code>fireworks<\/code> app:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">$ npx create-react-app fireworks --template typescript\n<\/code><\/span><\/pre>\n<p>Once the installation is complete, let\u2019s add a few packages we\u2019ll use throughout the app with this command:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">$ npm i animejs @types\/animejs @mui\/material @emotion\/react @emotion\/styled\n<\/code><\/span><\/pre>\n<p>Now let\u2019s jump into the first component we need to make.<\/p>\n<h2>Make the fireworks component<\/h2>\n<p>We\u2019re going to have two main components: one for the fireworks animation and one for the form users will be able to customize the fireworks with. Let\u2019s start with the fireworks component. In the <code>src<\/code> directory, create a new folder called <code>components<\/code>. Inside this new folder, add a file and name it <code>Fireworks.tsx<\/code>. This is where we\u2019ll have all of the code for the fireworks animation.<\/p>\n<p>Go ahead and open that file and add the following code and then we\u2019ll go through it all:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ Fireworks.tsx<\/span>\n<span class=\"hljs-keyword\">import<\/span> Button <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@mui\/material\/Button\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> Container <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@mui\/material\/Container\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> anime <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"animejs\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { useState, useRef, useEffect } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">\"..\/Fireworks.css\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> CustomizeForm <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/CustomizeForm\"<\/span>;\n\n<span class=\"hljs-keyword\">export<\/span> interface CustomizationProps {\n  <span class=\"hljs-attr\">color<\/span>: string;\n  size: number;\n  duration: number;\n  sparkAmount: number&#91;];\n  rows: number&#91;];\n}\n\n<span class=\"hljs-keyword\">const<\/span> Fireworks = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n  <span class=\"hljs-keyword\">const<\/span> &#91;customizations, setCustomizations] =\n    useState &lt;\n    CustomizationProps &gt;\n    {\n      <span class=\"hljs-attr\">color<\/span>: <span class=\"hljs-string\">\"bf6d20\"<\/span>,\n      <span class=\"hljs-attr\">size<\/span>: <span class=\"hljs-number\">450<\/span>,\n      <span class=\"hljs-attr\">duration<\/span>: <span class=\"hljs-number\">150<\/span>,\n      <span class=\"hljs-attr\">sparkAmount<\/span>: <span class=\"hljs-built_in\">Array<\/span>.from(<span class=\"hljs-built_in\">Array<\/span>(<span class=\"hljs-number\">10<\/span>)),\n      <span class=\"hljs-attr\">rows<\/span>: <span class=\"hljs-built_in\">Array<\/span>.from(<span class=\"hljs-built_in\">Array<\/span>(<span class=\"hljs-number\">3<\/span>)),\n    };\n\n  <span class=\"hljs-keyword\">const<\/span> animation = useRef(<span class=\"hljs-literal\">null<\/span>);\n\n  <span class=\"hljs-keyword\">const<\/span> handleClick = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    <span class=\"hljs-comment\">\/\/ @ts-ignore<\/span>\n    animation.current.play();\n  };\n\n  useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n    <span class=\"hljs-comment\">\/\/ @ts-ignore<\/span>\n    animation.current = anime.timeline({\n      <span class=\"hljs-attr\">direction<\/span>: <span class=\"hljs-string\">\"alternate\"<\/span>,\n      <span class=\"hljs-attr\">duration<\/span>: customizations.duration,\n      <span class=\"hljs-attr\">autoplay<\/span>: <span class=\"hljs-literal\">false<\/span>,\n      <span class=\"hljs-attr\">easing<\/span>: <span class=\"hljs-string\">\"easeInOutSine\"<\/span>,\n    });\n\n    <span class=\"hljs-comment\">\/\/ @ts-ignore<\/span>\n    animation.current.add(\n      {\n        <span class=\"hljs-attr\">targets<\/span>: <span class=\"hljs-string\">`.dots li`<\/span>,\n        <span class=\"hljs-attr\">translateX<\/span>: anime.stagger(<span class=\"hljs-number\">10<\/span>, {\n          <span class=\"hljs-attr\">grid<\/span>: &#91;customizations.rows.length, customizations.sparkAmount.length],\n          <span class=\"hljs-attr\">from<\/span>: <span class=\"hljs-string\">\"center\"<\/span>,\n          <span class=\"hljs-attr\">axis<\/span>: <span class=\"hljs-string\">\"x\"<\/span>,\n        }),\n        <span class=\"hljs-attr\">translateY<\/span>: anime.stagger(<span class=\"hljs-number\">10<\/span>, {\n          <span class=\"hljs-attr\">grid<\/span>: &#91;customizations.rows.length, customizations.sparkAmount.length],\n          <span class=\"hljs-attr\">from<\/span>: <span class=\"hljs-string\">\"center\"<\/span>,\n          <span class=\"hljs-attr\">axis<\/span>: <span class=\"hljs-string\">\"y\"<\/span>,\n        }),\n        <span class=\"hljs-attr\">rotateZ<\/span>: anime.stagger(&#91;<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">90<\/span>], {\n          <span class=\"hljs-attr\">grid<\/span>: &#91;customizations.rows.length, customizations.sparkAmount.length],\n          <span class=\"hljs-attr\">from<\/span>: <span class=\"hljs-string\">\"center\"<\/span>,\n          <span class=\"hljs-attr\">axis<\/span>: <span class=\"hljs-string\">\"x\"<\/span>,\n        }),\n        <span class=\"hljs-attr\">delay<\/span>: anime.stagger(<span class=\"hljs-number\">200<\/span>, {\n          <span class=\"hljs-attr\">grid<\/span>: &#91;customizations.rows.length, customizations.sparkAmount.length],\n          <span class=\"hljs-attr\">from<\/span>: <span class=\"hljs-string\">\"center\"<\/span>,\n        }),\n        <span class=\"hljs-attr\">easing<\/span>: <span class=\"hljs-string\">\"easeInOutQuad\"<\/span>,\n      },\n      <span class=\"hljs-built_in\">Math<\/span>.random() * customizations.duration\n    );\n  }, &#91;customizations]);\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Container<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">CustomizeForm<\/span>\n        <span class=\"hljs-attr\">customizations<\/span>=<span class=\"hljs-string\">{customizations}<\/span>\n        <span class=\"hljs-attr\">setCustomizations<\/span>=<span class=\"hljs-string\">{setCustomizations}<\/span>\n      \/&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"player\"<\/span>&gt;<\/span>\n        {customizations.rows.map((_, i) =&gt; (\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ul<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"dots\"<\/span>&gt;<\/span>\n            {customizations.sparkAmount.map((_, i) =&gt; (\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>\n                <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span>\n                  <span class=\"hljs-attr\">backgroundColor:<\/span> `#${<span class=\"hljs-attr\">customizations.color<\/span>}`,\n                  <span class=\"hljs-attr\">height:<\/span> `${<span class=\"hljs-attr\">customizations.size<\/span> + <span class=\"hljs-attr\">Math.random<\/span>() * <span class=\"hljs-attr\">3<\/span>}<span class=\"hljs-attr\">px<\/span>`,\n                  <span class=\"hljs-attr\">maxHeight:<\/span> \"<span class=\"hljs-attr\">100<\/span>%\",\n                  <span class=\"hljs-attr\">maxWidth:<\/span> \"<span class=\"hljs-attr\">100<\/span>%\",\n                  <span class=\"hljs-attr\">width:<\/span> `${<span class=\"hljs-attr\">customizations.size<\/span>}<span class=\"hljs-attr\">px<\/span>`,\n                }}\n                <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{i}<\/span>\n              \/&gt;<\/span>\n            ))}\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ul<\/span>&gt;<\/span>\n        ))}\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Button<\/span> <span class=\"hljs-attr\">variant<\/span>=<span class=\"hljs-string\">\"contained\"<\/span> <span class=\"hljs-attr\">color<\/span>=<span class=\"hljs-string\">\"success\"<\/span> <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{handleClick}<\/span>&gt;<\/span>\n          Play\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Button<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Container<\/span>&gt;<\/span><\/span>\n  );\n};\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> Fireworks;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We start off by importing everything we need. There\u2019s some stuff coming from third-party packages and we have a couple of imports we\u2019ll define as we go through this app. You\u2019ll notice there\u2019s a custom stylesheet and another component called <code>CustomizeForm<\/code>. We\u2019ll get to these a little later.<\/p>\n<p>For now, we\u2019ll move on and define the types for the options users will be able to change for the animation. They\u2019ll be able to play with the duration of the animation, the color of the fireworks, how many there are, and how big they are. Next, we start defining what happens in the component.<\/p>\n<p>We define a new state variable with some default values to define the initial layout of the fireworks. Then we define a reference to an element that the animation will render in. After that, the <code>handleClick<\/code> method is defined which will play the animation any time a button is clicked.<\/p>\n<p>Now we\u2019re at the fun part. The <code>useEffect<\/code> hook is where we actually define the animation. We set <code>animation.current<\/code> to follow a <code>timeline<\/code>. You can see where that <code>customizations<\/code> state is being used to update the animation duration when a user changes it. Then we add an animation for each of the elements in the <code>.dots<\/code> class.<\/p>\n<p>Next, we define what types of translations and rotations should happen to all of the fireworks elements. Every time the user updates a value, we\u2019ll be able to see the change in the fireworks.<\/p>\n<p>Finally, we get to define the <code>render<\/code> method which has all of these elements we\u2019ve been talking about. Again, we don\u2019t have the <code>CustomizeForm<\/code> component yet, but we will in just a bit. For the most part, we\u2019re making a grid the size that the user defines it. There are some CSS values that get changed dynamically and the play button. Then we\u2019re done with the <code>Fireworks<\/code> component!<\/p>\n<p>Now let\u2019s define some styles for those classes we have.<\/p>\n<h3>Add the CSS<\/h3>\n<p>In the root of the app, add a new file called <code>Fireworks.css<\/code>. Then add the following code inside it:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\"><span class=\"hljs-comment\">\/* Fireworks.css *\/<\/span>\n<span class=\"hljs-selector-class\">.player<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: flex;\n  <span class=\"hljs-attribute\">flex-direction<\/span>: column;\n  <span class=\"hljs-attribute\">justify-content<\/span>: center;\n  <span class=\"hljs-attribute\">align-items<\/span>: center;\n}\n\n<span class=\"hljs-selector-class\">.dots<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: flex;\n  <span class=\"hljs-attribute\">align-items<\/span>: center;\n  <span class=\"hljs-attribute\">list-style<\/span>: none;\n  <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">100px<\/span>;\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-attribute\">margin-top<\/span>: <span class=\"hljs-number\">30px<\/span>;\n  <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n}\n\n<span class=\"hljs-selector-class\">.dots<\/span> <span class=\"hljs-selector-tag\">li<\/span> {\n  <span class=\"hljs-attribute\">border-radius<\/span>: <span class=\"hljs-number\">2px<\/span>;\n  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">2px<\/span>;\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>These are the classes we defined on the grid in our <code>Fireworks<\/code> component. They clean up some container configurations that can be done with MUI, but can be easier to implement with plain CSS. Those were the only styles we needed so we\u2019re good to go here.<\/p>\n<h3>Get user input<\/h3>\n<p>Now let\u2019s make that <code>CustomizeForm<\/code> component that lets users make changes to the fireworks. In the <code>components<\/code> folder, add a new file called <code>CustomizeForm.tsx<\/code>. Add the following code to this file:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ CustomizeForm.tsx<\/span>\n<span class=\"hljs-keyword\">import<\/span> Container <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@mui\/material\/Container\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> Stack <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@mui\/material\/Stack\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> TextField <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@mui\/material\/TextField\"<\/span>;\n<span class=\"hljs-keyword\">import<\/span> { CustomizationProps } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/Fireworks\"<\/span>;\n\ninterface CustomizeFormProps {\n  <span class=\"hljs-attr\">customizations<\/span>: CustomizationProps;\n  setCustomizations: <span class=\"hljs-function\">(<span class=\"hljs-params\">options: CustomizationProps<\/span>) =&gt;<\/span> <span class=\"hljs-keyword\">void<\/span>;\n}\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">CustomizeForm<\/span>(<span class=\"hljs-params\">{\n  customizations,\n  setCustomizations,\n}: CustomizeFormProps<\/span>) <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">updateFireworks<\/span>(<span class=\"hljs-params\">e: any<\/span>) <\/span>{\n    e.preventDefault();\n\n    <span class=\"hljs-keyword\">const<\/span> { color, size, duration, sparkAmount, rows } = customizations;\n\n    <span class=\"hljs-keyword\">const<\/span> newValues = {\n      <span class=\"hljs-attr\">color<\/span>: e.currentTarget.color.value || color,\n      <span class=\"hljs-attr\">size<\/span>:\n        e.currentTarget.size.value !== <span class=\"hljs-string\">\"\"<\/span>\n          ? <span class=\"hljs-built_in\">Number<\/span>(e.currentTarget.size.value)\n          : size,\n      <span class=\"hljs-attr\">duration<\/span>:\n        e.currentTarget.duration.value !== <span class=\"hljs-string\">\"\"<\/span>\n          ? <span class=\"hljs-built_in\">Number<\/span>(e.currentTarget.duration.value)\n          : duration,\n      <span class=\"hljs-attr\">sparkAmount<\/span>:\n        e.currentTarget.sparkAmount.value !== <span class=\"hljs-string\">\"\"<\/span>\n          ? <span class=\"hljs-built_in\">Array<\/span>.from(<span class=\"hljs-built_in\">Array<\/span>(<span class=\"hljs-built_in\">Number<\/span>(e.currentTarget.sparkAmount.value)))\n          : sparkAmount,\n      <span class=\"hljs-attr\">rows<\/span>:\n        e.currentTarget.rows.value !== <span class=\"hljs-string\">\"\"<\/span>\n          ? <span class=\"hljs-built_in\">Array<\/span>.from(<span class=\"hljs-built_in\">Array<\/span>(<span class=\"hljs-built_in\">Number<\/span>(e.currentTarget.rows.value)))\n          : rows,\n    };\n\n    setCustomizations(newValues);\n  }\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Container<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span>\n        <span class=\"hljs-attr\">onChange<\/span>=<span class=\"hljs-string\">{(e)<\/span> =&gt;<\/span> updateFireworks(e)}\n        style={{ marginBottom: \"24px\", marginTop: \"24px\", width: \"800px\" }}\n      &gt;\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Stack<\/span> <span class=\"hljs-attr\">spacing<\/span>=<span class=\"hljs-string\">{2}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">TextField<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"color\"<\/span> <span class=\"hljs-attr\">label<\/span>=<span class=\"hljs-string\">\"Color\"<\/span> <span class=\"hljs-attr\">variant<\/span>=<span class=\"hljs-string\">\"standard\"<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"color\"<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">TextField<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"size\"<\/span> <span class=\"hljs-attr\">label<\/span>=<span class=\"hljs-string\">\"Size\"<\/span> <span class=\"hljs-attr\">variant<\/span>=<span class=\"hljs-string\">\"standard\"<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"size\"<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">TextField<\/span>\n            <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"sparkAmount\"<\/span>\n            <span class=\"hljs-attr\">label<\/span>=<span class=\"hljs-string\">\"Number of sparks\"<\/span>\n            <span class=\"hljs-attr\">variant<\/span>=<span class=\"hljs-string\">\"standard\"<\/span>\n            <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"sparkAmount\"<\/span>\n          \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">TextField<\/span>\n            <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"rows\"<\/span>\n            <span class=\"hljs-attr\">label<\/span>=<span class=\"hljs-string\">\"Number of firework rows\"<\/span>\n            <span class=\"hljs-attr\">variant<\/span>=<span class=\"hljs-string\">\"standard\"<\/span>\n            <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"rows\"<\/span>\n          \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">TextField<\/span>\n            <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"duration\"<\/span>\n            <span class=\"hljs-attr\">label<\/span>=<span class=\"hljs-string\">\"Duration\"<\/span>\n            <span class=\"hljs-attr\">variant<\/span>=<span class=\"hljs-string\">\"standard\"<\/span>\n            <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"duration\"<\/span>\n          \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Stack<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Container<\/span>&gt;<\/span><\/span>\n  );\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This is a basic form with some input fields that triggers a state change. We import the packages like usual and we also import a type from the <code>Fireworks<\/code> component to define the options users change. Then we define the props this component expects which are the state variable and method we made in the <code>Fireworks<\/code> component.<\/p>\n<p>Next is the component itself. It looks like a lot more is happening than it really is. The <code>updateFireworks<\/code> function is getting the form values and defaulting to the existing <code>customizations<\/code> values if users do change them. Then it updates the state which will re-render the <code>Fireworks<\/code> elements with these new values.<\/p>\n<p>At the end, we have the <code>form<\/code> with the five options users can change for their fireworks. Any time a value is changed, it triggers a form event to call the <code>updateFireworks<\/code> function with the new values. That\u2019s all for the user form! Now let\u2019s make the last update to show all of this work in the browser.<\/p>\n<h3>Update the <code>App.tsx<\/code> file<\/h3>\n<p>Open <code>App.tsx<\/code> and delete everything out of it. This is where we\u2019re going to show our fireworks and the form in action. Add the following code to the file:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/ App.tsx<\/span>\n<span class=\"hljs-keyword\">import<\/span> Fireworks <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/components\/Fireworks\"<\/span>;\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">App<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Fireworks<\/span> \/&gt;<\/span><\/span>;\n}\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> App;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Now all of that behind-the-scenes work will finally be shown to users. If you run the app with <code>npm start<\/code>, you should see something like this now:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/res.cloudinary.com\/mediadevs\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/v1656079907\/e-603fc55d218a650069f5228b\/ujg3cue3apsdz90v0ogj.png\" alt=\"finished app\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"2000\" height=\"1283\"\/><\/p>\n<p>That\u2019s it! Now we\u2019re done with this little fireworks animation and you can start diving deeper into this library.<\/p>\n<h2>Finished code<\/h2>\n<p>You can check out all of the code in the <code>qr-card<\/code> folder of <a href=\"https:\/\/github.com\/flippedcoder\/media-projects\/tree\/main\/fireworks\">this repo<\/a>. You can also check out the app in <a href=\"https:\/\/codesandbox.io\/s\/pedantic-babbage-hb0pw6\">this Code Sandbox<\/a>.<\/p>\n<p>&lt;CodeSandBox\ntitle=\u201cpedantic-babbage-hb0pw6\u201d\nid=\u201cpedantic-babbage-hb0pw6\u201d\n\/&gt;<\/p>\n<h2>Conclusion<\/h2>\n<p>There are several good animation packages out there for JavaScript apps like, <a href=\"https:\/\/threejs.org\/\">three.js<\/a>, <a href=\"http:\/\/velocityjs.org\/\">velocity.js<\/a>, and <a href=\"https:\/\/greensock.com\/gsap\/\">GSAP<\/a>. It doesn\u2019t hurt to do a little research into all of them if you know you\u2019re going to be working with browser animations. Most of them have great documentation and examples so you should be able to get up and running with any of them.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28511,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,177,246,371],"class_list":["post-28510","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-javascript","tag-react","tag-under-review"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Create a Fireworks Animation in React<\/title>\n<meta name=\"description\" content=\"You can do a lot of interesting animations in the browser and still have a performant app. There are plenty of libraries that help you handle this and we&#039;re going to look at one called anime.js.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Create a Fireworks Animation in React\" \/>\n<meta property=\"og:description\" content=\"You can do a lot of interesting animations in the browser and still have a performant app. There are plenty of libraries that help you handle this and we&#039;re going to look at one called anime.js.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-06-28T10:19:45+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924250\/Web_Assets\/blog\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7.jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"2017\" \/>\n\t<meta property=\"og:image:height\" content=\"3024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Create a Fireworks Animation in React\",\"datePublished\":\"2022-06-28T10:19:45+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/\"},\"wordCount\":6,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924250\/Web_Assets\/blog\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7.jpg?_i=AA\",\"keywords\":[\"Guest Post\",\"Javascript\",\"React\",\"Under Review\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/\",\"name\":\"Create a Fireworks Animation in React\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924250\/Web_Assets\/blog\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7.jpg?_i=AA\",\"datePublished\":\"2022-06-28T10:19:45+00:00\",\"description\":\"You can do a lot of interesting animations in the browser and still have a performant app. There are plenty of libraries that help you handle this and we're going to look at one called anime.js.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924250\/Web_Assets\/blog\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924250\/Web_Assets\/blog\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7.jpg?_i=AA\",\"width\":2017,\"height\":3024},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Create a Fireworks Animation in React\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Create a Fireworks Animation in React","description":"You can do a lot of interesting animations in the browser and still have a performant app. There are plenty of libraries that help you handle this and we're going to look at one called anime.js.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/","og_locale":"en_US","og_type":"article","og_title":"Create a Fireworks Animation in React","og_description":"You can do a lot of interesting animations in the browser and still have a performant app. There are plenty of libraries that help you handle this and we're going to look at one called anime.js.","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/","og_site_name":"Cloudinary Blog","article_published_time":"2022-06-28T10:19:45+00:00","og_image":[{"width":2017,"height":3024,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924250\/Web_Assets\/blog\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7.jpg?_i=AA","type":"image\/jpeg"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/"},"author":{"name":"","@id":""},"headline":"Create a Fireworks Animation in React","datePublished":"2022-06-28T10:19:45+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/"},"wordCount":6,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924250\/Web_Assets\/blog\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7.jpg?_i=AA","keywords":["Guest Post","Javascript","React","Under Review"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/","name":"Create a Fireworks Animation in React","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924250\/Web_Assets\/blog\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7.jpg?_i=AA","datePublished":"2022-06-28T10:19:45+00:00","description":"You can do a lot of interesting animations in the browser and still have a performant app. There are plenty of libraries that help you handle this and we're going to look at one called anime.js.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924250\/Web_Assets\/blog\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924250\/Web_Assets\/blog\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7.jpg?_i=AA","width":2017,"height":3024},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/create-a-fireworks-animation-in-react\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Create a Fireworks Animation in React"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681924250\/Web_Assets\/blog\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7\/02e52199fed3ade5648f8f799e8d008f564524e7-2017x3024-1_28511ef9b7.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28510","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28510"}],"version-history":[{"count":0,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28510\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28511"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28510"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28510"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28510"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}