6 MIN READ
   //   Mar 3, 2020

React Native: Let's Animate the SVGs!

Kuldeep Singh

A simpler way to animated SVGs in React Native.

Animations are an important feature that one can include in his/her app. They give a much better user experience and when it comes to SVGs, animations become all the more important. But as you may already know, they are not supported in React Native by default. Which means if you take an online animated SVG and use it in your React Native app, you will not see its animations as you would see on a browser.
This blog is an attempt to work around this shortcoming of React Native. There are a few online libraries available for the same, but none are well explained and there are not many blogs about this. So, sit tight, as we discuss the implementation of animated SVGs via an example.

Prerequisites

  1. We will be needing some of the properties of the SVG that we need to animate. These can be obtained by opening the SVG file in any code editor or in any SVG to JSX converter available online.

  2. We will be using an online library react-native-svg-animations with some modifications and hence it should be installed beforehand.

Getting Started

We will choose an animated SVGs from loading.io and understand how its animations will be implemented in React Native. The SVG that we will be implementing is: 

React Native: Let's Animate the SVGs

Let’s see what properties we will be using. Following is the code obtained as we convert SVG into JSX: 

<svg

  xmlns="http://www.w3.org/2000/svg"

  width="200"

  height="200"

  display="block"

  preserveAspectRatio="xMidYMid"

  viewBox="0 0 100 100"

  style={{ margin: "auto" }}

>

  <path

     style={{

       WebkitTransformOrigin: 50,

       MsTransformOrigin: 50,

       transformOrigin: 50

     }}

     fill="none"

     stroke="#e90c59"

     strokeDasharray="42.76482137044271 42.76482137044271"

     strokeLinecap="round"

     strokeWidth="6.4"

     d="M19.44 24C9.12 24 4 34.64 4 40s5.12 16 15.44 16c15.44 0 25.68-32 41.12-32C70.88 24 76 34.64 76 40s-5.12 16-15.44 16c-15.44 0-25.68-32-41.12-32z"

   >

     <animate

       attributeName="stroke-dashoffset"

       dur="1s"

       keyTimes="0;1"

       repeatCount="indefinite"

       values="0;256.58892822265625"

     ></animate>

   </path>

</svg>

The most important property that is needed is the d prop that is passed on to the <path> component which defines the path to be drawn. It is a list of path commands in the form of letters and numbers.
Apart from this, we will be using the strokeDasharray property for our example which is used to create dashes within a stroke. So, instead of a single stroke completing the animation, there will be multiple strokes with dashes / blank spaces between them. The number and length of strokes are defined by the length and the values of the array that we pass to this property.

Implementation

We need to import AnimatedSVGPath from the module that we installed.

import { AnimatedSVGPath } from 'react-native-svg-animations'

We will be implementing the following render method:

import { AnimatedSVGPath } from 'react-native-svg-animations'



render() {

  const d = "M24.3 30C11.4 30 5 43.3 5 50s6.4 20 19.3 20c19.3 0 32.1-40 51.4-40 C88.6 30 95 43.3 95 50s-6.4 20-19.3 20C56.4 70 43.6 30 24.3 30z"

  return (

    <View>

      <AnimatedSVGPath

        strokeColor={"red"}

        duration={1000}

        strokeWidth={10}

        height={400}

        width={400}

        scale={0.75}

        delay={0}

        d={d}

        loop={true}

        strokeDashArray={[42.76482137044271, 42.76482137044271]}

      />

      <TouchableOpacity onPress = {this.handleClick}>

        <Text> CLICK ME </Text>

      </TouchableOpacity>

    </View>

  );

}

Now if you look at the properties of this component, you will notice that it uses the d and strokeDashArray properties that we obtained earlier from the SVG.

You can read and understand more about this module here

Apart from this, we added an onPress event on <TouchableOpacity> to check whether it hinders the animation of SVG in any way.

Modifications to the Installed Module

While using react-native-svg-animations we faced the following issues : 

  • ISSUE WITH STROKEDASHARRAY PROPERTY

strokeDashArray was not a part of its props originally, so we needed to modify the original module in order to enable users to pass values on their own. Consider the return method of the AnimatedSVGPath class:

const { strokeDashArray: dashArray } = props;

return (

  <Svg

    height={(height * scale) + 5}

    width={(width * scale) + 5}

  >

    <Path

      strokeDasharray={dashArray || [this.length, this.length]}

      strokeDashoffset={this.strokeDashoffset}

      strokeWidth={strokeWidth}

      strokeLinecap={strokeLinecap}

      stroke={strokeColor}

      scale={scale}

      fill={fill}

      d={d}

    />

  </Svg>

);


If you look at the strokeDasharray property of the <Path> component, its value was originally [ this.length, this.length ] and the user was not able to define the number of strokes he/she needs in the animation. We modified it by adding a condition { dashArray || [ this.length, this.length ] } to enable users to pass its value through props according to their requirements.

Before and after using strokeDasharray property: 

Animate SVG in React Native

React Native: Let's Animate the SVGs
 

  • DELAY ISSUE BETWEEN EACH ITERATION

After solving the first issue and successful implementation of the animations, we experienced a little delay between each iteration of the animation. This can also be seen pretty clearly in the above gif. After some research, we found out that we need to add easing field to the Animated.timing function inside the animate method as shown below:

animate = () => {

    const {

      delay,

      duration,

      loop,

      easing = 'linear',

    } = this.props;

    this.strokeDashoffset.setValue(this.length);



    Animated.sequence([

      Animated.delay(delay),

      Animated.timing(this.strokeDashoffset, {

        toValue: 0,

        duration: duration,

        easing: Easing[easing],

        useNativeDriver: true

      })

    ]).start(() => {

      if (loop) {

          this.animate();

      }

    });

  }

Easing needs to be imported from ‘react-native’ first and then by providing easing: Easing.linear, the delay between each iteration is eliminated.

You can understand it in detail here.

Before and after using Easing property: 

Animate SVG

React Native: Let's Animate the SVGs

It is clearly visible from the above gifs that the issue has been fixed.

So, these were the two issues that we faced while working with this module. We fixed them and also raised a PR for the same. There won’t be an issue if you intend to use the same library in future.

Wrapping this up!

With the issues fixed and everything explained, now anyone can implement SVG animations in React Native without any hassle. You can check out the example code here in case you wish to have a look at the whole code. This will give you more insight into what we did here. 

It was really fun to work on this, learnt a lot and tried out some cool things with SVG animations. I hope this blog sails you through if you ever find yourself in the middle of this ocean!

Keep learning!