HTML5 Canvas 實現刮獎效果

最近有在看canvas的一些東西,以前在手機端看過有些活動頁面可以實現在手機端刮獎效果,就類似刮彩票顯示中獎的效果,然後自己想了一下要怎麼實現。實現原理是用canvas遮擋住中獎的結果,然後再原來的canvas層繪製透明效果讓底部的中獎結果實顯示出來。

具體主要的canvas api如下:

詳情參考: canvas API

關鍵參數是這個 globalCompositeOperation  這個參數設置對了纔可以實現透明繪製效果,具體參考上面的API接口文檔。

代碼如下:

<!DOCTYPE html>
<!--[if lt IE 7]><html class="no-js lt-ie9 lt-ie8 lt-ie7"><![endif]-->
<!--[if IE 7]><html class="no-js lt-ie9 lt-ie8"><![endif]-->
<!--[if IE 8]><html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--><html class="no-js"><!--<![endif]-->

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="./index.css" disabled>
    <title>刮獎</title>
    <meta name="description" content="刮獎">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        body{margin: 0;padding:0;}
        .canvas-box {position:relative;width:200px;height:200px;}
        #canvas{position:absolute;left:0;z-index:99;}
        .word {position:absolute;left:0;width: 200px; height: 100px;line-height:100px;text-align:center;font-size:16px;}
    </style>
</head>
<body>
  <div class="canvas-box">
    <canvas id="canvas" width="200" height="100"></canvas>
    <div class="word">一等獎</div>
  </div>
</body>
<script>
  const reusult = ['一等獎', '二等獎', '三等獎', '四等獎', '謝謝惠顧'];
  let startFill = false; // 鼠標按鈕開始塗抹效果標識
  let canvasDom = document.querySelector('#canvas');  // canvas元素
  let canvasDomX = canvasDom.getContext("2d");  // 畫板
  let touchRadius = 15;    // 默認手指觸摸半徑,可以自定義設置
  // 繪製遮擋層
  let setCanvas = () => {
    var c=document.getElementById("canvas");
    var ctx=c.getContext("2d");
    ctx.fillStyle="#ccc";
    ctx.fillRect(0,0,200,100);
  };
  let setResult = (elem) => {
     let randomNum = Math.floor(Math.random() * 5);
     document.querySelector(elem).innerHTML =  reusult[randomNum];
  };

  // 得到塗抹的百分比
  let getTransparentPercent = function (ctx, width, height) {
      var imgData = ctx.getImageData(0, 0, width, height),    // 得到canvas的像素信息
          pixles = imgData.data,
          transPixs = [];
      for (var i = 0, j = pixles.length; i < j; i += 4) {    // 因爲存儲的結構爲[R, G, B, A],所以要每次跳4個長度
          var a = pixles[i + 3];    // 拿到存儲alpha通道的值
          if (a === 0) {    // alpha通道爲0,就代表透明
              transPixs.push(i);
          }
      }
      // 全部的帶透明度和不帶透明度計算比例
      return (transPixs.length / (pixles.length / 4) * 100).toFixed(2);
  }
  // 繪製塗擦效果圓形
  // @param { integer } 圓心的x座標
  // @param { integer } 圓心的y座標
  // @param { integer } 圓心半徑
  // @param { string } 填充的顏色(本例中會通過其餘代碼設置爲‘透明’,所以這個設置可以忽略)
  let fillCircle = function (x, y, radius, fillColor) {
    this.fillStyle = fillColor || "#eee";
    this.beginPath();
    this.moveTo(x, y);
    this.arc(x, y, radius, 0, Math.PI * 2, false);    // 標準畫圓
    this.fill();
  };

  let int = () => {
    setResult('.word'); // 隨機設置中獎的結果
    setCanvas();  // 繪製畫布遮擋住底部中獎結果
    // 鼠標按下監聽
    canvasDom.addEventListener('mousedown', function(e) {
      startFill = true;
      let x = e.clientX;
      let y = e.clientY;
      canvasDomX.globalCompositeOperation = 'destination-out'; // 設置繪製時透明效果可以看到底部中獎結果
      fillCircle.call(canvasDomX, x, y, touchRadius, '#ccc');
    }, false);
    // 鼠標移動監聽
    canvasDom.addEventListener('mousemove', function(e) {
      if (startFill) {
        let x = e.clientX;
        let y = e.clientY;
        canvasDomX.globalCompositeOperation = 'destination-out';
        fillCircle.call(canvasDomX, x, y, touchRadius, '#ccc');
        let percent = getTransparentPercent(canvasDomX, 200, 100);
        console.log("當前塗抹比例爲: " + percent + " %");
        // 塗抹超過50%提示中獎信息
        if (percent > 50) {
          alert('您的中獎信息爲:' + document.querySelector('.word').innerHTML);
          startFill = false;
          document.location.reload();
        }
      }
    }, false);
    // 鼠標彈起監聽
    canvasDom.addEventListener('mouseup', function(e) {
      startFill = false;
    }, false);
  };
  
  // 頁面初始化
  int();
</script>
</html>

運行結果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章