h5实战|刮刮乐

99 阅读1分钟

在做运营活动的相关功能时,刮刮乐也是常客了。本篇文章主要是总结用vue实现刮刮乐功能的思路和方法。

关键canvasAPI

globalCompositeOperation = 'destination-out'; //橡皮擦模式

代码内容

<script setup>
import { ref, onMounted } from 'vue'
onMounted(() => {
  let canvas = document.querySelector('#canvas');
  let context = canvas.getContext('2d');
  // 绘制涂层
  context.beginPath();
  context.fillStyle = 'grey';
  context.fillRect(0, 0, 400, 300);

  //计算已经擦除的面积与原画布面积占比
  const calcClearArea = () => {
    //获取canvas 的像素信息
    const pixels = context.getImageData(0, 0, 400, 300).data;
    let transparentPixels = 0;
    for (let i = 0; i < pixels.length; i += 4) {
      if (pixels[i + 1] < 128) {
        transparentPixels++
      }
    }
    console.log((transparentPixels / pixels.length * 4 * 100).toFixed(2))
    return (transparentPixels / pixels.length * 4 * 100).toFixed(2)
  }

  //清除涂层
  const clear = (alpha) => {
    return () => {
      context.save();
      context.globalCompositeOperation = "source-in";
      context.fillStyle = context.fillStyle + (alpha -= 1).toString(16);
      context.fillRect(0, 0, 400, 300);
      context.restore();
      if (alpha > 210) {
        requestAnimationFrame(clear(alpha))
      }
    }
  }

  // 监听鼠标移动事件
  canvas.addEventListener('mousemove', (e) => {
    // 当鼠标左键按下&&移动鼠标时,清除鼠标附近涂层
    if (e.which === 1 && e.button === 0) {
      const x = e.clientX, y = e.clientY;
      context.globalCompositeOperation = 'destination-out';
      context.beginPath();
      // 清除以鼠标位置为圆心,半径为10px的圆的范围
      context.arc(x - 200, y, 10, 0, Math.PI * 2);
      context.fill();
    }
  })

  canvas.addEventListener("mouseup", (e) => {
    const pixels = calcClearArea();
    if (pixels >= 30) {
      requestAnimationFrame(clear(255));
     }
  })
})
</script>

<template>
  <div class="page">
    <div class="img">
      <img src="./images/1.png" style="width:400px;height:300px;" />
    </div>
    <canvas id="canvas" width="400" height="300"></canvas>     
  </div>
</template>

<style scoped>
.page {
  position: relative;
}
.img {
  width: 400px;
  height: 300px;
  position: absolute;
  left: 0;
  z-index: -1;
}
</style>