用`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 小时前
Ubuntu22.04如何安装新版本的Node.js和npm
linux·运维·前端·人工智能·ubuntu·npm·node.js
Seveny074 小时前
pnpm相对于npm,yarn的优势
前端·npm·node.js
yddddddy5 小时前
css的基本知识
前端·css
昔人'5 小时前
css `lh`单位
前端·css
前端君6 小时前
实现最大异步并发执行队列
javascript
Nan_Shu_6147 小时前
Web前端面试题(2)
前端
知识分享小能手7 小时前
React学习教程,从入门到精通,React 组件核心语法知识点详解(类组件体系)(19)
前端·javascript·vue.js·学习·react.js·react·anti-design-vue
蚂蚁RichLab前端团队8 小时前
🚀🚀🚀 RichLab - 花呗前端团队招贤纳士 - 【转岗/内推/社招】
前端·javascript·人工智能
孩子 你要相信光8 小时前
css之一个元素可以同时应用多个动画效果
前端·css
萌萌哒草头将军8 小时前
Oxc 和 Rolldown Q4 更新计划速览!🚀🚀🚀
javascript·vue.js·vite