我找到了这个很棒的脚本,让它下雨五彩纸屑:http://jsfiddle.net/hcxabsgh/请注意粒子如何具有这种扭曲/转动/倾斜效果,以使其感觉更自然。
我一直在尝试使粒子变圆,这也很好用:http://jsfiddle.net/rqr9hb7x/2/
但是我无法像矩形示例中那样让粒子绕其轴扭曲/转动/倾斜。
我认为它应该可以使用ctx.setTransform(),因为它处理倾斜参数,但它似乎扭曲了整个画布而不是单个粒子。有人知道如何正确处理这个问题吗?
this.draw = function () {
ctx.beginPath();
ctx.save();
//ctx.setTransform(1, 0, 0, 1, 0, 0); // straigt
ctx.setTransform(1, .3, 0, .7, 0, 0); // skewed - to make dynamic
ctx.arc(this.x + this.tilt, this.y + this.tilt + (this.r / 4), (this.r / 2), 0, Math.PI * 2, false);
ctx.restore();
ctx.fillStyle = this.color;
return ctx.fill();
}
使用 setTransform
倾斜
您希望随时间旋转粒子的局部 x 轴。x 轴是 setTransform
的前两个参数。要随时间旋转该轴,请使用 cos(angle)
和 sin(angle)
来设置 x 轴的 x 和 y 分量。
由于您希望它是粒子的局部,因此您还需要设置粒子原点(旋转点),然后将粒子绘制为 0,0。起源是setTransform
的最后两个参数
您想要的绘制函数是
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();
}
例
看着给定的小提琴代码,我无法弄清楚他们试图做什么,因为它太复杂了,所以我重写了整个事情,现在需要第三种代码并且没有jQuery。
运行您追求的外汇的演示...
或????
(function () {
requestAnimationFrame(mainLoop);
const ctx = canvas.getContext("2d");
var W,H;
var confetti = new Particles();
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 frame
var id = 0;
stopButton.addEventListener("click",() => particlesPerFrame = 0 );
startButton.addEventListener("click",() => particlesPerFrame = maxParticlesPerFrame);
const randI = (min, max = min + (min = 0)) => (Math.random() * (max - min) + min) | 0;
const rand = (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,
get color() { return colors.options[((colors.index++) / colors.step | 0) % colors.options.length] }
}
function Confetti() { 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++;
return this;
},
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;
return this.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 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);
ctx.fill();
}
}
function Particles() {
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(new Confetti()) }
}
}
function mainLoop(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: 5px 10px;
font-size: 20px;
}
<div id="content">
Confetti World
<br /> I 💙 confetti!
<br />
<div class="buttonContainer">
<button id="stopButton">Stop Confetti</button>
<button id="startButton">Drop Confetti</button>
</div>
</div>
<canvas id="canvas"></canvas>
注意:其中一些代码和内容是从这个小提琴复制的。