You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Canvas带编号平移动画实现各圆生成不同1-60随机数的问题

实现思路与修改方案

问题根因

  • 全局的randomNumber仅在代码初始化时生成一次,所有圆绘制时都读取同一个固定值,所以编号完全一致
  • 描边颜色的判断逻辑仅全局执行一次,无法适配不同编号的圆的配色规则

修改思路

  1. 预先创建1-60的数字池,每次取随机数后从池中移除,保证所有圆的编号不重复
  2. 每个Circle实例创建时单独分配随机编号、计算对应描边颜色,作为实例自有属性存储,不依赖全局变量
  3. 绘制时读取当前实例自身的编号和颜色属性

完整修改后代码

// Single Animated Circle - Get Canvas element by Id
var canvas = document.getElementById("canvas");

// Set Canvas dimensions
canvas.width = 300;
canvas.height = 900;

// Get drawing context
var ctx = canvas.getContext("2d");

// Radius
var radius = 13;
// Starting Position
var x = radius;
var y = radius;

// Speed in x and y direction
var dx = 1;
var dy = 0;

// 生成1-60数字池,用于获取不重复随机数
function createNumberPool() {
  const pool = []
  for(let i = 1; i <= 60; i++) {
    pool.push(i)
  }
  return pool
}
const numberPool = createNumberPool()
// 从数字池中取随机数
function getUniqueRandomNum() {
  const randomIndex = Math.floor(Math.random() * numberPool.length)
  return numberPool.splice(randomIndex, 1)[0]
}

class Circle {
  constructor(data) {
    this.data = data;
    // 每个实例单独分配唯一随机编号
    this.number = getUniqueRandomNum()
    // 计算当前编号对应的描边颜色
    if (this.number > 0 && this.number <= 10) {
      this.strokeStyle = "#0b0bf1";
    } else if (this.number > 10 && this.number <= 20) {
      this.strokeStyle = "#f10b0b";
    } else if (this.number > 20 && this.number <= 30) {
      this.strokeStyle = "#0bf163";
    } else if (this.number > 30 && this.number <= 40) {
      this.strokeStyle = "#f1da0b";
    } else if (this.number > 40 && this.number <= 50) {
      this.strokeStyle = "#950bf1";
    } else if (this.number > 50 && this.number <= 60) {
      this.strokeStyle = "#0bf1e5";
    }
  }

  draw() {
    if (
      this.data.x + this.data.radius > 300 ||
      this.data.x - this.data.radius < 0
    ) {
      this.data.x = this.data.radius;
    }
    this.data.x += this.data.dx;

    ctx.beginPath();
    ctx.arc(this.data.x, this.data.y, this.data.radius, 0, Math.PI * 2, false);
    // 使用当前实例对应的描边颜色
    ctx.strokeStyle = this.strokeStyle
    ctx.stroke();
    // 使用当前实例的编号绘制文本
    ctx.fillText(this.number, this.data.x - 5, this.data.y + 3);
  }
}

circles = [];

circles.push(new Circle({ radius, x, y, dx, dy }));
setTimeout(function () {
  circles.push(new Circle({ radius, x, y: y * 4, dx, dy }));
}, 500);
setTimeout(function () {
  circles.push(new Circle({ radius, x, y: y * 8, dx, dy }));
}, 1000);
setTimeout(function () {
  circles.push(new Circle({ radius, x, y: y * 12, dx, dy }));
}, 1500);
setTimeout(function () {
  circles.push(new Circle({ radius, x, y: y * 16, dx, dy }));
}, 2000);
setTimeout(function () {
  circles.push(new Circle({ radius, x, y: y * 20, dx, dy }));
}, 2500);

function animate3() {
  requestAnimationFrame(animate3);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  circles.forEach((item) => item.draw());
}
animate3();

内容的提问来源于stack exchange,提问作者Pedro Fernandes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 18:06:00