Project Icon

react-native-signature-canvas

React Native 画布签名组件 支持Android iOS和Expo

react-native-signature-canvas是一个基于Canvas的React Native签名组件,支持Android、iOS和Expo平台。提供背景图片、覆盖图、笔触样式等自定义选项,可生成base64编码的PNG签名图片。组件包含多种回调函数和控制方法,方便开发者在移动应用中实现灵活的电子签名功能。

react-native-signature-canvas

npm GitHub last commit runs with expo

基于Canvas的React Native签名组件,适用于Android、iOS和Expo

  • 支持Android、iOS和Expo
  • 已在RN 0.69上测试
  • 核心使用 signature_pad.js
  • 生成签名的base64编码png图像 注意:React Native Signature Canvas v1.5.0开始支持Expo SDK v33.0.0及以上版本。

安装(适用于React Native V0.60.0或Expo SDK v35.0.0)

yarn add react-native-signature-canvas

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

该包依赖于 react-native-webview,特别是在使用React Native CLI时需要。要安装react-native-webview,请按照此处提到的步骤操作。

安装(适用于React Native V0.5x.x或Expo SDK < v33)

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

使用方法

基本用法

import Signature from "react-native-signature-canvas";

自定义用法

import SignatureScreen from "react-native-signature-canvas";

属性


属性类型描述
androidHardwareAccelerationDisabledbooleanreact-native-webview的androidHardwareAccelerationDisabled选项。默认为false
autoClearboolean点击确认按钮后是否自动清除签名
backgroundColorstring默认为"rgba(255,255,255,0)"(透明),画布的背景颜色
bgHeightnumber背景图像的高度
bgWidthnumber背景图像的宽度
bgSrcstring背景图像源URI(URL)
clearTextstring清除按钮文本
confirmTextstring保存按钮文本
customHtml(injectedJavaScript: string) => string允许修改布局或元素的HTML字符串
dataURLstring默认为"",Base64字符串,从dataURL绘制保存的签名
descriptionTextstring签名的描述文本
dotSizenumber单个点的半径(非笔画宽度)
imageTypestring"image/png"(默认)、"image/jpeg"、"image/svg+xml",导出签名的图像类型
minWidthnumber线条的最小宽度。默认为0.5
maxWidthnumber线条的最大宽度。默认为2.5
minDistancenumber仅当前一个点距离超过x像素时才添加下一个点。默认为5
nestedScrollEnabledboolean在scrollview内部使用时启用嵌套滚动
showsVerticalScrollIndicatorboolean布尔值,决定是否在WebView中显示垂直滚动指示器。默认值为true
onOKfunction保存非空签名后的回调函数
onEmptyfunction尝试保存空签名后的回调函数
onClearfunction清除签名后的回调函数
onGetDatafunction调用getData()时的回调函数
onBeginfunction开始新笔画时的回调函数
onEndfunction笔画结束时的回调函数
onLoadEndfunctionwebview画布加载结束时的回调函数
onUndofunction调用undo()时的回调函数
onRedofunction调用redo()时的回调函数
onDrawfunction启用绘图时的回调函数
onErasefunction启用擦除时的回调函数
onChangePenColorfunction更改笔颜色后的回调函数
onChangePenSizefunction更改笔大小后的回调函数
overlayHeightnumber覆盖图像的高度
overlayWidthnumber覆盖图像的宽度
overlaySrcstring覆盖图像源URI(URL)必须是具有透明背景的.png文件
penColorstring默认为"black",笔的颜色
rotatedboolean将签名板旋转90度
styleobject包装视图的样式
trimWhitespaceboolean修剪图像白色空间
webStylestring用于覆盖默认样式的webview样式,所有样式:https://github.com/YanYuanFE/react-native-signature-canvas/blob/master/h5/css/signature-pad.css
androidLayerTypenone、software、hardware设置android webview的layerType

方法


函数描述
clearSignature()清除当前签名
changePenColor(color)更改笔颜色
changePenSize(minW, maxW)更改笔大小
draw()启用签名绘制
erase()启用签名擦除
getData()触发onGetData回调,传入单个data JSON字符串
readSignature()读取画布上的当前签名,并触发onOKonEmpty回调
undo()撤销上一笔
redo()重做上一笔

要调用这些方法,请使用useRef hook:

import SignatureScreen from "react-native-signature-canvas";

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

  // 在ref.current.readSignature()读取非空base64字符串后调用
  const handleOK = (signature) => {
    console.log(signature);
    onOK(signature); // 来自组件props的回调
  };

  // 在ref.current.readSignature()读取空字符串后调用
  const handleEmpty = () => {
    console.log("Empty");
  };

  // 在ref.current.clearSignature()之后调用
  const handleClear = () => {
    console.log("clear success!");
  };

  // 在笔画结束后调用
  const handleEnd = () => {
    ref.current.readSignature();
  };

  // 在ref.current.getData()之后调用
  const handleData = (data) => {
    console.log(data);
  };

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

export default Sign;

使用背景图像

您可以使用bgSrc属性设置一个不可擦除的背景图像来绘制您的签名。请确保提供图像的宽度和高度。

const imgWidth = 300;
const imgHeight = 200;
const style = `.m-signature-pad {box-shadow: none; border: none; }
              .m-signature-pad--body {border: none;}
              .m-signature-pad--footer {display: none; margin: 0px;}
              body,html {
              width: ${imgWidth}px; height: ${imgHeight}px;}`;
...
<View style={{ width: imgWidth, height: imgHeight }}>
  <SignatureScreen
    ref={ref}
    bgSrc="https://via.placeholder.com/300x200/ff726b"
    bgWidth={imgWidth}
    bgHeight={imgHeight}
    webStyle={style}
    onOK={handleOK}
  />
</View>

使用覆盖图像

覆盖图是一个不可擦除的图像,可以用作指引,类似于填色书。请确保图像格式为.png,并且具有透明背景。同时,不要忘记提供图像的宽度和高度。 使用overlaySrc属性提供链接。

const imgWidth = 256;
const imgHeight = 256;
const style = `.m-signature-pad {box-shadow: none; border: none; }
              .m-signature-pad--body {border: none;}
              .m-signature-pad--footer {display: none; margin: 0px;}
              body,html {
              width: ${imgWidth}px; height: ${imgHeight}px;}`;
...
<View style={{ width: imgWidth, height: imgHeight }}>
  <SignatureScreen
    ref={ref}
    overlaySrc="http://pngimg.com/uploads/circle/circle_PNG63.png"
    overlayWidth={imgWidth}
    overlayHeight={imgHeight}
    webStyle={style}
    onOK={handleOK}
  />
</View>

将Base64图像保存为文件

如果您使用的是expo,可以使用expo-file-system将base64图像保存为本地文件;如果您使用的是react-native-cli,请使用react-native-fs

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

const handleOK = (signature) => {
  const path = FileSystem.cacheDirectory + "sign.png";
  FileSystem.writeAsStringAsync(
    path,
    signature.replace("data:image/png;base64,", ""),
    { encoding: FileSystem.EncodingType.Base64 }
  )
    .then(() => FileSystem.getInfoAsync(path))
    .then(console.log)
    .catch(console.error);
};

基本参数

<Signature
  // 点击保存按钮时的处理函数
  onOK={(img) => console.log(img)}
  onEmpty={() => console.log("empty")}
  // 签名的描述文本
  descriptionText="Sign"
  // 清除按钮文本
  clearText="Clear"
  // 保存按钮文本
  confirmText="Save"
  // 字符串,用于覆盖默认样式的webview样式,所有样式: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}
  imageType={"image/svg+xml"}
/>

如果您创建自己的触发器来读取签名和/或清除签名,可以通过传入webStyle属性的css样式来隐藏内置的清除和保存按钮。

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

自定义确认和清除按钮

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

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

  const handleOK = (signature) => {
    console.log(signature);
    onOK
返回 (
  <View style={styles.container}>
    <SignatureScreen ref={ref} onOK={handleOK} webStyle={style} />
    <View style={styles.row}>
      <Button title="清除" onPress={handleClear} />
      <Button title="确认" 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",
  },
});

## 示例

- Android <br/>
  <img src="http://img.yanyuanfe.cn/signature-android.png" width="400" />

- iOS <br/>
  <img src="http://img.yanyuanfe.cn/signature-ios.png" width="400" />

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

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

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

  const handleEmpty = () => {
    console.log("空白");
  };

  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={handleOK}
        onEmpty={handleEmpty}
        descriptionText="签名"
        clearText="清除"
        confirmText="保存"
        webStyle={style}
      />
    </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,
  },
});

## 使用 TypeScript

要使用 TypeScript,只需导入 `SignatureViewRef`,并在 [useRef hook](https://reactjs.org/docs/hooks-reference.html#useref) 中指明引用的类型为 `SignatureViewRef`,这样就可以使用常规的 `ref` 方法。

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

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("空白");
  };

  const handleClear = () => {
    console.log("清除成功!");
  };

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

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

export default Sign;

## 在 ScrollView 中使用的示例

当在 ScrollView 中使用 `react-native-signature-canvas` 时,你只能在画布上得到一个点,而 ScrollView 会处理手势,使其无法用于画布。
解决方法是使用 `ScrollView` 的 `scrollEnabled` 属性。
这里有一个示例:

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

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="签名"
          clearText="清除"
          confirmText="保存"
          imageType="image/jpeg"
        />
      </View>
    </ScrollView>
  );
};

export default SignInScroll;
项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号