Skip to content

Commit

Permalink
Merge branch 'master' into new-headless
Browse files Browse the repository at this point in the history
  • Loading branch information
catdad committed Nov 18, 2023
2 parents 0a3954a + d8bad6f commit e3a0f38
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 19 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ You can then `require('canvas-confetti');` to use it in your project build. _Not
You can also include this library in your HTML page directly from a CDN:

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

_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)._
Expand Down
9 changes: 8 additions & 1 deletion build/serve.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const path = require('path');
const http = require('http');
const send = require('send');
const root = require('rootrequire');
const { networkInterfaces } = require('os');

const PORT = 9001;

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

send(req, file).pipe(res);
}).listen(PORT, () => {
console.log(`listening at http://localhost:${PORT}`);
console.log('listening at:');
console.log(` http://localhost:${PORT}`);

Object.values(networkInterfaces())
.reduce((memo, value) => [...memo, ...value], [])
.filter(value => value.family === 'IPv4')
.forEach(({ address }) => console.log(` http://${address}:${PORT}`));
});


Expand Down
50 changes: 35 additions & 15 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
<meta name="keywords" content="canvas,confetti,component,module,animation,javascript,catdad">

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

<title>🎊</title>
<title>canvas confetti</title>

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

Expand Down Expand Up @@ -49,6 +50,10 @@
[data-theme="light"][auto-theme] {
--theme-switch: var(--switch-auto-black);
}

html {
scroll-behavior: smooth;
}

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

<div class="container">
<div class="group" data-name="stars">
<div class="group" data-name="fireworks">
<div class="flex-rows">
<div class="left">
<h2><a href="#stars" id="stars" class="anchor">Stars</a></h2>
<h2><a href="#fireworks" id="fireworks" class="anchor">Fireworks</a></h2>
<button class="run">
Run
<span class="icon">
Expand All @@ -430,22 +435,20 @@ <h2><a href="#stars" id="stars" class="anchor">Stars</a></h2>
</div>
<div class="description">
<p>
You can combine multiple calls to confetti with any settings in order to create
a more complex effect. Go ahead, combine different shapes, sizes, etc. Stagger them
for an extra boost of excitement.
Why click a button repeatedly when you can have code do it for you? Shoot some firework
of confetti from the sides of page so you can still read the content in the center.
</p>
<p class="center">✨ Celebrate with a burst of stars! ✨</p>
</div>
</div>
<div class="editor"></div>
</div>
</div>

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

var defaults = {
scalar: 2,
spread: 270,
particleCount: 25,
origin: { y: 0.4 },
startVelocity: 35
spread: 180,
particleCount: 30,
origin: { y: -0.1 },
startVelocity: -35
};

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

<script>
// render favicon live, because why not
addEventListener("load", (event) => {
const image = confetti.shapeFromText('🎊', { scalar: 512/10 });
const canvas = new OffscreenCanvas(image.bitmap.width, image.bitmap.height);
const ctx = canvas.getContext('bitmaprenderer');
ctx.transferFromImageBitmap(image.bitmap);

canvas.convertToBlob().then(blob => {
const icon = document.getElementById('favicon');
icon.setAttribute('href', URL.createObjectURL(blob));
});
});
</script>

<script src="/analytics.js" async></script>
</body>
</html>
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "canvas-confetti",
"version": "1.9.0",
"version": "1.9.1",
"description": "performant confetti animation in the browser",
"main": "src/confetti.js",
"module": "dist/confetti.module.mjs",
Expand Down
57 changes: 56 additions & 1 deletion src/confetti.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* globals Map */

(function main(global, module, isWorker, workerSize) {
var canUseWorker = !!(
global.Worker &&
Expand All @@ -11,6 +13,25 @@
global.URL.createObjectURL);

var canUsePaths = typeof Path2D === 'function' && typeof DOMMatrix === 'function';
var canDrawBitmap = (function () {
// this mostly supports ssr
if (!global.OffscreenCanvas) {
return false;
}

var canvas = new OffscreenCanvas(1, 1);
var ctx = canvas.getContext('2d');
ctx.fillRect(0, 0, 1, 1);
var bitmap = canvas.transferToImageBitmap();

try {
ctx.createPattern(bitmap, 'no-repeat');
} catch (e) {
return false;
}

return true;
})();

function noop() {}

Expand All @@ -29,6 +50,36 @@
return null;
}

var bitmapMapper = (function (skipTransform, map) {
// see https://github.com/catdad/canvas-confetti/issues/209
// creating canvases is actually pretty expensive, so we should create a
// 1:1 map for bitmap:canvas, so that we can animate the confetti in
// a performant manner, but also not store them forever so that we don't
// have a memory leak
return {
transform: function(bitmap) {
if (skipTransform) {
return bitmap;
}

if (map.has(bitmap)) {
return map.get(bitmap);
}

var canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
var ctx = canvas.getContext('2d');
ctx.drawImage(bitmap, 0, 0);

map.set(bitmap, canvas);

return canvas;
},
clear: function () {
map.clear();
}
};
})(canDrawBitmap, new Map());

var raf = (function () {
var TIME = Math.floor(1000 / 60);
var frame, cancel;
Expand Down Expand Up @@ -101,6 +152,9 @@
worker.removeEventListener('message', workerDone);

prom = null;

bitmapMapper.clear();

done();
resolve();
}
Expand Down Expand Up @@ -375,7 +429,7 @@
// apply the transform matrix from the confetti shape
matrix.multiplySelf(new DOMMatrix(fetti.shape.matrix));

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

context.globalAlpha = (1 - progress);
Expand Down Expand Up @@ -435,6 +489,7 @@
animationFrame = destroy = null;

context.clearRect(0, 0, size.width, size.height);
bitmapMapper.clear();

done();
resolve();
Expand Down

0 comments on commit e3a0f38

Please sign in to comment.