On my canvas I have 2 types of circles :
those I created directly from the context (= decorativeStars):
drawDecorativeStar = (decorativeStar) => {
this.ctx.beginPath();
this.ctx.arc(decorativeStar.x, decorativeStar.y, decorativeStar.radius, 0, 2 * Math.PI);
this.ctx.fillStyle = "rgba(254, 255, 242," + decorativeStar.alpha + ")";
this.ctx.fill();
this.ctx.closePath();
}
and those created as Path2D because I wanted them to be clickable (=planetPaths):
createPlanetPaths = (planets) => {
for (var i = 0; i < planets.length; i++) {
this.planetPaths[i] = {
ref: new Path2D(),
x: Math.random() * WIDTH_CANVAS,
y: Math.random() * HEIGHT_CANVAS,
radius: this.getPlanetRadius(planets[i]),
color: planets[i].color,
}
}
}
drawPlanets = (planetPaths) => {
for (let i = 0; i < planetPaths.length; i++) {
planetPaths[i].ref.arc(planetPaths[i].x, planetPaths[i].y, planetPaths[i].radius, 0, 2 * Math.PI);
planetPaths[i].ref.gradient = this.ctx.createLinearGradient((planetPaths[i].x - planetPaths[i].radius), (planetPaths[i].y - planetPaths[i].radius), 1.02 * (planetPaths[i].x + planetPaths[i].radius), 1.02 * (planetPaths[i].y + planetPaths[i].radius));
planetPaths[i].ref.gradient.addColorStop(0, planetPaths[i].color);
planetPaths[i].ref.gradient.addColorStop(1, 'red');
this.ctx.fillStyle = planetPaths[i].ref.gradient;
this.ctx.fill(planetPaths[i].ref);
}
};
Now i'd like to animate these circles, using requestAnimationFrame. My problem is that this.ctx.clearRect(0, 0, WIDTH_CANVAS, HEIGHT_CANVAS);
seem to have no effect on the Path2D objects, while it works for the others.
Is there another way to clear Path2D objects?
EDIT, here my updateCanvas method, to generate the animation:
updateCanvas() {
this.ctx.clearRect(0, 0, WIDTH_CANVAS, HEIGHT_CANVAS);
for (let i = 0; i < this.planetPaths.length; i++) {
var planetPath = this.planetPaths[i];
if (planetPath.x < WIDTH_CANVAS) {
planetPath.x += 1;
} else {
planetPath.x = 0;
}
}
for (let i = 0; i < this.decorativeStars.length; i++) {
var star = this.decorativeStars[i];
if (star.decreasing == true) {
star.alpha -= star.decreasingIncreasingRatio;
if (star.alpha < 0.10) { star.decreasing = false; }
}
else {
star.alpha += star.decreasingIncreasingRatio;
if (star.alpha > 0.95) { star.decreasing = true; }
}
// star.x+=0.01;
}
this.drawDecorativeStars(this.decorativeStars);
this.drawPlanets(this.planetPaths);
this.myReq = requestAnimationFrame(this.updateCanvas);
}
You are using the Path2D object incorrectly.
In the drawPlanets
function you are adding sub-paths to the path each time you call draw.
planetPaths[i].ref.arc(planetPaths[i].x, planetPaths[i].y, planetPaths[i].radius, 0, 2 * Math.PI);
Thus every time you draw the path with this.ctx.fill(planetPaths[i].ref);
you draw all the sub paths you have added up to that time.
Path2D
Path2D
object.Path2D
or transform the path when you render it.Create the path and all unchanging states once (init), then render many times (each frame)
You code should look more like...
createPlanetPaths = planets => {
for (const planet of planets) {
const path = new Path2D();
const x = Math.random() * WIDTH_CANVAS;
const y = Math.random() * HEIGHT_CANVAS;
const radius = this.getPlanetRadius(planet);
path.arc(x, y, radius, 0, 2 * Math.PI);
const gradient = this.ctx.createLinearGradient((px - radius), (y - radius), 1.02 * (x + radius), 1.02 * (y + radius));
gradient.addColorStop(0, planet.color);
gradient.addColorStop(1, 'red');
this.planetPaths[i] = {path, gradient};
}
}
drawPlanets = planetPaths => {
for (const planetPath of planetPaths) {
this.ctx.fillStyle = planetPath.gradient;
this.ctx.fill(planetPath.path);
}
}