animejs

I was working on some code to display a green circle with a tick (for success) and a red circle with a cross (for failure) within rows in ag-Grid to denote whether service calls succeeded or failed for each row of data. Having the graphics seemed good but what I really wanted was to animate the display of these graphics to make it obvious to the user that these graphics changes/updated.

animejs looked to be a perfect solution to the problem.

There’s lots of great examples using animejs here.

Obviously to begin with I’ve created a React application using the standard scaffolding, and then using yarn installed anime, i.e.

yarn add animejs
yarn add @types/animejs

We’ll create a standard React component (SuccessFailureComponent.tsx) for displaying our new animated component.

import React from 'react';
import anime from "animejs";

interface SuccessFailureProps {
    success: boolean;
}

export class SuccessFailureComponent 
   extends React.Component<SuccessFailureProps, {}> {
      render() {
         // to be implemented
      }
}

In this code we’ve added the property success, which when true will display the green circle with a tick and when false the red circle with the cross.

To begin with we’ll add the following code to draw our graphics to the render function

const backColour = this.props.success ? 
   "#0c3" : 
   "red";
const symbol = this.props.success ? 
   "M9 16l5 5 9-9": 
   "M9 9l14 14 M23 9L9 23";

return (
   <svg className="status" xmlns="http://www.w3.org/2000/svg"
      width="32"
      height="32"
      viewBox="0 0 42 42">
      <circle className="circle"
         cx="16"
         cy="16"
         r="16"
         fill={backColour}/>
      <path d={symbol}
         fill="none"
         stroke="white"
         stroke-width="2.5"   
         stroke-linecap="round"/> :
   </svg>
);

In the above we use the Scalable Vector Graphics element to wrap drawing primitives to first draw a circle with the required fill colour and then using the symbol const which is the drawing of a tick or cross.

If we run the React app at this point (assuming we’ve also added the following component to the App.tsx render method

<SuccessFailureComponent success={false}/>
<SuccessFailureComponent success={true}/>

then we’ll see the two SVG graphics displayed.

Animating our graphics

We’ve come all this way in a post about animation and not animated anything, so let’s now do that. Back in the component, add

componentDidMount() {
   var timeline = anime.timeline({ 
      autoplay: true
   });

   timeline
      .add({
         targets: '.status',
         scale: [{ 
            value: [0, 1], 
            duration: 600, 
            easing: 'easeOutQuad' }
         ]
      });
}

When the application is refreshed you’ll see the graphics scale from nothing to full sized.

In the first line we create the anime timeline which has parameters which will simply start the animation immediately. We then use the add function with the target “status” (our SVG element) to scale the SVG from nothing to full sized with a duration of 600ms. Finally we specify the easing function to use.

We can also add more animation transitions to the timeline, for example the following additions to the timeline code (above) will result in the icons moving right by 10 pixels then returning to where they started

.add({
   targets: '.status',            
   translateX: 10
})
.add({
   targets: '.status',
   translateX: 0
});

Or maybe we’d like to just spin the graphics using

.add({
   targets: '.status',            
   rotate: 360
});

There’s more than just the timeline function, there’s also stagger which allows the animation of multiple elements. Also keyframes which allows us to create an array of keyframes for our animations.

This easings.net is a great resource for seeing how different easing functions might look. If you want to (for example) add a little bounce back to the easing try, easeOutBack.

The anime documentation also has some great examples along with the documentation of fairly simple transitions.