目前已完成功能包括線條標(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'
},
});