-
Notifications
You must be signed in to change notification settings - Fork 0
/
fireworks.js
86 lines (86 loc) · 2.56 KB
/
fireworks.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
78
79
80
81
82
83
84
85
86
const defaultColors = ["#2d80ee", "#1b4e8f", "#112e55"];
function fireworks(opts) {
if (!opts) {
throw new Error("Missing options for fireworks");
}
const {
x,
y,
canvasWidth = 300,
canvasHeight = 300,
particleTimeout = 1000,
colors = defaultColors,
bubbleSizeMinimum = 10,
bubbleSizeMaximum = 25,
bubbleSpeedMinimum = 6,
bubbleSpeedMaximum = 10,
count: bubbleCount = 25,
canvasLeftOffset = canvasWidth / 2,
canvasTopOffset = canvasHeight / 2,
parentNode = document.body,
} = opts;
const ratio = window.devicePixelRatio;
const cvs = document.createElement("canvas");
const ctx = cvs.getContext("2d");
if (!ctx) {
console.log(`fireworks: unable to get 2d canvas context`);
return;
}
cvs.style.zIndex = "100";
cvs.style.position = "absolute";
cvs.style.pointerEvents = "none";
cvs.style.top = `${y - canvasTopOffset}px`;
cvs.style.left = `${x - canvasLeftOffset}px`;
cvs.style.height = `${canvasHeight}px`;
cvs.style.width = `${canvasWidth}px`;
cvs.height = canvasHeight * ratio;
cvs.width = canvasWidth * ratio;
parentNode.appendChild(cvs);
let particles = [];
for (let i = 0; i < bubbleCount; i++) {
particles.push({
x: cvs.width / 2,
y: cvs.height / 2,
color: colors[Math.floor(Math.random() * colors.length)],
radius: randomRange(bubbleSizeMinimum, bubbleSizeMaximum),
speed: randomRange(bubbleSpeedMinimum, bubbleSpeedMaximum),
rotation: randomRange(0, 360, -1),
opacity: randomRange(0, 0.5, -1),
friction: 0.96,
gravity: 0.05,
yVel: 0,
});
}
// console.table(particles);
render(cvs.width, cvs.height, particles, ctx);
setTimeout(function () {
parentNode.removeChild(cvs);
}, particleTimeout);
}
function render(width, height, particles, ctx) {
requestAnimationFrame(() => {
render(width, height, particles, ctx);
});
ctx.clearRect(0, 0, width, height);
particles.forEach(function (p, i) {
p.x += p.speed * Math.cos((p.rotation * Math.PI) / 180);
p.y += p.speed * Math.sin((p.rotation * Math.PI) / 180);
p.opacity -= 0.005;
p.speed *= p.friction;
p.radius *= p.friction;
p.yVel += p.gravity;
p.y += p.yVel;
if (p.opacity < 0 || p.radius < 0) {
return;
}
ctx.beginPath();
ctx.globalAlpha = p.opacity;
ctx.fillStyle = p.color;
ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, false);
ctx.fill();
});
return ctx;
}
function randomRange(a, b, c = 0) {
return parseFloat((Math.random() * ((a ? a : 1) - (b ? b : 0)) + (b ? b : 0)).toFixed(c > 0 ? c : 0));
}