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 aView
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 aPath
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 theCanvas
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.