{"id":27745,"date":"2022-02-16T17:18:53","date_gmt":"2022-02-16T17:18:53","guid":{"rendered":"http:\/\/Display-Floating-Avatars-for-Event-Attendees"},"modified":"2022-02-16T17:18:53","modified_gmt":"2022-02-16T17:18:53","slug":"display-floating-avatars-for-event-attendees","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/","title":{"rendered":"Display Floating Avatars for Event Attendees"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>I recall registering for one of the previous editions of the Next.js conference and seeing animation on the landing page with participants\u2019 avatars joyously floating around.<\/p>\n<p>In this article, we will recreate that animation using <a href=\"https:\/\/animejs.com\/\">anime.js<\/a> and React. A registration form will be displayed when the website loads. This form will contain four elements: an input field for the user\u2019s name, a button for uploading an avatar, a checkbox that the user selects to indicate whether or not the avatar should be displayed on the page, and a submit button.<\/p>\n<p>Cloudinary will handle image uploads and display. You will need a Cloudinary account so create one <a href=\"https:\/\/cloudinary.com\/users\/register\/free\">here<\/a> if you do not already have one. We will use <a href=\"https:\/\/ant.design\/\">antd<\/a> for UI components in our application.<\/p>\n<p>Here is a <a href=\"https:\/\/codesandbox.io\/s\/floating-avatars-rvo54?file=\/src\/cloudinaryConfig.js:150-166\">link<\/a> to the demo CodeSandbox.<\/p>\n<\/div>\n  \n  <div class=\"wp-block-cloudinary-code-sandbox \">\n    <iframe\n      src=\"https:\/\/codesandbox.io\/embed\/floating-avatars-rvo54?theme=dark&amp;codemirror=1&amp;highlights=&amp;editorsize=50&amp;fontsize=14&amp;expanddevtools=0&amp;hidedevtools=0&amp;eslint=0&amp;forcerefresh=0&amp;hidenavigation=0&amp;initialpath=%2F&amp;module=&amp;moduleview=0&amp;previewwindow=&amp;view=&amp;runonclick=1\"\n      height=\"500\"\n      style=\"width: 100%;\"\n      title=\"floating-avatars-rvo54\"\n      loading=\"lazy\"\n      allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n      sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n    ><\/iframe>\n  <\/div>\n\n  <div class=\"wp-block-cloudinary-markdown \"><h2>Project Setup<\/h2>\n<p>Create a new React app using the following command:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">    npx create-react-app floating_avatars\n<\/code><\/span><\/pre>\n<p>Next, add the project dependencies using the following command:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">    <span class=\"hljs-selector-tag\">npm<\/span> <span class=\"hljs-selector-tag\">install<\/span> <span class=\"hljs-selector-tag\">animejs<\/span> <span class=\"hljs-selector-tag\">antd<\/span> <span class=\"hljs-keyword\">@ant-design<\/span>\/icons cloudinary-react axios\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><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>Next, we need to import the CSS for antd. To do this, add the following to the <code>App.css<\/code> file in your <code>src<\/code> directory:<\/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-keyword\">@import<\/span> <span class=\"hljs-string\">\"~antd\/dist\/antd.css\"<\/span>;\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>Next, we need to create some environment variables to hold our Cloudinary details. We will be sending images to Cloudinary via unsigned POST requests for this tutorial. To do this, we need our account cloud name and an unsinged <a href=\"https:\/\/cloudinary.com\/documentation\/upload_presets\">upload preset<\/a>. Create a new file called <code>.env<\/code> at the root of your project and add the following to it:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">    REACT_APP_CLOUD_NAME = YOUR CLOUD NAME HERE\n    REACT_APP_UPLOAD_PRESET = YOUR UNSIGNED UPLOAD PRESET KEY HERE\n<\/code><\/span><\/pre>\n<p>This will be used as a default when the project is set up on another system. To update your local environment, create a copy of the <code>.env<\/code> file using the following command:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">    <span class=\"hljs-selector-tag\">cp<\/span> <span class=\"hljs-selector-class\">.env<\/span> <span class=\"hljs-selector-class\">.env<\/span><span class=\"hljs-selector-class\">.local<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><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>By default, this local file is added to <code>.gitignore<\/code> and mitigates the security risk of inadvertently exposing secret credentials to the public. You can update <code>.env.local<\/code> with your Cloudinary cloud name and generated upload preset.<\/p>\n<p>Next, create a file named <code>cloudinaryConfig.js<\/code> in your <code>src<\/code> folder. This file will access the environment variables and prevent repeated <code>process.env.<\/code> calls throughout the project. Add the following to your <code>cloudinaryConfig.js<\/code> 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-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> cloudName = process.env.REACT_APP_CLOUD_NAME;\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> uploadPreset = process.env.REACT_APP_UPLOAD_PRESET;\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> uploadTag = <span class=\"hljs-string\">\"floating_avatar_registration\"<\/span>;\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>In addition, we declared a constant named <code>uploadTag<\/code>. This will be attached to the uploaded images with the user\u2019s permission to display in the floating avatars.<\/p>\n<h2>Create Helper Class for API Requests<\/h2>\n<p>To help with requests to the Cloudinary API, create a new file called <code>api.js<\/code> and add the following to it:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> axios <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"axios\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { cloudName, uploadPreset, uploadTag } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/cloudinaryConfig\"<\/span>;\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> getAvatarResources = <span class=\"hljs-function\">(<span class=\"hljs-params\">{ successCallback }<\/span>) =&gt;<\/span> {\n      axios\n        .get(<span class=\"hljs-string\">`https:\/\/res.cloudinary.com\/<span class=\"hljs-subst\">${cloudName}<\/span>\/image\/list\/<span class=\"hljs-subst\">${uploadTag}<\/span>.json`<\/span>)\n        .then(<span class=\"hljs-function\">(<span class=\"hljs-params\">response<\/span>) =&gt;<\/span> successCallback(response.data.resources));\n    };\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> uploadFile = <span class=\"hljs-function\">(<span class=\"hljs-params\">{ file, successCallback, addTag }<\/span>) =&gt;<\/span> {\n      <span class=\"hljs-keyword\">const<\/span> url = <span class=\"hljs-string\">`https:\/\/api.cloudinary.com\/v1_1\/<span class=\"hljs-subst\">${cloudName}<\/span>\/image\/upload`<\/span>;\n      <span class=\"hljs-keyword\">const<\/span> data = <span class=\"hljs-keyword\">new<\/span> FormData();\n      data.append(<span class=\"hljs-string\">\"file\"<\/span>, file);\n      data.append(<span class=\"hljs-string\">\"upload_preset\"<\/span>, uploadPreset);\n      <span class=\"hljs-keyword\">if<\/span> (addTag) {\n        data.append(<span class=\"hljs-string\">\"tags\"<\/span>, uploadTag);\n      }\n      axios\n        .post(url, data, {\n          <span class=\"hljs-attr\">headers<\/span>: {\n            <span class=\"hljs-string\">\"Content-Type\"<\/span>: <span class=\"hljs-string\">\"multipart\/form-data\"<\/span>,\n          },\n        })\n        .then(<span class=\"hljs-function\">(<span class=\"hljs-params\">response<\/span>) =&gt;<\/span> successCallback(response.data));\n    };\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><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>In the <code>getAvatarResources<\/code> function, we use the Client-side asset lists feature to retrieve the list of images with our set tag. To ensure that this feature is available on your Cloudinary account, you must ensure that the Resource list option is <a href=\"https:\/\/cloudinary.com\/documentation\/advanced_url_delivery_options#client_side_asset_lists\">enabled<\/a>. By default, the list delivery type is restricted.<\/p>\n<p>The <code>uploadFile<\/code> function uploads the selected avatar to Cloudinary. With the selected file, a boolean flag named <code>addTag<\/code> and a callback function in the event of a successful upload, the <code>uploadFile<\/code> function makes a POST request to Cloudinary, providing the file and the upload preset we defined earlier. If the value of  <code>addTag<\/code> is set to true, a tag is attached to the request to include the avatar in the animation(s) on the index page.<\/p>\n<h2>Create Avatar Selector component<\/h2>\n<p>Create a new folder called <code>components<\/code> in your <code>src<\/code> directory. In the <code>src\/components<\/code> directory, create a new file called <code>AvatarSelector.js<\/code> and add the following to it:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> { Button, Upload } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"antd\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { UploadOutlined } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@ant-design\/icons\"<\/span>;\n    <span class=\"hljs-keyword\">const<\/span> AvatarSelector = <span class=\"hljs-function\">(<span class=\"hljs-params\">{ setUploadedFile, isUploading }<\/span>) =&gt;<\/span> {\n      <span class=\"hljs-keyword\">const<\/span> props = {\n        <span class=\"hljs-attr\">name<\/span>: <span class=\"hljs-string\">\"file\"<\/span>,\n        <span class=\"hljs-attr\">onRemove<\/span>: <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n          setUploadedFile(<span class=\"hljs-literal\">null<\/span>);\n        },\n        <span class=\"hljs-attr\">beforeUpload<\/span>: <span class=\"hljs-function\">(<span class=\"hljs-params\">file<\/span>) =&gt;<\/span> {\n          setUploadedFile(file);\n          <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-literal\">false<\/span>;\n        },\n        <span class=\"hljs-attr\">showUploadList<\/span>: <span class=\"hljs-literal\">false<\/span>,\n        <span class=\"hljs-attr\">maxCount<\/span>: <span class=\"hljs-number\">1<\/span>,\n      };\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Upload<\/span> {<span class=\"hljs-attr\">...props<\/span>}&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Button<\/span> <span class=\"hljs-attr\">icon<\/span>=<span class=\"hljs-string\">{<\/span>&lt;<span class=\"hljs-attr\">UploadOutlined<\/span> \/&gt;<\/span>} loading={isUploading}&gt;\n            Click to Upload\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Button<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Upload<\/span>&gt;<\/span><\/span>\n      );\n    };\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> AvatarSelector;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><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>The AvatarSelector component takes two props:<\/p>\n<ol>\n<li>\n<code>setUploadedFile<\/code> &#8211; this callback function is used to update the application state with the latest image uploaded by the user.<\/li>\n<li>\n<code>isUploading<\/code> &#8211; This flag is used to set the status of the upload button. If this value is <code>true<\/code>, it indicates that the currently selected image is being uploaded to Cloudinary.<\/li>\n<\/ol>\n<p>By returning <code>false<\/code> in the <code>beforeUpload<\/code> method, we disable the <code>Upload<\/code> component\u2019s default behavior, which uploads the selected file to a provided URL. We also restrict the maximum number of files to 1.<\/p>\n<h2>Create Floating Avatar component<\/h2>\n<p>In your <code>src\/component<\/code> folder, create a new file called <code>FloatingAvatars.js<\/code> and add the following to it:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> { useEffect, useRef } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/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> { cloudName, uploadPreset } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/util\/cloudinaryConfig\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { Image, Transformation } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"cloudinary-react\"<\/span>;\n    <span class=\"hljs-keyword\">const<\/span> FloatingAvatars = <span class=\"hljs-function\">(<span class=\"hljs-params\">{ avatars }<\/span>) =&gt;<\/span> {\n      <span class=\"hljs-keyword\">const<\/span> refs = useRef(&#91;]);\n      <span class=\"hljs-keyword\">const<\/span> windowHeight = <span class=\"hljs-built_in\">window<\/span>.innerHeight;\n      <span class=\"hljs-keyword\">const<\/span> windowWidth = <span class=\"hljs-built_in\">window<\/span>.innerWidth;\n      <span class=\"hljs-keyword\">const<\/span> animation = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        anime({\n          <span class=\"hljs-attr\">targets<\/span>: refs.current,\n          <span class=\"hljs-attr\">translateY<\/span>: <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> anime.random(<span class=\"hljs-number\">0<\/span>, windowHeight \/ <span class=\"hljs-number\">2<\/span>),\n          <span class=\"hljs-attr\">translateX<\/span>: <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> anime.random(<span class=\"hljs-number\">0<\/span>, windowWidth \/ <span class=\"hljs-number\">2<\/span>),\n          <span class=\"hljs-attr\">easing<\/span>: <span class=\"hljs-string\">\"easeInOutSine\"<\/span>,\n          <span class=\"hljs-attr\">duration<\/span>: <span class=\"hljs-number\">5000<\/span>,\n          <span class=\"hljs-attr\">loop<\/span>: <span class=\"hljs-literal\">true<\/span>,\n          <span class=\"hljs-attr\">direction<\/span>: <span class=\"hljs-string\">\"alternate\"<\/span>,\n          <span class=\"hljs-attr\">complete<\/span>: animation,\n        });\n      };\n      useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        animation();\n      });\n      <span class=\"hljs-keyword\">const<\/span> getRandomNumber = <span class=\"hljs-function\">(<span class=\"hljs-params\">min, max<\/span>) =&gt;<\/span> <span class=\"hljs-built_in\">Math<\/span>.random() * (max - min) + min;\n      <span class=\"hljs-keyword\">const<\/span> randomTop = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> getRandomNumber(<span class=\"hljs-number\">0<\/span>, windowHeight \/ <span class=\"hljs-number\">2<\/span>);\n      <span class=\"hljs-keyword\">const<\/span> randomLeft = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> getRandomNumber(<span class=\"hljs-number\">0<\/span>, windowWidth \/ <span class=\"hljs-number\">2<\/span>);\n      <span class=\"hljs-keyword\">return<\/span> avatars.map(<span class=\"hljs-function\">(<span class=\"hljs-params\">avatar, index<\/span>) =&gt;<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>\n          <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{index}<\/span>\n          <span class=\"hljs-attr\">ref<\/span>=<span class=\"hljs-string\">{(el)<\/span> =&gt;<\/span> (refs.current&#91;index] = el)}\n          style={{\n            position: \"absolute\",\n            top: `${randomTop()}px`,\n            left: `${randomLeft()}px`,\n          }}\n        &gt;\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Image<\/span>\n            <span class=\"hljs-attr\">publicId<\/span>=<span class=\"hljs-string\">{<\/span>`${<span class=\"hljs-attr\">avatar.public_id<\/span>}<span class=\"hljs-attr\">.png<\/span>`}\n            <span class=\"hljs-attr\">cloudName<\/span>=<span class=\"hljs-string\">{cloudName}<\/span>\n            <span class=\"hljs-attr\">upload_preset<\/span>=<span class=\"hljs-string\">{uploadPreset}<\/span>\n            <span class=\"hljs-attr\">secure<\/span>=<span class=\"hljs-string\">{true}<\/span>\n          &gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Transformation<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">{50}<\/span> <span class=\"hljs-attr\">height<\/span>=<span class=\"hljs-string\">{50}<\/span> <span class=\"hljs-attr\">gravity<\/span>=<span class=\"hljs-string\">\"face\"<\/span> <span class=\"hljs-attr\">crop<\/span>=<span class=\"hljs-string\">\"thumb\"<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Transformation<\/span> <span class=\"hljs-attr\">radius<\/span>=<span class=\"hljs-string\">\"max\"<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Transformation<\/span> <span class=\"hljs-attr\">effect<\/span>=<span class=\"hljs-string\">\"trim\"<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Image<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      ));\n    };\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> FloatingAvatars;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><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 component takes a list of Cloudinary image resources, renders them in random positions, and applies the specified animation. The <code>Image<\/code> and <code>Transformation<\/code> components from the Cloudinary-react package are used to dynamically generate a 50px by 50px rounded image focusing on the face. The image is also automatically converted to png format as specified, allowing the trimmed section\u2019s background to be transparent (instead of white).<\/p>\n<p>The animation function targets the rendered images and animates them along a random course. This is done by generating random values for the translateX and translateY properties of the <code>anime<\/code> function.<\/p>\n<h2>Putting It All Together<\/h2>\n<p>Update your <code>src\/App.js<\/code> with the following:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">\".\/App.css\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { Button, Card, Checkbox, Col, Form, Input, message } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"antd\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> AvatarSelector <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/components\/AvatarSelector\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { useEffect, useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> FloatingAvatars <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/components\/FloatingAvatar\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { getAvatarResources, uploadFile } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/utils\/api\"<\/span>;\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\">const<\/span> &#91;avatars, setAvatars] = useState(&#91;]);\n      <span class=\"hljs-keyword\">const<\/span> &#91;uploadedFile, setUploadedFile] = useState(<span class=\"hljs-literal\">null<\/span>);\n      <span class=\"hljs-keyword\">const<\/span> &#91;isUploading, setIsUploading] = useState(<span class=\"hljs-literal\">false<\/span>);\n      useEffect(<span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        getAvatarResources({ <span class=\"hljs-attr\">successCallback<\/span>: setAvatars });\n      }, &#91;]);\n      <span class=\"hljs-keyword\">const<\/span> onFinish = <span class=\"hljs-function\">(<span class=\"hljs-params\">values<\/span>) =&gt;<\/span> {\n        setIsUploading(<span class=\"hljs-literal\">true<\/span>);\n        <span class=\"hljs-keyword\">const<\/span> showUploadedAvatar = values.showAvatar || <span class=\"hljs-literal\">false<\/span>;\n        uploadFile({\n          <span class=\"hljs-attr\">file<\/span>: uploadedFile,\n          <span class=\"hljs-attr\">successCallback<\/span>: <span class=\"hljs-function\">(<span class=\"hljs-params\">data<\/span>) =&gt;<\/span> {\n            setIsUploading(<span class=\"hljs-literal\">false<\/span>);\n            <span class=\"hljs-keyword\">if<\/span> (showUploadedAvatar) {\n              setAvatars(<span class=\"hljs-function\">(<span class=\"hljs-params\">oldAvatars<\/span>) =&gt;<\/span> &#91;...oldAvatars, data]);\n            }\n            message.success(<span class=\"hljs-string\">`Welcome <span class=\"hljs-subst\">${values.username}<\/span>!!!`<\/span>);\n          },\n          <span class=\"hljs-attr\">addTag<\/span>: showUploadedAvatar,\n        });\n      };\n      <span class=\"hljs-keyword\">const<\/span> onFailedSubmission = <span class=\"hljs-function\">(<span class=\"hljs-params\">errorInfo<\/span>) =&gt;<\/span> {\n        <span class=\"hljs-built_in\">console<\/span>.log(<span class=\"hljs-string\">\"Failed:\"<\/span>, errorInfo);\n      };\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"App\"<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">margin:<\/span> \"<span class=\"hljs-attr\">5<\/span>%\" }}&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Card<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">margin:<\/span> \"<span class=\"hljs-attr\">auto<\/span>\", <span class=\"hljs-attr\">width:<\/span> \"<span class=\"hljs-attr\">50<\/span>%\" }}&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Form<\/span>\n              <span class=\"hljs-attr\">onFinish<\/span>=<span class=\"hljs-string\">{onFinish}<\/span>\n              <span class=\"hljs-attr\">onFinishFailed<\/span>=<span class=\"hljs-string\">{onFailedSubmission}<\/span>\n              <span class=\"hljs-attr\">autoComplete<\/span>=<span class=\"hljs-string\">\"off\"<\/span>\n            &gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Form.Item<\/span>\n                <span class=\"hljs-attr\">label<\/span>=<span class=\"hljs-string\">\"Username\"<\/span>\n                <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"username\"<\/span>\n                <span class=\"hljs-attr\">rules<\/span>=<span class=\"hljs-string\">{&#91;<\/span>\n                  {\n                    <span class=\"hljs-attr\">required:<\/span> <span class=\"hljs-attr\">true<\/span>,\n                    <span class=\"hljs-attr\">message:<\/span> \"<span class=\"hljs-attr\">Please<\/span> <span class=\"hljs-attr\">input<\/span> <span class=\"hljs-attr\">your<\/span> <span class=\"hljs-attr\">username<\/span>\",\n                  },\n                ]}\n              &gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Input<\/span> \/&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Form.Item<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Col<\/span> <span class=\"hljs-attr\">span<\/span>=<span class=\"hljs-string\">{16}<\/span> <span class=\"hljs-attr\">offset<\/span>=<span class=\"hljs-string\">{9}<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">AvatarSelector<\/span> <span class=\"hljs-attr\">setUploadedFile<\/span>=<span class=\"hljs-string\">{setUploadedFile}<\/span> \/&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Col<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Form.Item<\/span>\n                <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"showAvatar\"<\/span>\n                <span class=\"hljs-attr\">valuePropName<\/span>=<span class=\"hljs-string\">\"checked\"<\/span>\n                <span class=\"hljs-attr\">wrapperCol<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">offset:<\/span> <span class=\"hljs-attr\">9<\/span>, <span class=\"hljs-attr\">span:<\/span> <span class=\"hljs-attr\">16<\/span> }}\n              &gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Checkbox<\/span>&gt;<\/span>Show my avatar<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Checkbox<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Form.Item<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Form.Item<\/span> <span class=\"hljs-attr\">wrapperCol<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">offset:<\/span> <span class=\"hljs-attr\">10<\/span>, <span class=\"hljs-attr\">span:<\/span> <span class=\"hljs-attr\">16<\/span> }}&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Button<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"primary\"<\/span> <span class=\"hljs-attr\">htmlType<\/span>=<span class=\"hljs-string\">\"submit\"<\/span> <span class=\"hljs-attr\">loading<\/span>=<span class=\"hljs-string\">{isUploading}<\/span>&gt;<\/span>\n                  Submit\n                <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Button<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Form.Item<\/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\">Card<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">FloatingAvatars<\/span> <span class=\"hljs-attr\">avatars<\/span>=<span class=\"hljs-string\">{avatars}<\/span> \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/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-8\"><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>In this component, we create three state variables:<\/p>\n<ul>\n<li>\n<code>avatars<\/code> holds the list of Cloudinary resources to be rendered by the <code>FloatingAvatars<\/code> component.<\/li>\n<li>\n<code>uploadedFile<\/code> holds the file uploaded using the <code>AvatarSelector<\/code> component.<\/li>\n<li>\n<code>isUploading<\/code> is used to show a loading animation on the <code>AvatarSelector<\/code> and submit button when the user completes the form.<\/li>\n<\/ul>\n<p>We are calling the <code>getAvatarResources<\/code> function we declared in <code>api.js<\/code> in a <code>useEffect<\/code> hook and providing the <code>setAvatars<\/code> function as a callback if the API call is successful. This way, the avatars array is populated with the list of Cloudinary resources.<\/p>\n<p>We also render a form with a single field for the <code>username<\/code>, a checkbox with which the user can indicate whether or not they would like their avatar to be displayed. The <code>AvatarComponent<\/code> is also rendered to allow the user to select an avatar. Finally, we rendered the <code>FloatingAvatars<\/code> component, passing in the necessary props.<\/p>\n<p>The <code>onFinish<\/code> function is called when the <strong>Submit<\/strong> button is clicked. This function handles the upload of the selected file using the <code>uploadFile<\/code> function we declared in the <code>api.js<\/code> file. On a successful upload, if the user selected the <strong>Show my avatar<\/strong> checkbox, the returned resource is added to the array of Cloudinary resources, and the newly uploaded image is displayed on the screen.<\/p>\n<p>Using the following command, start your application on <a href=\"http:\/\/localhost:3000\/\">http:\/\/localhost:3000\/<\/a>.<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">    npm run dev\n<\/code><\/span><\/pre>\n<p>The final result will look like the gif shown below.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_256673EF7783CAA02AAD71A94C150557077F73F4D4FF18FFBEBEA09695853B2A_1642733220711_CleanShot+2022-01-21+at+06.46.41.gif\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"800\" height=\"455\"\/><\/p>\n<p>Find the complete project <a href=\"https:\/\/github.com\/ifeoma-imoh\/floating-avatars\">here<\/a> on GitHub.<\/p>\n<h2>Conclusion<\/h2>\n<p>In this article, we looked at how to animate floating avatars using the anime.js library. Additionally, we looked at how to use Cloudinary to handle the upload and storage of media, the dynamic transformation, and the rendering of images in a developer-friendly manner. Finally, using antd, we generated a clean and intuitive user interface with minimal code and styling.<\/p>\n<!-- Thank you for your content! Really awesome project would highly recommend it to peers. The content was easy to understand and follow the procedure. The only thing I would note to the reader is npm might not work perhaps npx to create react application - [npm create-react-app]\/[npx\u2026.]? Other than this no notes, thank you for the awesome content\nThat was a great catch!! Thank you very much.-->\n<p><strong>Resources you may find helpful:<\/strong><\/p>\n<ul>\n<li>\n<a href=\"https:\/\/animejs.com\/documentation\/\">Animejs Documentation<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/ant.design\/\">Ant Design Documentation<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/cloudinary.com\/documentation\/react_integration\">Cloudinary React SDK v1<\/a>\n<\/li>\n<\/ul>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":27746,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,370,175,246,371,373],"class_list":["post-27745","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-image","tag-jamstack","tag-react","tag-under-review","tag-upload"],"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>Display Floating Avatars for Event Attendees<\/title>\n<meta name=\"description\" content=\"This post describes how to add animation to avatars using the anime.js library.\" \/>\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\/display-floating-avatars-for-event-attendees\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Display Floating Avatars for Event Attendees\" \/>\n<meta property=\"og:description\" content=\"This post describes how to add animation to avatars using the anime.js library.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-02-16T17:18:53+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926375\/Web_Assets\/blog\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3.jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"3648\" \/>\n\t<meta property=\"og:image:height\" content=\"2432\" \/>\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\/display-floating-avatars-for-event-attendees\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Display Floating Avatars for Event Attendees\",\"datePublished\":\"2022-02-16T17:18:53+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/\"},\"wordCount\":6,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926375\/Web_Assets\/blog\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3.jpg?_i=AA\",\"keywords\":[\"Guest Post\",\"Image\",\"JAMStack\",\"React\",\"Under Review\",\"Upload\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/\",\"name\":\"Display Floating Avatars for Event Attendees\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926375\/Web_Assets\/blog\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3.jpg?_i=AA\",\"datePublished\":\"2022-02-16T17:18:53+00:00\",\"description\":\"This post describes how to add animation to avatars using the anime.js library.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926375\/Web_Assets\/blog\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926375\/Web_Assets\/blog\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3.jpg?_i=AA\",\"width\":3648,\"height\":2432},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Display Floating Avatars for Event Attendees\"}]},{\"@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":"Display Floating Avatars for Event Attendees","description":"This post describes how to add animation to avatars using the anime.js library.","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\/display-floating-avatars-for-event-attendees\/","og_locale":"en_US","og_type":"article","og_title":"Display Floating Avatars for Event Attendees","og_description":"This post describes how to add animation to avatars using the anime.js library.","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/","og_site_name":"Cloudinary Blog","article_published_time":"2022-02-16T17:18:53+00:00","og_image":[{"width":3648,"height":2432,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926375\/Web_Assets\/blog\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3.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\/display-floating-avatars-for-event-attendees\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/"},"author":{"name":"","@id":""},"headline":"Display Floating Avatars for Event Attendees","datePublished":"2022-02-16T17:18:53+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/"},"wordCount":6,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926375\/Web_Assets\/blog\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3.jpg?_i=AA","keywords":["Guest Post","Image","JAMStack","React","Under Review","Upload"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/","name":"Display Floating Avatars for Event Attendees","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926375\/Web_Assets\/blog\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3.jpg?_i=AA","datePublished":"2022-02-16T17:18:53+00:00","description":"This post describes how to add animation to avatars using the anime.js library.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926375\/Web_Assets\/blog\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681926375\/Web_Assets\/blog\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3.jpg?_i=AA","width":3648,"height":2432},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/display-floating-avatars-for-event-attendees\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Display Floating Avatars for Event Attendees"}]},{"@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\/v1681926375\/Web_Assets\/blog\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3\/147af43a7580f63559038bcf0ec3f16410e1268f-3648x2432-1_27746396a3.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/27745","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=27745"}],"version-history":[{"count":0,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/27745\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/27746"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=27745"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=27745"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=27745"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}