react-native 画笔(写字板、手写板)--1

参考链接:https://www.jianshu.com/p/504c639063b3
前提:集成好react-native-svg

以上链接博主大佬用的是ART绘画系统,受此启发我就使用SVG画图了,因为项目里面还有其他操作,例如箭头、圆圈、矩形等类似电脑截图后编辑操作,而ART用法个人不是很熟悉,所以采用SVG,SVG不是很熟悉的可以看一下我之前写的这篇https://www.jianshu.com/p/ef91237a89a4,也可以自己上菜鸟教程简单的练一下再上手,做了个小demo,效果图如下:

441637732888_.pic.jpg

把以下代码复制粘贴到一个新页面即可尝试,至于Util.size.width、Util.size.height是屏幕宽高,换一下就好了。这只是画线功能,其他功能效果(例如圆圈、矩形、箭头等功能)请看另外一篇文章: https://www.jianshu.com/p/06d3bdfae98a

import React, {Component} from 'react';
import {View, Text, StyleSheet, Image, TouchableOpacity, PanResponder, ART, ImageBackground} from 'react-native'
import Util from './common/util'
import Svg, {Path} from "react-native-svg";

class SvgDrawTest extends Component {
    constructor(props) {
        super(props);
        this.allPoint = ''
        this.state = {
            // drawPath: 'M25 10 L98 65 L70 25 L16 77 L11 30 L0 4 L90 50 L50 10 L11 22 L77 95 L20 25'
            drawPath: ''
        }
    }

    componentWillMount() {
        this._panResponderDrawLine = PanResponder.create({
            onStartShouldSetPanResponder: (evt, gestureState) => true,
            onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
            onMoveShouldSetPanResponder: (evt, gestureState) => true,
            onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

            onPanResponderGrant: (evt, gestureState) => {
                let tempfirstX = evt.nativeEvent.pageX
                let tempFirstY = evt.nativeEvent.pageY
                this.firstPoint = ' M' + tempfirstX + ' ' + tempFirstY
                this.allPoint = this.allPoint + this.firstPoint   //上一次的画的全部的点(this.allPoint),拼接上当前这次画的M点,在svg中M为线的起始点,拼接上后在 onPanResponderMove 中将当前移动的所有点再次拼接,当前和之前的拼接完之后,更新页面线条
            },

            onPanResponderMove: (evt, gestureState) => {
                let pointX = evt.nativeEvent.pageX
                let pointY = evt.nativeEvent.pageY
                // console.log(`X:${pointX}`, `Y:${pointY}`)
                let point = ' L' + pointX + ' ' + pointY
                this.allPoint += point
                console.log('point====', this.allPoint)
                let drawPath = this.allPoint
                this.setState({
                    drawPath
                })
            },

            onPanResponderTerminationRequest: (evt, gestureState) => true,
            onPanResponderRelease: (evt, gestureState) => { },

            onPanResponderTerminate: (evt, gestureState) => { },

            onShouldBlockNativeResponder: (evt, gestureState) => {
                return true;
            },
        })

    }

    clearOut(){
        this.allPoint = ''
        this.setState({
            drawPath:''
        })
    }

    render() {
        return (
            
                
                    
                        
                    
                
                this.clearOut()} style={styles.btn}>
                    清空
                
            

    );
    }
}

export default SvgDrawTest;
const styles = StyleSheet.create({
    btn:{elevation:5,backgroundColor:'#fff',paddingHorizontal:30,paddingVertical:10,borderRadius:999,justifyContent:'center',alignItems:'center'},
})

在项目里使用实例,效果图如下


192451637727165_.pic.jpg

本来在手势那里,因为画图是在图片范围内,我是尝试用locationX,locationY 而不是pageX、pageY,后来发现
locationX超过范围后那个点会返回对立的那一面,想着解决太麻烦了,所以采用pageX和pageY,如图所见,手势起始点的位置和移动的位置点减去他的边距即可。目前是画笔,后续操作实现了再更新实现代码。

import React, {Component} from 'react';
import {View, Text, Image, StyleSheet, PanResponder,TouchableOpacity} from 'react-native'
import Svg, {Path} from "react-native-svg";

let marginY = 50 + 15 + 5  //头部导航height 50  下方内容padding 15  图片与父盒子距离 5
let marginX = 15 + 5  //  下方内容padding 15  图片与父盒子距离 5

class Comp3 extends Component {
    constructor(props) {
        super(props);
        this.allPoint = ''
        this.state = {
            drawPath: ''
        }
    }

    componentWillMount() {

        this._panResponderDrawLine = PanResponder.create({
            onStartShouldSetPanResponder: (evt, gestureState) => true,
            onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
            onMoveShouldSetPanResponder: (evt, gestureState) => true,
            onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

            onPanResponderGrant: (evt, gestureState) => {
                let tempfirstX = evt.nativeEvent.pageX.toFixed(0)-marginX
                let tempFirstY = evt.nativeEvent.pageY.toFixed(0)-marginY
                this.firstPoint = ' M' + tempfirstX + ' ' + tempFirstY
                this.allPoint += this.firstPoint   //上一次的画的全部的点(this.allPoint),拼接上当前这次画的M点,在svg中M为线的起始点,拼接上后在 onPanResponderMove 中将当前移动的所有点再次拼接,当前和之前的拼接完之后,更新页面线条
            },

            onPanResponderMove: (evt, gestureState) => {
                let pointX = evt.nativeEvent.pageX.toFixed(0)-marginX
                let pointY = evt.nativeEvent.pageY.toFixed(0)-marginY
                // console.log(`X:${pointX}`, `Y:${pointY}`)
                let point = ` L${pointX} ${pointY}`
                this.allPoint += point
                let drawPath = this.allPoint
                this.setState({
                    drawPath
                })
            },

            onPanResponderTerminationRequest: (evt, gestureState) => true,
            onPanResponderRelease: (evt, gestureState) => { },
            onPanResponderTerminate: (evt, gestureState) => {},
            onShouldBlockNativeResponder: (evt, gestureState) => {
                return true;
            },
        })
    }


    render() {
        return (
            
                
                    
                    
                        
                    
                

                
                    
                        选择
                        
                            
                                
                            
                            
                                
                            
                        
                    

                    
                        线条选择
                        
                            
                                
                            
                            
                                
                            
                            
                                
                            
                            
                                
                            
                        
                    

                    
                        
                            粗细
                            色彩
                        
                        
                            
                                
                                
                                    
                                
                            

                            
                                
                                
                            
                        
                    

                    
                        操作
                        
                            
                                撤销
                            
                            {this.setState({drawPath:''});this.allPoint = ''}} style={styles.bottom_btn}>
                                清空
                            
                            
                                保存
                            
                        
                    

                
            
        );
    }
}

export default Comp3;
const styles = StyleSheet.create({
    /**内容*/
    content_left: {
        backgroundColor: '#fff',
        flex: 3,
        marginRight: 15,
        padding: 5,
    },
    content_left_camera: {
        flex: 1,
    },

    camera_bottom: {
        backgroundColor: '#fff',
        height: '25%',
        flexDirection: 'row',
        alignItems: 'center',
        justifyContent: 'center'
    },

    bottom_item: {
        paddingHorizontal: 10,
        borderRightWidth: 1,
        borderColor: '#eee',
        height: '70%',
        justifyContent: 'space-between'
    },
    bottom_icon: {
        flexDirection: 'row',
        alignItems: 'center',
        justifyContent: 'space-between',
    },
    bottom_title: {fontSize: 12, marginBottom: 10},
    bottom_btn: {
        borderWidth: 1,
        borderRadius: 999,
        width: '30%',
        borderColor: '#A5AAC1',
        justifyContent: 'center',
        alignItems: 'center',
        paddingVertical: 3
    },
    colorSelect: {
        flexDirection: 'row',
        alignItems: 'center',
        borderWidth: 1,
        borderRadius: 5,
        paddingHorizontal: 2,
        paddingVertical: 2,
        borderColor: '#eee'
    },


});

你可能感兴趣的:(react-native 画笔(写字板、手写板)--1)