I'm currently trying to make a sparkle effect that happens within the canvas. However, as I was testing out the animation, I noticed that some circles would be erased for a frame, and then reappear again.
This seems to be caused when a sparkle of a higher index is removed by splicing. You can notice the flash whenever a sparkle shrinks to a radius of 0. If this is the actual reason why it causes the issue, I really don't understand why splicing would cause such an issue.
https://jsfiddle.net/sketti21/2gfarp74/82/
// Handles the animation of the sparkles.
function animate(timestamp)
{
// Observe the timestamp gives by requestAnimationFrame in console.
// console.log(timestamp);
// Clears the previous frame;
draw.clearRect(0, 0, canvas.width, canvas.height);
// Loop through each index of sparkles. Doing this lets us draw multiple
// sparkles at once.
for (i = 0; i < sparkles.length; i++)
{
if (sparkles[i] != null)
{
// If the sparkle's delay is not set, then set it.
// This is necessary to do here since the timestamp that requestAnimationFrame
// puts in as a parameter is always growing.
if (sparkles[i].delay == null)
{
sparkles[i].delay = Math.floor(Math.random()*config.maxDelay) + timestamp;
}
// Handles whether to animate the next frame or to remove this sparkle from array.
// If timestamp is larger than sparkle's delay, this means it's time to
// animate this sparkle.
if (timestamp > sparkles[i].delay)
{
// Increment the input variable and calculate the radius of circle.
sparkles[i].inputX += config.increment;
var radius = getRadius(sparkles[i].inputX, sparkles[i].multiplier);
console.log("Radius of index " + i + ": " + radius);
console.log("Multiplier of index " + i + ": " + sparkles[i].multiplier);
if (radius < 0)
{
radius = 0;
}
// Drawing the circle.
draw.beginPath();
draw.arc(sparkles[i].x,
sparkles[i].y,
radius, 0, 360);
draw.fill();
draw.closePath();
// If the sparkle's radius drops below 0, then remove it from the array.
if (radius == 0)
{
sparkles.splice(i, 1);
console.log("spliced indexes " + i + " to " + (i + 1));
}
}
}
}
if (sparkles.length > 0)
{
animControl = window.requestAnimationFrame(animate);
}
else
{
console.log("Refilled the array.");
for (i = 0; i < config.maxSparkles; i++)
{
sparkles[i] = new Sparkle();
}
animControl = window.requestAnimationFrame(animate);
}
}
Let me summarize the logic of my code to make reading through it quicker and easier:
- Create the sparkles array.
- Start the animation. (animate())
- Clear the canvas.
- Fill sparkles array up to config.maxSparkles.
- requestAnimationFrame(animate)
- Clear the canvas.
- If a random delay hasn't been assigned to the Sparkle object, then calculate a delay that's below config.maxDelay and add the timestamp.
If the current timestamp is greater than the Sparkle's delay..
8a. Calculate and draw each sparkle individually for this frame.
8b. If the Sparkle radius = 0, then splice that sparkle out of the sparkles array.
If there are elements in the sparkles array, then requestAnimationFrame(animate)
9a. Else, refill the array up to config.maxSparkles.
... So on and so forth.
Any help is greatly appreciated!