本文主要是使用canvas实现刮刮乐的效果

最终效果见如下链接


Canvas图像合成属性

在实现刮刮乐之前首先介绍一下canvas一个非常厉害的属性,图像合成globalCompositeOperation

这个属性是设置在画笔上的,设置方式为ctx.globalCompositeOperation = [属性值]

我们称原来画板上的图像为原图像,新画的为目标图像,属性值和效果如下表

属性值 效果
source-over 默认值,目标图像覆盖原图像
source-atop 目标图像外的原图像不可见
source-in 只显示与原图像交集部分的目标图像,原图像透明
source-out 只显示不与原图像相交的部分的目标图像,原图像透明
destination-over 原图像覆盖目标图像
destination-atop 原图像外的目标图像不可见
destination-in 只显示与目标图像交集部分的原图像,目标图像透明
destination-out 只显示不与目标图像相交的部分的原图像,目标图像透明

可以看出source开头的都是目标图像显示为主,destination都是原图像显示为主

这里想要实现刮刮乐功能,其实就是利用了destination-out属性值,用一张灰色的原图当成刮刮乐需要刮除的层,当我们开始刮的时候本质上就是在原图上画目标图像,让原图只显示不与目标图像相交的部分,即刮过(画了目标图像)的原图区域透明

刮刮乐实现

按照刚才分析的,我们需要现在画布上画一个灰色的刮卡区域,这个图层可以画在某个显示文字或者图片的div之上,这样子挂完之后就可以显示对应的文字了

1
2
3
4
5
6
ctx.beginPath()
ctx.globalCompositeOperation = "source-over"
ctx.fillStyle = "grey"
ctx.fillRect(0, 0, 500, 100)
ctx.stroke()
ctx.closePath()

接下来实现一下刮卡的功能,我们以鼠标在画板上的位置为中心来不停地画一个小圆圈,来模拟手指刮卡的过程,具体实现过程见下方代码及注释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 能否刮卡
var canDarw = false
// 鼠标点击激活刮卡功能
c1.onmousedown = function () {
canDraw = true
}
// 鼠标松开或者移出关闭刮卡功能
c1.onmouseup = function () {
canDraw = false
}
c1.onmouseout = function () {
canDraw = false
}
// 监听鼠标移动画圆
c1.onmousemove = function (evt) {
if (canDraw) {
ctx.beginPath()
var x = evt.pageX - c1.offsetLeft;
var y = evt.pageY - c1.offsetTop;
ctx.globalCompositeOperation = "destination-out"
ctx.arc(x, y, 20, 0, 2 * Math.PI)
ctx.fill()
ctx.closePath()
}
}

手机端的手指触控同理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 手指触控
c1.ontouchstart = function(){
canDraw = true
}
c1.ontouchend = function () {
canDraw = false
}
c1.addEventListener("touchmove",function(evt){
console.log([evt])
if (canDraw) {
ctx.beginPath()
var x = evt.touches[0].pageX - c1.offsetLeft;
var y = evt.touches[0].pageY - c1.offsetTop;
ctx.globalCompositeOperation = "destination-out"
ctx.arc(x, y, 20, 0, 2 * Math.PI)
ctx.fill()
ctx.closePath()
}
})

刮层下文字的显示就比较简单的,想要起到抽奖的效果只要每次随机roll一个数字,把对应数组中的内容替换到刮层下的dom元素中,roll数字可以用随机数(0到1)乘上数组长度,然后下取整作为抽取数字即可