Code Monkey home page Code Monkey logo

react-native-sketch-canvas's Introduction

react-native-sketch-canvas

A React Native component for drawing by touching on both iOS and Android.

    
    

Features

  • Support iOS and Android
  • Stroke thickness and color are changable while drawing.
  • Can undo strokes one by one.
  • Can serialize path data to JSON. So it can sync other devices or someone else and continue to edit.
  • Save drawing to a non-transparent image (png or jpg) or a transparent image (png only)
  • Use vector concept. So sketches won't be cropped in different sizes of canvas.
  • Support translucent colors and eraser.
  • Support drawing on an image (Thanks to diego-caceres-galvan)
  • High performance (See below. Thanks to jeanregisser)
  • Can draw multiple canvases in the same screen.
  • Can draw multiple multiline text on canvas.

Installation


Install from npm (only support RN >= 0.40)

npm install @terrylinla/react-native-sketch-canvas --save

Link native code

react-native link @terrylinla/react-native-sketch-canvas

Usage


● Using without UI component (for customizing UI)

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  View,
} from 'react-native';

import { SketchCanvas } from '@terrylinla/react-native-sketch-canvas';

export default class example extends Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={{ flex: 1, flexDirection: 'row' }}>
          <SketchCanvas
            style={{ flex: 1 }}
            strokeColor={'red'}
            strokeWidth={7}
          />
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF',
  },
});

AppRegistry.registerComponent('example', () => example);

Properties


Prop Type Description
style object Styles to be applied on canvas component
strokeColor string Set the color of stroke, which can be #RRGGBB or #RRGGBBAA. If strokeColor is set to #00000000, it will automatically become an eraser.
NOTE: Once an eraser path is sent to Android, Android View will disable hardware acceleration automatically. It might reduce the canvas performance afterward.
strokeWidth number The thickness of stroke
onStrokeStart function An optional function which accpets 2 arguments x and y. Called when user's finger touches the canvas (starts to draw)
onStrokeChanged function An optional function which accpets 2 arguments x and y. Called when user's finger moves
onStrokeEnd function An optional function called when user's finger leaves the canvas (end drawing)
onSketchSaved function An optional function which accpets 2 arguments success and path. If success is true, image is saved successfully and the saved image path might be in second argument. In Android, image path will always be returned. In iOS, image is saved to camera roll or file system, path will be set to null or image location respectively.
onPathsChange function An optional function which accpets 1 argument pathsCount, which indicates the number of paths. Useful for UI controls. (Thanks to toblerpwn)
user string An identifier to identify who draws the path. Useful when undo between two users
touchEnabled bool If false, disable touching. Default is true.
localSourceImage object Require an object (see below) which consists of filename, directory(optional) and mode(optional). If set, the image will be loaded and display as a background in canvas. (Thanks to diego-caceres-galvan))(Here for details)
permissionDialogTitle string Android Only: Provide a Dialog Title for the Image Saving PermissionDialog. Defaults to empty string if not set
permissionDialogMessage string Android Only: Provide a Dialog Message for the Image Saving PermissionDialog. Defaults to empty string if not set

Methods


Method Description
clear() Clear all the paths
undo() Delete the latest path. Can undo multiple times.
addPath(path) Add a path (see below) to canvas.
deletePath(id) Delete a path with its id
save(imageType, transparent, folder, filename, includeImage, cropToImageSize) Save image to camera roll or filesystem. If localSourceImage is set and a background image is loaded successfully, set includeImage to true to include background image and set cropToImageSize to true to crop output image to background image.
Android: Save image in imageType format with transparent background (if transparent sets to True) to /sdcard/Pictures/folder/filename (which is Environment.DIRECTORY_PICTURES).
iOS: Save image in imageType format with transparent background (if transparent sets to True) to camera roll or file system. If folder and filename are set, image will save to temporary directory/folder/filename (which is NSTemporaryDirectory())
getPaths() Get the paths that drawn on the canvas
getBase64(imageType, transparent, includeImage, cropToImageSize, callback) Get the base64 of image and receive data in callback function, which called with 2 arguments. First one is error (null if no error) and second one is base64 result.

Constants


Constant Description
MAIN_BUNDLE Android: empty string, ''
iOS: equivalent to [[NSBundle mainBundle] bundlePath]
DOCUMENT Android: empty string, ''
iOS: equivalent to NSDocumentDirectory
LIBRARY Android: empty string, ''
iOS: equivalent to NSLibraryDirectory
CACHES Android: empty string, ''
iOS: equivalent to NSCachesDirectory

● Using with build-in UI components

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Alert,
} from 'react-native';

import RNSketchCanvas from '@terrylinla/react-native-sketch-canvas';

export default class example extends Component {
  render() {
    return (
      <View style={styles.container}>
        <View style={{ flex: 1, flexDirection: 'row' }}>
          <RNSketchCanvas
            containerStyle={{ backgroundColor: 'transparent', flex: 1 }}
            canvasStyle={{ backgroundColor: 'transparent', flex: 1 }}
            defaultStrokeIndex={0}
            defaultStrokeWidth={5}
            closeComponent={<View style={styles.functionButton}><Text style={{color: 'white'}}>Close</Text></View>}
            undoComponent={<View style={styles.functionButton}><Text style={{color: 'white'}}>Undo</Text></View>}
            clearComponent={<View style={styles.functionButton}><Text style={{color: 'white'}}>Clear</Text></View>}
            eraseComponent={<View style={styles.functionButton}><Text style={{color: 'white'}}>Eraser</Text></View>}
            strokeComponent={color => (
              <View style={[{ backgroundColor: color }, styles.strokeColorButton]} />
            )}
            strokeSelectedComponent={(color, index, changed) => {
              return (
                <View style={[{ backgroundColor: color, borderWidth: 2 }, styles.strokeColorButton]} />
              )
            }}
            strokeWidthComponent={(w) => {
              return (<View style={styles.strokeWidthButton}>
                <View  style={{
                  backgroundColor: 'white', marginHorizontal: 2.5,
                  width: Math.sqrt(w / 3) * 10, height: Math.sqrt(w / 3) * 10, borderRadius: Math.sqrt(w / 3) * 10 / 2
                }} />
              </View>
            )}}
            saveComponent={<View style={styles.functionButton}><Text style={{color: 'white'}}>Save</Text></View>}
            savePreference={() => {
              return {
                folder: 'RNSketchCanvas',
                filename: String(Math.ceil(Math.random() * 100000000)),
                transparent: false,
                imageType: 'png'
              }
            }}
          />
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF',
  },
  strokeColorButton: {
    marginHorizontal: 2.5, marginVertical: 8, width: 30, height: 30, borderRadius: 15,
  },
  strokeWidthButton: {
    marginHorizontal: 2.5, marginVertical: 8, width: 30, height: 30, borderRadius: 15,
    justifyContent: 'center', alignItems: 'center', backgroundColor: '#39579A'
  },
  functionButton: {
    marginHorizontal: 2.5, marginVertical: 8, height: 30, width: 60,
    backgroundColor: '#39579A', justifyContent: 'center', alignItems: 'center', borderRadius: 5,
  }
});

AppRegistry.registerComponent('example', () => example);

Properties


Prop Type Description
containerStyle object Styles to be applied on container
canvasStyle object Styles to be applied on canvas component
onStrokeStart function See above
onStrokeChanged function See above
onStrokeEnd function See above
onPathsChange function See above
onClosePressed function An optional function called when user taps closeComponent
onUndoPressed function An optional function that accepts a argument id (the deleted id of path) and is called when user taps "undo"
onClearPressed function An optional function called when user taps clearComponent
user string See above
closeComponent component An optional component for closing
eraseComponent component An optional component for eraser
undoComponent component An optional component for undoing
clearComponent component An optional component for clearing
saveComponent component An optional component for saving
strokeComponent function An optional function which accpets 1 argument color and should return a component.
strokeSelectedComponent function An optional function which accpets 3 arguments color, selectedIndex, isColorChanged and should return a component. isColorChanged is useful for animating when changing color. Because rerendering also calls this function, we need isColorChanged to determine whether the component is rerendering or the selected color is changed.
strokeWidthComponent function An optional function which accpets 1 argument width and should return a component.
strokeColors array An array of colors. Example: [{ color: '#000000' }, {color: '#FF0000'}]
defaultStrokeIndex numbber The default index of selected stroke color
defaultStrokeWidth number The default thickness of stroke
minStrokeWidth number The minimum value of thickness
maxStrokeWidth number The maximum value of thickness
strokeWidthStep number The step value of thickness when tapping strokeWidthComponent.
savePreference function A function which is called when saving image and should return an object (see below).
onSketchSaved function See above

Methods


Method Description
clear() See above
undo() See above
addPath(path) See above
deletePath(id) See above
save()

Constants


Constant Description
MAIN_BUNDLE See above
DOCUMENT See above
LIBRARY See above
CACHES See above

Background Image


To use an image as background, localSourceImage(see below) reqires an object, which consists of filename, directory(optional) and mode(optional).
Note: Because native module cannot read the file in JS bundle, file path cannot be relative to JS side. For example, '../assets/image/image.png' will fail to load image.

Typical Usage

  • Load image from app native bundle

* Android: 1. Put your images into android/app/src/main/res/drawable. 2. Set `filename` to the name of image files with or without file extension. 3. Set `directory` to ''
* iOS: 1. Open Xcode and add images to project by right clicking `Add Files to [YOUR PROJECT NAME]`. 2. Set `filename` to the name of image files with file extension. 3. Set `directory` to MAIN_BUNDLE (e.g. RNSketchCanvas.MAIN_BUNDLE or SketchCanvas.MAIN_BUNDLE) * Load image from camera 1. Retrive photo complete path (including file extension) after snapping. 2. Set `filename` to that path. 3. Set `directory` to ''

Content Mode

  • AspectFill

* AspectFit (default)

* ScaleToFill

Objects


SavePreference object

{
  folder: 'RNSketchCanvas',
  filename: 'image',
  transparent: true,
  imageType: 'jpg',
  includeImage: true,
  includeText: false,
  cropToImageSize: true
}
Property Type Description
folder? string Android: the folder name in Pictures directory
iOS: if filename is not null, image will save to temporary directory with folder and filename, otherwise, it will save to camera roll
filename? string the file name of image
iOS: Set to null to save image to camera roll.
transparent boolean save canvas with transparent background, ignored if imageType is jpg
imageType string image file format
Options: png, jpg
includeImage? boolean Set to true to include the image loaded from LocalSourceImage. (Default is true)
includeImage? boolean Set to true to include the text drawn from Text. (Default is true)
cropToImageSize? boolean Set to true to crop output image to the image loaded from LocalSourceImage. (Default is false)

Path object

{
  drawer: 'user1',
  size: { // the size of drawer's canvas
    width: 480,
    height: 640
  },
  path: {
    id: 8979841, // path id
    color: '#FF000000', // ARGB or RGB
    width: 5,
    data: [
      "296.11,281.34",  // x,y
      "293.52,284.64",
      "290.75,289.73"
    ]
  }
}

LocalSourceImage object

{
  filename: 'image.png',  // e.g. 'image.png' or '/storage/sdcard0/Pictures/image.png'
  directory: '', // e.g. SketchCanvas.MAIN_BUNDLE or '/storage/sdcard0/Pictures/'
  mode: 'AspectFill'
}
Property Type Description Default
filename string the fold name of the background image file (can be a full path)
directory? string the directory of the background image file (usually used with constants) ''
mode? boolean Specify how the background image resizes itself to fit or fill the canvas.
Options: AspectFill, AspectFit, ScaleToFill
AspectFit

CanvasText object

{
  text: 'TEXT',
  font: '',
  fontSize: 20,
  fontColor: 'red',
  overlay: 'TextOnSketch',
  anchor: { x: 0, y: 1 },
  position: { x: 100, y: 200 },
  coordinate: 'Absolute',
  alignment: 'Center',
  lineHeightMultiple: 1.2
}
Property Type Description Default
text string the text to display (can be multiline by \n)
font? string Android: You can set font to fonts/[filename].ttf to load font in android/app/src/main/assets/fonts/ in your Android project
iOS: Set font that included with iOS
fontSize? number font size 12
fontColor? string text color black
overlay? string Set to TextOnSketch to overlay drawing with text, otherwise the text will be overlaid with drawing.
Options: TextOnSketch, SketchOnText
SketchOnText
anchor? object Set the origin point of the image. (0, 0) to (1, 1). (0, 0) and (1, 1) indicate the top-left and bottom-right point of the image respectively. { x: 0, y: 0 }
position object Set the position of the image on canvas. If coordinate is Ratio, (0, 0) and (1, 1) indicate the top-left and bottom-right point of the canvas respectively. { x: 0, y: 0 }
coordinate? string Set to Absolute and Ratio to treat position as absolute position (in point) and proportion respectively.
Options: Absolute, Ratio
Absolute
alignment? string Specify how the text aligns inside container. Only work when text is multiline text. Left
lineHeightMultiple? number Multiply line height by this factor. Only work when text is multiline text. 1.0

Performance


  1. For non-transparent path, both Android and iOS performances are good. Because when drawing non-transparent path, only last segment is drawn on canvas, no matter how long the path is, CPU usage is stable at about 20% and 15% in Android and iOS respectively.
  2. For transparent path, CPU usage stays at around 25% in Android, however, in iOS, CPU usage grows to 100% :(.

Example


The source code includes 3 examples, using build-in UI components, using with only canvas, and sync between two canvases.

Check full example app in the example folder

Troubleshooting


Please refer here.

react-native-sketch-canvas's People

Contributors

creambyemute avatar diego-caceres avatar jeanregisser avatar rumblechen avatar terrylinla avatar toblerpwn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-sketch-canvas's Issues

Problems with ScrollView

If you place a SketchCanvas in a ScrollView, drawing vertical lines causes problems, i.e. the canvas stops drawing your line and instead scrolls vertically.

I'm on Android 7, Samsung Galaxy A5.

render fails in some cases where initial path crosses itself

while drawing the initial path on an empty canvas, if your original line creates a circle, and the path crosses its origin, it can in some cases drop rendered frames when you 'release' your finger and end your current path.

however, if the canvas is re-drawn (i.e. if you begin another line), it self-corrects immediately.

in the following video demonstration, i use black for the first path, and pink for the second path: https://youtu.be/oBBSGfU941k

when i release my finger from the first path's drawing, you will see much of the drawing disappear. the moment i begin the second (pink) path, you'll notice everything re-renders as expected immediately.

Loading image or SVG to pre-fill canvas?

Hi, thanks for this awesome library! It's got a lot of the features I need for a little project I am working on.

Would it be difficult to load an existing image to fill the canvas, which you can then draw on top of?

I've tested the addPath-function. But I'm a bit unsure how to convert an SVG to the format that function takes as a parameter.

Render passes are very inefficient; re-renders entire canvas every frame!

The goal here should be to only re-render the small part of the canvas that has changed (been drawn on) between each frame.

Here are two helpful blog posts about smoothing (and other things) on Android:

https://medium.com/square-corner-blog/smooth-signatures-9d92df119ff8 (see the "Surgically Invalidate" section)

https://medium.com/square-corner-blog/smoother-signatures-be64515adb33 (see the "Responsiveness" section)

Note that the same principles apply to iOS - but the methods will differ, slightly. For example, in one project I used the UIView object's setNeedsDisplayInRect: and specified only the rect/space representing the space between the last two touches to be re-rendered.

method 'getBase64()' is missing in index.js

Currently i'm using RN-sketch-canvas version 0.6.0. In the docs there are mentioned a lot of methods that can be used. Yet 'getBase64()' is missing in the index.js file, therefore I cannot use this method. I've linked the project react-native link.

RN Version: 0.55.4
RN-sketch-canvas version: 0.6.0

Import method 1:

import Canvas from '@terrylinla/react-native-sketch-canvas';

Import method 2:

import { SketchCanvas } from '@terrylinla/react-native-sketch-canvas';

Am I missing something?

on iOS SketchCanvas save and getBase64 functionalities are not working

Thank you for this awesome library. It works perfectly on Android.

On iOS simulator, it crashes when I try to save the SketchCanvas using save() method and returns an empty canvas base64 with getBase64 callback function. Both these features work on android though. I am not getting any other error message in the debugger.

I am using react-native 0.52.0

Tapping does not draw a dot on `SketchCanvas`

Using the following component on React Native 0.52:

<SketchCanvas
  style={{ flex: 1}}
  strokeColor={'red'}
  strokeWidth={7}
/>

Tapping on the canvas does not draw a dot. Instead, nothing is drawn at all.

Package name throws deprecation warning on Gradle 4.4

The project name '@terrylinla/react-native-sketch-canvas' contains at least one of the following characters: [ , /, , :, <, >, ", ?, *, |]. This has been deprecated and is scheduled to be removed in Gradle 5.0. Set the 'rootProject.name' or adjust the 'include' statement (see https://docs.gradle.org/4.4/dsl/org.gradle.api.initialization.Settings.html#org.gradle.api.initialization.Settings:include(java.lang.String[]) for more details).

I was forced to update Gradle to version 4.4 due to breaking changes in react-native-firebase (a very popular project).

Can it edit base on photo?

i want to use it on the photo, but i can't figure out how to add a background map for the canvas. How can i make it? Thx.

Cannot draw on `SketchCanvas` when wrapped in children of `TouchableWithoutFeedback`

Using an empty React Native project (0.52 or 0.51), this code will not allow you to draw in the canvas:

// DOES NOT WORK
export default class App extends Component<{}> {
  render() {
    return (
      <TouchableWithoutFeedback style={{flex: 1}}>
        <View style={{flex: 1}}>
          <SketchCanvas
            style={{ flex: 1}}
            strokeColor={'red'}
            strokeWidth={7}
          />
        </View>
      </TouchableWithoutFeedback>
    );
  }
}

It isn't clear to me exactly why, but I suspect the SketchCanvas is not receiving touches at all - or else perhaps evaluating them and rejecting them.

Interestingly, removing the child of the TouchableWithoutFeedback Component fixes the problem. See:

// WORKS
export default class App extends Component<{}> {
  render() {
    return (
      <TouchableWithoutFeedback style={{flex: 1}}>
        {/* <View style={{flex: 1}}> */}
          <SketchCanvas
            style={{ flex: 1}}
            strokeColor={'red'}
            strokeWidth={7}
          />
        {/* </View> */}
      </TouchableWithoutFeedback>
    );
  }
}

Excellent project otherwise! Excited to understand this behavior (or see a fix) and start using it. :)

[ios] Should/Could canvas manager create new canvas every time it gets called?

I mean this part of RNSketchCanvasManager:

    if (!self.sketchCanvasView) {
        self.sketchCanvasView = [[RNSketchCanvas alloc] initWithEventDispatcher: self.bridge.eventDispatcher];
    }

I'd like to remove the if check, but not sure if it's good. I'll explain my use case below.

I'm utilizing the SkecthCanvas component to implement something like a sketchbook. And I may have several sketchbooks available at the same time, but only 1 of them is active on the screen. I'd like all of them to be independent and have their own strokes, of course. However, if I close number 1 and open number 2, the strokes of number 1 is still showing on number 2, obviously it's because there is only 1 true canvas. That's why I'm thinking of creating new canvas every time it's called.

So if anyone or the author would give some advice it would be appreciated, thanks.

Linking on iOS

Hi!

How can I link this library manually on iOS? It works for me in Android but not in iOS.

Thank you!

Error linking on iOS app

Hi,

I am trying to implements this library in an iOS app. I have already used it on an Android app but when i use: react-native link @terrylinla/react-native-sketch-canvas

It returns to me the next error:

rnpm-install info Android module @terrylinla/react-native-sketch-canvas is already linked
rnpm-install info Linking @terrylinla/react-native-sketch-canvas ios dependency
rnpm-install WARN ERRGROUP Group 'Libraries' does not exist in your Xcode project. We have created it automatically for you.
rnpm-install ERR! Something went wrong while linking. Error: Cannot read property 'children' of null
Please file an issue here: https://github.com/facebook/react-native/issues

Can anyone help me?

Thanks!!

How can I change stroke width mid-drawing?

I'd like to use this module for capturing signatures, but I'd like the signatures themselves to look more 'realistic'. One way is to change the stroke width based on velocity.

Is there away to achieve this with your module?

Handle the json value from server

So, I tried JSON.stringify(this.canvas.getPaths()) and then sent it to server and then storing it in the.state.checkpath.
But,

              <SketchCanvas
                ref={ref => {
                  this.canvas = ref;
                  cpath = JSON.parse(this.state.checkpath);
                  console.log(check);
                  console.log(JSON.parse(this.state.checkpath));
                  this.canvas.addPath(check);
                }}

Does not seem to work, it's giving me data.path.id error

red box in android

I haven't been able to get this project working in android.
On iOS I've experience no issue, however on android I simply get a red box surrounding where the canvas would be. I've tried uninstalling the library, clearing all caches, etc. I've also unlinked and re-linked the library with no luck.
Has anybody else experienced this and found a fix?

How do we load previously generated paths?

Firstly, thanks for writing this component.

I'd like to control the UI side of things myself and just make use of SketchCanvas but I'm struggling to understand how I can apply previous paths.

If I store an array of paths (sketch) as described in the docs and have the following in my app:

componentDidMount() {
  sketch.map((movement) => {
    console.log('drawing', movement.path)
    this.refs.canvas.addPath(movement)
  })
}

I would expect the canvas to display them but it remains blank. It could be that I have to somehow invalidate the render so it redraws, but I'm unsure if what I'm trying to accomplish is supported.

Android sketch 'pen' brush size is incorrect

currently does not respect higher DPI - e.g. the lines drawn are 'smaller' than they should be.

@terrylinla - This was a shortcoming of my previous 'retina' PR; I plan to fix this soon & will submit a PR to you if you don't beat me to it.

Curved lines are not 'smooth'; use literal pixel interpretation

Typical implementations on iPhone use a quadratic curve implementation, which requires that the two previous points to be available (which I think we have stored in an array, fortunately!).

While a smooth line may not be desirable in all use cases, we should still have support for it (e.g. via Prop) - this is preferred certainly for any sort of 'signature'-type component, but also probably for the majority of free drawing applications.

@terrylinla - I have some experience with this on iPhone, and will submit a PR within the next few weeks if you don't beat me to it. Haven't looked into Android before.

Multiple canvas?

I am trying to put multiple on the same screen, but seeing weird behavior. Does it support having multiple?

Eraser function

Can you add the eraser function,such as CGContextSetBlendMode(context, kCGBlendModeClear) in iOS

Gradle files use outdated functionality

> Configure project :@terrylinla/react-native-sketch-canvas
WARNING: Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html
WARNING: The specified Android SDK Build Tools version (25.0.0) is ignored, as it is below the minimum supported version (27.0.3) for Android Gradle Plugin 3.1.2.
Android SDK Build Tools 27.0.3 will be used.
To suppress this warning, remove "buildToolsVersion '25.0.0'" from your build.gradle file, as each version of the Android Gradle Plugin now has a default version of the build tools.

Invariant Violation: Native component for "RNSketchCanvas" does not exist

When rendering <SketchCanvas /> directly (not via RNSketchCanvas), I see the following

Invariant Violation: Native component for "RNSketchCanvas" does not exist

This error is located at:
    in RNSketchCanvas (at SketchCanvas.js:206)
    in SketchCanvas (at postSketchInput.js:45)
    in RCTView (at View.js:112)
...

Implementation code is:

...

// sketch view module
import { SketchCanvas } from '@terrylinla/react-native-sketch-canvas';

export default class PostSketchInput extends Component {

  render() {
    const width = Dimensions.get('window').width - PostInputPadding * 2
    return (
      <View style={[styles.container, styles.shadow, {
        height: width,
        width: width
      }]}>
        <SketchCanvas
          style={styles.input}
          strokeColor={'red'}
          strokeWidth={7}
        />
      </View>
    )
  }
}

...

onStrokeChanged don't pass any value

I am trying to manage the position of the strokes but the onStrokeChanged method don't pass any value. It's just null. Is there any other way to get the drawn position?

Release archive crashes at startup on Android and iPhone on modern React Native (0.51)

Crash on iPhone is as follows:

*** Terminating app due to uncaught exception 'RCTFatalException: Unhandled JS Exception: undefined is not an object (evaluating 'h.View.propTypes.style')', reason: 'Unhandled JS Exception: undefined is not an object (evaluating 'h.View.prop..., stack:
<unknown>@668:5435
a@2:837
<unknown>@667:245
a@2:837
<unknown>@666:135
a@2:837
<unknown>@662:604
a@2:837
<unknown>@13:349
a@2:837
<unknown>@12:24
a@2:837
<unknown>@2:309
global code@711:9
'

...and on Android:

com.facebook.react.common.JavascriptException: undefined is not an object (evaluating 'h.View.propTypes.style'), stack:
<unknown>@664:5435
a@2:850
<unknown>@2:392
t@2:399
<unknown>@663:245
a@2:850
<unknown>@2:392
t@2:399
<unknown>@662:135
a@2:850
<unknown>@2:392
t@2:399
<unknown>@658:604
a@2:850
<unknown>@2:392
t@2:399
<unknown>@13:349
a@2:850
<unknown>@2:392
t@2:399
<unknown>@12:24
a@2:850
<unknown>@2:322
t@2:399
global code@707:9
at com.facebook.react.modules.core.ExceptionsManagerModule.showOrThrowError(ExceptionsManagerModule.java

Android: Native component for "RNSketchCanvas" does not exist

in iOS its working but sadly not on android with "react-native run-android"

code:
...
import { SketchCanvas } from '@terrylinla/react-native-sketch-canvas';
...
render() {
...
<SketchCanvas
ref={ref => this.canvas = ref}
style={{ flex: 1 }}
strokeColor={'red'}
strokeWidth={7}
/>
...
}

Feature: add realtime path/stroke count callback/event

Use case: I have an "Undo" button, and I want to disable it when there are 0 strokes on the screen. Using onStrokeStart(), I can tell when the initial strokes begin, but if the canvas reverts to 0 strokes (via undo(), or clear() or any other similar action), there is no callback or event to monitor.

Use (optional?) 'proportional' line history for extensibility of drawings

Imagine you save a drawing on a 200 x 200 pixel canvas, but you want to display it on a different device that has e.g. 500 x 500 pixels as its canvas (or 322 x 322 pixels, or any other arbitrary size). How do you achieve this without up-scaling an image?

I propose we store each line as a 'percentage' or 'proportion' of the width of the canvas.

Using this approach, each x,y coordinate is no longer stored as an actual pixel-wise coordinate, but instead as a representation of its position within the canvas where 0 is equal to the origin of each axis, and 1 is equal to the terminus of each axis (and 0.5 is equal to the mid-point).

These float or coordinate values would require a fine level of detail in practice, because of course we want to be very precise with our coordinates, e.g. imagine an x,y coordinate of 0.251123123, 0.5000000000123 - this coordinate would be located just over 1/4th of the canvas along the x axis, and just over 1/2 of the canvas on the y axis. All coordinates would then be between 0,0 and 1,1.

You might imagine a line that gos straight across the x-axis at 1/3 of the way 'down' the y-axis being represented as:

[
  {0.0, 0.333333333},
  {0.001, 0.333333333},
  {0.003, 0.333333333},
  {0.005, 0.333333333},
  {0.008, 0.333333333},
  {0.01, 0.333333333},
  {0.012, 0.333333333},
  {0.013, 0.333333333},
  {0.014, 0.333333333},
  {0.015, 0.333333333},
  {0.016, 0.333333333},
]

(These are just example values; actual snapshots of screen touches would not look like this.)

This feels (to me) like the best way to achieve a flexible, extensible coordinate system that can be used as the data source for a drawing across multiple canvas sizes while maintaining full (or very near full) fidelity. The intent for most systems would then be to store & re-render these lines instead of an actual .png or base64 representation of the lines.

Prevent Event Bubbling

Is there any way to prevent event bubbling? I am currently using this with in a ScrollView thats within a TabView so if I try and draw either vertically or horizontally it seems as if though the ScrollView/Tab takes over. Any way of preventing event bubbling so that when I am drawing within the canvas the ScrollView/Tab wont gent any events?

This is probably related to #57

SketchCanvas gets cut off in landscape mode in iOS

In iOS, when I change the device orientation to landscape, my drawings are only visible on one half of the canvas.

screen shot 2018-07-20 at 3 32 16 pm

I know the canvas is taking up the whole area, because I made the background colour of the SketchCanvas red.

It seems like the canvas size isn't being updated on rotation. The weird part is that if I redraw the paths from the landscape canvas onto another canvas, it shows the full drawing.

Multiple Canvas in Android producing the same results

I have 3 canvas in one screen and have each ref saved in an array of canvas variable.
After drawing and clicking the "Done" button, the result of each base64 result turns out to be the same, or in my case, the last canvas that was mounted.

Example:

class CanvasExample extends Component {
    constructor(props) {
        super();
        this.state = {
            ...props,
            canvas: []
        }
    }

    HandleDone = () => {
        this.state.canvas.map(canvas => {
            canvas.getBase64('jpg', false, (err, result) => {
                if (err) {
                    return console.log(err);
                }

                return console.log(result);
            })
        });

        let canvas1 = this.getSignatureRender(this.state.canvas[0]);
        let canvas2 = this.getSignatureRender(this.state.canvas[1]);
        let canvas3 = this.getSignatureRender(this.state.canvas[2]);

        Promise.all([canvas1, canvas2, canvas3]).then(values => {
            console.log(values);
        }).catch(error => console.log(error));
    };

    getSignatureRender(canvas) {
        return new Promise((resolve, reject) => {
            canvas.getBase64('jpg', false, (err, result) => {
                if (err) {
                    return reject(err);
                }

                return resolve(result);
            })
        })
    }

    render() {
        return (
            <Container>
                <SketchCanvas
                    ref={ref => this.state.canvas[0] = ref}
                    style={{ alignItems: 'center', justifyContent: 'center', width: '100%', height: 220, backgroundColor: '#e9e9e9' }}
                    strokeColor={'black'}
                    strokeWidth={2}
                />

                <SketchCanvas
                    ref={ref => this.state.canvas[1] = ref}
                    style={{ alignItems: 'center', justifyContent: 'center', width: '100%', height: 220, backgroundColor: '#e9e9e9' }}
                    strokeColor={'black'}
                    strokeWidth={2}
                />

                <SketchCanvas
                    ref={ref => this.state.canvas[2] = ref}
                    style={{ alignItems: 'center', justifyContent: 'center', width: '100%', height: 220, backgroundColor: '#e9e9e9' }}
                    strokeColor={'black'}
                    strokeWidth={2}
                />
                <Button onPress={() => this.HandleDone()} block style={{ borderRadius: 0, backgroundColor: '#2babe2' }} />
            </Container>
        );
    }
};

Thank you!

Edit:
getPaths() returns the correct results but not getBase64

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.