@gdn/react-native-simple-canvas
Version:
A simple canvas component for React Native that allows drawing and signature capture.
148 lines • 6.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.SimpleCanvas = exports.clearCanvas = void 0;
const react_1 = __importStar(require("react"));
const react_native_1 = require("react-native");
const react_native_svg_1 = require("react-native-svg");
const canvas_1 = require("./helpers/canvas");
const clearCanvas = (ref) => {
var _a;
(_a = ref.current) === null || _a === void 0 ? void 0 : _a.resetImage();
};
exports.clearCanvas = clearCanvas;
const SimpleCanvas = ({ onDragEvent, onCanvasChange, strokeColor = 'black', strokeWidth = 3, backgroundColor = 'transparent', style, minPoints = 2, ref, }) => {
const [paths, setPaths] = (0, react_1.useState)([]);
const pointsRef = (0, react_1.useRef)([]);
const svgRef = (0, react_1.useRef)(null);
const isDrawing = (0, react_1.useRef)(false);
const canvasRef = (0, react_1.useRef)(null);
const canvasOffset = (0, react_1.useRef)({ x: 0, y: 0 });
const addPoint = (0, react_1.useCallback)((point) => {
pointsRef.current.push(point);
return true;
}, []);
const resetImage = (0, react_1.useCallback)(() => {
setPaths([]);
pointsRef.current = [];
onCanvasChange === null || onCanvasChange === void 0 ? void 0 : onCanvasChange(true);
}, [onCanvasChange]);
const isEmpty = (0, react_1.useCallback)(() => {
return paths.length === 0;
}, [paths]);
const getPoints = (0, react_1.useCallback)(() => {
return [...pointsRef.current];
}, []);
const setPoints = (0, react_1.useCallback)((newPoints) => {
if (newPoints.length < minPoints)
return;
pointsRef.current = newPoints;
const path = (0, canvas_1.spline)(newPoints, 1, false);
setPaths([path]);
onCanvasChange === null || onCanvasChange === void 0 ? void 0 : onCanvasChange(false);
}, [minPoints, onCanvasChange]);
const onLayout = (0, react_1.useCallback)(() => {
var _a;
(_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.measureInWindow((x, y) => {
canvasOffset.current = { x, y };
});
}, []);
const panResponder = (0, react_1.useMemo)(() => react_native_1.PanResponder.create({
onStartShouldSetPanResponder: () => true,
onMoveShouldSetPanResponder: () => true,
onPanResponderGrant: (event) => {
const { pageX, pageY } = event.nativeEvent;
const point = {
x: pageX - canvasOffset.current.x,
y: pageY - canvasOffset.current.y
};
isDrawing.current = true;
pointsRef.current = [point];
setPaths(prevPaths => [...prevPaths, `M ${point.x} ${point.y}`]);
onDragEvent === null || onDragEvent === void 0 ? void 0 : onDragEvent();
},
onPanResponderMove: (event) => {
if (!isDrawing.current)
return;
const { pageX, pageY } = event.nativeEvent;
const point = {
x: pageX - canvasOffset.current.x,
y: pageY - canvasOffset.current.y
};
if (addPoint(point)) {
if (pointsRef.current.length >= minPoints) {
const path = (0, canvas_1.spline)(pointsRef.current, 1, false);
setPaths(prevPaths => {
const newPaths = [...prevPaths];
newPaths[newPaths.length - 1] = path;
return newPaths;
});
onCanvasChange === null || onCanvasChange === void 0 ? void 0 : onCanvasChange(false);
}
}
},
onPanResponderRelease: () => {
isDrawing.current = false;
},
}), [onDragEvent, addPoint, minPoints, onCanvasChange]);
(0, react_1.useImperativeHandle)(ref, () => ({
getSVG: () => svgRef,
resetImage,
isEmpty,
getPoints,
setPoints
}), [resetImage, isEmpty, getPoints, setPoints]);
const pathElements = (0, react_1.useMemo)(() => paths.map((path, index) => (<react_native_svg_1.Path key={index} d={path} stroke={strokeColor} strokeWidth={strokeWidth} fill="none" strokeLinecap="round" strokeLinejoin="round"/>)), [paths, strokeColor, strokeWidth]);
return (<react_native_1.View style={[styles.container, style]}>
<react_native_1.View ref={canvasRef} onLayout={onLayout} style={[styles.canvas, { backgroundColor }]} {...panResponder.panHandlers}>
<react_native_svg_1.Svg ref={svgRef} height="100%" width="100%">
{pathElements}
</react_native_svg_1.Svg>
</react_native_1.View>
</react_native_1.View>);
};
exports.SimpleCanvas = SimpleCanvas;
exports.SimpleCanvas.displayName = 'SimpleCanvas';
const styles = react_native_1.StyleSheet.create({
container: {
flex: 1,
},
canvas: {
flex: 1,
borderWidth: 1,
borderColor: '#ccc',
},
});
//# sourceMappingURL=SimpleCanvas.js.map