4.1.0 • Published 3 years ago

@pcgnpm/react-native-signature-canvas-optimized v4.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

react-native-signature-canvas-optimized

npm.io npm.io npm GitHub last commit

React Native Signature Component based Canvas for Android && IOS && expo

  • Forked from (https://github.com/YanYuanFE/react-native-signature-canvas)
  • Supports Android and iOS and Expo
  • Pure JavaScript implementation with no native dependencies
  • Tested with RN 0.50
  • Core use signature_pad.js
  • Only depend on react and react native
  • Generates a base64 encoded png image of the signature Note: Expo support for React Native Signature Canvas v1.5.0 started with Expo SDK v33.0.0.

Installation(for React Native V0.60.0 or Expo SDK v35.0.0)

npm install --save react-native-signature-canvas-optimized

Installation(for React Native V0.5x.x or Expo SDK < v33)

npm install --save react-native-signature-canvas-optimized@1.4.2

Usage

import Signature from 'react-native-signature-canvas-optimized';

Properties


PropTypeDescription
descriptionTextstringdescription text for signature
clearTextstringclear button text
confirmTextstringsave button text
webStylestringwebview style for overwrite default style, all style: https://github.com/YanYuanFE/react-native-signature-canvas/blob/master/h5/css/signature-pad.css
onOKfunctionhandle function when you click save button
onEmptyfunctionhandle function of empty signature when you click save button
onClearfunctionhandle function when you click clear button
onBeginfunctionhandle function when a new stroke is started
onEndfunctionhandle function when the stroke has ended
customHtmlfunctionhtml string that lets you modify things like the layout or elements.
autoClearbooleanis auto clear the signature after click confirm button
trimWhitespacebooleantrim image whitespace
rotatedbooleanrotate signature pad 90 degrees
imageTypestringdefault is "", "image/jpeg"、"image/svg+xml", imageType of export signature
dataURLstringdefault is "", Base64 string, Draws signature image from data URL.
optimizeSvgbooleangroups the paths to apply common stroke parameters and limit point precision to reduce markup size. Default is false.
penColorstringdefault is "black", color of pen
backgroundColorstringdefault is "rgba(255,255,255,1)", backgroundColor of canvas
dotSizenumberradius of a single dot
minWidthnumberminimum width of a line. Defaults to 0.5
androidHardwareAccelerationDisabledbooleanandroidHardwareAccelerationDisabled for react-native-webview. Default is false
styleobjectstyle of wrapper view

Methods


FunctionDescription
readSignature()Reads the current signature on the canvas and triggers either the onOK or onEmpty callbacks
clearSignature()Clears the current signature

You need to use ref like:

import SignatureScreen from 'react-native-signature-canvas-optimized';

const Sign = ({text, onOK}) => {
  const ref = useRef();

  const handleSignature = signature => {
    console.log(signature);
    onOK(signature);
  };

  const handleEmpty = () => {
    console.log('Empty');
  }

  const handleClear = () => {
    console.log('clear success!');
  }

  const handleEnd = () => {
      ref.current.readSignature();
  }

  return (
    <SignatureScreen
        ref={ref}
        onEnd={handleEnd}
        onOK={handleSignature}
        onEmpty={handleEmpty}
        onClear={handleClear}
        autoClear={true}
        descriptionText={text}
    />
  );
}

export default Sign;

Save with optimized SVG xml

If you use expo, you can use expo-file-system for save base64 image as local file, if you use react-native-cli, use react-native-fs.

import * as FileSystem from 'expo-file-system';

const handleSignature = signature => {
    const path = FileSystem.cacheDirectory + 'sign.svg';
    FileSystem.writeAsStringAsync(path, signature.replace('data:image/svg+xml;base64,', ''), {encoding: FileSystem.EncodingType.Base64}).then(res => {
      console.log(res);
      FileSystem.getInfoAsync(path, {size: true, md5: true}).then(file => {
        console.log(file);
      })
    }).catch(err => {
      console.log("err", err);
    })
};

Basic parameters

<Signature
  // handle when you click save button
  onOK={(img) => console.log(img)}
  onEmpty={() => console.log("empty")}
  // description text for signature
  descriptionText="Sign"
  // clear button text
  clearText="Clear"
  // save button text
  confirmText="Save"
  // String, webview style for overwrite default style, all style: https://github.com/YanYuanFE/react-native-signature-canvas/blob/master/h5/css/signature-pad.css
  webStyle={`.m-signature-pad--footer
    .button {
      background-color: red;
      color: #FFF;
    }`
  }
  optimizeSvg={true}
  // Produces SVG signature image by grouping stroke paths 
  autoClear={true}
  imageType={"image/svg+xml"}
  // Optimization only applicable to SVG images
  dotSize={2.5}
  // Renders stroke performed on canvas
  minWidth={2}
/>

Save Base64 Image as File

If you use expo, you can use expo-file-system for save base64 image as local file, if you use react-native-cli, use react-native-fs.

import * as FileSystem from 'expo-file-system';

const handleSignature = signature => {
    const path = FileSystem.cacheDirectory + 'sign.png';
    FileSystem.writeAsStringAsync(path, signature.replace('data:image/png;base64,', ''), {encoding: FileSystem.EncodingType.Base64}).then(res => {
      console.log(res);
      FileSystem.getInfoAsync(path, {size: true, md5: true}).then(file => {
        console.log(file);
      })
    }).catch(err => {
      console.log("err", err);
    })
};

Basic parameters

<Signature
  // handle when you click save button
  onOK={(img) => console.log(img)}
  onEmpty={() => console.log("empty")}
  // description text for signature
  descriptionText="Sign"
  // clear button text
  clearText="Clear"
  // save button text
  confirmText="Save"
  // String, webview style for overwrite default style, all style: https://github.com/YanYuanFE/react-native-signature-canvas/blob/master/h5/css/signature-pad.css
  webStyle={`.m-signature-pad--footer
    .button {
      background-color: red;
      color: #FFF;
    }`
  }
  autoClear={true}
/>

If you create your own triggers for the readSignature and/or clearSignature you can hide the built in Clear and Save buttons with css styles passed into the webStyle property.

const webStyle = `.m-signature-pad--footer
    .save {
        display: none;
    }
    .clear {
        display: none;
    }
`;
...
  <Signature
    webStyle={webStyle}
    onOK={handleOK}
    onEmpty={handleEmpty}
    onEnd={handleEnd}
  />

Custom Button for Confirm and Clear

import React, {useRef} from 'react';
import { StyleSheet, View, Button } from 'react-native';
import SignatureScreen from 'react-native-signature-canvas-optimized';

const Sign = ({onOK}) => {
  const ref = useRef();

  const handleSignature = signature => {
    console.log(signature);
    onOK(signature);
  };

  const handleClear = () => {
    ref.current.clearSignature();
  }

  const handleConfirm = () => {
    console.log("end");
    ref.current.readSignature();
  }

  const style = `.m-signature-pad--footer {display: none; margin: 0px;}`;

  return (
    <View style={styles.container}>
      <SignatureScreen
          ref={ref}
          onOK={handleSignature} 
          webStyle={style}
          optimizeSvg={true}
      />
      <View style={styles.row}>
        <Button
            title="Clear"
            onPress={handleClear}
        />
        <Button
          title="Confirm"
          onPress={handleConfirm}
        />
      </View>
    </View>
  );
}

export default Sign;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    height: 250,
    padding: 10,
  },
  row: {
    display: "flex",
    flexDirection: "row",
    justifyContent: 'space-between',
    width: '100%',
    alignItems: 'center',
  }
});

Example

  • Android

  • iOS

import React, { useState } from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
import Signature from 'react-native-signature-canvas-optimized';

export const SignatureScreen = () => {
  const [signature, setSign] = useState(null);

  const handleSignature = signature => {
    console.log(signature);
    setSign(signature);
  };

  const handleEmpty = () => {
    console.log('Empty');
  }

  const style = `.m-signature-pad--footer
    .button {
      background-color: red;
      color: #FFF;
    }`;
  return (
    <View style={{ flex: 1 }}>
      <View style={styles.preview}>
        {signature ? (
          <Image
            resizeMode={"contain"}
            style={{ width: 335, height: 114 }}
            source={{ uri: signature }}
          />
        ) : null}
      </View>
      <Signature
        onOK={handleSignature}
        onEmpty={handleEmpty}
        descriptionText="Sign"
        clearText="Clear"
        confirmText="Save"
        webStyle={style}
        imageType="image/svg+xml"
        optimizeSvg={true}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  preview: {
    width: 335,
    height: 114,
    backgroundColor: "#F8F8F8",
    justifyContent: "center",
    alignItems: "center",
    marginTop: 15
  },
  previewText: {
    color: "#FFF",
    fontSize: 14,
    height: 40,
    lineHeight: 40,
    paddingLeft: 10,
    paddingRight: 10,
    backgroundColor: "#69B2FF",
    width: 120,
    textAlign: "center",
    marginTop: 10
  }
});

Using Typescript

To use Typescript just import SignatureViewRef and in useRef hook inform that the reference is of the SignatureViewRef type, with that the readSignature and clearSignature methods will be available.

import React, { useRef } from 'react';
import SignatureScreen, { SignatureViewRef } from 'react-native-signature-canvas-optimized';

interface Props {
  text: string;
  onOK: (signature) => void;
}

const Sign: React.FC<Props> = ({text, onOK}) => {
  const ref = useRef<SignatureViewRef>(null);

  const handleSignature = signature => {
    console.log(signature);
    onOK(signature);
  };

  const handleEmpty = () => {
    console.log('Empty');
  }

  const handleClear = () => {
    console.log('clear success!');
  }

  const handleEnd = () => {
      ref.current?.readSignature();
  }

  return (
    <SignatureScreen
        ref={ref}
        onEnd={handleEnd}
        onOK={handleSignature}
        onEmpty={handleEmpty}
        onClear={handleClear}
        autoClear={true}
        descriptionText={text}
        optimizeSvg={true}
    />
  );
}

export default Sign;

Example inside ScrollView

When using react-native-signature-canvas-optimized inside a ScrollView, you will only get a point on the canvas and the ScrollView will handle the gesture making it unused for the canvas. The work around is to use the scrollEnabled prop of ScrollView. Here an example:

import React, {useState} from 'react';
import {ScrollView, View} from 'react-native';
import Signature from 'react-native-signature-canvas-optimized';

const SignInScroll = () => {
  const [scrollEnabled, setScrollEnabled] = useState(true);

  return (
    <ScrollView scrollEnabled={scrollEnabled}>
      <View style={{height: 300}}>
        <Signature
          onOK={(img) => console.log(img)}
          onBegin={() => setScrollEnabled(false)}
          onEnd={() => setScrollEnabled(true)}
          descriptionText="Sign"
          clearText="Clear"
          confirmText="Save"
          imageType="image/jpeg"
        />
      </View>
    </ScrollView>
  );
};

export default SignInScroll;