Drawing (with Skia) in React Native
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
Canvascomponent inside a
Viewso we can show the text later:
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
Paththese can be done in two ways, one programatically like on Android and iOS canvas for example. The other as a
Pathlike 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
Canvascomponent 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
Pathwe just added, inside the
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
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…
Shopify have added animation, and you’re best to read about it on their website.
- I have chosen to use their
useTiminghook. 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
Pathup 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
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.