整体功能

这段代码创建了一个全屏的 Canvas 元素,并在页面加载后自动启动一个动画,显示随机生成的白色光点。这些光点会向上飘动并逐渐消失,同时会有新的光点不断生成,形成持续的动画效果。

效果可查看页面

代码

<script>
function dotsCanvas() {
  const canvas = document.createElement('canvas');
  canvas.style.cssText = ['position: fixed', 'z-index: 2147483647', 'left: 0', 'top: 0', 'pointer-events: none'].join(';');
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  document.body.append(canvas);
  const context = canvas.getContext('2d');
  const dots = [];
  const TAU = Math.PI * 2;
  const timer = {
    now: 0,
    last: Date.now(),
    diff: 16.7 //animation frequency 60hz.
  };
  function createDot() {
    dots.push({
      x: Math.random() * canvas.width,
      y: Math.random() * canvas.height,
      radius: Math.random() + 1, //generate random in the range 1 - 2.
      opacity: 0.5 * (Math.random() + 1), //generate random in the range 0.5 - 1.
      speedX: Math.random() * 2 - 1, //generate random in the range -1 - 1
      speedY: -Math.random() * 0.1 - 0.5, //generate random in the range -0.6 - 0.5, moving upward, the speed of ascent decrease.
      angle: Math.random() * TAU, //generate random in the range 0 - TAU, initial angle random.
      angularSpeed: (Math.random() - 0.5) * 0.1 //generate random in the range -0.05 - 0.05, random angular speed increase.
    });
  }
  function updateDots() {
    for (let i = 0; i < dots.length; i++) {
      let dot = dots[i];
      dot.x += dot.speedX;
      dot.y += dot.speedY;
      dot.angle += dot.angularSpeed;
      dot.x += Math.sin(dot.angle) * 0.1; //left or right swing effect
      if (dot.opacity <= 0) {
        dots.splice(i, 1);
        i--;
        continue;
      }
      dot.opacity -= 0.01;
      context.beginPath();
      context.arc(dot.x, dot.y, dot.radius, 0, TAU);
      context.fillStyle = `rgba(255, 255, 255, ${dot.opacity})`;
      context.fill();
    }
  }
  function animate() {
    timer.now = Date.now();
    if (timer.now - timer.last > timer.diff) {
      timer.last = timer.now;
      context.clearRect(0, 0, canvas.width, canvas.height);
      if (dots.length < 10) createDot();
      updateDots();
    }
    requestAnimationFrame(animate);
  }
  function throttle(func, delay) {
    let timer = undefined;
    return function() {
      if (!timer) {
        timer = setTimeout(() => {
          func.apply(this, arguments);
          timer = undefined;
        }, delay);
      }
    };
  }
  window.addEventListener('resize', throttle(function() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
  }, 200));
  animate();
}
window.addEventListener('load', () => {
  dotsCanvas();
});
</script>
这个动画可以作为网页的背景效果,增添视觉吸引力,同时不会影响用户与页面的交互。