canvas实现刮刮乐,刮刮卡,js实现刮刮乐,刮刮卡

代码直接复制拿去用,不会看注释.记得底部下载刷子图片.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>

    <style>
      .card-body {
        position: relative;
        width: 340px;
        height: 160px;
        margin: 0 auto;
      }
      .canvas {
        /* 利用绝对定位让灰色涂层与刮卡结果重叠 */
        position: absolute;
        top: 0;
        left: 0;
        z-index: 2;
        width: 100%;
        height: 100%;
      }
      .gift {
        /* 利用绝对定位让灰色涂层与刮卡结果重叠 */
        position: absolute;
        top: 0;
        left: 0;
        z-index: 1;
        width: 100%;
        height: 100%;
        font-size: 32px;
        text-align: center;
        line-height: 160px;
        background-color: #fcfcfc;
      }
    </style>
  </head>
  <body>
    <div class="card-body">
      <!-- 灰色涂层 -->
      <canvas class="canvas">sorry, 浏览器不支持canvas</canvas>
      <!-- 刮卡结果 -->
      <div class="gift">谢谢参与</div>
    </div>

    <script>
      // 设置是否擦除状态和刷子图片
      var isErasering = false,
        lastPoint,
        brush = new Image();
      brush.src = './shuazi.png';

      // 获取canvas并设置其宽高
      let canvas = document.querySelector('.canvas'),
        card = document.querySelector('.card-body');
      canvas.width = card.offsetWidth;
      canvas.height = card.offsetHeight;

      let ctx = canvas.getContext('2d');

      // 绘制涂层
      function drawCanvas() {
        ctx.save();
        ctx.beginPath();
        ctx.fillStyle = '#e5e5e5';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = 'red';
        ctx.font = '24px "微软雅黑"';
        ctx.fillText(
          '请开始刮奖',
          canvas.width / 2 - 64,
          canvas.height / 2 + 4
        );
        ctx.closePath();
        ctx.restore();
      }

      // 获取鼠标或者手指当前点的位置
      function getPointPosition(e, canvas) {
        let mx,
          my,
          offsetX = 0,
          offsetY = 0;
        if (canvas.offsetParent !== null) {
          // 由于canvas刚开始是绝对定位,其offsetLeft和offsetTop为0,需要不断向上寻找其父级,
          // 计算父级的offsetLeft和offsetTop,直到向上寻找到body元素,因为body的offsetParent为null
          do {
            offsetX += canvas.offsetLeft;
            offsetY += canvas.offsetTop;
          } while ((canvas = canvas.offsetParent));
        }

        // 鼠标在页面中的坐标减去canvas在页面中的坐标就是鼠标在canvas中的坐标
        mx = e.pageX - offsetX;
        my = e.pageY - offsetY;

        return {
          x: mx,
          y: my,
        };
      }

      // 计算从鼠标移动开始到结束时点之间的距离
      function distance(point1, point2) {
        return Math.sqrt(
          Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2)
        );
      }

      // 计算从鼠标移动开始到结束时两点之间与x轴的夹角、
      function angle(point1, point2) {
        return Math.atan2(point2.x - point1.x, point2.y - point1.y);
      }

      // 鼠标按下或手指触摸开始时事件
      function moveStart(e) {
        isErasering = true;
        lastPoint = getPointPosition(e, canvas);
      }

      // 鼠标移动或手指滑动时事件
      function move(e) {
        if (!isErasering) {
          return;
        }

        var currentPoint = getPointPosition(e, canvas);
        // console.log(currentPoint)
        var dist = distance(lastPoint, currentPoint);
        var ang = angle(lastPoint, currentPoint);
        var x;
        var y;

        // 计算并绘制鼠标或手指移动时的实时路径
        for (var i = 0; i < dist; i++) {
          x = lastPoint.x + Math.sin(ang) * i - 25;
          y = lastPoint.y + Math.cos(ang) * i - 25;

          // destination-out效果是将源图像(刷子图案)绘制到目标图像(灰色涂层)上,源图像是透明的
          ctx.globalCompositeOperation = 'destination-out';

          // 在鼠标或手指移动过的地方绘制刷子图案
          // console.log(ctx.drawImage);
          ctx.drawImage(brush, x, y);
        }
        lastPoint = currentPoint;
        handleFilledPercentage(getFilledPercentage());
      }

      // 鼠标或手指松开时事件
      function moveEnd(e) {
        isErasering = false;
      }

      // 计算已经刮过的区域占整个区域的百分比
      function getFilledPercentage() {
        let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        // imgData.data是个数组,存储着指定区域每个像素点的信息,数组中4个元素表示一个像素点的rgba值
        let pixels = imgData.data;
        let transPixels = [];
        for (let i = 0; i < pixels.length; i += 4) {
          // 严格上来说,判断像素点是否透明需要判断该像素点的a值是否等于0,
          // 为了提高计算效率,这儿设置当a值小于128,也就是半透明状态时就可以了
          if (pixels[i + 3] < 128) {
            transPixels.push(pixels[i + 3]);
          }
        }
        return (
          ((transPixels.length / (pixels.length / 4)) * 100).toFixed(2) + '%'
        );
      }

      // 设置阈值,去除灰色涂层
      function handleFilledPercentage(percentage) {
        percentage = percentage || 0;
        if (parseInt(percentage) > 50) {
          // 去除画布方法一:直接将canvas涂层删掉
          // canvas.parentNode.removeChild(canvas);
          // 去除画布方法二:将canvas涂层设置为透明
          ctx.fillStyle = 'rgba(255, 255, 255)';
          ctx.fillRect(0, 0, canvas.width, canvas.height);
        }
      }

      // 监听鼠标和touch事件
      canvas.addEventListener('mousedown', moveStart, false);
      canvas.addEventListener('touchstart', moveStart, false);
      canvas.addEventListener('mousemove', move, false);
      canvas.addEventListener('touchmove', move, false);
      canvas.addEventListener('mouseup', moveEnd, false);
      canvas.addEventListener('touchend', moveEnd, false);

      drawCanvas();
    </script>
  </body>
</html>

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值