Drawing in React Native with React Native SVG: Tutorial for Beginners

Drawing in a React Native application can be useful for cases where you want to take signatures, draw, or create collaborative experiences in your React Native Expo Apps. Thankfully it can easily be done with the use of the react-native-svg library. You may be wondering what is SVG?

SVG stands for Scalable Vector Graphics. It is a widely-used XML-based file format for describing two-dimensional vector graphics. Unlike raster graphics (e.g., JPEG or PNG images), which are composed of pixels and can lose quality when scaled, SVG graphics are based on mathematical equations that define shapes and paths, allowing them to be scaled to any size without losing quality.

SVG graphics are highly versatile and commonly used for web graphics, data visualization, logos, icons, and other scalable graphics.

React Native SVG is a library that enables you to use SVG files and render vector graphics in your React Native applications. It allows you to incorporate SVG graphics into your mobile app UI, just like any other React Native component. The library bridges the gap between React Native's native components and SVG elements, making it possible to display and manipulate scalable vector graphics within the app.

React Native SVG provides a set of components that correspond to SVG elements, such as <Svg>, <Circle>, <Rect>, <Path>, etc. In this tutorial, we will be showing how to use the Path component but in reality, once you learn how to do this you should be easily able to modify the code to your liking. The example we will create in this tutorial will look as follows.

Before we get started, be sure to subscribe and support the channel if you have not!

Subscribe:

Youtube

Support:

https://www.buymeacoffee.com/mmshilleh

Step 1-) Create an Expo Application

To do this, you need to have an expo as a prerequisite and run “expo init”.

Step 2-) NPM Install react-native-svg

This is the only library you will need to run the code. npm i react-native-svg

STEP 3-) Code Walkthrough

The code for the component is as follows

 

import React, { useState } from 'react';
import { View, StyleSheet, Dimensions, TouchableOpacity, Text } from 'react-native';
import { Svg, Path } from 'react-native-svg';

const { height, width } = Dimensions.get('window');

export default () => {
  const [paths, setPaths] = useState([]);
  const [currentPath, setCurrentPath] = useState([]);
  const [isClearButtonClicked, setClearButtonClicked] = useState(false);

  const onTouchEnd = () => {
    paths.push(currentPath);
    setCurrentPath([]);
    setClearButtonClicked(false);
  };

  const onTouchMove = (event) => {
    const newPath = [...currentPath];
    const locationX = event.nativeEvent.locationX;
    const locationY = event.nativeEvent.locationY;
    const newPoint = `${newPath.length === 0 ? 'M' : ''}${locationX.toFixed(0)},${locationY.toFixed(0)} `;
    newPath.push(newPoint);
    setCurrentPath(newPath);
  };

  const handleClearButtonClick = () => {
    setPaths([]);
    setCurrentPath([]);
    setClearButtonClicked(true);
  };

  return (
    <View style={styles.container}>
      <View style={styles.svgContainer} onTouchMove={onTouchMove} onTouchEnd={onTouchEnd}>
        <Svg height={height * 0.7} width={width}>
          <Path
            d={paths.join('')}
            stroke={isClearButtonClicked ? 'transparent' : 'red'}
            fill={'transparent'}
            strokeWidth={3}
            strokeLinejoin={'round'}
            strokeLinecap={'round'}
          />
          {paths.length > 0 &&
            paths.map((item, index) => (
              <Path
                key={`path-${index}`}
                d={currentPath.join('')}
                stroke={isClearButtonClicked ? 'transparent' : 'red'}
                fill={'transparent'}
                strokeWidth={2}
                strokeLinejoin={'round'}
                strokeLinecap={'round'}
              />
            ))}
        </Svg>
      </View>
      <TouchableOpacity style={styles.clearButton} onPress={handleClearButtonClick}>
        <Text style={styles.clearButtonText}>Clear</Text>
      </TouchableOpacity>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  svgContainer: {
    height: height * 0.7,
    width,
    borderColor: 'black',
    backgroundColor: 'white',
    borderWidth: 1,
  },
  clearButton: {
    marginTop: 10,
    backgroundColor: 'black',
    paddingVertical: 10,
    paddingHorizontal: 20,
    borderRadius: 5,
  },
  clearButtonText: {
    color: 'white',
    fontSize: 16,
    fontWeight: 'bold',
  },
});

Code Breakdown:

Import Statements:

  • The code imports required modules from react, react-native, and react-native-svg.
  • These modules are needed to create the drawing canvas and handle touch events.
  • Dimensions:
    • The Dimensions object is used to get the height and width of the device's window. You do not necessarily need this but it helps us size our drawing canvas easily.
  • State Variables:
    • The code defines three state variables using the useState hook: paths, currentPath, and isClearButtonClicked.
    • paths: An array that stores all the completed drawing paths as strings. You will need to record these so that you can draw more than one line/path.
    • currentPath: An array that stores the current drawing path as it's being drawn, which eventually becomes added to the paths variable.
    • isClearButtonClicked: A boolean flag to track whether the "Clear" button has been clicked.
  • onTouchEnd() Function:
    • This function is called when the touch event ends on the drawing canvas.
    • It pushes the currentPath (the completed drawing path) into the paths array.
    • It resets the currentPath to an empty array and sets isClearButtonClicked to false.
  • onTouchMove(event) Function:
    • This function is called when the user moves their finger on the drawing canvas (during touch events).
    • It calculates the locationX and locationY coordinates of the touch event.
    • It creates a new point in the currentPath array as a string in the format "Mx,y ", where x and y are the coordinates. This is how the SVG interprets coordinates and displays them connected in a smooth manner.
    • It updates the currentPath with the new point.
  • handleClearButtonClick() Function:
    • This function is called when the "Clear" button is clicked.
    • It clears the paths array and the currentPath array, effectively resetting the drawing canvas.
    • It sets isClearButtonClicked to true.
  • Return Statement:
    • The main component is returned, and it renders a View containing two elements: the drawing canvas and a "Clear" button.
  • Drawing Canvas (<Svg> and <Path>):
    • The drawing canvas is created using the <Svg> component from react-native-svg.
    • The <Svg> component sets the height to 70% of the device window height and the width to the device window width.
    • A <Path> component is used to draw the current path (currentPath) and all completed paths (paths) on the canvas. Be aware there are other types of components you can use depending on your applicaiton.
    • The color and styling of the paths are determined by the stroke and strokeWidth props, which you can adjust.
  • "Clear" Button (<TouchableOpacity>):
    • The "Clear" button is created using the <TouchableOpacity> component from react-native.
    • When clicked, it calls the handleClearButtonClick() function to reset the drawing canvas.
  • Styles:
    • The code includes some styling using the StyleSheet.create() function to define the appearance of the drawing canvas and the "Clear" button. You will probably have to style as you need be.

Overall, this code creates a simple drawing app in React Native. Users can draw on the canvas using their finger, and the drawing paths are stored and displayed using SVG <Path> components. The "Clear" button allows users to reset the canvas and start drawing again.

Conclusion

Hope you learned how to create your canvas in React Native. If you have any questions let me know. Do not forget to subscribe and support the channel above, thanks!

Create a free account to access full content.

All access to code and resources on ShillehTek.

Signup Now

Already a member? Sign In

Explore More on Our Blog

Controlling an LED with a Snap Using the KY-037 Sound Sensor and Raspberry Pi

Controlling an LED with a Snap Using the KY-037 Sound Sensor and Raspberry Pi

Discover how to set up, code, and activate the LED based on detected sound with the Raspberry Pi...

Getting Started with the KY-037 Sound Sensor and Raspberry Pi: Detecting Sound Using Python

Getting Started with the KY-037 Sound Sensor and Raspberry Pi: Detecting Sound Using Python

In this tutorial, I’ll guide you through setting up the KY-037 sound sensor with a Raspberry Pi using...

How to Post to Reddit Using Python

How to Post to Reddit Using Python

Post to reddit automatically using a Python script.

How to Create a Time-Lapse Video with a Raspberry Pi Camera

How to Create a Time-Lapse Video with a Raspberry Pi Camera

Learn how to make a timelapse with your Raspberry Pi in Python.

How to Integrate the MPU6050 with the STM32 Blue Pill

How to Integrate the MPU6050 with the STM32 Blue Pill

Learn how to measure acceleration with the STM32 and the MPU6050 in the Arduino IDE.

Getting Started with STM32 Blue Pill in Arduino IDE Using a USB to TTL Converter — Write Your First Program

Getting Started with STM32 Blue Pill in Arduino IDE Using a USB to TTL Converter — Write Your First Program

This comprehensive tutorial will guide you through the process of setting up and programming the STM32 Blue Pill...

Automate Task Scheduling in AWS with Lambda, Step Functions, and CloudWatch

Automate Task Scheduling in AWS with Lambda, Step Functions, and CloudWatch

In this tutorial, I'll show you how to automatically schedule tasks in AWS at regular intervals using AWS...

Implementing Google reCAPTCHA in a Simple React and Node.js App

Implementing Google reCAPTCHA in a Simple React and Node.js App

Learn how to protect your React applications from bots and spam with Google reCAPTCHA integration! This step-by-step tutorial...

AWS Lambda Tutorial: Using Selenium with Chromedriver in Python

AWS Lambda Tutorial: Using Selenium with Chromedriver in Python

In this tutorial, I will guide you through the process of running Selenium with ChromeDriver inside an AWS...

How to Connect MLX90614 Infrared Thermometer to Raspberry Pi Pico W: MicroPython Tutorial!

How to Connect MLX90614 Infrared Thermometer to Raspberry Pi Pico W: MicroPython Tutorial!

Learn how to use the MLX90614 with the Raspberry Pi Pico W and get infrared values in MicroPython.

Back to blog

Leave a comment

Please note, comments need to be approved before they are published.