圣诞节小游戏

把你想要的礼物在活动中画出来,提交之后会自动进行抽奖(优惠劵),中奖等级一共分为3个,最后把抽得的优惠劵以邮件的方式发送给你。

没有分享的用户可以免费玩3次,之后分享一次玩一次。

技术栈

前端: weui zepto animate
后台: NodeJs Express

问题展现

touch 事件的 canvas 画板问题

首先要吐槽一下 zepto ,官方的版本中竟然不带 touch 事件 还要自己去编译一次。

画板

在红色范围中 就是 canvas 的大小

实现一个画板的原理非常的简单,我们给 canvas 加上 touchmove 事件 ,然后获取到对应的 x 和 y 坐标就可以了。

但是在使用 touchmove 的时候 并没有给我提供offsetXoffsetY 这两个属性,而只提供了:

touch 事件

page 坐标

针对于当前页面坐标,页面左上角定位开始。
page 坐标

client 坐标

触摸目标在视口中的坐标,这里也就是和 page 一致

screen 坐标

针对当前屏幕的坐标 屏幕左上角定位开始。

screen 坐标

但是我想要的是从当前 canvas 开始的坐标,即 canvas 的左上角:

canvas 坐标

如果现在直接使用 page 坐标,画出来的 x 和 y 会有偏差,代码如下:

function getPoint(e){
    var point = new Object();
    point.x = e.touches[0].pageX;
    point.y = e.touches[0].pageY;
    return point;
}

效果图:

有偏移

可以明显的看到画笔和内容有偏移,这主要是因为我们现在拿的当前页面的坐标。

那我们怎么去获取 canvas 的坐标呢?

实际上,可以去获取当前 canvas 元素距离屏幕和偏移量,能够拿到 left 偏移 就能够获取到 x 真正的坐标,拿到 top 偏移 就能够获取到 y 真正的坐标。

修改代码:

function getPoint(e){
    var point = new Object();
    point.x = e.touches[0].pageX - $("#canvas")[0].offsetLeft;
    point.y = e.touches[0].pageY - $("#canvas")[0].offsetTop;
    return point;
}

效果图:

无偏移

给 canvas 设置自适应的宽高

首先! 一定不要使用 css 修改 canvas 标签的宽和高,为什么这样说呢?

canvas{
    width: 100%;
    height: 100%;
}

效果图:

效果图

能看见我们画出来的东西也不正常了,要设置宽和高 我们只通过 canvas 标签的 width 和 height 来设置,但是这个标签只支持 px 的值。

不过我们可以给父级元素设置一个宽高百分之百,然后在这个页面加载完成后 去获取父级元素的宽高,然后给 canvas 设置上去 就能够实现自动适应。

var canvasNode = $("#canvas");
var canvas = canvasNode.get(0);
canvas.width = canvasNode.parent().width(); 
canvas.height = canvasNode.parent().height();

保存屏幕截图

客户有这样一个要求,画完之后呢 把画的内容放到第三个页面,然后长按图片进行保存。

保存礼劵

不过这个页面并不是一张图片,而是 布局+图片

在微信浏览器里面 如果是一张图片 长按之后会自动出现保存 所以这里我选择了最简单的实现方式: 生成图片之后 直接覆盖到当前页面 然后把透明图设置为0,这样用户在长按的时候 其实按中的是我生成的图片。

内容生成图片的开源解决方案:html2canvas

最后

好久没有写前端了啊! 好多人都说后端比前端复杂,学前端的人也越来越多 但是我不这么觉得 况且现在前端工程师越来越不像前端了(node/react) 你们说呢?