canvas实现刮刮奖效果

「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

实现效果

常见活动页刮刮奖效果

思路

第一步:首先做好刮奖的内容html,然后使用canvas绘制一层蒙层覆盖在奖品内容上,可以在蒙层上使用canvas写3个字“刮一刮”,看起更有效果。
第二步:接下来使用鼠标(pc端),手指(wap端)按下蒙层区域,在以按下点的区域使用canvas画一个透明的圆圈,这时蒙层下的奖品文案就会显示出来。
第三步:判断刮开的区域占总canvas区域的80%(自定义)时,去除蒙层,需要在我们每次触碰到蒙层,也就是在刮的时候去计算面积。

实现

步骤一:做好奖品内容dom
这里样式我就不贴了,样式可以自己随意写

<div class="scrapeLottoBox">
  <div class="scrapeLottoBox-btn">刮开优惠</div>
  <div class="scrapeLottoBox-price"><span>¥123</span>.00</div>
</div>
复制代码

WX20211129-234945@2x.png

步骤二:使用canvas画出蒙层,覆盖住123。

<div class="scrapeLottoBox">
  <div class="scrapeLottoBox-btn">刮开优惠</div>
  <div class="scrapeLottoBox-price"><span>¥123</span>.00</div>
  <!-- 蒙层 -->
  <canvas id="scrapeLottoCanvas" width="150" height="70"></canvas>
</div>

let myCanvas = document.getElementById("scrapeLottoCanvas");
// 搭建环境,填充蒙层色
let cxt = myCanvas.getContext("2d"); // 创建画布
cxt.globalAlpha = 1; // 设置透明度
cxt.fillStyle = "#ccc"; // 设置背景灰色
cxt.fillRect(0, 0, 300, 140); // 绘制填充矩形 300 140为宽高
// 绘制文本“刮一刮”
cxt.fillStyle = "#000";
cxt.font = "18px 微软雅黑";
cxt.textAlign = "center";
cxt.textBaseline = "middle";
cxt.fillText('刮一刮', 73, 35, 100);
复制代码

效果:

WX20211130-000847@2x.png

步骤三:当点击或者按下移动时,canvas画出透明小圆圈

let flag = false;
// pc端事件监听
myCanvas.addEventListener('mousedown', function (e) {
  flag = true;
  drawArc(e) // 绘制
})
myCanvas.addEventListener('mousemove', function (e) {
  if (flag == true) {
    drawArc(e) // 绘制
  }
})
// wap端事件监听
myCanvas.addEventListener('touchstart', function (e) {
  flag = true;
  drawArc(e) // 绘制
})
myCanvas.addEventListener('touchmove', function (e) {
  if (flag == true) {
    drawArc(e) // 绘制
  }
})

// 绘画区域
function drawArc(e) {
  var canvasPos = myCanvas.getBoundingClientRect(); // 获取矩形canvas在页面中的绝对位置
  var pageScrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 获取页面滚动的高度(处理页面下滑后才出现刮奖,计算坐标点)
  var pageScrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; // 同理
  var mouseX = (e.pageX || e.targetTouches[0].pageX) - canvasPos.left - pageScrollLeft; // 点击点坐标的X轴距离 - 矩形左上角X轴距离 - 页面卷出去的X距离
  var mouseY = (e.pageY || e.targetTouches[0].pageY) - canvasPos.top - pageScrollTop; // 同理
  cxt.globalCompositeOperation = "destination-out"; // 相交部分不显示
  cxt.beginPath(); // 开始一条路径
  cxt.fillStyle = "white"; // 白色
  cxt.moveTo(mouseX, mouseY); // 移动到位置 mouseX,mouseY
  cxt.arc(mouseX, mouseY, 6, 0, 2 * Math.PI); // 画一个圆 半径为6
  cxt.fill(); // 填充
}
复制代码

效果:
WX20211130-003126@2x.png

步骤四:当鼠标或手指抬起时,计算已刮开的区域

// pc端事件监听
myCanvas.addEventListener('mouseup', function () {
  flag = false;
  calcArea(); // 计算
})
// wap端事件监听
myCanvas.addEventListener('touchend', function () {
  flag = false;
  calcArea(); // 计算
})

// 计算区域
function calcArea() {
  // 获取像素点的数据
  var myImg = cxt.getImageData(0, 0, myCanvas.width, myCanvas.height);
  var num = 0;
  var max = myImg.data.length / 4; // 取1/4计算区域比例即可,节省计算开销
  for (var i = 0; i < myImg.data.length; i += 4) {
    if (myImg.data[i + 3] == 0) {
      num++;
    }
  }
  // 0 - 1 为区域百分比,此时80%时清空全部蒙层
  if (num >= max * 0.8) {
    myCanvas.remove()
  }
}
复制代码

完成!

贴上完整代码

<!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>
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
  <style>
    /**
    * 刮刮奖
    */
    .scrapeLottoBox{
      width: 285px;
      height: 120px;
      position: absolute;
      left: 0;
      top: 0;
      right: 0;
      bottom: 0;
      margin: auto;
      background: url('https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6ace29d7c26e4e88a51ec638111d0a3f~tplv-k3u1fbpfcp-watermark.image') center/100% no-repeat;
    }
    .scrapeLottoBox-btn{
      font-size: 20px;
      color: #fff;
      width: 50px;
      position: absolute;
      right: 25px;
      top: 30px;
      text-align: center;
    }
    .scrapeLottoBox-price{
      color: #f51e55;
      width: 150px;
      text-align: center;
      position: absolute;
      left: 30px;
      top: 25px;
      font-size: 16px;
    }
    .scrapeLottoBox-price>span{
      font-size: 40px;
      line-height: 67px;
      font-weight: 700;
    }
    .scrapeLottoBox>#scrapeLottoCanvas{
      position: absolute;
      left: 30px;
      top: 25px;
    }
  </style>
</head>
<body>
  <div class="scrapeLottoBox">
    <div class="scrapeLottoBox-btn">刮开优惠</div>
    <div class="scrapeLottoBox-price"><span>¥123</span>.00</div>
    <!-- 蒙层 -->
    <canvas id="scrapeLottoCanvas" width="150" height="70"></canvas>
  </div>
  
  <script>
    /**
     * 创建刮刮奖
     */
    createScrapeLotto()
    function createScrapeLotto() {
      let myCanvas = document.getElementById("scrapeLottoCanvas");
      // 搭建环境
      let cxt = myCanvas.getContext("2d");
      cxt.globalAlpha = 1;
      cxt.fillStyle = "#ccc";
      cxt.fillRect(0, 0, 300, 140);
      // 文本
      cxt.fillStyle = "#000";
      cxt.font = "18px 微软雅黑";
      cxt.textAlign = "center";
      cxt.textBaseline = "middle";
      cxt.fillText('刮一刮', 73, 35, 100);
      
      // pc
      let flag = false;
      myCanvas.addEventListener('mousedown', function (e) {
        flag = true;
        drawArc(e)
      })
      myCanvas.addEventListener('mousemove', function (e) {
        if (flag == true) {
          drawArc(e)
        }
      })
      myCanvas.addEventListener('mouseup', function () {
        flag = false;
        calcArea();
      })
      // wap
      myCanvas.addEventListener('touchstart', function (e) {
        flag = true;
        drawArc(e)
      })
      myCanvas.addEventListener('touchmove', function (e) {
        if (flag == true) {
          drawArc(e)
        }
      })
      myCanvas.addEventListener('touchend', function () {
        flag = false;
        calcArea();
      })

      // 绘画区域
      function drawArc(e) {
        var canvasPos = myCanvas.getBoundingClientRect();
        var pageScrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        var pageScrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
        var mouseX = (e.pageX || e.targetTouches[0].pageX) - canvasPos.left - pageScrollLeft;
        var mouseY = (e.pageY || e.targetTouches[0].pageY) - canvasPos.top - pageScrollTop;
        cxt.globalCompositeOperation = "destination-out";
        cxt.beginPath();
        cxt.fillStyle = "white";
        cxt.moveTo(mouseX, mouseY);
        cxt.arc(mouseX, mouseY, 6, 0, 2 * Math.PI);
        cxt.fill();
      }

      // 计算区域
      function calcArea() {
        var myImg = cxt.getImageData(0, 0, myCanvas.width, myCanvas.height);
        var num = 0;
        var max = myImg.data.length / 4;
        for (var i = 0; i < myImg.data.length; i += 4) {
          if (myImg.data[i + 3] == 0) {
            num++;
          }
        }
        if (num >= max * 0.4) {
          myCanvas.remove()
        }
      }
    }
  </script>
</body>
</html>
复制代码

总结

勤于动手实践见真知!

猜你喜欢

转载自juejin.im/post/7036160268937723917