说在前面
🎈刮刮卡大家应该都玩过吧,还记得小时候的小卖部总会有各种各样的刮卡抽奖活动,刮卡时那心跳的感觉让我们更加的欲罢不能,随着时代的发展,现在很多回忆也都有了网页版,通过canvas我们可以很方便的实现一个刮刮卡的功能效果,那么不使用canvas的话呢?我们也可以很快速的实现这个功能!
效果预览
-
canvas模式
-
dom模式
体验地址
http://jyeontu.xyz/jvuewheel/#/JScratchCard
组件实现
设计图
我们可以使用若干个小块来拼接成完整的一大块涂层,后面只需要判断鼠标事件,将鼠标划过的小块设置样式透明即可,有了大致的思路之后我们便可以开始动手来开始敲代码了。
参数说明
- width
刮刮卡的宽度,默认为300px
- height
刮刮卡的高度,默认为200px
- mode
刮刮卡的模式,有canvas和dom两种模式,默认为canvas模式
- color
刮刮卡涂层颜色,默认为gray
- block
刮刮卡涂层小块配置,mode为dom时需要设置小块的宽度width和高度height
功能实现
一、dom模式
html
刮刮卡的内容通过插槽的方式传入展示。
<div :id="uid + 'j-scratch-card'" class="j-scratch-card">
<div :id="uid + 'j-scratch-card-bg'" class="j-scratch-card-bg">
<slot name="j-scratch-card-bg-slot"></slot>
</div>
<div
:id="uid + 'j-scratch-card-mask'"
class="j-scratch-card-mask"
></div>
</div>
初始化刮刮卡样式
通过传入参数初始化刮刮卡样式。
const scratchCardId = this.uid + "j-scratch-card";
const scratchCardDom = document.getElementById(scratchCardId);
scratchCardDom.style.width = this.width;
scratchCardDom.style.height = this.height;
生成刮刮卡涂层小块
计算应该生成的小块行数和列数。
const block = this.block;
const col = Math.ceil(
parseInt(this.height) / parseInt(block.height)
);
const row = Math.ceil(parseInt(this.width) / parseInt(block.width));
for (let i = 0; i < col; i++) {
const colDom = document.createElement("div");
colDom.style = "display:flex;";
colDom.classList.add("j-scratch-card-mask-col");
for (let j = 0; j < row; j++) {
const rowDom = document.createElement("div");
rowDom.classList.add("j-scratch-card-mask-row");
rowDom.id = `j-scratch-card-mask-row-${col}-${row}`;
rowDom.style = `width:${block.width};height:${block.height};background-color: ${this.color};`;
rowDom.addEventListener("mouseover", e => {
if (!this.isMouseDown) return;
e.target.style.opacity = "0";
});
colDom.appendChild(rowDom);
}
scratchCardMaskDom.appendChild(colDom);
}
监听鼠标事件
监听涂层的鼠标事件。
const scratchCardMaskId = this.uid + "j-scratch-card-mask";
const scratchCardMaskDom = document.getElementById(
scratchCardMaskId
);
scratchCardMaskDom.addEventListener("mousedown", () => {
this.isMouseDown = true;
});
window.addEventListener("mouseup", () => {
this.isMouseDown = false;
});
window.addEventListener("dragend", () => {
this.isMouseDown = false;
});
二、canvas模式
相比于dom原生实现,canvas实现的效果和性能会更好,所以主流还是使用canvas来实现刮刮卡的效果,所以这里我也实现了canvas模式的刮刮卡。
html
<div style="position: relative;" v-if="mode == 'canvas'">
<canvas
:id="uid + '-canvas'"
:width="parseInt(width)"
:height="parseInt(height)"
>
</canvas>
<div class="canvas-bg">
<slot name="j-scratch-card-bg-slot"></slot>
</div>
</div>
初始化刮刮卡样式
通过传入参数初始化刮刮卡样式。
const canvas = document.getElementById(this.uid + "-canvas");
const ctx = canvas.getContext("2d");
// 填充的颜色
ctx.fillStyle = this.color;
// 填充矩形 fillRect(起始X,起始Y,终点X,终点Y)
ctx.fillRect(0, 0, parseInt(this.width), parseInt(this.height));
监听鼠标事件
监听涂层的鼠标事件。
canvas.onmousedown = () => {
this.isMouseDown = true;
};
canvas.onmousemove = e => {
if (!this.isMouseDown) return;
// 计算鼠标在canvas里的位置
const x = e.layerX - canvas.offsetLeft;
const y = e.layerY - canvas.offsetTop;
// 设置globalCompositeOperation
ctx.globalCompositeOperation = "destination-out";
// 画圆
ctx.arc(x, y, 10, 0, 2 * Math.PI);
// 填充圆形
ctx.fill();
};
canvas.onmouseup = () => {
this.isMouseDown = false;
};
组件库引用
这里我将这个组件打包进了自己的一个组件库,并将其发布到了npm上,有需要的同学也可以直接引入该组件进行使用。
引入教程可以看这里:http://jyeontu.xyz/jvuewheel/#/installView
引入后即可直接使用。
源码地址
组件库已开源,想要查看完整源码的可以到 gitee 查看,自己也整理了相关的文档对其进行了简单介绍,具体如下:
组件文档
jvuewheel: http://jyeontu.xyz/jvuewheel/#/JScratchCard
Gitee源码
Gitee源码:gitee.com/zheng_yongt…
觉得有帮助的同学可以帮忙给我点个star,感激不尽~~~
有什么想法或者改良可以给我提个pr,十分欢迎~~~
有什么问题都可以在评论告诉我~~~
往期精彩
说在后面
🎉这里是JYeontu,喜欢算法,GDCPC打过卡;热爱羽毛球,大运会打过酱油。毕业一年,两年前端开发经验,目前担任H5前端开发,算法业余爱好者,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。