How To Create a Canvas App With React Native

Ben Hur
TribalScale
Published in
6 min readMar 3, 2023

Written by: Ben Hur Martins Carvalho, Agile Software Engineer, TribalScale

📫 Subscribe to receive our content here.

💬 Have any questions about our development capabilities? Click here to chat with one of our experts!

Photo by Steve Johnson on Unsplash

Recently I created my first react-native library, a field that allows the app user to sign using their finger and returns an array of strings with the path of the SVG created. It displays the signature and allows you to save it in a database. You can check it out on npm: react-native-signing-field, it’s easy to install and use.

With the same concept I thought it would be cool to improve and create a simple canvas app, with options like choosing color and size of the stroke. Here is the result:

First let's walk through the concept of how the SVG is made, then we can go component by component.

Starting The Project

For this app we’ll use react-native-svg and react-native-reanimated, both require additional steps after the installation with npm or yarn. I recommend you take a look at the docs linked above and install it in a recently created app.

SVG Paths

SVGs can be different forms, but what we’re looking at here are just the lines, or strokes, with no filling between them, and we can manage stroke width and stroke color.

Each path (or line) will be an array of strings, so when the user first touches the screen we’ll capture that event, take the screen coordinates (x and y), and start to build that path, and with each update of that coordinate (when the user actually swipes the finger on the screen) we’ll add more data to that path.

The path starts with the letter M, and each next segment will start with the letter L. So if the user start the gesture in the section x: 100, and y: 100, our first segment will be:

["M 100 100"]

Now the user slides their finger down to the section x: 105 and y: 100, our path will update to:

["M 100 100", "L 105 100"]

Code

It’s a quite simple app, we basically have two components. First we’ll take a look at the floating settings bar, then the canvas.

Settings Bar

For the settings bar let's start with the default styles:

Basically each small floating container will have an absolute position, with a transparent background and a fixed position from the bottom, the other style is related to each button. The position related to the left and right for each one of the containers we can declare inside each one.

The next component is the small circle where we see the different sizes of strokes:

And declare the constants we’ll use for the main settings component:

And the main settings component:

Let's check section-by-section of this component:

  • Props (2–5): colors and size are managed by the parent component, so the value itself and the setter will be passed as props.
  • States (8–9): we keep the open/closed state inside this component, in case we want to refactor it into two, we should pass this state through props as well, considering we can't keep both open.
  • Constants (11–12): a state derived from the open/closed state, that will give us the current width of each one of the selector containers.
  • Animated styles (14–25): for each container we are passing these animated styles as well, that will give life to the open/close action, you can see that we are using withTiming to ease transition of the width update.
  • Selector handlers (27–34): for each one we handle the selection of value, because we’re not only calling the setter passed by props, but updating our open/closed state as well.
  • Open/close handlers (36–43): this one has a special handler, not updating directly because we want to also close the other container.
  • Component (45–94): basically this is two components held together (yes, I know that we are missing a key on them 😅). Each one has an Animated.View with the animations we declared before, and inside each one we’ll show, in case it is closed, only the preview of what value we have selected (color or size), or if it's open we will show the possible selectable values.

Result:

Canvas

Now, for the last part we’ll take a look at implementing the canvas logic, to better understand it, let's first see the path type:

export type PathType = {
path: string[];
color: string;
stroke: number;
};

As mentioned before, we have an array of strings that gives us each position the stroke has traveled, then we have the color selected at the moment we started the stroke and also the stroke width. This is the type of each path, and we’ll keep a state of multiples paths.

Some more detail on each part of this code:

  • setNewPath: the function that is first called when the movement starts, we update the path state creating a new element in the array of paths.
  • updatePath: first I get the last path that we have, pushing a new path on the string array. Then I update the state with the new updated path and remove the previous one, the stroke and color are not changed here.
  • Component (View): our component here starts with a simple view that uses a non usual props, the first two props (onStartShouldSetResponder, onMoveShouldSetResponder) will be responsible to inform that our View will track movements when first starting and when updating. Then we have two other props (onResponderStart, onResponderMove) that gets the event argument that contains the x and y position.
  • Component (SVG): Here we start with an empty SVG that gets re-rendered with one or more paths based on our state. Each array of paths are joined in one big string here.
  • Component (Settings): Now in the end we have our previously developed settings to manage our color and stroke size.

Conclusion

Building this app was easier than I thought it would be, and mixing simple solutions produced this great result. If you want to check out the whole code, take a look on my GitHub repo, and if you like it or have some questions/comments, feel free to leave a comment. Thanks!

Ben is an Agile Software Engineer here at TribalScale and is based in Brazil. He is a front-end developer and his stack today is React Native and ReactJS, before TribalScale he worked as a full stack developer for 8 years. Outside of work he has multiple hobbies, a recent one is leather craft, and loves spending time with his 1 year old son.

TribalScale is a global innovation firm that helps enterprises adapt and thrive in the digital era. We transform teams and processes, build best-in-class digital products, and create disruptive startups. Learn more about us on our website. Connect with us on Twitter, LinkedIn & Facebook!

--

--

Ben Hur
TribalScale

I am a React Native Developer with passion to build things.