PluginProbe
Extendify / 3.2.1
Extendify v3.2.1
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
← All changes | src/Agent/lib/confetti.js +82 -9 3.1.23.2.1 View file →
@@ -1,6 +1,8 @@
1 1 import confetti from 'canvas-confetti';
2 2
3 +export const CANVAS_CONFETTI = 'extendify-agent:canvas-confetti';
4 +
3 5 let confettiInstance = null;
4 6
5 7 const ensureConfettiInstance = () => {
6 8 if (confettiInstance) return confettiInstance;
@@ -22,9 +24,77 @@
22 24 });
23 25 return confettiInstance;
24 26 };
25 27
26 -export const throwSideConfetti = () => {
28 +// Its own canvas is what confines a burst to the element that asked.
29 +export const confettiIn = (canvas) =>
30 + confetti.create(canvas, { disableForReducedMotion: true, resize: true });
31 +
32 +const TOP = () => ({ x: Math.random(), y: 0 });
33 +
34 +// A zero start velocity is what makes it fall rather than be thrown.
35 +export const FALLING = {
36 + interval: 55,
37 + perDrop: 2,
38 + drift: 0.5,
39 + origin: TOP,
40 + colors: [
41 + '#26ccff',
42 + '#a25afd',
43 + '#ff5e7e',
44 + '#88ff5a',
45 + '#fcff42',
46 + '#ffa62d',
47 + '#ff36ff',
48 + ],
49 + shot: {
50 + particleCount: 1,
51 + startVelocity: 0,
52 + gravity: 0.9,
53 + ticks: 300,
54 + scalar: 0.85,
55 + },
56 +};
57 +
58 +// An absent interval is what makes it fire once instead of repeating.
59 +export const THROW = {
60 + perDrop: 2,
61 + origin: (i) => ({ x: i, y: 0.75 }),
62 + shot: {
63 + particleCount: 70,
64 + startVelocity: 50,
65 + spread: 75,
66 + decay: 0.91,
67 + ticks: 220,
68 + scalar: 0.95,
69 + },
70 +};
71 +
72 +const pick = (list) => list[Math.floor(Math.random() * list.length)];
73 +
74 +// A multi-particle shot cannot spread at zero velocity, so it lands as one clump.
75 +// A one-particle shot takes only the first colour of the palette.
76 +export const dropConfetti = (
77 + shoot,
78 + { interval, shot, drift = 0, perDrop = 1, colors, origin = TOP },
79 +) => {
80 + const drop = () => {
81 + for (let i = 0; i < perDrop; i++) {
82 + shoot({
83 + ...shot,
84 + origin: origin(i),
85 + ...(drift && { drift: (Math.random() * 2 - 1) * drift }),
86 + ...(colors && { colors: [pick(colors)] }),
87 + });
88 + }
89 + };
90 + drop();
91 + if (!interval) return () => {};
92 + const timer = setInterval(drop, interval);
93 + return () => clearInterval(timer);
94 +};
95 +
96 +export const throwSideConfetti = (shoot) => {
27 97 const LEFT = {
28 98 count: 200,
29 99 defaults: {
30 100 origin: { y: 0.7, x: 0 },
@@ -36,20 +106,23 @@
36 106 { ratio: 0.1, spread: 120, startVelocity: 25, decay: 0.92, scalar: 1.2 },
37 107 { ratio: 0.1, spread: 120, startVelocity: 45 },
38 108 ],
39 109 };
40 - throwConfetti(LEFT);
41 - throwConfetti({
42 - ...LEFT,
43 - defaults: {
44 - origin: { y: 0.7, x: 1 },
110 + const shooter = shoot ?? ensureConfettiInstance();
111 + throwConfetti(LEFT, shooter);
112 + throwConfetti(
113 + {
114 + ...LEFT,
115 + defaults: {
116 + origin: { y: 0.7, x: 1 },
117 + },
45 118 },
46 - });
119 + shooter,
120 + );
47 121 };
48 122
49 -const throwConfetti = (config) => {
123 +const throwConfetti = (config, shoot) => {
50 124 const { count = 1, defaults, shots } = config;
51 - const shoot = ensureConfettiInstance();
52 125
53 126 shots.forEach(({ ratio = 1, ...opts }) => {
54 127 shoot({
55 128 ...(defaults ?? {}),