从前有匹马叫代码
心若没有栖息的地方,到哪里都是流浪

 先来一张图看看,这是现实中的,那么我们如何在程序上实现这样的效果呢,主流方案是采用canvas来实现

首先要实现这种效果,核心点是了解canvas的globalCompositeOperation属性,这个属性的作用是控制canvas上不同图层之间的显示效果,传送门

我们这里只需要使用到"destination-out"属性,这个属性描述的效果是,当新图层绘制到原始图层上时候,原始图层保持在新图层不重叠的部分

 有了这个效果之后,我们只需要将要显示的东西放置在canvas后面就可以了,至于刮卡的效果,就是在mosemove事件里面,动态绘制透明的图层到canvas上就好了

<script setup lang="ts">
import { onMounted, shallowRef } from "vue";

const w = 300,
    h = 150;
const ctx = shallowRef<CanvasRenderingContext2D | null>(null);
const mousedown = shallowRef(false);

function init() {
    const canvas = document.getElementById("scratch") as HTMLCanvasElement;
    canvas.addEventListener("touchstart", eventDown); //鼠标移动开始
    canvas.addEventListener("touchend", eventUp); //鼠标移动结束
    canvas.addEventListener("touchmove", eventMove); //鼠标移动
    canvas.addEventListener("mousedown", eventDown); //鼠标点击
    canvas.addEventListener("mouseup", eventUp); //鼠标松开
    canvas.addEventListener("mousemove", eventMove); //鼠标移动中
    ctx.value = canvas.getContext("2d");
    if (ctx.value) {
        ctx.value.fillStyle = "gray"; //灰色
        ctx.value.fillRect(0, 0, w, h); //顶部绘图填充矩阵灰色
        ctx.value.globalCompositeOperation = "destination-out";
    }
}

function eventDown(e) {
    //监听鼠标按住
    e.preventDefault();
    mousedown.value = true;
}
function eventUp(e) {
    //监听鼠标松开
    e.preventDefault();
    mousedown.value = false;
}
function eventMove(e) {
    //监听鼠标按住并移动,执行绘图函数
    e.preventDefault();
    if (mousedown.value) {
        var x = (e.clientX + document.body.scrollLeft || e.pageX) - 0 || 0,
            y = (e.clientY + document.body.scrollTop || e.pageY) - 0 || 0;
        ctx?.value?.beginPath(); //绘图开始路径
        ctx?.value?.rect(x, y, 20, 20); //创建一个正方形刮刮痕迹形状
        ctx?.value?.fill();
    }
}

onMounted(() => {
    init();
});
</script>

<template>
    <div>
        <canvas id="scratch" width="300px" height="150px"></canvas>
        <div
            id="background"
            class="w-300px h-150px bg-blue absolute top-0 left-0 z--1"
        ></div>
    </div>
</template>

<style>
#background {
    background-size: contain;
    background-image: url("https://wallpaperm.cmcm.com/b26f4834677e2f0c2cedbd24788b4362.jpg");
}
</style>

 

posted on 2024-08-12 10:23  从前有匹马叫代码  阅读(25)  评论(0编辑  收藏  举报