Drawing (with Skia) in React Native

Tony Owen
5 min readDec 24, 2021

I’ve recently moved onto a project at work using React Native. As a native Android developer I’ve been used to getting something like the above design from the designers and thinking, Right … lets crack out Canvas.

There seem to be a few canvas libraries, which I’ll be honest I haven’t tried. But then I saw a video whilst mindlessly scrolling through YouTube. Brought to us by William Candillon, showing Shopify’s new library using Skia inside React Native here

As many will know, I have a love for Flutter. Which uses Skia heavily, so I was intrigued. Lets see if this can bring React Native closer to Flutter (sorry, it won’t beat it for me.. many reasons).

Something I’ve been asked to do a fair few times in my career is make a progress indicator like the gif at the top, so I thought that would be a good place to start.

I won’t cover installation, you can follow the excellent instructions from Shopify here.

Assuming we’re all setup lets begin:

  • To start with I create a custom React component, so that I could pass a percentage in and make it reusable:
  • Next I’ll wrap the Canvas component inside a View so we can show the text later:

This Canvas is what we will now use to draw the arcs required

  • First lets add some constants, nobody wants magic numbers when we’re drawing

With these setup we can start.

  • We need to create a Path these can be done in two ways, one programatically like on Android and iOS canvas for example. The other as a Path like an SVG. I will be doing this programatically…

This will firstly move the pointer to 0 on the X-axis, and half the views width (also the height) on the Y-axis. Then we draw an arc from one side to the other.

  • Now we have this we can draw the grey arc, that always remains static. Inside the Canvas component add the following:

Here we use the Path component, and pass our path in, setting the color as transparent as we will nest out Paint component, and now we have this…

The next step is to add another arc, with a sweep gradient, and only fill a percentage of the arc…

  • Firstly, without animation, lets add the following directly below our Path we just added, inside the Canvas component…

Very similar to the first arc, we use the same path we defined, but this time we tell it to end the path. This will enable us to set the arc to 50%, 75% etc.

Again we make the Path transparent as we’re nesting the Paint component. This time we’re also going to nest a SweepGradient component inside the Paint

The SweepGradient takes a few params, c is the center of the gradient, colors the colors we want to use, start the angle to start from, and end the angle to end at. In this case we also want to edit the end of the gradient so that we always see the full gradient even if its 10% full of 100% full. So some manipulation of the end angle is required.

We now have something like this…

Animation

Shopify have added animation, and you’re best to read about it on their website.

  • I have chosen to use their useTiming hook. So I’ve added this block to my component:

This will create an animated value from 0, to the percentage needed (eg 0.5), it will last 2 seconds, and the animation will ease out.

  • Now we just need to hook our Path up to the progress value…

And thats it, we now have a sweeping progress indicator, animated, and that looks identical on both Android and iOS…

For the text in this case, I just added a View underneath the Canvas

A quick animated component, good fun to play around with, and excellent documentation. This library is in alpha at the time of writing this, so we may not want to SHIP IT!!! just yet. But I’m hopeful that this will become stable very soon, and make React Native apps a bit prettier.

--

--