用`canvas`实现刮刮乐效果

1. 布局

上面用来显示底部的文字,或者图片也行

然后绝对定位,再放入canvas覆盖

html 复制代码
<style>
    .wrapper {
        position: relative;
        width: 300px;
        height: 250px;
        background-color: #fcc;
    }

    .ticket {
        display: flex;
        position: absolute;
        inset: 0;
    }

    .label {
        margin: auto;
        color: #fff;
        font-size: 66px;
        user-select: none;
    }

    canvas {
        position: absolute;
    }
</style>

<body>
    <div class="wrapper">
        <div class="ticket">
            <span class="label">一等奖</span>
        </div>
    </div>
<body>

2. 创建画布

传入的参数是父容器,让他们的大小一致

js 复制代码
function createScratchTicket(wrapper) {
    const cvs = document.createElement('canvas')
    const ctx = cvs.getContext('2d')
    cvs.width = wrapper.clientWidth
    cvs.height = wrapper.clientHeight

    // 绘制刮奖区域
    ctx.fillStyle = '#999'
    ctx.fillRect(0, 0, cvs.width, cvs.height)

    return cvs
}

3. 设置样式

注意globalCompositeOperation这个属性,他可以让我们选择后面画的图与前面的图之间的绘制关系

js 复制代码
function setStyle(ctx) {
    // 什么颜色都行
    ctx.fillStyle = 'transparent'
    ctx.lineWidth = 15
    ctx.lineCap = 'round'
    ctx.lineJoin = 'round'
    ctx.globalCompositeOperation = 'destination-out'
}

这是MDN的描述

developer.mozilla.org/zh-CN/docs/...

也就是说,设置了这个属性,当我们往画布上填充新的内容时,就能产生涂抹效果

4. 初始化

把画布放入容器中,然后设置上面的样式,再绑定事件

js 复制代码
 function init() {
    const wrapper = document.querySelector('.wrapper')
    const cvs = createScratchTicket(wrapper)
    const ctx = cvs.getContext('2d')
    wrapper.appendChild(cvs)

    setStyle(ctx)
    bindEvent(cvs, ctx)
}

5. 事件

当鼠标按下时,记录位置,鼠标移动时,填充画布,鼠标抬起时,删除事件即可

js 复制代码
  function bindEvent(el, ctx) {
    el.onmousedown = function ({ clientX, clientY }) {
        ctx.moveTo(clientX, clientY)

        el.onmousemove = function ({ clientX, clientY }) {
            ctx.lineTo(clientX, clientY)
            ctx.stroke()
        }

        el.onmouseup = function () {
            el.onmousemove = null
            el.onmouseup = null
        }
    }
}

6. 问题

上面的绑定事件,有个小问题,当你的鼠标移出浏览器时,就不能解绑事件

解决方法就是多绑定一个事件,不过这样你的鼠标刮图时,就不能超出元素了

js 复制代码
function bindEvent(el, ctx) {
    el.onmousedown = function ({ clientX, clientY }) {
        ctx.moveTo(clientX, clientY)

        el.onmousemove = function ({ clientX, clientY }) {
            ctx.lineTo(clientX, clientY)
            ctx.stroke()
        }

        // 移出浏览器或元素时也会解绑
        el.onmouseup = el.onmouseout = function () {
            el.onmousemove = null
            el.onmouseup = null
        }
    }
}

源码:gitee.com/cjl2385/dig...

相关推荐
缓慢更新4 小时前
AI 辅助生成单测:从接口定义到用例的流水线
java·服务器·前端·网络·数据库·人工智能
陈随易5 小时前
AI 运维服务器,安全又可靠的方法
前端·后端·程序员
风骏时光牛马6 小时前
AI稳定性治理体系构建与疑难问题深度分析
前端
IT_陈寒6 小时前
JavaScript的this坑人实录,这次我真的记下来了
前端·人工智能·后端
开开心心就好7 小时前
音频降噪剪辑工具,音量裁剪一键处理
运维·服务器·前端·spring·ocr·音视频·1024程序员节
螺丝钉tina9 小时前
[Playwright] [02]常用命令与调试:Debug UI、Mode和 Trace Viewer
开发语言·javascript·测试工具·ui·自动化
PedroQue999 小时前
0.8.2 新增 backFallback 配置,无 tabbar 页返回无忧
前端·uni-app
淡漠的蓝精灵9 小时前
web.py:一个简单到极致的 Python Web 框架
开发语言·前端·python·其他
开开心心就好10 小时前
竖式除法出题工具,整除余数混合模式
运维·服务器·前端·javascript·ocr·perl·1024程序员节
起个名字费劲死了10 小时前
Halcon学习一:骰子识别
前端·python·学习