Building a Hand Drawing App with React Native Skia and Gesture Handler

Tanner West
React Native Rocket
5 min readAug 26, 2022
Photo by Erik Mclean on Unsplash

Now that the Skia 2D graphics library is available in React Native, we have so many opportunities to create graphics intensive applications that weren’t possible before. A personal goal of mine for a while was to explore React Native Gesture Handler, then Skia crossed my radar and I wanted to get some experience with it as well. The idea struck me to build a proof-of-concept hand drawing app that captures user input via Gesture Handler and paints it to a canvas component using RN Skia. This article covers the basics of getting that app up and running.

Getting Started with React Native Gesture Handler

The first step in this project is understanding RN Gesture Handler’s API. You can read about it more in depth in Software Mansion’s documentation, but it’s pretty straightforward. Here’s what a basic component looks like:

We wrap the component we want to capture gestures from in a <GestureDetector> and pass a gesture prop for the type of gesture we want to react to. This prop takes the form of a Gesture object that we configure with the code we want to run when certain events occur (when the gesture starts, updates, and ends). If you want to react to multiple types of gestures, just wrap you component in an additional<GestureDetector> for each type of gesture.

In the above recording, notice how onTouchesMove gets called before onStart and onUpdate. It gets called any time the input moves, regardless of whether a gesture has been recognized. Gesture Handler only fires onStart and onUpdate once the movement has been recognized as a gesture. This distinction will be relevant to our drawing app!

Understanding the Basics of Canvas in RN Skia

If you’ve worked with 2D graphics like SVGs in the past, these concepts should be familiar. Either way, they’re easy to pick up. A canvas implements a XY coordinate system that we use to draw our graphics. By default, the coordinates 0, 0 are at the upper left corner of the canvas. The X axis moves from left to right and the Y axis is up and down.

React Native Skia gives us many convenient way to draw on our canvas. For example, if you want to use the Path component to draw a line, you can use the classic SVG path notation and pass the value to your component as a string. Alternatively, you can use Skia’s Path object to build a path point by point.

Understanding how the SVG notation in the previous example works is critical to understand the app we’ll build. You should definitely read MDN’s article on the topic, but be sure you understand at least these two things:

  • Instructions with the syntax M {xCoordinate} {yCoordinate} tell the canvas to “move to” the provided coordinates; this instruction on its own doesn’t draw anything, but it provides the starting coordinates for the next operation.
  • Instructions with the syntax L {xCoordinate} {yCoordinate} tell the canvas to draw a line from its current position to the coordinates provided.

We can also very easily draw shapes on our canvas. Here’s how we draw circles, for example:

Finally, using the ImageSvg component from React Native Skia, we can draw any arbitrary SVG to our canvas, including those we import from external sources.

Drawing with Gesture Handler and Skia

Now that we understand the basics of Gesture Handler and Skia, we’re ready to bring the two concepts together and start drawing!

We’ll create a freehand drawing feature that captures user pan gestures data and uses it to draw paths on the Skia Canvas. This is actually much easier that it might sound at first, if you keep in mind these concepts:

  • Gesture Handler’s Gesture.Pan.onUpdate() will run our callback function when the user moves their finger, providing us with new coordinates of the user’s finger each time
  • Skia Paths can be defined using SVG notation, which can include a series of L {xCoord} {yCoord} statements to draw lines

With those principles in mind, check out this component:

The most important parts of this component to understand are lines 25 and 32.

  • On 25, when Gesture Handler detects the beginning of a gesture, we push a new path object into our paths array. This object has an array called segments that will contain a list of SVG notation instructions to draw that path. Initially, we create a “move” command to begin our path at the starting coordinates of our gesture.
  • Each time the gesture updates, we push a new path segment into our array (line 32). These segments contain a command in SVG notation to draw a line to the updated coordinates.

Then, we simply map over the values in paths inside our canvas to draw them. The path prop for each Path component is created by joining each segment string to form valid SVG notation.

There you have it! With fewer than 60 lines of code, we created a basic hand drawing component with React Native Gesture Handler and Skia.The power and potential of these two libraries combined really impress me. I hope you feel the same way!

Check out my RN Skia Draw repo on GitHub for a ready to install Expo app that demonstrates these principles and also shows how to “stamp” the SVG star images shown above to the Canvas using a Tap gesture!

As always, follow me here on Medium and on Twitter @useRNRocket for more React Native content! Tweet me with any comments, questions, or corrections.

--

--