不使用canvas怎么实现一个刮刮卡效果?

说在前面

🎈刮刮卡大家应该都玩过吧,还记得小时候的小卖部总会有各种各样的刮卡抽奖活动,刮卡时那心跳的感觉让我们更加的欲罢不能,随着时代的发展,现在很多回忆也都有了网页版,通过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,十分欢迎~~~
有什么问题都可以在评论告诉我~~~

往期精彩

vue封装一个3D轮播图组件

vue实现一个鼠标滑动预览视频封面组件(精灵图版本)

node封装一个图片拼接插件

基于inquirer封装一个控制台文件选择器

node封装一个控制台进度条插件

密码太多不知道怎么记录?不如自己写个密码箱小程序

微信小程序实现一个手势图案锁组件

vue封装一个弹幕组件

为了学(mo)习(yu),我竟开发了这样一个插件

程序员的浪漫之——情侣日常小程序

vue简单实现词云图组件

说在后面

🎉这里是JYeontu,喜欢算法,GDCPC打过卡;热爱羽毛球,大运会打过酱油。毕业一年,两年前端开发经验,目前担任H5前端开发,算法业余爱好者,有空会刷刷算法题,平时喜欢打打羽毛球🏸 ,也喜欢写些东西,既为自己记录📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解🙇,写错的地方望指出,定会认真改进😊,在此谢谢大家的支持,我们下文再见🙌。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JYeontu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值