T.R.E. 飘动旗帜

实现原理:通过遍历 getImageData 函数返回的元素逐像素获取原始画布每个点的rgba值,然后每一帧通过运动函数对每个点的位置进行偏移,对比原画布,获取该点在原位置的rgba值,然后直接对a分量进行修改,修改的依据仍然是斜率。
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>T.R.E. 飘扬旗帜</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <style>
    * {
      margin: 0;
      padding: 0;
    }
    
    html,
    body {
      width: 100%;
      height: 100%;
    }
    
    #canvas {
      position: absolute;
      top: 50%;
      left: 50%;
      transform-origin: center;
      transform: translate3d(-50%, -50%, 0);
    }
  </style>
</head>

<body>
  <canvas id="canvas"></canvas>
  <script>
    var canvas = document.getElementById('canvas')
    var ctx = canvas.getContext('2d')

    var IMG_MAX_WIDTH = 600
    var IMG_MAX_HEIGHT = 600
    var imgWidth, imgHeight

    var image = new Image()
    image.src = 'tre.jpg'

    var amplitude = 25 // 振幅
    var period = 1.5 // 周期数
    var frequency = 1 // 频率
    var wavelength // 波长
    var v // 波速
    var cftX // x系数
    var cftA // 振幅系数

    image.onload = function(ev) {

      imgWidth = Math.floor(image.width)
      imgHeight = Math.floor(image.height)

      var canvas = document.getElementById('canvas')
      var scale = 1
      if (imgWidth > IMG_MAX_WIDTH) {
        scale = IMG_MAX_WIDTH / imgWidth
      }
      if (imgHeight > IMG_MAX_HEIGHT) {
        scale = scale * IMG_MAX_HEIGHT / imgHeight
      }

      canvasWidth = imgWidth
      canvasHeight = imgHeight + amplitude * 2
      canvas.width = canvasWidth
      canvas.height = canvasHeight


      wavelength = imgWidth / period
      cftX = 2 * Math.PI / wavelength
      cftA = amplitude / imgWidth
      v = wavelength * frequency

      tick()
    }

    var fps = 60 // 每秒帧数
    var interval = 1000 / fps // 连续帧之间间隔(理论)
    var stop = false // 停止动画
    var timeNow = Date.now() // 当前时间
    var timeLast = timeNow // 上一帧时间
    var delta = 0 // 连续帧之间间隔(实际)

    var y = 0
    var lastY = 0
    var distance = 0
    var tick = function() {
      if (stop) return false
      timeNow = Date.now()
      delta = timeNow - timeLast
      if (delta > interval) {
        timeLast = timeNow
        distance += (delta / 1000 * v)
        ctx.clearRect(0, 0, canvasWidth, canvasHeight)
        for (var x = 0; x < imgWidth; x++) {
          y = cftA * x * Math.sin(cftX * (x - distance)) + amplitude
          ctx.drawImage(image, x, 0, 1, imgHeight, x, y, 1, imgHeight)
          ctx.fillStyle = 'rgba(255,255,255,' + (x === 0 ? 0 : (y - lastY) * 0.5) + ')'
          ctx.fillRect(x, y, 1, imgHeight)
          lastY = y
        }
      }
      requestAnimationFrame(tick)
    }
  </script>
</body>

</html>

本文链接地址: T.R.E. 飘动旗帜

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注