我试图了解如何在 React Native 中进行签名捕获。我的应用程序是使用
create-react-native-app
和 Expo
创建的,我希望不必弹出应用程序即可让此功能正常工作。
是否可以将这样的东西包装在网络视图中? https://github.com/szimek/signature_pad
我也看过这个项目,https://github.com/RepairShopr/react-native-signature-capture,但它需要我弹出应用程序并使用
react-native link
。
寻找有关如何实现此功能的任何建议或建议,同时使我的项目尽可能简单(理想情况下,使用 create-react-native-app,但如果不可能,有人可以向我解释为什么吗?)
React Native 的工作方式是,React Native 中可用的每个组件都映射到底层平台中的本机组件。
即。 a
<Image />
在 Android 中是 ImageView
,在 iOS 中是 UIImageView.h
。
Javascript 代码本身在每个平台上的 Javascript 线程中运行,当您在 React Native 中使用组件时,有一个转换层将信息从 JS 传递到 React Native 桥,然后创建相应的本机组件。
默认情况下,React Native 包含以下组件:https://facebook.github.io/react-native/docs/components-and-apis.html#basic-components 这意味着只有这些组件会出现 - React Native 中现成的。如果你想要其他组件,那么你有 2 个选择,要么创建一个“复合”组件,将你的 JS 组件写入其他 JS 组件,要么,如果你的功能需要 React Native 尚未公开的原生组件,则编写你自己的“ native”组件向您的 React Native 代码公开某些本机功能。
Expo 的工作方式是,他们包装了 React Native 和一些第三方组件,并将其构建在他们的应用程序中。您不能使用他们不支持的第 3 方本机组件的原因是,当使用该组件时,应用程序本身没有从 JS 到本机 Android/iOS 视图的转换代码。
因此,要完成您所要求的操作,您需要找到 Expo 已包含在其平台/应用程序中的“本机”绘图组件。或者您需要找到一个使用其他默认 React Native 组件(或 Expo 支持的其他组件)构建的“复合”绘图组件。
即。在 Android 上,我可能会使用 Canvas 视图构建它,但据我所知,React Native 本身并不支持该对象,所以我可能会自己编写这个,等等。
Expo 很难支持所有第 3 方“原生”组件,因为 React Native 是开源的,而且迭代速度如此之快,以至于大多数社区构建的组件并不总是最新的,或者它们可能会相互冲突。
我知道已经有一段时间了,但是这里有一篇有趣的文章:https://blog.expo.io/drawing-signatures-with-expo-25d1629ca1ac
等等,但是怎么样?
使用“expo-pixi”,您可以添加一个组件,让您选择画笔的颜色、粗细和不透明度。然后,当您的用户抬起手指时,您会收到回调。从那里,您可以截取透明视图的屏幕截图,或者获取原始点数据(如果您需要的话)。
在尝试了上述所有解决方案以及其他 GitHub 问题超过 24 小时后,我最终使用了这个解决方案:
安装这些软件包
expo install react-native-svg
npm install git+https://github.com/MarangoniEduardo/expo-draw
签名组件代码
import React, { useState, useRef } from "react";
import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
import ExpoDraw from "expo-draw";
import { captureRef as takeSnapshotAsync } from "react-native-view-shot";
const DrawSignatureScreen = (props) => {
const [strokes, setStrokes] = useState([]); // Added state for strokes
const signatureRef = useRef(null);
const clearCanvas = async () => {
signatureRef.current.clear();
setStrokes([]); // Clear strokes
};
const saveCanvas = async () => {
try {
const signature_result = await takeSnapshotAsync(signatureRef.current, {
format: "jpg", // 'png' also supported
quality: 0.5, // quality 0 for very poor 1 for very good
result: "tmpfile",
});
console.log("Signature file:", signature_result);
} catch (error) {
console.log(error);
}
};
return (
<View style={styles.container}>
<Text style={styles.formTitle}>Enter your signature here</Text>
<View style={styles.canvasContainer}>
<ExpoDraw
strokes={strokes} // Pass strokes to ExpoDraw
ref={signatureRef}
containerStyle={styles.canvas}
rewind={(undo) => console.log("Undo", undo)}
clear={(clear) => console.log("Clear", clear)}
color={"#000000"}
strokeWidth={4}
enabled={true}
onChangeStrokes={(strokes) => setStrokes(strokes)} // Update strokes
/>
<View style={styles.buttonsContainer}>
<TouchableOpacity style={styles.button} onPress={clearCanvas}>
<Text style={styles.buttonText}>Reset</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={saveCanvas}>
<Text style={styles.buttonText}>Sign</Text>
</TouchableOpacity>
</View>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
formTitle: {
fontSize: 20,
marginBottom: 20,
},
canvasContainer: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
canvas: {
backgroundColor: "rgba(0, 0, 0, 0.01)",
height: 300,
width: 500,
},
buttonsContainer: {
flexDirection: "row",
justifyContent: "space-evenly",
marginTop: 20,
},
button: {
padding: 10,
height: 50,
borderRadius: 10,
backgroundColor: "green",
alignItems: "center",
},
buttonText: {
fontSize: 18,
color: "white",
},
});
export default DrawSignatureScreen;