说在前面
🎈刮刮卡大家应该都玩过吧,还记得小时候的小卖部总会有各种各样的刮卡抽奖活动,刮卡时那心跳的感觉让我们更加的欲罢不能,随着时代的发展,现在很多回忆也都有了网页版,通过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前端开发,算法业余爱好者,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。