UNPKG

@sourcetoad/react-native-sketch-canvas

Version:

react-native-sketch-canvas allows you to draw / sketch on both iOS and Android devices and sync the drawing data between users. Of course you can save as image.

284 lines (278 loc) 11.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _memoizeOne = _interopRequireDefault(require("memoize-one")); var _react = _interopRequireDefault(require("react")); var _reactNative = require("react-native"); var _handlePermissions = require("./handlePermissions.js"); var _types = require("./types.js"); var _SketchCanvasNativeComponent = _interopRequireWildcard(require("./specs/SketchCanvasNativeComponent.js")); var _NativeSketchCanvasModule = _interopRequireDefault(require("./specs/NativeSketchCanvasModule.js")); var _jsxRuntime = require("react/jsx-runtime"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } class SketchCanvas extends _react.default.Component { ref = /*#__PURE__*/_react.default.createRef(); static defaultProps = { style: null, strokeColor: '#000000', strokeWidth: 3, onPathsChange: () => {}, onStrokeStart: (_x, _y) => {}, onStrokeChanged: () => {}, onStrokeEnd: () => {}, onSketchSaved: () => {}, onGenerateBase64: () => {}, user: null, touchEnabled: true, text: null, localSourceImage: null, permissionDialogTitle: '', permissionDialogMessage: '' }; state = { text: null }; constructor(props) { super(props); this._pathsToProcess = []; this._paths = []; this._path = null; this._handle = null; this._screenScale = _reactNative.Platform.OS === 'ios' ? 1 : _reactNative.PixelRatio.get(); this._offset = { x: 0, y: 0 }; this._size = { width: 0, height: 0 }; this._initialized = false; this.panResponder = _reactNative.PanResponder.create({ // Ask to be the responder: onStartShouldSetPanResponder: (_evt, _gestureState) => true, onStartShouldSetPanResponderCapture: (_evt, _gestureState) => true, onMoveShouldSetPanResponder: (_evt, _gestureState) => true, onMoveShouldSetPanResponderCapture: (_evt, _gestureState) => true, onPanResponderGrant: (evt, gestureState) => { if (!this.props.touchEnabled) { return; } const e = evt.nativeEvent; this._offset = { x: e.pageX - e.locationX, y: e.pageY - e.locationY }; this._path = { id: parseInt(String(Math.random() * 100000000), 10), color: this.props.strokeColor, width: this.props.strokeWidth, data: [] }; if (this.ref.current) { _SketchCanvasNativeComponent.Commands.newPath(this.ref.current, this._path.id, (0, _reactNative.processColor)(this._path.color), this._path.width ? this._path.width * this._screenScale : 0); _SketchCanvasNativeComponent.Commands.addPoint(this.ref.current, parseFloat((Number((gestureState.x0 - this._offset.x).toFixed(2)) * this._screenScale).toString()), parseFloat((Number((gestureState.y0 - this._offset.y).toFixed(2)) * this._screenScale).toString())); } const x = parseFloat((gestureState.x0 - this._offset.x).toFixed(2)), y = parseFloat((gestureState.y0 - this._offset.y).toFixed(2)); this._path.data.push(`${x},${y}`); this.props.onStrokeStart?.(x, y); }, onPanResponderMove: (_evt, gestureState) => { if (!this.props.touchEnabled) { return; } if (this._path && this.ref.current) { _SketchCanvasNativeComponent.Commands.addPoint(this.ref.current, parseFloat((Number((gestureState.moveX - this._offset.x).toFixed(2)) * this._screenScale).toString()), parseFloat((Number((gestureState.moveY - this._offset.y).toFixed(2)) * this._screenScale).toString())); const x = parseFloat((gestureState.moveX - this._offset.x).toFixed(2)), y = parseFloat((gestureState.moveY - this._offset.y).toFixed(2)); this._path.data.push(`${x},${y}`); this.props.onStrokeChanged?.(x, y); } }, onPanResponderRelease: (_evt, _gestureState) => { this._handleStrokeEnd(); }, onPanResponderTerminate: (_evt, _gestureState) => { this._handleStrokeEnd(); }, onShouldBlockNativeResponder: (_evt, _gestureState) => { return true; } }); } _handleStrokeEnd = () => { if (!this.props.touchEnabled) { return; } if (this._path) { this.props.onStrokeEnd?.({ path: this._path, size: this._size, drawer: this.props.user }); this._paths.push({ path: this._path, size: this._size, drawer: this.props.user }); } if (this.ref.current) { _SketchCanvasNativeComponent.Commands.endPath(this.ref.current); } }; _processText(text) { text && text.forEach(t => t.fontColor = (0, _reactNative.processColor)(t.fontColor)); return text; } getProcessedText = (0, _memoizeOne.default)(text => { const textCopy = text ? text.map(t => Object.assign({}, t)) : null; return this._processText(textCopy); }); clear() { this._paths = []; this._path = null; if (this.ref.current) { _SketchCanvasNativeComponent.Commands.clear(this.ref.current); } } undo() { let lastId = -1; this._paths.forEach(d => lastId = d.drawer === this.props.user ? d.path.id : lastId); if (lastId >= 0) { this.deletePath(lastId); } return lastId; } addPath(data) { if (this._initialized) { if (this._paths.filter(p => p.path.id === data.path.id).length === 0) { this._paths.push(data); } const pathData = data.path.data.map(p => { const coor = p.split(',').map(pp => parseFloat(pp).toFixed(2)); return `${coor[0] * this._screenScale * this._size.width / data.size.width},${coor[1] * this._screenScale * this._size.height / data.size.height}`; }); if (this.ref.current) { _SketchCanvasNativeComponent.Commands.addPath(this.ref.current, data.path.id, (0, _reactNative.processColor)(data.path.color), data.path.width ? data.path.width * this._screenScale : 0, pathData); } } else { this._pathsToProcess.filter(p => p.path.id === data.path.id).length === 0 && this._pathsToProcess.push(data); } } setInitialPaths(initialPaths) { if (!this._initialized || !this.ref.current || !initialPaths || initialPaths.length === 0) { return; } // Convert paths to the format expected by native addInitialPaths command const pathsArray = initialPaths.map(data => { const pathData = data.path.data.map(p => { const coor = p.split(',').map(pp => parseFloat(pp).toFixed(2)); return `${coor[0] * this._screenScale * this._size.width / data.size.width},${coor[1] * this._screenScale * this._size.height / data.size.height}`; }); return { pathId: data.path.id, color: (0, _reactNative.processColor)(data.path.color), width: data.path.width ? data.path.width * this._screenScale : 0, points: pathData }; }); // Add valid paths to internal tracking initialPaths.forEach(data => { if (this._paths.filter(p => p.path.id === data.path.id).length === 0) { this._paths.push(data); } }); // Call native batch operation _SketchCanvasNativeComponent.Commands.addInitialPaths(this.ref.current, pathsArray); } deletePath(id) { this._paths = this._paths.filter(p => p.path.id !== id); if (this.ref.current) { _SketchCanvasNativeComponent.Commands.deletePath(this.ref.current, id); } } save(imageType, transparent, folder, filename, includeImage, includeText, cropToImageSize) { if (this.ref.current) { _SketchCanvasNativeComponent.Commands.save(this.ref.current, imageType, folder, filename, transparent, includeImage, includeText, cropToImageSize); } } getPaths() { return this._paths; } getBase64(imageType, transparent, includeImage, includeText, cropToImageSize) { if (_reactNative.Platform.OS === 'ios') { if (this.ref.current) { _SketchCanvasNativeComponent.Commands.transferToBase64(this.ref.current, imageType, transparent, includeImage, includeText, cropToImageSize); } } else { if (this.ref.current) { _SketchCanvasNativeComponent.Commands.transferToBase64(this.ref.current, imageType, transparent, includeImage, includeText, cropToImageSize); } } } async componentDidMount() { await (0, _handlePermissions.requestPermissions)(this.props.permissionDialogTitle || '', this.props.permissionDialogMessage || ''); } render() { return /*#__PURE__*/(0, _jsxRuntime.jsx)(_SketchCanvasNativeComponent.default, { ref: this.ref, style: this.props.style, onLayout: e => { this._size = { width: e.nativeEvent.layout.width, height: e.nativeEvent.layout.height }; this._initialized = true; // Handle any queued paths using individual operations this._pathsToProcess.length > 0 && this._pathsToProcess.forEach(p => this.addPath(p)); }, ...this.panResponder.panHandlers, onChange: e => { const { eventType, pathsUpdate, success, path } = e.nativeEvent || {}; const isSuccess = success !== undefined; const isSave = eventType === _types.OnChangeEventType.Save; const isPathsUpdate = eventType === _types.OnChangeEventType.PathsUpdate; if (!isSave && isPathsUpdate) { this.props.onPathsChange?.(pathsUpdate); } else if (isSave) { this.props.onSketchSaved?.(success, path); } else if (isSuccess) { this.props.onSketchSaved?.(success, ''); } }, onGenerateBase64: e => { this.props.onGenerateBase64?.(e.nativeEvent || {}); }, onCanvasReady: () => { this.props.onCanvasReady?.(); // Handle initial paths prop using batch operation if (this.props.initialPaths && this.props.initialPaths.length > 0) { this.setInitialPaths(this.props.initialPaths); } }, onInitialPathsLoaded: e => { this.props.onInitialPathsLoaded?.(e.nativeEvent || {}); }, localSourceImage: this.props.localSourceImage, permissionDialogTitle: this.props.permissionDialogTitle, permissionDialogMessage: this.props.permissionDialogMessage, text: this.getProcessedText(this.props.text) }); } } SketchCanvas.MAIN_BUNDLE = _NativeSketchCanvasModule.default.getConstants().MainBundlePath; SketchCanvas.DOCUMENT = _NativeSketchCanvasModule.default.getConstants().NSDocumentDirectory; SketchCanvas.LIBRARY = _NativeSketchCanvasModule.default.getConstants().NSLibraryDirectory; SketchCanvas.CACHES = _NativeSketchCanvasModule.default.getConstants().NSCachesDirectory; var _default = exports.default = SketchCanvas; //# sourceMappingURL=SketchCanvas.js.map