Last active
September 24, 2019 13:18
-
-
Save azl397985856/03b2ea4f463043d64e81761ee05e716f to your computer and use it in GitHub Desktop.
draw-taro.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Taro, { Component } from '@tarojs/taro'; | |
import { Canvas, View, Image } from '@tarojs/components'; | |
import { AtButton } from 'taro-ui'; | |
function getTouchPos(e) { | |
const rect = { | |
left: 0, | |
top: 0, | |
}; | |
// 小程序下有e.changedTouches[0].x,没有e.changedTouches[0].clientX | |
// h5下有e.changedTouches[0].clientX,没有e.changedTouches[0].x | |
// 因此需要做兼容 | |
const touch = e.changedTouches[0]; | |
return { | |
x: +(touch.clientX || touch.x) - rect.left, | |
y: +(touch.clientY || touch.y) - rect.top, | |
}; | |
} | |
let ctx = {}; | |
// 画笔的颜色 | |
const BLACK = '#000'; | |
const RED = '#e60000'; | |
// 不用state,否则会在小程序下造成性能问题 | |
const initialCoord = { | |
x: 0, | |
y: 0, | |
}; | |
let drawing = false; | |
let mousePos = initialCoord; // 当前手的位置 | |
let lastPos = initialCoord; // 上一帧手的位置 | |
let screen = {}; | |
function classNames() {} | |
function draw() { | |
if (drawing) { | |
ctx.moveTo(lastPos.x, lastPos.y); | |
ctx.lineTo(mousePos.x, mousePos.y); | |
// drawLineNoAliasing(ctx, lastPos.x, lastPos.y, mousePos.x, mousePos.y); | |
ctx.stroke(); | |
ctx.draw(process.env.TARO_ENV === 'weapp' ? true : false); | |
lastPos = mousePos; | |
} | |
} | |
export default class Draw extends Component { | |
constructor() { | |
super(); | |
this.state = { | |
color: BLACK, // 画笔的颜色 | |
}; | |
this.config = { | |
allowsBounceVertical: 'NO', // 防止滚动 | |
disableScroll: true, // 防止滚动 | |
pageOrientation: 'landscape', | |
}; | |
// 防止滚动 | |
document && | |
document.body.addEventListener('touchmove', e => e.preventDefault(), { | |
passive: false, | |
}); | |
this.handleTouchStart = this.handleTouchStart.bind(this); | |
this.handleTouchEnd = this.handleTouchEnd.bind(this); | |
this.handleMove = this.handleMove.bind(this); | |
this.setupCanvasContext = this.setupCanvasContext.bind(this); | |
this.clearCanvas = this.clearCanvas.bind(this); | |
} | |
componentDidMount() { | |
// 创建上下文 | |
ctx = Taro.createCanvasContext('ctx', this); | |
// 设置上下文 | |
this.setupCanvasContext(BLACK); | |
// 开启新路径(用于clear) | |
ctx.beginPath(); | |
// 每隔1000 / 60 ms draw一次 | |
// this.interval = setInterval(draw, 34); | |
} | |
componentWillUnmount() { | |
clearInterval(this.interval); | |
} | |
setupCanvasContext(color) { | |
const res = Taro.getSystemInfoSync(); | |
const pixelRatio = res.pixelRatio; | |
screen = { | |
width: res.windowWidth, | |
height: res.windowHeight, | |
}; | |
const lineWidth = | |
process.env.TARO_ENV === 'h5' | |
? pixelRatio * 2 | |
: Taro.pxTransform(5).slice(0, -3); | |
ctx.setLineWidth(lineWidth); | |
ctx.setStrokeStyle(color); | |
ctx.setLineJoin('round'); | |
ctx.setLineCap('round'); | |
} | |
interval; | |
handleTouchStart(e) { | |
drawing = true; | |
lastPos = mousePos = getTouchPos(e); | |
} | |
handleTouchEnd() { | |
drawing = false; | |
} | |
handleMove(e) { | |
mousePos = getTouchPos(e); | |
if (mousePos.y > screen.height) { | |
drawing = false; | |
} | |
draw() | |
} | |
clearCanvas() { | |
ctx.closePath(); | |
ctx.clearRect(0, 0, 9999, 9999); | |
ctx.draw(); | |
ctx.beginPath(); | |
this.setupCanvasContext(this.state.color); | |
} | |
save = async () => { | |
// 是否画过,如果压根没有画,点击确定则不需要保存 | |
const r = await Taro.canvasGetImageData({ | |
canvasId: 'ctx', | |
x: 0, | |
y: 0, | |
width: screen.width, | |
height: screen.height, | |
}); | |
const matrix = process.env.TARO_ENV === 'h5' ? r.data.data : r.data; | |
// 啥也没画 | |
if (matrix.every(b => b === 0)) return Taro.navigateBack(); | |
}; | |
changePenColor(color) { | |
this.setState({ | |
color, | |
}); | |
this.setupCanvasContext(color); | |
} | |
renderCanvas = () => { | |
if (process.env.TARO_ENV === 'weapp') { | |
return ( | |
<Canvas | |
canvasId="ctx" | |
width="1000vw" | |
height="1000vh" | |
style="width:100vw;height:100vh;" | |
onTouchMove={this.handleMove} | |
onTouchStart={this.handleTouchStart} | |
onTouchEnd={this.handleTouchEnd} | |
/> | |
); | |
} else if (process.env.TARO_ENV === 'alipay') { | |
return ( | |
<canvas | |
// eslint-disable-next-line taro/props-reserve-keyword | |
id="ctx" | |
style="width:100vw;height:100vh;" | |
onTouchMove={this.handleMove} | |
onTouchStart={this.handleTouchStart} | |
onTouchEnd={this.handleTouchEnd} | |
disable-scroll | |
/> | |
); | |
} else { | |
return ( | |
<Canvas | |
onTouchMove={this.handleMove} | |
onTouchStart={this.handleTouchStart} | |
onTouchEnd={this.handleTouchEnd} | |
canvasId="ctx" | |
style="width:100vw;height:100vh;" | |
/> | |
); | |
} | |
}; | |
render() { | |
const { color } = this.state; | |
return ( | |
<View className={classNames('wrapper')}> | |
<View className={classNames('canvas')}>{this.renderCanvas()}</View> | |
<View onTouchStart={this.handleTouchEnd}> | |
<View className={classNames('pens')} onClick={e => e.stopPropagation()}> | |
<View | |
className={classNames('pen-black')} | |
onClick={this.changePenColor.bind(this, BLACK)} | |
> | |
{color === BLACK ? ( | |
<Image | |
className={classNames('icon-select')} | |
src={require('./assets/system-selects.svg')} | |
/> | |
) : ( | |
'' | |
)} | |
</View> | |
<View | |
className={classNames('pen-red')} | |
onClick={this.changePenColor.bind(this, RED)} | |
> | |
{color === RED ? ( | |
<Image | |
className={classNames('icon-select')} | |
src={require('./assets/system-selects.svg')} | |
/> | |
) : ( | |
'' | |
)} | |
</View> | |
</View> | |
<View className={classNames('btns')} onClick={e => e.stopPropagation()}> | |
<View className={classNames('btn-clear')} onClick={this.clearCanvas}> | |
清除 | |
</View> | |
<AtButton className={classNames('btn-ok')} onClick={this.save}> | |
确定 | |
</AtButton> | |
</View> | |
</View> | |
</View> | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment