js实现粒子时钟特效(渡一)

该代码示例展示了如何用JavaScript和HTML5Canvas创建一个粒子时钟效果。它涉及到粒子的生成、移动以及根据时间文本更新粒子位置,同时利用getImageData方法检测文本颜色来确定粒子的起点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

js实现粒子时钟特效

源码:
JS

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d', {
  willReadFrequently: true,
});

function initCanvasSize() {
  canvas.width = window.innerWidth * devicePixelRatio;
  canvas.height = window.innerHeight * devicePixelRatio;
}

initCanvasSize();

/**
 * 获取 [min, max] 范围内的随机整数
 */
function getRandom(min, max) {
  return Math.floor(Math.random() * (max + 1 - min) + min);
}

class Particle {
  constructor() {
    const r = Math.min(canvas.width, canvas.height) / 2;
    const cx = canvas.width / 2;
    const cy = canvas.height / 2;
    const rad = (getRandom(0, 360) * Math.PI) / 180;
    this.x = cx + r * Math.cos(rad);
    this.y = cy + r * Math.sin(rad);
    this.size = getRandom(2 * devicePixelRatio, 7 * devicePixelRatio);
  }

  draw() {
    ctx.beginPath();
    ctx.fillStyle = '#5445544d';
    ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
    ctx.fill();
  }

  moveTo(tx, ty) {
    const duration = 500; // 500ms的运动时间
    const sx = this.x,
      sy = this.y;
    const xSpeed = (tx - sx) / duration;
    const ySpeed = (ty - sy) / duration;
    const startTime = Date.now();
    const _move = () => {
      const t = Date.now() - startTime;
      const x = sx + xSpeed * t;
      const y = sy + ySpeed * t;
      this.x = x;
      this.y = y;
      if (t >= duration) {
        this.x = tx;
        this.y = ty;
        return;
      }
      // x,y改动一点
      requestAnimationFrame(_move);
    };
    _move();
  }
}

const partciles = [];
let text = null;
function clear() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
}

function draw() {
  clear();
  update();
  partciles.forEach((p) => p.draw());
  requestAnimationFrame(draw);
}

draw();

function getText() {
  return new Date().toTimeString().substring(0, 8);
}

function update() {
  const newText = getText();
  if (newText === text) {
    return;
  }
  clear();
  text = newText;
  // 画文本
  const { width, height } = canvas;
  ctx.fillStyle = '#000';
  ctx.textBaseline = 'middle';
  ctx.font = `${140 * devicePixelRatio}px 'DS-Digital', sans-serif`;
  ctx.fillText(text, (width - ctx.measureText(text).width) / 2, height / 2);
  const points = getPoints();
  clear();
  for (let i = 0; i < points.length; i++) {
    let p = partciles[i];
    if (!p) {
      p = new Particle();
      partciles.push(p);
    }
    const [x, y] = points[i];
    p.moveTo(x, y);
  }
  if (points.length < partciles.length) {
    partciles.splice(points.length);
  }
}

function getPoints() {
  const { width, height, data } = ctx.getImageData(
    0,
    0,
    canvas.width,
    canvas.height
  );
  const points = [];
  const gap = 6;
  for (let i = 0; i < width; i += gap) {
    for (let j = 0; j < height; j += gap) {
      const index = (i + j * width) * 4;
      const r = data[index];
      const g = data[index + 1];
      const b = data[index + 2];
      const a = data[index + 3];
      if (r === 0 && g === 0 && b === 0 && a === 255) {
        points.push([i, j]);
      }
    }
  }
  return points;
}

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>颗粒时钟</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      canvas {
        background: radial-gradient(#fff, #8c738c);
        display: block;
        width: 100vw;
        height: 100vh;
      }
    </style>
  </head>
  <body>
    <canvas></canvas>
    <script src="./index.js"></script>
  </body>
</html>

拿都拿了,点个赞收藏一下吧~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值