Skip to content

Instantly share code, notes, and snippets.

@azl397985856
Last active September 24, 2019 13:18
Show Gist options
  • Save azl397985856/03b2ea4f463043d64e81761ee05e716f to your computer and use it in GitHub Desktop.
Save azl397985856/03b2ea4f463043d64e81761ee05e716f to your computer and use it in GitHub Desktop.
draw-taro.js
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