Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

99
Views
Animating multiple circles in a canvas

I'm trying to make an animation inside a canvas: here, a numbered circle must be drawn and move from left to right one single time, disappearing as soon as it reaches the end of animation.

For now I managed to animate it in loop, but I need to animate at the same time (or with a set delay) multiple numbered circles, strating in different rows (changing y position) so they wont overlap.

Any idea how can I manage this? my JS code is the following:

// 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;

// Generate random number
var randomNumber = Math.floor(Math.random() * 60) + 1;

if (randomNumber > 0 && randomNumber <= 10) {
  ctx.strokeStyle = "#0b0bf1";
} else if (randomNumber > 10 && randomNumber <= 20) {
  ctx.strokeStyle = "#f10b0b";
} else if (randomNumber > 20 && randomNumber <= 30) {
  ctx.strokeStyle = "#0bf163";
} else if (randomNumber > 30 && randomNumber <= 40) {
  ctx.strokeStyle = "#f1da0b";
} else if (randomNumber > 40 && randomNumber <= 50) {
  ctx.strokeStyle = "#950bf1";
} else if (randomNumber > 50 && randomNumber <= 60) {
  ctx.strokeStyle = "#0bf1e5";
}

function animate3() {
  requestAnimationFrame(animate3);

  ctx.clearRect(0, 0, 300, 900);

  if (x + radius > 300 || x - radius < 0) {
    x = radius;
  }

  x += dx;

  ctx.beginPath();
  ctx.arc(x, y, 12, 0, Math.PI * 2, false);
  ctx.stroke();
  ctx.fillText(randomNumber, x - 5, y + 3);
}

// Animate the Circle

animate3();
<canvas id="canvas"></canvas>

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Here is a solution which doesn't use classes as such and separates the animation logic from the updating - which can be useful if you want more precise control over timing.

// Some helper functions
const clamp = (number, min, max) => Math.min(Math.max(number, min), max);

// Choose and remove random member of arr with equal probability 
const takeRandom = arr => arr.splice(parseInt(Math.random() * arr.length), 1)[0]

// Call a function at an interval, passing the amount of time that has passed since the last call
function update(callBack, interval) {
  let now = performance.now();
  let last;
  setInterval(function() {
    last = now;
    now = performance.now();
    callBack((now - last) / 1000);
  })
}

const settings = {
  width: 300,
  height: 150,
  radius: 13,
  gap: 5,
  circles: 5,
  maxSpeed: 100,
  colors: ["#0b0bf1", "#f10b0b", "#0bf163", "#f1da0b", "#950bf1", "#0bf1e5"]
};
const canvas = document.getElementById("canvas");
canvas.width = settings.width;
canvas.height = settings.height;
const ctx = canvas.getContext("2d");

// Set circle properties
const circles = [...Array(settings.circles).keys()].map(i => ({
  number: i + 1,
  x: settings.radius,
  y: settings.radius + (settings.radius * 2 + settings.gap) * i,
  radius: settings.radius,
  dx: settings.maxSpeed * Math.random(), // This is the speed in pixels per second
  dy: 0,
  color: takeRandom(settings.colors)
}));

function drawCircle(circle) {
  ctx.strokeStyle = circle.color;
  ctx.beginPath();
  ctx.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2, false);
  ctx.stroke();
  ctx.fillText(circle.number, circle.x - 5, circle.y + 3);
}

function updateCircle(circle, dt) {
  // Update a circle's position after dt seconds
  circle.x = clamp(circle.x + circle.dx * dt, circle.radius + 1, settings.width - circle.radius - 1);
  circle.y = clamp(circle.y + circle.dy * dt, circle.radius + 1, settings.height - circle.radius - 1);
}

function animate() {
  ctx.clearRect(0, 0, settings.width, settings.height);
  circles.forEach(drawCircle);
  requestAnimationFrame(animate);
}

update(dt => circles.forEach(circle => updateCircle(circle, dt)), 50);
animate();
<canvas id="canvas" style="border: solid 1px black"></canvas>

about 4 years ago · Juan Pablo Isaza Report

0

Here I transformed your sample code into a class ...
We pass all the data as a parameter, you can see that in the constructor, I simplified a lot of your code to keep it really short, but all the same drawing you did is there in the draw function

Then all we need to do is create instances of this class and call the draw function inside that animate3 loop you already have.

You had a hardcoded value on the radius:
ctx.arc(x, y, 12, 0, Math.PI * 2, false)
I assume that was a mistake and fix it on my code

var canvas = document.getElementById("canvas");
canvas.width = canvas.height = 300;
var ctx = canvas.getContext("2d");

class Circle {
  constructor(data) {
    this.data = data
  }

  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.stroke();
    ctx.fillText(this.data.number, this.data.x - 5, this.data.y + 3);
  }
}

circles = []
circles.push(new Circle({radius:13, x: 10, y: 15, dx: 1, dy: 0, number: "1"}))
circles.push(new Circle({radius:10, x: 10, y: 50, dx: 2, dy: 0, number: "2"}))


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

Code should be easy to follow let me know if you have any questions

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!