示例6 - canvas绘制彩虹雨

112 阅读1分钟

html:

  <body>
    <canvas id="c"></canvas>
  </body>

css:

    body {
      background-color: black;
    }
    #c {
      opacity: 0.8;
    }
    canvas {
      position: absolute;
      top: 0;
      left: 0;
    }

js:

    // 初始化
    let c = document.getElementById('c');
    let bg = document.getElementById('bg');
    const w = (c.width = window.innerWidth);
    const h = (c.height = window.innerHeight);
    const ctx = c.getContext('2d');
    const accelleration = 0.02; // 控制雨点下落的速度
    const total = w;
    const size = w / total;
    const occupation = w / total;
    const repaintColor = 'rgba(0, 0, 0, .1)';
    const colors = [];
    const dots = [];
    const dotsVel = [];

    /* 360/total 表示颜色范围,这里用色相表示,所有颜色都在一个色相环里 */
    var portion = 360 / total;
    for (var i = 0; i < total; ++i) {
      colors[i] = portion * i;
      dots[i] = h; // 屏幕高度
      dotsVel[i] = 10; // 10?
    }

    function draw() {
      window.requestAnimationFrame(draw);

      /* 相当于给整个屏幕重新刷漆。repaintColor(透明度) 值越大,雨点的拖尾效果越小 */
      ctx.fillStyle = repaintColor;
      ctx.fillRect(0, 0, w, h);

      for (var i = 0; i < total; ++i) {
        var currentY = dots[i] - 1;
        dots[i] += dotsVel[i] += accelleration;

        ctx.fillStyle = 'hsl(' + colors[i] + ', 80%, 50%)';
        /* *绘制* */
        /* (x = 当前列; y; 宽度为1; 高度为 ) */
        ctx.fillRect(occupation * i, currentY, 2, dotsVel[i] + 1);

        if (dots[i] > h && Math.random() < 0.001) {
          dots[i] = dotsVel[i] = 0;
        }
      }
    }

    draw();
    /**
     * 问题:这个anim()方法中在一个requestAnimationFrame周期中一共绘制了多少次:
     * 1 - 单次绘制:重新给页面画上黑色的背景
     * 2 - for{}循环:循环了屏幕宽度那么多次,每次循环绘制一个雨点
     *
     * 如果当前列的雨点超出了屏幕的高度,且加一个随机数,重置当前雨点到原点
     */

成品:

image.png