UNPKG

@kichiyaki/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.

389 lines (354 loc) 10.7 kB
import React from 'react'; import PropTypes from 'prop-types'; import { View, TouchableOpacity, FlatList, ViewPropTypes } from 'react-native'; import SketchCanvas from './src/SketchCanvas'; export default class RNSketchCanvas extends React.Component { static propTypes = { containerStyle: ViewPropTypes.style, canvasStyle: ViewPropTypes.style, onStrokeStart: PropTypes.func, onStrokeChanged: PropTypes.func, onStrokeEnd: PropTypes.func, onClosePressed: PropTypes.func, onUndoPressed: PropTypes.func, onClearPressed: PropTypes.func, onPathsChange: PropTypes.func, user: PropTypes.string, closeComponent: PropTypes.node, eraseComponent: PropTypes.node, undoComponent: PropTypes.node, clearComponent: PropTypes.node, saveComponent: PropTypes.node, strokeComponent: PropTypes.func, strokeSelectedComponent: PropTypes.func, strokeWidthComponent: PropTypes.func, strokeColors: PropTypes.arrayOf( PropTypes.shape({ color: PropTypes.string }) ), defaultStrokeIndex: PropTypes.number, defaultStrokeWidth: PropTypes.number, minStrokeWidth: PropTypes.number, maxStrokeWidth: PropTypes.number, strokeWidthStep: PropTypes.number, savePreference: PropTypes.func, onSketchSaved: PropTypes.func, text: PropTypes.arrayOf( PropTypes.shape({ text: PropTypes.string, font: PropTypes.string, fontSize: PropTypes.number, fontColor: PropTypes.string, overlay: PropTypes.oneOf(['TextOnSketch', 'SketchOnText']), anchor: PropTypes.shape({ x: PropTypes.number, y: PropTypes.number }), position: PropTypes.shape({ x: PropTypes.number, y: PropTypes.number }), coordinate: PropTypes.oneOf(['Absolute', 'Ratio']), alignment: PropTypes.oneOf(['Left', 'Center', 'Right']), lineHeightMultiple: PropTypes.number, }) ), localSourceImage: PropTypes.shape({ filename: PropTypes.string, directory: PropTypes.string, mode: PropTypes.string, }), permissionDialogTitle: PropTypes.string, permissionDialogMessage: PropTypes.string, }; static defaultProps = { containerStyle: null, canvasStyle: null, onStrokeStart: () => {}, onStrokeChanged: () => {}, onStrokeEnd: () => {}, onClosePressed: () => {}, onUndoPressed: () => {}, onClearPressed: () => {}, onPathsChange: () => {}, user: null, closeComponent: null, eraseComponent: null, undoComponent: null, clearComponent: null, saveComponent: null, strokeComponent: null, strokeSelectedComponent: null, strokeWidthComponent: null, strokeColors: [ { color: '#000000' }, { color: '#FF0000' }, { color: '#00FFFF' }, { color: '#0000FF' }, { color: '#0000A0' }, { color: '#ADD8E6' }, { color: '#800080' }, { color: '#FFFF00' }, { color: '#00FF00' }, { color: '#FF00FF' }, { color: '#FFFFFF' }, { color: '#C0C0C0' }, { color: '#808080' }, { color: '#FFA500' }, { color: '#A52A2A' }, { color: '#800000' }, { color: '#008000' }, { color: '#808000' }, ], alphlaValues: ['33', '77', 'AA', 'FF'], defaultStrokeIndex: 0, defaultStrokeWidth: 3, minStrokeWidth: 3, maxStrokeWidth: 15, strokeWidthStep: 3, savePreference: null, onSketchSaved: () => {}, text: null, localSourceImage: null, permissionDialogTitle: '', permissionDialogMessage: '', }; constructor(props) { super(props); this.state = { color: props.strokeColors[props.defaultStrokeIndex].color, strokeWidth: props.defaultStrokeWidth, alpha: 'FF', }; this._colorChanged = false; this._strokeWidthStep = props.strokeWidthStep; this._alphaStep = -1; } getBase64( imageType, transparent, includeImage, includeText, cropToImageSize, callback ) { return this._sketchCanvas.getBase64( imageType, transparent, includeImage, includeText, cropToImageSize, callback ); } clear() { this._sketchCanvas.clear(); } undo() { return this._sketchCanvas.undo(); } addPath(data) { this._sketchCanvas.addPath(data); } deletePath(id) { this._sketchCanvas.deletePath(id); } buildFileName = (date = new Date()) => { return ( date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + ('0' + date.getDate()).slice(-2) + ' ' + ('0' + date.getHours()).slice(-2) + '-' + ('0' + date.getMinutes()).slice(-2) + '-' + ('0' + date.getSeconds()).slice(-2) ); }; save() { if (this.props.savePreference) { const p = this.props.savePreference(); this._sketchCanvas.save( p.imageType, p.transparent, p.folder ?? '', p.filename ?? this.buildFileName(), p.includeImage !== false, p.includeText !== false, p.cropToImageSize || false ); } else { this._sketchCanvas.save( 'png', false, '', this.buildFileName(), true, true, false ); } } nextStrokeWidth() { if ( (this.state.strokeWidth >= this.props.maxStrokeWidth && this._strokeWidthStep > 0) || (this.state.strokeWidth <= this.props.minStrokeWidth && this._strokeWidthStep < 0) ) this._strokeWidthStep = -this._strokeWidthStep; this.setState({ strokeWidth: this.state.strokeWidth + this._strokeWidthStep, }); } _renderItem = ({ item, index }) => ( <TouchableOpacity style={{ marginHorizontal: 2.5 }} onPress={() => { if (this.state.color === item.color) { const index = this.props.alphlaValues.indexOf(this.state.alpha); if (this._alphaStep < 0) { this._alphaStep = index === 0 ? 1 : -1; this.setState({ alpha: this.props.alphlaValues[index + this._alphaStep], }); } else { this._alphaStep = index === this.props.alphlaValues.length - 1 ? -1 : 1; this.setState({ alpha: this.props.alphlaValues[index + this._alphaStep], }); } } else { this.setState({ color: item.color }); this._colorChanged = true; } }} > {this.state.color !== item.color && this.props.strokeComponent && this.props.strokeComponent(item.color)} {this.state.color === item.color && this.props.strokeSelectedComponent && this.props.strokeSelectedComponent( item.color + this.state.alpha, index, this._colorChanged )} </TouchableOpacity> ); componentDidUpdate() { this._colorChanged = false; } render() { return ( <View style={this.props.containerStyle}> <View style={{ flexDirection: 'row' }}> <View style={{ flexDirection: 'row', flex: 1, justifyContent: 'flex-start', }} > {this.props.closeComponent && ( <TouchableOpacity onPress={() => { this.props.onClosePressed(); }} > {this.props.closeComponent} </TouchableOpacity> )} {this.props.eraseComponent && ( <TouchableOpacity onPress={() => { this.setState({ color: '#00000000' }); }} > {this.props.eraseComponent} </TouchableOpacity> )} </View> <View style={{ flexDirection: 'row', flex: 1, justifyContent: 'flex-end', }} > {this.props.strokeWidthComponent && ( <TouchableOpacity onPress={() => { this.nextStrokeWidth(); }} > {this.props.strokeWidthComponent(this.state.strokeWidth)} </TouchableOpacity> )} {this.props.undoComponent && ( <TouchableOpacity onPress={() => { this.props.onUndoPressed(this.undo()); }} > {this.props.undoComponent} </TouchableOpacity> )} {this.props.clearComponent && ( <TouchableOpacity onPress={() => { this.clear(); this.props.onClearPressed(); }} > {this.props.clearComponent} </TouchableOpacity> )} {this.props.saveComponent && ( <TouchableOpacity onPress={() => { this.save(); }} > {this.props.saveComponent} </TouchableOpacity> )} </View> </View> <SketchCanvas ref={(ref) => (this._sketchCanvas = ref)} style={this.props.canvasStyle} strokeColor={ this.state.color + (this.state.color.length === 9 ? '' : this.state.alpha) } onStrokeStart={this.props.onStrokeStart} onStrokeChanged={this.props.onStrokeChanged} onStrokeEnd={this.props.onStrokeEnd} user={this.props.user} strokeWidth={this.state.strokeWidth} onSketchSaved={(success, path) => this.props.onSketchSaved(success, path) } onPathsChange={this.props.onPathsChange} text={this.props.text} localSourceImage={this.props.localSourceImage} permissionDialogTitle={this.props.permissionDialogTitle} permissionDialogMessage={this.props.permissionDialogMessage} /> <View style={{ flexDirection: 'row' }}> <FlatList data={this.props.strokeColors} extraData={this.state} keyExtractor={() => Math.ceil(Math.random() * 10000000).toString()} renderItem={this._renderItem} horizontal showsHorizontalScrollIndicator={false} /> </View> </View> ); } } RNSketchCanvas.MAIN_BUNDLE = SketchCanvas.MAIN_BUNDLE; RNSketchCanvas.DOCUMENT = SketchCanvas.DOCUMENT; RNSketchCanvas.LIBRARY = SketchCanvas.LIBRARY; RNSketchCanvas.CACHES = SketchCanvas.CACHES; export { SketchCanvas };