Skip to content

Commit e3a0f38

Browse files
committed
Merge branch 'master' into new-headless
2 parents 0a3954a + d8bad6f commit e3a0f38

File tree

5 files changed

+101
-19
lines changed

5 files changed

+101
-19
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ You can then `require('canvas-confetti');` to use it in your project build. _Not
3030
You can also include this library in your HTML page directly from a CDN:
3131

3232
```html
33-
<script src="https://cdn.jsdelivr.net/npm/[email protected].0/dist/confetti.browser.min.js"></script>
33+
<script src="https://cdn.jsdelivr.net/npm/[email protected].1/dist/confetti.browser.min.js"></script>
3434
```
3535

3636
_Note: you should use the latest version at the time that you include your project. You can see all versions [on the releases page](https://github.com/catdad/canvas-confetti/releases)._

build/serve.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const path = require('path');
22
const http = require('http');
33
const send = require('send');
44
const root = require('rootrequire');
5+
const { networkInterfaces } = require('os');
56

67
const PORT = 9001;
78

@@ -25,7 +26,13 @@ http.createServer(function (req, res) {
2526

2627
send(req, file).pipe(res);
2728
}).listen(PORT, () => {
28-
console.log(`listening at http://localhost:${PORT}`);
29+
console.log('listening at:');
30+
console.log(` http://localhost:${PORT}`);
31+
32+
Object.values(networkInterfaces())
33+
.reduce((memo, value) => [...memo, ...value], [])
34+
.filter(value => value.family === 'IPv4')
35+
.forEach(({ address }) => console.log(` http://${address}:${PORT}`));
2936
});
3037

3138

index.html

+35-15
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
<meta name="keywords" content="canvas,confetti,component,module,animation,javascript,catdad">
99

1010
<meta name="theme-color" content="#393939">
11+
<link id="favicon" rel="shortcut icon" type="image/png" />
1112

12-
<title>🎊</title>
13+
<title>canvas confetti</title>
1314

1415
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans&display=swap" rel="stylesheet">
1516

@@ -49,6 +50,10 @@
4950
[data-theme="light"][auto-theme] {
5051
--theme-switch: var(--switch-auto-black);
5152
}
53+
54+
html {
55+
scroll-behavior: smooth;
56+
}
5257

5358
html, body {
5459
margin: 0;
@@ -417,10 +422,10 @@ <h2><a href="#realistic" id="realistic" class="anchor">Realistic Look</a></h2>
417422
</div>
418423

419424
<div class="container">
420-
<div class="group" data-name="stars">
425+
<div class="group" data-name="fireworks">
421426
<div class="flex-rows">
422427
<div class="left">
423-
<h2><a href="#stars" id="stars" class="anchor">Stars</a></h2>
428+
<h2><a href="#fireworks" id="fireworks" class="anchor">Fireworks</a></h2>
424429
<button class="run">
425430
Run
426431
<span class="icon">
@@ -430,22 +435,20 @@ <h2><a href="#stars" id="stars" class="anchor">Stars</a></h2>
430435
</div>
431436
<div class="description">
432437
<p>
433-
You can combine multiple calls to confetti with any settings in order to create
434-
a more complex effect. Go ahead, combine different shapes, sizes, etc. Stagger them
435-
for an extra boost of excitement.
438+
Why click a button repeatedly when you can have code do it for you? Shoot some firework
439+
of confetti from the sides of page so you can still read the content in the center.
436440
</p>
437-
<p class="center">✨ Celebrate with a burst of stars! ✨</p>
438441
</div>
439442
</div>
440443
<div class="editor"></div>
441444
</div>
442445
</div>
443446

444447
<div class="container">
445-
<div class="group" data-name="fireworks">
448+
<div class="group" data-name="stars">
446449
<div class="flex-rows">
447450
<div class="left">
448-
<h2><a href="#fireworks" id="fireworks" class="anchor">Fireworks</a></h2>
451+
<h2><a href="#stars" id="stars" class="anchor">Stars</a></h2>
449452
<button class="run">
450453
Run
451454
<span class="icon">
@@ -455,9 +458,11 @@ <h2><a href="#fireworks" id="fireworks" class="anchor">Fireworks</a></h2>
455458
</div>
456459
<div class="description">
457460
<p>
458-
Why click a button repeatedly when you can have code do it for you? Shoot some firework
459-
of confetti from the sides of page so you can still read the content in the center.
461+
You can combine multiple calls to confetti with any settings in order to create
462+
a more complex effect. Go ahead, combine different shapes, sizes, etc. Stagger them
463+
for an extra boost of excitement.
460464
</p>
465+
<p class="center">✨ Celebrate with a burst of stars! ✨</p>
461466
</div>
462467
</div>
463468
<div class="editor"></div>
@@ -859,10 +864,10 @@ <h2><a href="#custom-canvas" id="custom-canvas" class="anchor">Custom Canvas</a>
859864

860865
var defaults = {
861866
scalar: 2,
862-
spread: 270,
863-
particleCount: 25,
864-
origin: { y: 0.4 },
865-
startVelocity: 35
867+
spread: 180,
868+
particleCount: 30,
869+
origin: { y: -0.1 },
870+
startVelocity: -35
866871
};
867872

868873
confetti({
@@ -973,6 +978,21 @@ <h2><a href="#custom-canvas" id="custom-canvas" class="anchor">Custom Canvas</a>
973978
};
974979
</script>
975980

981+
<script>
982+
// render favicon live, because why not
983+
addEventListener("load", (event) => {
984+
const image = confetti.shapeFromText('🎊', { scalar: 512/10 });
985+
const canvas = new OffscreenCanvas(image.bitmap.width, image.bitmap.height);
986+
const ctx = canvas.getContext('bitmaprenderer');
987+
ctx.transferFromImageBitmap(image.bitmap);
988+
989+
canvas.convertToBlob().then(blob => {
990+
const icon = document.getElementById('favicon');
991+
icon.setAttribute('href', URL.createObjectURL(blob));
992+
});
993+
});
994+
</script>
995+
976996
<script src="/analytics.js" async></script>
977997
</body>
978998
</html>

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "canvas-confetti",
3-
"version": "1.9.0",
3+
"version": "1.9.1",
44
"description": "performant confetti animation in the browser",
55
"main": "src/confetti.js",
66
"module": "dist/confetti.module.mjs",

src/confetti.js

+56-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* globals Map */
2+
13
(function main(global, module, isWorker, workerSize) {
24
var canUseWorker = !!(
35
global.Worker &&
@@ -11,6 +13,25 @@
1113
global.URL.createObjectURL);
1214

1315
var canUsePaths = typeof Path2D === 'function' && typeof DOMMatrix === 'function';
16+
var canDrawBitmap = (function () {
17+
// this mostly supports ssr
18+
if (!global.OffscreenCanvas) {
19+
return false;
20+
}
21+
22+
var canvas = new OffscreenCanvas(1, 1);
23+
var ctx = canvas.getContext('2d');
24+
ctx.fillRect(0, 0, 1, 1);
25+
var bitmap = canvas.transferToImageBitmap();
26+
27+
try {
28+
ctx.createPattern(bitmap, 'no-repeat');
29+
} catch (e) {
30+
return false;
31+
}
32+
33+
return true;
34+
})();
1435

1536
function noop() {}
1637

@@ -29,6 +50,36 @@
2950
return null;
3051
}
3152

53+
var bitmapMapper = (function (skipTransform, map) {
54+
// see https://github.com/catdad/canvas-confetti/issues/209
55+
// creating canvases is actually pretty expensive, so we should create a
56+
// 1:1 map for bitmap:canvas, so that we can animate the confetti in
57+
// a performant manner, but also not store them forever so that we don't
58+
// have a memory leak
59+
return {
60+
transform: function(bitmap) {
61+
if (skipTransform) {
62+
return bitmap;
63+
}
64+
65+
if (map.has(bitmap)) {
66+
return map.get(bitmap);
67+
}
68+
69+
var canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
70+
var ctx = canvas.getContext('2d');
71+
ctx.drawImage(bitmap, 0, 0);
72+
73+
map.set(bitmap, canvas);
74+
75+
return canvas;
76+
},
77+
clear: function () {
78+
map.clear();
79+
}
80+
};
81+
})(canDrawBitmap, new Map());
82+
3283
var raf = (function () {
3384
var TIME = Math.floor(1000 / 60);
3485
var frame, cancel;
@@ -101,6 +152,9 @@
101152
worker.removeEventListener('message', workerDone);
102153

103154
prom = null;
155+
156+
bitmapMapper.clear();
157+
104158
done();
105159
resolve();
106160
}
@@ -375,7 +429,7 @@
375429
// apply the transform matrix from the confetti shape
376430
matrix.multiplySelf(new DOMMatrix(fetti.shape.matrix));
377431

378-
var pattern = context.createPattern(fetti.shape.bitmap, 'no-repeat');
432+
var pattern = context.createPattern(bitmapMapper.transform(fetti.shape.bitmap), 'no-repeat');
379433
pattern.setTransform(matrix);
380434

381435
context.globalAlpha = (1 - progress);
@@ -435,6 +489,7 @@
435489
animationFrame = destroy = null;
436490

437491
context.clearRect(0, 0, size.width, size.height);
492+
bitmapMapper.clear();
438493

439494
done();
440495
resolve();

0 commit comments

Comments
 (0)