用`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...

相关推荐
非凡ghost10 分钟前
AI修图不“造假“,摄影师的出片效率加速器
服务器·前端·人工智能·电脑
2601_9516152011 分钟前
网页设计模板源码 web前端模板网页源码下载
前端
mmsx11 分钟前
osmdroid 地图实战 03|地图的"分层世界":离线方案、图层模型与 Overlay 体系
android·前端
郭邯35 分钟前
从零到一:我用 AI 写了个复利计算器,顺便治好了我的"公式恐惧症"
前端
Pointer Pursuit37 分钟前
C++11特性(二)
前端·c++·算法
天道kabuto43 分钟前
Vue3 升级踩坑:子组件 click 事件为什么会触发两次?
前端
Nayana44 分钟前
《Web 到 HarmonyOS》-- Ability、Stage、模块化与路由导航
前端
ShineWinsu1 小时前
对于 Vue 3:从为什么学 Vue,到声明式渲染与数据响应式的解析
前端·javascript·vue.js
粥里有勺糖1 小时前
视野修炼-技术周刊第132期 | 一些有趣的组件
前端·github·aigc
এ慕ོ冬℘゜2 小时前
样式控制 .css ()
前端·css