特效 - 刮刮卡

使用组合实现刮刮卡特效

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    html {
      width: 100vw;
      height: 100vh;
    }
    body {
      min-height: 100%;
      padding: 1vw;
      text-align: center;
    }
    #card {
      width: 540px;
      height: 200px;
      margin: 0 auto;
      background: url(https://img.xiaoyulive.top/img/date/20180913/Doraemon.png) no-repeat center;
      border: 1px solid rgba(0, 0, 0, .5);
    }
  </style>
</head>
<body class="container">
  <h1>刮刮卡来了,试试运气?</h1>
  <div id="card">
    <canvas id="canvasOne" width="500" height="300"></canvas>
  </div>
  <script>
    window.addEventListener('load', eventWindowLoaded, false);
    var Debugger = function () { };
    Debugger.log = function (message) {
      try {
        console.log(message);
      } catch (exception) {
        return;
      }
    }
    function eventWindowLoaded() {
      canvasApp();
    }
    function canvasApp() {
      Debugger.log('Drawing Canvas');
      var canvas = document.getElementById('canvasOne');
      var ctx = canvas.getContext('2d');
      var card = document.getElementById('card');
      var width = card.offsetWidth;
      var height = card.offsetHeight;
      canvas.width = width;
      canvas.height = height;
      var isDrawing;
      var lastPoint;
      var brush = new Image();
      brush.src = 'https://img.xiaoyulive.top/img/date/20180913/brush.png';
      canvas.addEventListener('mousedown', mouseDown, false);
      canvas.addEventListener('touchstart', mouseDown, false);
      canvas.addEventListener('mousemove', mouseMove, false);
      canvas.addEventListener('touchmove', mouseMove, false);
      canvas.addEventListener('mouseup', mouseUp, false);
      canvas.addEventListener('touchend', mouseUp, false);
	  // 返回两点之间的距离
      function distanceBetween(point1, point2) {
        return Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
      }
	  // 返回两点之间的角度
      function angleBetween(point1, point2) {
        return Math.atan2(point2.x - point1.x, point2.y - point1.y);
      }
      // Only test every 'stride' pixel. 'stride'x faster
      // but might lead to inaccuracy
      function getFilledInPixels(stride) {
        if (!stride || stride < 1) {
          stride = 1;
        }
        var pixels = ctx.getImageData(0, 0, width, height);
        var pdata = pixels.data;
        var len = pdata.length;
        var total = len / stride;
        var count = 0;
        // console.log(len);
        // Iterate over all pixels
        for (var i = 0; i < len; i += stride) {
          if (parseInt(pdata[i]) === 0) {
            count++;
          }
        }
        return Math.round((count / total) * 100);
      }
	  // 返回当前点击位置相对于canvas的偏移
      function getMouse(e, canvas) {
        var offsetX = 0;
        var offsetY = 0;
        var mx;
        var my;
        if (canvas.offsetParent !== undefined) {
          // while 将 canvas 赋予其相对偏移的父元素,当 canvas === null 时退出循环
          // 获取 canvas 相对于每一个父元素的偏移,得到的offsetX和offsetY为canvas相对于页面的偏移
          do {
            offsetX += canvas.offsetLeft;
            offsetY += canvas.offsetTop
          } while ((canvas = canvas.offsetParent));
        }
		// 获取点击位置相对canvas的偏移
        mx = (e.pageX || e.touches[0].clientX) - offsetX;
        my = (e.pageY || e.touches[0].clientY) - offsetY;
        return {
          x: mx,
          y: my
        }
      }
	  // 计算已显示区域所占百分比
      function handlePercentage(filledInPixels) {
        filledInPixels = filledInPixels || 0;
        console.log(filledInPixels + '%');
        // 当显示区域大于40%,则全部显示
        if (filledInPixels > 40) {
          canvas.parentNode.removeChild(canvas);
        }
      }
	  // 鼠标点击或手指按下时的处理
      function mouseDown(e) {
        isDrawing = true;
        // 记录起始点
        lastPoint = getMouse(e, canvas);
      }
      // 鼠标移动或手指移动是的处理
      function mouseMove(e) {
        if (!isDrawing) {
          return;
        }
		// 记录当前点
        var currentPoint = getMouse(e, canvas);
        // 获取当前点与上一个点的距离和角度
        var dist = distanceBetween(lastPoint, currentPoint);
        var angle = angleBetween(lastPoint, currentPoint);
        var x;
        var y;
        for (var i = 0; i < dist; i++) {
          x = lastPoint.x + Math.sin(angle) * i;
          y = lastPoint.y + Math.cos(angle) * i;
          // destination-out 模式相当于擦除效果
          ctx.globalCompositeOperation = 'destination-out';
          // 绘制笔刷
          ctx.drawImage(brush, x - 25, y - 25);
          // 或者下面的圆形笔擦
          // var radius = 10;
          // var fillStyle = '#fff';
          // ctx.beginPath();
          // ctx.arc(x, y, radius, 0, Math.PI * 2, true);
          // ctx.closePath();
          // ctx.fill();
        }
		// 为上一个点重新赋值
        lastPoint = currentPoint;
        handlePercentage(getFilledInPixels(32));
      }
	  // 鼠标抬起或手指抬起时的处理
      function mouseUp(e) {
        isDrawing = false;
      }
	  // 初始绘制
      function draw() {
        ctx.save();
        ctx.fillStyle = '#ddd';
        ctx.fillRect(0, 0, width - 2, height - 2);
        ctx.restore();
      }
      draw();
    }
  </script>
</body>
</html>

详见CodePen: Canvas: 刮刮卡

MIT Licensed | Copyright © 2018-present 滇ICP备16006294号

Design by Quanzaiyu | Power by VuePress