Javascript: Confetti Particles Falling Down In Canvas
Solution 1:
Skew using setTransform
You want to rotate the particles local x axis over time. The x axis is the first two arguments of setTransform
. To rotate that axis over time you use cos(angle)
and sin(angle)
to set the x and y component of the x axis.
As you want that to be local to the particle you need to also set the particle origin (point of rotation) and then draw the particle at 0,0. The origin is the last two arguments of setTransform
The draw function you want is
draw() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.setTransform(
Math.cos(this.tiltAngle), // set the x axis to the tilt angle
Math.sin(this.tiltAngle),
0, 1,
this.x, this.y // set the origin
);
ctx.arc(0, 0, (this.r / 2), 0, Math.PI * 2, false); // draw at origin (0,0)
ctx.fill();
}
Example
Looking at the code at the fiddle given, i could not work out what they were trying to do as it was way over complicated, so I rewrote the whole thing which now takes a 3rd as much code and no jQuery.
Run demo for the FX you are after...
maybe????
(function () {
requestAnimationFrame(mainLoop);
const ctx = canvas.getContext("2d");
var W,H;
var confetti = newParticles();
var droppedCount = 0;
var particlesPerFrame = 1.5;
var wind = 0;
var windSpeed = 1;
const windSpeedMax = 1;
const windChange = 0.01;
const windPosCoef = 0.002;
const maxParticlesPerFrame = 2; //max particles dropped per framevar id = 0;
stopButton.addEventListener("click",() => particlesPerFrame = 0 );
startButton.addEventListener("click",() => particlesPerFrame = maxParticlesPerFrame);
constrandI = (min, max = min + (min = 0)) => (Math.random() * (max - min) + min) | 0;
constrand = (min = 1, max = min + (min = 0)) => Math.random() * (max - min) + min;
const colors = {
options: "DodgerBlue,OliveDrab,Gold,pink,SlateBlue,lightblue,Violet,PaleGreen,SteelBlue,SandyBrown,Chocolate,Crimson".split(","),
index: 0,
step: 10,
getcolor() { return colors.options[((colors.index++) / colors.step | 0) % colors.options.length] }
}
functionConfetti() { this.setup() }
Confetti.prototype = {
setup(){
this.x = rand(-35,W + 35);
this.y = rand(-30,-35);
this.r = rand(10, 30);
this.d = rand(150) + 10; //density;this.color = colors.color;
this.tilt = randI(10);
this.tiltAngleIncremental = (rand(0.08) + 0.04) * (rand() < 0.5 ? -1 : 1);
this.tiltAngle = 0;
this.angle = rand(Math.PI * 2);
this.id = id++;
returnthis;
},
update() {
this.tiltAngle += this.tiltAngleIncremental * (Math.cos(wind + (this.d + this.x + this.y) * windPosCoef) * 0.2 + 1);
this.y += (Math.cos(this.angle + this.d) + 3 + this.r / 2) / 2;
this.x += Math.sin(this.angle);
this.x += Math.cos(wind + (this.d + this.x + this.y) * windPosCoef) * windSpeedMax;
this.y += Math.sin(wind + (this.d + this.x + this.y) * windPosCoef) * windSpeedMax;
this.tilt = (Math.sin(this.tiltAngle - (this.id / 3))) * 15;
returnthis.y > H; // returns true if particle is past bottom
},
draw() {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.setTransform(
Math.cos(this.tiltAngle), // set the x axis to the tilt angleMath.sin(this.tiltAngle),
0, 1,
this.x, this.y// set the origin
);
ctx.arc(0, 0, (this.r / 2), 0, Math.PI * 2, false);
ctx.fill();
}
}
functionParticles() {
const items = [];
const pool = [];
this.update = function() {
for (var i = 0; i < items.length; i++) {
if(items[i].update() === true){ pool.push(items.splice(i--,1)[0]) }
}
}
this.draw = function() { for (var i = 0; i < items.length; i++) { items[i].draw() } }
this.add = function() {
if (pool.length > 0) { items.push(pool.pop().setup()) }
else { items.push(newConfetti()) }
}
}
functionmainLoop(time) {
if (W !== innerWidth || H !== innerHeight) {
W = canvas.width = innerWidth;
H = canvas.height = innerHeight;
} else {
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0, 0, W, H);
}
windSpeed = Math.sin(time / 8000) * windSpeedMax;
wind += windChange;
while(droppedCount < particlesPerFrame){
droppedCount += 1;
confetti.add();
}
droppedCount -= particlesPerFrame;
confetti.update();
confetti.draw();
requestAnimationFrame(mainLoop);
}
})();
* {
margin: 0;
padding: 0;
}
body {
/*You can use any kind of background here.*/background: transparent;
}
canvas {
display: block;
position: relative;
zindex: 1;
pointer-events: none;
}
#content {
text-align: center;
width: 500px;
height: 300px;
position: absolute;
top: 50%;
left: 50%;
margin-left: -250px;
margin-top: -150px;
color: silver;
font-family: verdana;
font-size: 45px;
font-weight: bold;
}
.buttonContainer {
display: inline-block;
}
button {
padding: 5px10px;
font-size: 20px;
}
<divid="content">
Confetti World
<br /> I 💙 confetti!
<br /><divclass="buttonContainer"><buttonid="stopButton">Stop Confetti</button><buttonid="startButton">Drop Confetti</button></div></div><canvasid="canvas"></canvas>
Note Some of this code and content has been copied from this fiddle.
Post a Comment for "Javascript: Confetti Particles Falling Down In Canvas"