一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第四天,点击查看活动详情。
前言
上文提到了用组件的方式来实现刮刮奖,本文笔者将用canvas覆盖源图像的方式来自己实现。
实现
1.定义模板
<template>
<div>
<div
id="1"
class="scratchCard"
:style="'width:' + width + ';height:' + height"
>
<--源图像层-->
<div class="result"></div>
<--覆盖层-->
<canvas id="canvas"></canvas>
</div>
</div>
</template>
2.开始初始化canvas画布并定义样式
mounted() {
this.init();
},
methods: {
init() {
if (!this.isSupportCanvas()) {
alert("当前浏览器不支持canvas");
return;
}
//创建画布并添加样式
const canvasWrap = document.getElementById("1");
this.canvas = canvasWrap.querySelector("#canvas");
this.ctx = this.canvas.getContext("2d");
this.canvas.width = canvasWrap.clientWidth;
this.canvas.height = canvasWrap.clientHeight;
this.ctx.fillstyle = "#a0a0a0";
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
//开始绑定事件
this.bindevent();
},
}
3.添加判断并开始事件处理
bindevent() {
//判断是移动端还是pc端操作
if ("ontouchstart" in window) this.supportTouch = true;
this.events = this.supportTouch
? ["touchstart", "touchmove", "touchend"]
: ["mousedown", "mousemove", "mouseup"];
this.canvas.addEventListener(
this.events[0],
this.startEventHandler,
false
);
},
startEventHandler(e) {
//防止触摸时滑动滚动条
e.preventDefault();
//创建开始触摸事件回调(可自行添加逻辑处理)
if (this.firstTouch) {
this.startCallback();
this.firstTouch = false;
}
//显示奖品层在底层
this.showLucky = true;
//监听移动事件
this.canvas.addEventListener(
this.events[1],
this.moveEventHandler,
false
);
document.addEventListener(this.events[2], this.endEventHandler, false);
},
4.对于移动事件进行处理
moveEventHandler(e) {
e.preventDefault();
//判断为触摸还是鼠标
e = this.supportTouch ? e.touches[0] : e;
//getBoundingClientRect用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。
const canvasPos = this.canvas.getBoundingClientRect(),
scrollT = document.documentElement.scrollTop || document.body.scrollTop,
scrollL =
document.documentElement.scrollLeft || document.body.scrollLeft,
mouseX = e.pageX - canvasPos.left - scrollL,
mouseY = e.pageY - canvasPos.top - scrollT;
this.ctx.beginPath();
this.ctx.fillStyle = "#FFFFFF";
//在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
this.ctx.globalCompositeOperation = "destination-out";
//创建弧/曲线(用于创建圆形或部分圆)
this.ctx.arc(mouseX, mouseY, this.moveRadius, 0, 2 * Math.PI);
this.ctx.fill();
},
endEventHandler(e) {
e.preventDefault();
//移除事件句柄
this.canvas.removeEventListener(this.events[1], this.moveHandler, false);
document.removeEventListener(this.events[2], this.endMoveHandler, false);
this.endMoveHandler = null;
this.caleArea();
},
caleArea() {
let pixels = this.ctx.getImageData(
0,
0,
this.canvas.width,
this.canvas.height
),
transPixels = [];
pixels.data.map((item, i) => {
const pixel = pixels.data[i + 3];
if (pixel === 0) {
transPixels.push(pixel);
}
});
//判断刮得比例,大于这个比例之和就彻底清除
if (transPixels.length / pixels.data.length > this.ratio) {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.canvas.removeEventListener(this.events[0], this.startEventHandler);
this.canvas.removeEventListener(
this.events[1],
this.moveEventHandler,
false
);
document.removeEventListener(
this.events[2],
this.endEventHandler,
false
);
//结束的回调函数(可添加逻辑处理)
this.clearCallback();
}
},
5.实现效果
背景文字
图片
总结
本文通过canvas画布实现了简单的刮刮奖,借鉴了网上的一些文章的经验完成,希望大家能够有所收获!