-
-
Notifications
You must be signed in to change notification settings - Fork 56
/
Copy pathconfetti.js
77 lines (69 loc) · 2.25 KB
/
confetti.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// @ts-check
// Confetti effect done manually (not using particle component)
kaplay();
const DEF_COUNT = 80;
const DEF_GRAVITY = 800;
const DEF_AIR_DRAG = 0.9;
const DEF_VELOCITY = [1000, 4000];
const DEF_ANGULAR_VELOCITY = [-200, 200];
const DEF_FADE = 0.3;
const DEF_SPREAD = 60;
const DEF_SPIN = [2, 8];
const DEF_SATURATION = 0.7;
const DEF_LIGHTNESS = 0.6;
add([
text("click for confetti"),
anchor("top"),
pos(center().x, 0),
]);
function addConfetti(opt = {}) {
const sample = (s) => typeof s === "function" ? s() : s;
for (let i = 0; i < (opt.count ?? DEF_COUNT); i++) {
const p = add([
pos(sample(opt.pos ?? vec2(0, 0))),
choose([
rect(rand(5, 20), rand(5, 20)),
circle(rand(3, 10)),
]),
color(
sample(
opt.color
?? hsl2rgb(rand(0, 1), DEF_SATURATION, DEF_LIGHTNESS),
),
),
opacity(1),
lifespan(4),
scale(1),
anchor("center"),
rotate(rand(0, 360)),
]);
const spin = rand(DEF_SPIN[0], DEF_SPIN[1]);
const gravity = opt.gravity ?? DEF_GRAVITY;
const airDrag = opt.airDrag ?? DEF_AIR_DRAG;
const heading = sample(opt.heading ?? 0) - 90;
const spread = opt.spread ?? DEF_SPREAD;
const head = heading + rand(-spread / 2, spread / 2);
const fade = opt.fade ?? DEF_FADE;
const vel = sample(
opt.velocity ?? rand(DEF_VELOCITY[0], DEF_VELOCITY[1]),
);
let velX = Math.cos(deg2rad(head)) * vel;
let velY = Math.sin(deg2rad(head)) * vel;
const velA = sample(
opt.angularVelocity
?? rand(DEF_ANGULAR_VELOCITY[0], DEF_ANGULAR_VELOCITY[1]),
);
p.onUpdate(() => {
velY += gravity * dt();
p.pos.x += velX * dt();
p.pos.y += velY * dt();
p.angle += velA * dt();
p.opacity -= fade * dt();
velX *= airDrag;
velY *= airDrag;
p.scale.x = wave(-1, 1, time() * spin);
});
}
}
onKeyPress("space", () => addConfetti({ pos: mousePos() }));
onMousePress(() => addConfetti({ pos: mousePos() }));