react-native 畫筆(寫字板、手寫板)--2

目前已完成功能包括線條標(biāo)注箭頭、圓圈、畫筆、矩形、粗細(xì)、顏色、撤銷、清空、保存。移動(dòng)圖片,標(biāo)注文字暫時(shí)未完成,還有后期的一些功能未完善,如標(biāo)注后,點(diǎn)擊改標(biāo)注可以隨意修改其大小、位置、方向等,后面有時(shí)間再研究下。

其中箭頭是最麻煩的,其他功能一旦熟悉花的時(shí)間不多,但是光是箭頭花了差不多五天的時(shí)間,因?yàn)闆]有思路,想過用svg rotate旋轉(zhuǎn),后來發(fā)現(xiàn)也是不太好實(shí)現(xiàn),除了觸摸點(diǎn),箭頭三角形其他點(diǎn)也是需要旋轉(zhuǎn)一樣的角度,這個(gè)不太好算。
后面經(jīng)過分析通過三角函數(shù)將三角形箭頭的兩側(cè)的點(diǎn)算出來,算的三角形兩個(gè)側(cè)邊點(diǎn)在屏幕的坐標(biāo),就可以做出來了。當(dāng)然,箭頭三角形是等腰三角形,要是想要搞成像微信截圖那樣的箭頭,需要自己深入計(jì)算一下,思路一樣,SVG不是很熟悉的可以看一下我之前寫的這篇http://www.itdecent.cn/p/ef91237a89a4,也可以自己上菜鳥教程簡單的練一下再上手。先上效果圖后上代碼。

111571643003776_.pic.jpg

111561643003775_.pic.jpg
111621643003922_.pic.jpg

案例:

復(fù)制以下代碼,添加安裝react-native-svg、react-native-view-shot 、替換里面的圖片,新建一個(gè)頁面就可以查看效果

import React, {Component} from 'react';
import {View, Text, Image, StyleSheet, PanResponder, TouchableOpacity, TextInput} from 'react-native'
import Svg, {Path, Rect, Circle, Ellipse, Line} from "react-native-svg";
// import Util from "../common/util";
// import MyToast from "../common/MyToast";
import ViewShot from "react-native-view-shot";

// 這兩個(gè)是為了寫字板樣式若是有什么邊距問題,有padding或margin的加上去,以屏幕手勢起始點(diǎn)開始,如果沒有邊距問題都賦值為0就好
let marginY = 50  //頭部導(dǎo)航height 50
let marginX = 0  // 圖片與父盒子距離 0

class Comp3 extends Component {
    constructor(props) {
        super(props);
        this.allPathPointsAsign = ''  //所有點(diǎn)的合并
        this.allPathPointsList = []   //所有路徑點(diǎn)數(shù)組、用來操作撤銷
        this.state = {
            /**畫筆**/
            drawPath: '',

            /**規(guī)格**/
            size_id: 0,
            color_id: 0,
            currentSize: 3,   //默認(rèn)線條粗細(xì)
            currentColor: '#FF0000', //默認(rèn)線條顏色
            line_list: [
                {size: 3, selectColor: ''},
                {size: 6, selectColor: ''},
                {size: 9, selectColor: ''},
            ],
            color_list: ['#FF0000', '#000000', '#00FF00', '#0000FF', '#FF7700', '#FF00FF', '#00FFFF', '#000000', '#FF0000', '#00FF00', '#0000FF', '#FF7700', '#FF00FF', '#00FFFF', '#FF00FF', '#00FFFF',],

            /**矩形**/
            rectWidth: 0,
            rectHeight: 0,

            /**橢圓**/
            circleWidth: 0,
            circleHeight: 0,

            /**箭頭*/
            arrowPath: '',
            arrowSPath: '',

            /**所有操作集合數(shù)組**/
            myAllList: [],

            inputStyle: {
                left: 0,
                top: 0,
            },
            inputWidth: 0,
            inputHeight: 0,

            isShowLineSize: false,
            isShowColorful: false,
            isDrawing: false,
            drawType: 4,
            angle: 0,
            image_url: this.props.image_url,
        }
    }


    UNSAFE_componentWillMount() {
        this._panResponderDrawLine = PanResponder.create({
            // 要求成為響應(yīng)者:
            onStartShouldSetPanResponder: (evt, gestureState) => true,
            onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
            onMoveShouldSetPanResponder: (evt, gestureState) => false,
            onMoveShouldSetPanResponderCapture: (evt, gestureState) => false,

            onPanResponderGrant: (evt, gestureState) => {
                this.isMove = false
                this._onPanResponderGrant(evt, gestureState)
            },

            onPanResponderMove: (evt, gestureState) => {
                console.log('畫畫奪權(quán)')
                this.isMove = true
                this._onPanResponderMove(evt, gestureState)
            },

            onPanResponderTerminationRequest: (evt, gestureState) => true,
            onPanResponderRelease: (evt, gestureState) => {
                if (this.isMove) {   //判斷是否是移動(dòng)后,因?yàn)橛行┲皇屈c(diǎn)一下,但是并沒有畫線也push到了數(shù)組
                    this._onPanResponderRelease(evt, gestureState)
                }

            },

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

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

        this._panResponderChange = PanResponder.create({
            // 要求成為響應(yīng)者:
            onStartShouldSetPanResponder: (evt, gestureState) => true,
            onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
            onMoveShouldSetPanResponder: (evt, gestureState) => true,
            onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

            onPanResponderGrant: (evt, gestureState) => {
                //在這里點(diǎn)的時(shí)候激活一個(gè)矩形邊框,類似微信截圖的(當(dāng)然這個(gè)邊框是需要自己算的它的長寬高和距離頂部、左邊位置)
                console.log('點(diǎn)擊==激活===========', evt, gestureState)
            },

            onPanResponderMove: (evt, gestureState) => {
                //上方激活后,可以在這里變形這個(gè)圖形rotate、scale、translate、變形完了添加到數(shù)組里面的屬性遍歷出來即可
                console.log('移動(dòng)奪權(quán)移動(dòng)變形的在這里添加,如rotate、scale、translate等加到數(shù)組屬性里')

            },

            onPanResponderTerminationRequest: (evt, gestureState) => true,
            onPanResponderRelease: (evt, gestureState) => {
                console.log('放手======onPanResponderRelease==========', this.pathRef)
            },

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

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

    _onPanResponderGrant(evt, gestureState) {
        let drawType = this.state.drawType
        this.setState({
            isDrawing: true
        })

        /**畫線**/
        if (drawType === 4) {
            console.log('手指開始接觸====', evt.nativeEvent)
            let tempfirstX = evt.nativeEvent.pageX - marginX
            let tempFirstY = evt.nativeEvent.pageY - marginY
            this.firstPoint = ` M${tempfirstX} ${tempFirstY}`
            this.allPathPointsAsign = this.firstPoint
        }

        /**矩形**/
        if (drawType === 5) {
            console.log('矩形開始接觸====', evt.nativeEvent)
            this.rectFirstPageX = evt.nativeEvent.pageX - marginX    //減去marginX,marginY 是為了手勢起始點(diǎn)要以圖片左上角開始
            this.rectFirstPageY = evt.nativeEvent.pageY - marginY
            this.setState({
                rectFirstPageX: this.rectFirstPageX,
                rectFirstPageY: this.rectFirstPageY,
                rectWidth: 0,   //把上一次的矩形寬高清零
                rectHeight: 0,
            })
        }

        /**橢圓**/
        if (drawType === 3) {
            console.log('橢圓開始接觸====', evt.nativeEvent)
            this.circleFirstPageX = evt.nativeEvent.pageX - marginX    //減去marginX,marginY 是為了手勢起始點(diǎn)要以圖片左上角開始
            this.circleFirstPageY = evt.nativeEvent.pageY - marginY
            this.setState({
                circleFirstPageX: this.circleFirstPageX,
                circleFirstPageY: this.circleFirstPageY,
                circleWidth: 0,   //把上一次的矩形寬高清零
                circleHeight: 0,
            })
        }

        /**箭頭**/
        if (drawType === 2) {
            // console.log('箭頭開始接觸====', evt.nativeEvent)
            this.arrowFirstPageX = evt.nativeEvent.pageX - marginX    //減去marginX,marginY 是為了手勢起始點(diǎn)要以圖片左上角開始
            this.arrowFirstPageY = evt.nativeEvent.pageY - marginY

            let str = ` M${this.arrowFirstPageX} ${this.arrowFirstPageY}`
            console.log('str====', str)
            this.firstArrowPoint = str
            this.setState({
                arrowPath: '',
                arrowSPath: '',
            })
        }

        /**輸入文本**/
        if (drawType === 1) {
            this.touchPageX = evt.nativeEvent.pageX - marginX    //減去marginX,marginY 是為了手勢起始點(diǎn)要以圖片左上角開始
            this.touchPageY = evt.nativeEvent.pageY - marginY
            // return
            // console.log('this.touchPageX',this.touchPageX,'this.touchPageY',this.touchPageY)
        }
    }

    _onPanResponderMove(evt, gestureState) {
        let drawType = this.state.drawType

        /**畫線**/
        if (drawType === 4) {
            let pointX = evt.nativeEvent.pageX - marginX
            let pointY = evt.nativeEvent.pageY - marginY
            let point = ` L${pointX} ${pointY}`
            this.allPathPointsAsign += point
            // console.log('point====', this.allPathPointsAsign)
            let drawPath = this.allPathPointsAsign   //一次性畫了之后存到一個(gè)數(shù)組,目的是為了后面的撤銷操作

            let tempId = this.state.size_id            //在移動(dòng)的時(shí)候才給他賦值顏色/線條。而不是在選擇顏色的時(shí)候就直接賦值改變線條的顏色,
            let tempColorId = this.state.color_id          //若是在選擇顏色/線條的時(shí)候直接賦值,會(huì)改變前一次畫好的線的顏色/線條,不可取
            let currentSize = this.state.line_list[tempId].size  //使用臨時(shí)粗細(xì)是為了在切換線條大小的時(shí)候,前一次畫好的線條粗細(xì)不會(huì)發(fā)生變化
            let currentColor = this.state.color_list[tempColorId]  //使用臨時(shí)顏色是為了在切換線條大小的時(shí)候,前一次畫好的線條顏色不會(huì)發(fā)生變化

            this.setState({
                currentSize,   //當(dāng)前線的粗細(xì)
                currentColor,   //當(dāng)前線的顏色
                drawPath,
            })
        }

        /**矩形**/
        if (drawType === 5) {
            // console.log('矩形move====', evt.nativeEvent.pageX,'===',evt.nativeEvent.pageY)
            let pointX = evt.nativeEvent.pageX - marginX
            let pointY = evt.nativeEvent.pageY - marginY
            let rectWidth = pointX - this.rectFirstPageX
            let rectHeight = pointY - this.rectFirstPageY
            console.log('矩形寬高===', rectWidth, rectHeight)

            let tempId = this.state.size_id            //在移動(dòng)的時(shí)候才給他賦值顏色/線條。而不是在選擇顏色的時(shí)候就直接賦值改變線條的顏色,
            let tempColorId = this.state.color_id          //若是在選擇顏色/線條的時(shí)候直接賦值,會(huì)改變前一次畫好的線的顏色/線條,不可取
            let currentSize = this.state.line_list[tempId].size  //使用臨時(shí)粗細(xì)是為了在切換線條大小的時(shí)候,前一次畫好的線條粗細(xì)不會(huì)發(fā)生變化
            let currentColor = this.state.color_list[tempColorId]  //使用臨時(shí)顏色是為了在切換線條大小的時(shí)候,前一次畫好的線條顏色不會(huì)發(fā)生變化

            // 這部分代碼在以創(chuàng)建矩形時(shí)初始坐標(biāo)為原點(diǎn)(0,0),在向右或者向上框選的時(shí)候,是負(fù)值的,此時(shí)矩形時(shí)寬或者高是負(fù)數(shù)的,不會(huì)顯示
            // 所以在將寬高轉(zhuǎn)為整數(shù)的時(shí)候,這時(shí)候?qū)捀叩慕^對值作為初始值坐標(biāo)的增減,這樣才能實(shí)現(xiàn)寬高的增減

            let newPageX = this.rectFirstPageX + rectWidth
            let newPageY = this.rectFirstPageY + rectHeight
            if (rectHeight < 0) {
                rectHeight = Math.abs(rectHeight)   //高為絕對值
                this.setState({
                    rectFirstPageY: newPageY    //重新定位原點(diǎn)Y坐標(biāo)
                })
            }
            if (rectWidth < 0) {
                rectWidth = Math.abs(rectWidth)  //寬為絕對值
                this.setState({
                    rectFirstPageX: newPageX,  //重新定位原點(diǎn)X坐標(biāo)
                })
            }
            this.setState({
                rectWidth,
                rectHeight,
                currentSize,   //當(dāng)前線的粗細(xì)
                currentColor,   //當(dāng)前線的顏色
            })
        }

        /**橢圓**/
        if (drawType === 3) {
            console.log('橢圓正在畫====', evt.nativeEvent)
            let pointX = evt.nativeEvent.pageX - marginX
            let pointY = evt.nativeEvent.pageY - marginY
            let circleWidth = pointX - this.circleFirstPageX
            let circleHeight = pointY - this.circleFirstPageY
            console.log('矩形寬高===', circleWidth, circleHeight)

            let tempId = this.state.size_id            //在移動(dòng)的時(shí)候才給他賦值顏色/線條。而不是在選擇顏色的時(shí)候就直接賦值改變線條的顏色,
            let tempColorId = this.state.color_id          //若是在選擇顏色/線條的時(shí)候直接賦值,會(huì)改變前一次畫好的線的顏色/線條,不可取
            let currentSize = this.state.line_list[tempId].size  //使用臨時(shí)粗細(xì)是為了在切換線條大小的時(shí)候,前一次畫好的線條粗細(xì)不會(huì)發(fā)生變化
            let currentColor = this.state.color_list[tempColorId]  //使用臨時(shí)顏色是為了在切換線條大小的時(shí)候,前一次畫好的線條顏色不會(huì)發(fā)生變化

            // 這部分代碼在以創(chuàng)建矩形時(shí)初始坐標(biāo)為原點(diǎn)(0,0),在向右或者向上框選的時(shí)候,是負(fù)值的,此時(shí)矩形時(shí)寬或者高是負(fù)數(shù)的,不會(huì)顯示
            // 所以在將寬高轉(zhuǎn)為整數(shù)的時(shí)候,這時(shí)候?qū)捀叩慕^對值作為初始值坐標(biāo)的增減,這樣才能實(shí)現(xiàn)寬高的增減

            let newPageX = this.circleFirstPageX + circleWidth
            let newPageY = this.circleFirstPageY + circleHeight
            if (circleHeight < 0) {
                circleHeight = Math.abs(circleHeight)   //高為絕對值
                this.setState({
                    circleFirstPageY: newPageY    //重新定位原點(diǎn)Y坐標(biāo)
                })
            }
            if (circleWidth < 0) {
                circleWidth = Math.abs(circleWidth)  //寬為絕對值
                this.setState({
                    circleFirstPageX: newPageX,  //重新定位原點(diǎn)X坐標(biāo)
                })
            }
            this.setState({
                circleWidth,
                circleHeight,
                currentSize,   //當(dāng)前線的粗細(xì)
                currentColor,   //當(dāng)前線的顏色
            })
        }

        /**箭頭**/
        if (drawType === 2) {
            let pointX = evt.nativeEvent.pageX - marginX
            let pointY = evt.nativeEvent.pageY - marginY
            let y = 0, x = 0
            if (pointY > this.arrowFirstPageY) {
                y = -(pointY - this.arrowFirstPageY)    //如果超過原始點(diǎn)就為 -y  即在y的負(fù)半軸
            }
            if (pointY < this.arrowFirstPageY) {
                y = this.arrowFirstPageY - pointY    //如果小于原始點(diǎn)就為 y  即在y的正半軸
            }
            if (pointX > this.arrowFirstPageX) {
                x = pointX - this.arrowFirstPageX    //如果超過原始點(diǎn)就為 x  即在x的正半軸
            }
            if (pointX < this.arrowFirstPageX) {
                x = -(this.arrowFirstPageX - pointX)    //如果小于原始點(diǎn)就為 -x  即在x的負(fù)半軸
            }
            let k = y / x    //直線(箭頭)的斜率
            if (!k) {
                return
            }
            let c1 = Math.sqrt(Math.pow(Math.abs(x), 2) + Math.pow(Math.abs(y), 2))   //這是整個(gè)直線(箭頭)的長度
            let radian = Math.atan(Math.abs(k))   //主線條與X軸的弧度值
            let angle = radian * (180 / Math.PI)   //主線條與X軸的夾角    角度 = 弧度值 * (180/π)

            let {a, b} = this.autoSize(c1)   //三角形自動(dòng)大小
            // console.log('a====>>>',a,'b====>>>',b,)
            let c = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2))  //根據(jù)勾股定理計(jì)算斜邊,即三角形側(cè)邊長
            let a1, b1    //三角形側(cè)邊點(diǎn)與觸摸點(diǎn)的寬或高
            let newAngle = 45 - angle   //根據(jù)相似三角形求得夾角
            a1 = Math.sin(Math.PI / (180 / newAngle)) * c   //順時(shí)針方向三角形第一個(gè)側(cè)邊點(diǎn)與觸摸點(diǎn)的距離寬,用來計(jì)算第一個(gè)側(cè)邊點(diǎn)x坐標(biāo)
            b1 = Math.cos(Math.PI / (180 / newAngle)) * c   //順時(shí)針方向三角形第一個(gè)側(cè)邊點(diǎn)與觸摸點(diǎn)的距離高,用來計(jì)算第一個(gè)側(cè)邊點(diǎn)y坐標(biāo)

            // console.log('x、y===>>>', x, y)
            // console.log('k===>>>', k)
            // console.log('angle===>>>', angle)   //線與x軸的夾角
            let {twoPoints, tangle} = this.drawArrowPath(pointX, pointY, a1, b1, k, angle)
            let finalPath = twoPoints + tangle

            console.log('finalPath===>>>>', finalPath)
            console.log('tangle===>>>>', tangle)

            this.arrowPath = finalPath
            this.arrowSPath = tangle
            let tempId = this.state.size_id            //在移動(dòng)的時(shí)候才給他賦值顏色/線條。而不是在選擇顏色的時(shí)候就直接賦值改變線條的顏色,
            let tempColorId = this.state.color_id          //若是在選擇顏色/線條的時(shí)候直接賦值,會(huì)改變前一次畫好的線的顏色/線條,不可取
            let currentSize = this.state.line_list[tempId].size  //使用臨時(shí)粗細(xì)是為了在切換線條大小的時(shí)候,前一次畫好的線條粗細(xì)不會(huì)發(fā)生變化
            let currentColor = this.state.color_list[tempColorId]  //使用臨時(shí)顏色是為了在切換線條大小的時(shí)候,前一次畫好的線條顏色不會(huì)發(fā)生變化
            this.setState({
                currentSize,   //當(dāng)前線的粗細(xì)
                currentColor,   //當(dāng)前線的顏色
                arrowPath: finalPath,
                arrowSPath: tangle
            })
        }
    }

    autoSize(c1) {
        let a = 25, b = 12.5   //三角形三邊
        let size_id = this.state.size_id
        console.log('size_id====', size_id)
        if (c1 < 80 || size_id === 0) {
            a = 10;
            b = 10;
        } else if (c1 < 120 || size_id === 1) {
            a = 15;
            b = 15;
        } else if (c1 < 150 || size_id === 1) {
            a = 25;
            b = 12.5;
        }
        return {a, b}
    }

    drawArrowPath(pointX, pointY, a1, b1, k, angle) {
        let tangle   //定義三角形
        let firstM1  // 主體斜寬線與三角形連接點(diǎn)1
        let firstM2  // 主體斜寬線與三角形連接點(diǎn)2
        if (pointY < this.arrowFirstPageY && pointX > this.arrowFirstPageX) {   //第一象限
            tangle = ` M${pointX} ${pointY} L${pointX - a1} ${pointY + b1} L${pointX - b1} ${pointY - a1}`
            firstM1 = ` L${pointX - (a1 / 2)} ${pointY + (b1 / 2)}`
            firstM2 = ` L${pointX - (b1 / 2)} ${pointY - (a1 / 2)}`
        }
        if (pointY < this.arrowFirstPageY && pointX < this.arrowFirstPageX) {   //第二象限
            tangle = ` M${pointX} ${pointY} L${pointX + b1} ${pointY - a1} L${pointX + a1} ${pointY + b1}`
            firstM1 = ` L${pointX + (b1 / 2)} ${pointY - (a1 / 2)}`
            firstM2 = ` L${pointX + (a1 / 2)} ${pointY + (b1 / 2)}`
        }
        if (pointY > this.arrowFirstPageY && pointX < this.arrowFirstPageX) {   //第三象限
            tangle = ` M${pointX} ${pointY} L${pointX + a1} ${pointY - b1} L${pointX + b1} ${pointY + a1}`
            firstM1 = ` L${pointX + (a1 / 2)} ${pointY - (b1 / 2)}`
            firstM2 = ` L${pointX + (b1 / 2)} ${pointY + (a1 / 2)}`
        }
        if (pointY > this.arrowFirstPageY && pointX > this.arrowFirstPageX) {   //第四象限
            tangle = ` M${pointX} ${pointY} L${pointX - b1} ${pointY + a1} L${pointX - a1} ${pointY - b1}`
            firstM1 = `L${pointX - (b1 / 2)} ${pointY + (a1 / 2)}`
            firstM2 = `L${pointX - (a1 / 2)} ${pointY - (b1 / 2)}`
        }

        // firstM1 + `M${pointX - b1} ${pointY + a1} L${pointX} ${pointY}` +  firstM2
        if (k === 0 && pointX < this.arrowFirstPageX) {   //在 X 負(fù)半軸 上時(shí),即k=0
            tangle = ` M${pointX} ${pointY} L${pointX + a1} ${pointY - b1} L${pointX + a1} ${pointY + b1}`
            firstM1 = `L${pointX + (a1 / 2)} ${pointY - (b1 / 2)}`
            firstM2 = `L${pointX + (a1 / 2)} ${pointY + (b1 / 2)}`
        }
        if (k === 0 && pointX > this.arrowFirstPageX) {  //在 X 正半軸 上時(shí),即k=0
            tangle = ` M${pointX} ${pointY} L${pointX - a1} ${pointY + b1} L${pointX - a1} ${pointY - b1}`
            firstM1 = `L${pointX - (a1 / 2)} ${pointY + (b1 / 2)}`
            firstM2 = `L${pointX - (a1 / 2)} ${pointY - (b1 / 2)}`
        }
        if (angle === 90 && pointY > this.arrowFirstPageY) {  //在 Y 負(fù)半軸 上時(shí)
            tangle = ` M${pointX} ${pointY} L${pointX - a1} ${pointY - b1} L${pointX + a1} ${pointY - b1}`
            firstM1 = `L${pointX - (a1 / 2)} ${pointY - (b1 / 2)}`
            firstM2 = `L${pointX + (a1 / 2)} ${pointY - (b1 / 2)}`
        }
        if (angle === 90 && pointY < this.arrowFirstPageY) {  //在 Y 正半軸 上時(shí)
            tangle = ` M${pointX} ${pointY} L${pointX + a1} ${pointY + b1} L${pointX - a1} ${pointY + b1}`
            firstM1 = `L${pointX + (a1 / 2)} ${pointY + (b1 / 2)}`
            firstM2 = `L${pointX - (a1 / 2)} ${pointY + (b1 / 2)}`
        }
        // console.log('firstM1===', firstM1, 'firstM2===', firstM2,)

        let twoPoints = this.firstArrowPoint + firstM1 + firstM2   //兩點(diǎn)一直線
        return {twoPoints, tangle}
    }

    _onPanResponderRelease(evt, gestureState) {
        let drawType = this.state.drawType
        this.setState({
            isDrawing: false
        })
        /**畫線**/
        if (drawType === 4) {
            let obj = {
                size_id: this.state.size_id,
                color_id: this.state.color_id,
                path: this.allPathPointsAsign,
                pathType: 'line'
            }
            this.allPathPointsList.push(obj)      //將所有畫過的線以及他的粗細(xì)、顏色等保存起來
            console.log('this.allPathPointsList====', this.allPathPointsList)
            this.setState({
                myAllList: this.allPathPointsList
            })
        }

        /**矩形**/
        if (drawType === 5) {
            console.log('矩形放開手指====', evt.nativeEvent)
            let obj = {
                size_id: this.state.size_id,
                color_id: this.state.color_id,
                pageX: this.state.rectFirstPageX,
                pageY: this.state.rectFirstPageY,
                rectHeight: this.state.rectHeight,
                rectWidth: this.state.rectWidth,
                pathType: 'rect'
            }
            this.allPathPointsList.push(obj)      //將所有畫過的矩形以及他的粗細(xì)、顏色等保存起來
            console.log('this.allPathPointsList====', this.allPathPointsList)
            this.setState({
                myAllList: this.allPathPointsList
            })
        }

        /**橢圓**/
        if (drawType === 3) {
            console.log('橢圓完成====', evt.nativeEvent)
            let obj = {
                size_id: this.state.size_id,
                color_id: this.state.color_id,
                pageX: this.state.circleFirstPageX,
                pageY: this.state.circleFirstPageY,
                circleHeight: this.state.circleHeight,
                circleWidth: this.state.circleWidth,
                pathType: 'circle'
            }
            this.allPathPointsList.push(obj)      //將所有畫過的矩形以及他的粗細(xì)、顏色等保存起來
            console.log('this.allPathPointsList====', this.allPathPointsList)
            this.setState({
                myAllList: this.allPathPointsList
            })
        }

        /**箭頭**/
        if (drawType === 2) {
            console.log('箭頭完成====', evt.nativeEvent)
            let obj = {
                size_id: this.state.size_id,
                color_id: this.state.color_id,
                arrowPath: this.arrowPath,
                arrowSPath: this.arrowSPath,
                pathType: 'arrow'
            }
            this.allPathPointsList.push(obj)
            this.setState({
                myAllList: this.allPathPointsList
            })
            console.log('myAllList====', this.state.myAllList)
        }

        /**輸入文本**/
        if (drawType === 1) {
            // console.log('箭頭開始接觸====', evt.nativeEvent)
            this.touchPageX = evt.nativeEvent.pageX - marginX    //減去marginX,marginY 是為了手勢起始點(diǎn)要以圖片左上角開始
            this.touchPageY = evt.nativeEvent.pageY - marginY
            console.log('this.touchPageX', this.touchPageX, 'this.touchPageY', this.touchPageY)
            // if(){
            //
            // }
            let inputStyle = {
                left: this.touchPageX,
                top: this.touchPageY - this.state.inputHeight / 2,
            }
            this.setState({
                inputStyle
            })
        }

    }

    //撤銷
    revoke() {
        this.allPathPointsList.pop(1)
        this.setState({
            drawPath: '',  //這是清除已經(jīng)剛剛畫好的
            myAllList: this.allPathPointsList,
            rectWidth: 0,
            rectHeight: 0,
            circleWidth: 0,
            circleHeight: 0,
        })
    }

    //清空
    clearOut() {
        this.allPathPointsList = []
        this.setState({
            drawPath: '',  //這是清除已經(jīng)剛剛畫好的
            myAllList: [],
            rectWidth: 0,
            rectHeight: 0,
            circleWidth: 0,
            circleHeight: 0,
        })
    }

    //保存畫板內(nèi)容
    savePhoto() {
        this.refs.viewShot.capture().then(uri => {
            console.log("do something with ", uri);
            // Util.saveLocalImage(uri,(res)=>{
            //     console.log('保存成功====1111',res)
            //     MyToast.show('圖片保存成功');
            // },(err)=>{
            //     MyToast.show('圖片保存失敗')
            //     console.log('保存失敗====',err)
            // })
        });
    }

    //選擇線的粗細(xì)
    onSelectLineSize(item, id) {
        console.log('選擇線條粗細(xì)===', item)
        this.setState({
            isShowLineSize: false,
            size_id: id
        })
    }

    //選擇顏色id
    onSelectColor(item, id) {
        this.setState({
            isShowColorful: false,
            color_id: id
        })
    }

    //選擇繪畫類型(操作類型):  0:拖動(dòng)、1:添加字符、2-5:線條類型、6:粗細(xì)、7:色彩
    onSelectDrawType(type) {
        switch (type) {
            case 6 :
                this.setState({isShowLineSize: true});
                break;
            case 7 :
                this.setState({isShowColorful: true});
                break;
            default:
                this.setState({drawType: type});
        }
    }

    _onLayout(e) {
        console.log('_onLayout1===', e.nativeEvent)
        this.setState({
            inputWidth: e.nativeEvent.layout.width,
            inputHeight: e.nativeEvent.layout.height,
        })
    }

    render() {
        let {line_list, isShowColorful, color_list, drawType, isDrawing, image_url} = this.state
        return (
            <View style={styles.container}>
                <View style={{flex: 1, backgroundColor: '#fff'}}>

                    <ViewShot ref="viewShot" options={{format: "jpg", quality: 1.0}} style={{flex: 1}}>
                        <View style={{flex: 1,}} {...this._panResponderDrawLine.panHandlers} >


                            <Image
                                source={require('../../images/default.jpg')}
                                // source={{uri:image_url}}
                                style={{height: '100%', width: '100%', position: 'absolute'}}
                            />
                            <Svg height="100%" width="100%">
                                {
                                    //這是已經(jīng)存儲(chǔ)過的線
                                    this.state.myAllList.map((item, id) => {
                                        return (
                                            item.pathType === 'line' ?
                                                <Path
                                                    ref={ref => this.pathRef = ref}
                                                    key={id}
                                                    d={item.path}
                                                    fill="none"
                                                    strokeLinecap="round"
                                                    stroke={color_list[item.color_id]}
                                                    strokeWidth={line_list[item.size_id].size}
                                                    {...this._panResponderChange.panHandlers}
                                                /> :
                                                item.pathType === 'rect' ?
                                                    <Rect
                                                        key={id}
                                                        x={item.pageX}
                                                        y={item.pageY}
                                                        rx="2"
                                                        ry="2"
                                                        width={item.rectWidth}
                                                        height={item.rectHeight}
                                                        fill="none"
                                                        strokeWidth={line_list[item.size_id].size}
                                                        stroke={color_list[item.color_id]}
                                                    /> :
                                                    item.pathType === 'circle' ?
                                                        <Ellipse
                                                            key={id}
                                                            cx={item.pageX}
                                                            cy={item.pageY}
                                                            rx={item.circleWidth}
                                                            ry={item.circleHeight}
                                                            stroke={color_list[item.color_id]}
                                                            strokeWidth={line_list[item.size_id].size}
                                                            fill="none"
                                                        /> :
                                                        <View key={id}>
                                                            <Path
                                                                d={item.arrowPath}
                                                                fill={color_list[item.color_id]}
                                                                stroke={color_list[item.color_id]}
                                                                strokeWidth={1}
                                                            />
                                                            <Path
                                                                key={id}
                                                                d={item.arrowSPath}
                                                                fill={color_list[item.color_id]}
                                                                stroke={color_list[item.color_id]}
                                                                strokeWidth={1}
                                                            />
                                                        </View>

                                        )
                                    })
                                }
                                {/**這是正在畫著的線**/}
                                {
                                    drawType === 4 && isDrawing ?
                                        <Path
                                            d={this.state.drawPath}
                                            fill="none"
                                            strokeLinecap="round"
                                            stroke={this.state.currentColor}
                                            strokeWidth={this.state.currentSize}
                                        /> : null
                                }

                                {/**畫筆?? 結(jié)束**/}
                                {/***這是正在畫的矩形***/}
                                {
                                    drawType === 5 && isDrawing ?
                                        <Rect
                                            x={this.state.rectFirstPageX}
                                            y={this.state.rectFirstPageY}
                                            rx="2"
                                            ry="2"
                                            width={this.state.rectWidth}
                                            height={this.state.rectHeight}
                                            fill="none"
                                            strokeWidth={this.state.currentSize}
                                            stroke={this.state.currentColor}
                                        /> : null
                                }
                                {/***這是正在畫的橢圓***/}
                                {
                                    drawType === 3 && isDrawing ?
                                        <Ellipse
                                            cx={this.state.circleFirstPageX}
                                            cy={this.state.circleFirstPageY}
                                            rx={this.state.circleWidth}
                                            ry={this.state.circleHeight}
                                            stroke={this.state.currentColor}
                                            strokeWidth={this.state.currentSize}
                                            fill="none"
                                        /> : null
                                }
                                {/***這是箭頭***/}
                                {
                                    drawType === 2 && isDrawing ?
                                        <>
                                            <Path
                                                d={this.state.arrowPath}
                                                fill={this.state.currentColor}
                                                stroke={this.state.currentColor}
                                                strokeWidth={1}
                                            />
                                            <Path
                                                d={this.state.arrowSPath}
                                                fill={this.state.currentColor}
                                                stroke={this.state.currentColor}
                                                strokeWidth={1}
                                            />
                                        </> : null
                                }
                            </Svg>
                        </View>
                    </ViewShot>
                    {
                        // <View
                        //     onLayout={this._onLayout.bind(this)}
                        //     style={[inputStyle,{backgroundColor: 'transparent', position: 'absolute', flex: 1,}]}>
                        //     <TextInput
                        //         placeholder={'請輸入'}
                        //         placeholderTextColor='red'
                        //         multiline={false}
                        //         maxLength={11}
                        //         value={this.state.phone_mob}
                        //         autoFocus={true}
                        //         style={{fontSize: 13, width: '100%',color:'red'}}
                        //         onChangeText={(text) => this.setState({phone_mob: text})}
                        //         underlineColorAndroid={'transparent'}
                        //     />
                        // </View>
                    }
                    {isShowColorful ? this.renderColorful() : null}
                    {this.renderBottom()}
                </View>
            </View>
        );
    }


    renderBottom() {
        let {size_id, line_list, isShowLineSize, color_list, drawType} = this.state
        return (
            <View style={styles.camera_bottom}>
                <View style={[styles.bottom_item, {flex: 1}]}>
                    <Text style={styles.bottom_title}>選擇</Text>
                    <View style={styles.bottom_icon}>
                        <View>
                            <Image source={require('../../images/opera/icon1.png')}
                                   style={{width: 15, height: 15}}/>
                        </View>
                        <TouchableOpacity onPress={() => this.onSelectDrawType(1)}>
                            <Image source={require('../../images/opera/icon2.png')}
                                   style={{width: 15, height: 15}}/>
                        </TouchableOpacity>
                    </View>
                </View>

                <View style={[styles.bottom_item, {flex: 2}]}>
                    <Text style={styles.bottom_title}>線條選擇</Text>
                    <View style={styles.bottom_icon}>
                        <TouchableOpacity onPress={() => this.onSelectDrawType(2)}>
                            <Image
                                source={drawType === 2 ? require('../../images/opera/icon3_active.png') : require('../../images/opera/icon3.png')}
                                style={{width: 15, height: 15}}/>
                        </TouchableOpacity>
                        <TouchableOpacity onPress={() => this.onSelectDrawType(3)}>
                            <Image
                                source={drawType === 3 ? require('../../images/opera/icon4_active.png') : require('../../images/opera/icon4.png')}
                                style={{width: 15, height: 15}}/>
                        </TouchableOpacity>
                        <TouchableOpacity onPress={() => this.onSelectDrawType(4)}>
                            <Image
                                source={drawType === 4 ? require('../../images/opera/icon5_active.png') : require('../../images/opera/icon5.png')}
                                style={{width: 15, height: 15}}/>
                        </TouchableOpacity>
                        <TouchableOpacity onPress={() => this.onSelectDrawType(5)}>
                            <Image
                                source={drawType === 5 ? require('../../images/opera/icon6_active.png') : require('../../images/opera/icon6.png')}
                                style={{width: 15, height: 15}}/>
                        </TouchableOpacity>
                    </View>
                </View>

                <View style={[styles.bottom_item, {flex: 2}]}>
                    <View style={styles.bottom_icon}>
                        <Text style={styles.bottom_title}>粗細(xì)</Text>
                        <Text style={styles.bottom_title}>顏色</Text>
                    </View>
                    <View style={styles.bottom_icon}>
                        <TouchableOpacity onPress={() => this.onSelectDrawType(6)}
                                          style={{flexDirection: 'row', alignItems: 'center'}}>
                            <View style={{
                                height: line_list[size_id].size,
                                width: 60,
                                backgroundColor: '#333'
                            }}/>
                            <View>
                                <Image source={require('../../images/opera/triangle.png')}
                                       style={{width: 15, height: 15}}/>
                            </View>
                        </TouchableOpacity>

                        <TouchableOpacity style={styles.colorSelect} onPress={() => this.onSelectDrawType(7)}>
                            <View style={{
                                width: 16,
                                height: 16,
                                backgroundColor: color_list[this.state.color_id],
                                borderRadius: 2
                            }}/>
                            <Image source={require('../../images/opera/triangle.png')}
                                   style={{width: 15, height: 15}}/>
                        </TouchableOpacity>
                    </View>
                    {isShowLineSize ? this.renderLineSize() : null}
                </View>

                <View style={[styles.bottom_item, {flex: 2, borderRightWidth: 0}]}>
                    <Text style={styles.bottom_title}>操作</Text>
                    <View style={styles.bottom_icon}>
                        <TouchableOpacity onPress={() => this.revoke()} style={styles.bottom_btn}>
                            <Text style={{fontSize: 12}}>撤銷</Text>
                        </TouchableOpacity>
                        <TouchableOpacity onPress={() => this.clearOut()} style={styles.bottom_btn}>
                            <Text style={{fontSize: 12}}>清空</Text>
                        </TouchableOpacity>
                        <TouchableOpacity onPress={() => this.savePhoto()}
                                          style={[styles.bottom_btn, {backgroundColor: '#203990'}]}>
                            <Text style={{fontSize: 12, color: '#fff'}}>保存</Text>
                        </TouchableOpacity>
                    </View>
                </View>
            </View>
        )
    }

    //線條
    renderLineSize() {
        let {line_list} = this.state
        return (
            <View style={styles.lineSelect}>
                {
                    line_list.map((item, id) => {
                        return (
                            <TouchableOpacity onPress={() => this.onSelectLineSize(item, id)}
                                              key={id} style={{flex: 1, justifyContent: 'center'}}>
                                <View style={{
                                    height: item.size,
                                    width: 60,
                                    backgroundColor: '#333'
                                }}/>
                            </TouchableOpacity>
                        )
                    })
                }
            </View>
        )
    }

    //顏色
    renderColorful() {
        let {color_list} = this.state
        return (
            <View style={styles.kindsOfColors}>
                {
                    color_list.map((item, id) => {
                        return (
                            <TouchableOpacity onPress={() => this.onSelectColor(item, id)}
                                              key={id} style={[styles.ColorItem, {backgroundColor: item}]}>
                            </TouchableOpacity>
                        )
                    })
                }
            </View>
        )
    }

}

export default Comp3;
const styles = StyleSheet.create({
    /**內(nèi)容*/
    container: {
        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'
    },
    lineSelect: {
        backgroundColor: 'red',
        position: 'absolute',
        // bottom:0,
        height: '100%',
        width: 85,
    },
    kindsOfColors: {
        width: '100%',
        backgroundColor: '#fff',
        height: '50%',
        flexDirection: 'row',
        alignItems: 'center',
        flexWrap: 'wrap',
        justifyContent: 'space-around',
        paddingVertical: 10
    },
    ColorItem: {
        height: '50%',
        width: 60,
        borderWidth: 1,
        marginBottom: 5,
        borderColor: '#eee'
    },


});

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容