HTML5 Canvas实战之刮奖效果
近年来由于移动设备对HTML5的较好支持,经常有活动用刮奖的效果,最近也在看H5方面的内容,就自己实现了一个,现分享出来跟大家交流。
1、效果
2、原理
原理很简单,就是在刮奖区添加两个canvas,第一个canvas用于显示刮开后显示的内容,可以是一张图片或一个字符串,第二个canvas用于显示涂层,可以用一张图片或用纯色填充,第二个canvas覆盖在第一个canvas上面。
当在第二个canvas上点击或涂抹(点击然后拖动鼠标)时,把点击区域变为透明,这样就可以看到第一个canvas上的内容,即实现了刮奖效果。
3、实现
(1)定义Lottery类
function Lottery(id, cover, coverType, width, height, drawPercentCallback) {
this.conId = id;
this.conNode = document.getElementById(this.conId);
this.cover = cover || '#CCC';
this.coverType = coverType || 'color';
this.background = null;
this.backCtx = null;
this.mask = null;
this.maskCtx = null;
this.lottery = null;
this.lotteryType = 'image';
this.width = width || 300;
this.height = height || 100;
this.clientRect = null;
this.drawPercentCallback = drawPercentCallback;
}
对参数解释一下:
id:刮奖容器的id
cover:涂层内容,可以为图片地址或颜色值,可空,默认为 #ccc
coverType:涂层类型,值为 image 或 color,可空,默认为 color
width:刮奖区域宽度,默认为300px,可空
height:刮奖区域高度,默认为100px,可空
drawPercentCallback:刮开的区域百分比回调,可空
然后还定义了几个需要用到的变量:
background:第一个canvas元素
backCtx:background元素的2d上下文(context)
mask:第二个canvas元素
maskCtx:mask元素的2d上下文(context)
lottery:刮开后显示的内容,可以为图片地址或字符串
lotteryType:刮开后显示的内容类型,值为 image 或 text,要跟lottery匹配
clientRect:用于记录mask元素的 getBoundingClientRect() 值
(2)添加二个canvas到刮奖容器,并获取2d上下文
this.background = this.background || this.createElement('canvas', {
style: 'position:absolute;left:0;top:0;'
});
this.mask = this.mask || this.createElement('canvas', {
style: 'position:absolute;left:0;top:0;'
});
if (!this.conNode.innerHTML.replace(/[\w\W]| /g, '')) {
this.conNode.appendChild(this.background);
this.conNode.appendChild(this.mask);
this.clientRect = this.conNode ? this.conNode.getBoundingClientRect() : null;
this.bindEvent();
}
this.backCtx = this.backCtx || this.background.getContext('2d');
this.maskCtx = this.maskCtx || this.mask.getContext('2d');
这里用于了createElement工具方法,另外还绑定了事件,后面介绍。
(3)绘制第一个canvas
第一个canvas分两种类型,image 和 string,如果是图片直接用canvas的drawImage就可以了,如果是string,要先用白色填充,然后在上下左右居中的地方绘制字符串,代码如下:
if (this.lotteryType == 'image') {
var image = new Image(),
_this = this;
image.onload = function () {
_this.width = this.width;
_this.height = this.height;
_this.resizeCanvas(_this.background, this.width, this.height);
_this.backCtx.drawImage(this, 0, 0);
}
image.src = this.lottery;
} else if (this.lotteryType == 'text') {
this.width = this.width;
this.height = this.height;
this.resizeCanvas(this.background, this.width, this.height);
this.backCtx.save();
this.backCtx.fillStyle = '#FFF';
this.backCtx.fillRect(0, 0, this.width, this.height);
this.backCtx.restore();
this.backCtx.save();
var fontSize = 30;
this.backCtx.font = 'Bold ' + fontSize + 'px Arial';
this.backCtx.textAlign = 'center';
this.backCtx.fillStyle = '#F60';
this.backCtx.fillText(this.lottery, this.width / 2, this.height / 2 + fontSize / 2);
this.backCtx.restore();