react-native-image-draw
TypeScript icon, indicating that this package has built-in type declarations

0.2.2 • Public • Published

React Native Image Draw

Cross-platform React Native drawing component based on SVG

Installation

$ npm install react-native-image-draw
# or
$ yarn add react-native-image-draw

Also, you need to install react-native-gesture-handler and react-native-svg, and follow their installation instructions.

Usage

Simple example

Here's the most simple example:

import React from 'react';
import { Canvas } from 'react-native-image-draw';

export default () => <Canvas />;

https://user-images.githubusercontent.com/22248828/152838002-3bf01ff0-8c8d-43ec-abdf-4f856d200bc5.mp4

Complex example

Here's a more complex example:

Complex example - Code snippet
import React, { useRef } from 'react';
import { Button } from 'react-native';
import { Canvas, CanvasRef } from '@benjeau/react-native-draw';

export default () => {
  const canvasRef = useRef<CanvasRef>(null);

  const handleUndo = () => {
    canvasRef.current?.undo();
  };

  const handleClear = () => {
    canvasRef.current?.clear();
  };

  return (
    <>
      <Canvas
        ref={canvasRef}
        height={600}
        color="red"
        thickness={20}
        opacity={0.6}
        style={{ backgroundColor: 'black' }}
      />
      <Button title="Undo" onPress={handleUndo} />
      <Button title="Clear" onPress={handleClear} />
    </>
  );
};

https://user-images.githubusercontent.com/22248828/152837975-a51bdcf5-9a62-4aa2-8e5e-26c1d52fcf79.mp4

Example with @BenJeau/react-native-draw-extras

This uses the @benjeau/react-native-draw-extras npm package for the color picker and the bottom buttons/brush preview.

As this package does not depend on @BenJeau/react-native-draw-extras, it is completely optional and you can build your own supporting UI, just like the previous example

Extras example - Code snippet ```tsx import React, { useRef, useState } from 'react'; import { Animated, StyleSheet, View } from 'react-native'; import { BrushProperties, Canvas, CanvasControls, CanvasRef, DEFAULT_COLORS, DrawingTool, } from '@benjeau/react-native-draw';

export default () => { const canvasRef = useRef(null);

const [color, setColor] = useState(DEFAULT_COLORS[0][0][0]);
const [thickness, setThickness] = useState(5);
const [opacity, setOpacity] = useState(1);
const [tool, setTool] = useState(DrawingTool.Brush);
const [visibleBrushProperties, setVisibleBrushProperties] = useState(false);

const handleUndo = () => {
  canvasRef.current?.undo();
};

const handleClear = () => {
  canvasRef.current?.clear();
};

const handleToggleEraser = () => {
  setTool((prev) =>
    prev === DrawingTool.Brush ? DrawingTool.Eraser : DrawingTool.Brush
  );
};

const [overlayOpacity] = useState(new Animated.Value(0));
const handleToggleBrushProperties = () => {
  if (!visibleBrushProperties) {
    setVisibleBrushProperties(true);

    Animated.timing(overlayOpacity, {
      toValue: 1,
      duration: 200,
      useNativeDriver: true,
    }).start();
  } else {
    Animated.timing(overlayOpacity, {
      toValue: 0,
      duration: 200,
      useNativeDriver: true,
    }).start(() => {
      setVisibleBrushProperties(false);
    });
  }
};

return (
  <>
    <Canvas
      ref={canvasRef}
      height={600}
      color={color}
      thickness={thickness}
      opacity={opacity}
      tool={tool}
      style={{
        borderBottomWidth: StyleSheet.hairlineWidth,
        borderColor: '#ccc',
      }}
    />
    <View>
      <CanvasControls
        onUndo={handleUndo}
        onClear={handleClear}
        onToggleEraser={handleToggleEraser}
        onToggleBrushProperties={handleToggleBrushProperties}
        tool={tool}
        color={color}
        opacity={opacity}
        thickness={thickness}
      />
      {visibleBrushProperties && (
        <BrushProperties
          color={color}
          thickness={thickness}
          opacity={opacity}
          onColorChange={setColor}
          onThicknessChange={setThickness}
          onOpacityChange={setOpacity}
          style={{
            position: 'absolute',
            bottom: 80,
            left: 0,
            right: 0,
            padding: 10,
            backgroundColor: '#f2f2f2',
            borderTopEndRadius: 10,
            borderTopStartRadius: 10,
            borderWidth: StyleSheet.hairlineWidth,
            borderBottomWidth: 0,
            borderTopColor: '#ccc',
            opacity: overlayOpacity,
          }}
        />
      )}
    </View>
  </>
);

};

</details>

https://user-images.githubusercontent.com/22248828/152837922-757d3a13-1d35-409a-936a-b38ea9248262.mp4

## Props

### Canvas

| name                    | description                                                                            | type                                           | default                       |
| ----------------------- | -------------------------------------------------------------------------------------- | ---------------------------------------------- | ----------------------------- |
| `color`                 | Color of the brush strokes                                                             | `string`                                       | - (required)                  |
| `thickness`             | Thickness of the brush strokes                                                         | `number`                                       | - (required)                  |
| `opacity`               | Opacity of the brush strokes                                                           | `number`                                       | - (required)                  |
| `initialPaths`          | Paths to be already drawn                                                              | `PathType[]`                                   | `[]`                          |
| `height`                | Height of the canvas                                                                   | `number`                                       | height of the window - 80     |
| `width`                 | Width of the canvas                                                                    | `number`                                       | width of the window           |
| `style`                 | Override the style of the container of the canvas                                      | `StyleProp`                                    | -                             |
| `onPathsChange`         | Callback function when paths change                                                    | (paths: [`PathType`](./src/types.ts)[]) => any | -                             |
| `simplifyOptions`       | SVG simplification options                                                             | [`SimplifyOptions`](./src/Draw.tsx)            | see [below](#SimplifyOptions) |
| `eraserSize`            | Width of eraser (to compensate for path simplification)                                | `number`                                       | `5`                           |
| `tool`                  | Initial tool of the canvas                                                             | `brush` or `eraser`                            | `brush`                       |
| `combineWithLatestPath` | Combine current path with the last path if it's the same color, thickness, and opacity | `boolean`                                      | `false`                       |

### SimplifyOptions

| name                  | description                                                                   | type      | default |
| --------------------- | ----------------------------------------------------------------------------- | --------- | ------- |
| `simplifyPaths`       | Enable SVG path simplification on paths, except the one currently being drawn | `boolean` | `true`  |
| `simplifyCurrentPath` | Enable SVG path simplification on the stroke being drawn                      | `boolean` | `false` |
| `amount`              | Amount of simplification to apply                                             | `number`  | `10`    |
| `roundPoints`         | Ignore fractional part in the points. Improves performance                    | `boolean` | `true`  |

## Ref functions

| name       | description                                | type                       |
| ---------- | ------------------------------------------ | -------------------------- |
| `undo`     | Undo last brush stroke                     | `() => void`               |
| `clear`    | Removes all brush strokes                  | `() => void`               |
| `getPaths` | Get brush strokes data                     | `() => PathType[]`         |
| `addPath`  | Append a path to the current drawing paths | `(path: PathType) => void` |
| `getSvg`   | Get SVG path string of the drawing         | `() => string`             |

## Troubleshooting

If you cannot draw on the canvas, make sure you have followed the extra steps of [react-native-gesture-handler](https://github.com/software-mansion/react-native-gesture-handler)

## Helper functions

* If you need to create an SVG path, `createSVGPath()` is available to create the string representation of an SVG path.

## Contributing
- Fork it.
- Commit your changes and give your commit message some love.
- Push to your fork on github.
- Open a Pull Request.


## License

MIT

Package Sidebar

Install

npm i react-native-image-draw

Weekly Downloads

3

Version

0.2.2

License

MIT

Unpacked Size

125 kB

Total Files

44

Last publish

Collaborators

  • dhruvasagar