小程序canvas 口罩头像生成器开发
一、预览
代码 github.com/AnChunLi/sm…
二、代码细节
1.canvas事件绑定和业务实现
在canvas画布中,图像是实时绘制的,和SVG的区别是没有结构化,因此在给canva中绑定事件时,需要对整个canvas元素绑定对应事件,在小程序中支持touchstart、touchmove、touchend、touchcancel、longtap、error这几个事件。
在本demo中,口罩头像生成过程中需要对口罩进行拖动,放大、缩小、旋转等操作,就需要对口罩进行事件绑定,在canvas中对canvas元素绑定touchstart、touchmove、touchend等事件,然后根据事件返回坐标参数来判定是否作用于对应元素或者区域。
move(e) {
let x = e.touches[0].x,
y = e.touches[0].y,
dis = 30;
if (x < this.data.x + rectW -20 && x >= this.data.x+20 && y < this.data.y + rectW-20&& y >= this.data.y+20){
if (disX == 0) {
disX = x - this.data.x
}
if (disY == 0) {
disY = y - this.data.y
}
console.log('move');
this.setData({
x: x - disX,
y: y - disY
})
// ctx.requestAnimationFrame(this.drawMove);
this.drawMove();
} else if (x < this.data.x + rectW + dis && x >= this.data.x + rectW - dis && y < this.data.y + rectH + dis && y >= this.data.y + rectH - dis){
console.log("scale");
this.drawScale(x - this.data.x, y - this.data.y);
}
},
- 移动 监听touchmove事件,取得触控坐标与矩形区域原点的坐标差,然后实时计算得到矩形原点坐标,并进行绘制。
- 放大、缩小
传入手指触控坐标与矩形原点的坐标差
this.drawScale(x - this.data.x, y - this.data.y);
改变矩形长和宽,并实时绘制
drawScale(W, H) {
rectW = W;
rectH = H;
this.drawMove();
},
- 旋转 这是处理的最不优雅的部分,由于一开始的事件监听依赖矩形原点坐标,这就导致在旋转过程中,不能很好的绑定旋转控件,因此采用了一个笨办法,在canvas画布右上角设置了旋转控件,由于它是固定的对于绑定事件非常方便,没点击一次就会按顺时针方向整体旋转,对应旋转角度也会记录。
drawRotate(){
rotate = rotate + 0.08;
ctx.drawImage(this.data.headImg, 0, 0, this.data.windowW * 0.9, this.data.windowW * 0.9);
ctx.drawImage('img/rotate.png', this.data.windowW * 0.9 - 40, 0, 40, 40);
ctx.translate(this.data.x + rectW / 2, this.data.y + rectH / 2);
ctx.rotate(rotate);
ctx.drawImage(this.data.kouzhaoImg, - rectW / 2 + rectW * 0.25 / 2, - rectH / 2 + rectH / 6 / 2, rectW * 0.75, rectH * 5 / 6);
ctx.setLineDash([5, 5]);
ctx.setStrokeStyle('#fff');
ctx.setLineWidth(3);
ctx.strokeRect(- rectW / 2, - rectH / 2, rectW, rectH);
ctx.drawImage('img/cancel.png', - rectW / 2 - 20, - rectH / 2 - 20, 40, 40);
ctx.drawImage('img/move.png', - rectW / 2 + rectW - 20, - rectH / 2 + rectH - 20, 40, 40);
ctx.draw();
},
2.canvas图片圆角实现
在css中,实现图片圆角极其简单,但在canvas中实现起来并不是一行代码所能解决的问题,因此在这里也说下其实现。
// 绘制圆角
shareCtx.beginPath();
shareCtx.arc(x+dis, y + dis, radius, Math.PI, 1.5* Math.PI);
shareCtx.moveTo(x + dis, y);
shareCtx.lineTo(x + a - dis, y);
shareCtx.arc(x + a - dis, y + dis, radius, 1.5*Math.PI, 2 * Math.PI,);
shareCtx.lineTo(x + a, y + dis);
shareCtx.lineTo(x + a, y + a - dis);
shareCtx.arc(x + a - dis, y + a - dis, radius, 0, 0.5 * Math.PI, false);
shareCtx.lineTo(x + a - dis, y + a);
shareCtx.lineTo(x + dis, y + a);
shareCtx.arc(x + dis, y + a - dis, radius, 0.5 * Math.PI, 1 * Math.PI);
shareCtx.lineTo(x, y + a - dis);
shareCtx.lineTo(x, y + dis);
shareCtx.closePath();
shareCtx.clip();
shareCtx.drawImage(headImg, x, y, a, a);
shareCtx.draw();