canvas-confetti
Advanced tools
Comparing version
@@ -1,2 +0,2 @@ | ||
// canvas-confetti v1.8.0 built on 2023-10-03T21:26:00.980Z | ||
// canvas-confetti v1.9.0 built on 2023-10-05T21:53:03.203Z | ||
!(function (window, module) { | ||
@@ -362,2 +362,33 @@ // source content | ||
)); | ||
} else if (fetti.shape.type === 'bitmap') { | ||
var rotation = Math.PI / 10 * fetti.wobble; | ||
var scaleX = Math.abs(x2 - x1) * 0.1; | ||
var scaleY = Math.abs(y2 - y1) * 0.1; | ||
var width = fetti.shape.bitmap.width * fetti.scalar; | ||
var height = fetti.shape.bitmap.height * fetti.scalar; | ||
var matrix = new DOMMatrix([ | ||
Math.cos(rotation) * scaleX, | ||
Math.sin(rotation) * scaleX, | ||
-Math.sin(rotation) * scaleY, | ||
Math.cos(rotation) * scaleY, | ||
fetti.x, | ||
fetti.y | ||
]); | ||
// apply the transform matrix from the confetti shape | ||
matrix.multiplySelf(new DOMMatrix(fetti.shape.matrix)); | ||
var pattern = context.createPattern(fetti.shape.bitmap, 'no-repeat'); | ||
pattern.setTransform(matrix); | ||
context.globalAlpha = (1 - progress); | ||
context.fillStyle = pattern; | ||
context.fillRect( | ||
fetti.x - (width / 2), | ||
fetti.y - (height / 2), | ||
width, | ||
height | ||
); | ||
context.globalAlpha = 1; | ||
} else if (fetti.shape === 'circle') { | ||
@@ -664,3 +695,3 @@ context.ellipse ? | ||
function createPathFetti(pathData) { | ||
function shapeFromPath(pathData) { | ||
if (!canUsePaths) { | ||
@@ -725,2 +756,48 @@ throw new Error('path confetti are not supported in this browser'); | ||
function shapeFromText(textData) { | ||
var text, | ||
scalar = 1, | ||
color = '#000000', | ||
// see https://nolanlawson.com/2022/04/08/the-struggle-of-using-native-emoji-on-the-web/ | ||
fontFamily = '"Twemoji Mozilla", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", "EmojiOne Color", "Android Emoji", "system emoji", sans-serif'; | ||
if (typeof textData === 'string') { | ||
text = textData; | ||
} else { | ||
text = textData.text; | ||
scalar = 'scalar' in textData ? textData.scalar : scalar; | ||
fontFamily = 'fontFamily' in textData ? textData.fontFamily : fontFamily; | ||
color = 'color' in textData ? textData.color : color; | ||
} | ||
// all other confetti are 10 pixels, | ||
// so this pixel size is the de-facto 100% scale confetti | ||
var fontSize = 10 * scalar; | ||
var font = '' + fontSize + 'px ' + fontFamily; | ||
var canvas = new OffscreenCanvas(fontSize, fontSize); | ||
var ctx = canvas.getContext('2d'); | ||
ctx.font = font; | ||
var size = ctx.measureText(text); | ||
var width = Math.floor(size.width); | ||
var height = Math.floor(size.fontBoundingBoxAscent + size.fontBoundingBoxDescent); | ||
canvas = new OffscreenCanvas(width, height); | ||
ctx = canvas.getContext('2d'); | ||
ctx.font = font; | ||
ctx.fillStyle = color; | ||
ctx.fillText(text, 0, fontSize); | ||
var scale = 1 / scalar; | ||
return { | ||
type: 'bitmap', | ||
// TODO these probably need to be transfered for workers | ||
bitmap: canvas.transferToImageBitmap(), | ||
matrix: [scale, 0, 0, scale, -width * scale / 2, -height * scale / 2] | ||
}; | ||
} | ||
module.exports = function() { | ||
@@ -733,3 +810,4 @@ return getDefaultFire().apply(this, arguments); | ||
module.exports.create = confettiCannon; | ||
module.exports.shapeFromPath = createPathFetti; | ||
module.exports.shapeFromPath = shapeFromPath; | ||
module.exports.shapeFromText = shapeFromText; | ||
}((function () { | ||
@@ -736,0 +814,0 @@ if (typeof window !== 'undefined') { |
{ | ||
"name": "canvas-confetti", | ||
"version": "1.8.0", | ||
"version": "1.9.0", | ||
"description": "performant confetti animation in the browser", | ||
@@ -37,3 +37,3 @@ "main": "src/confetti.js", | ||
"jimp": "^0.2.28", | ||
"puppeteer": "^1.0.0", | ||
"puppeteer": "^19.11.1", | ||
"rootrequire": "^1.0.0", | ||
@@ -40,0 +40,0 @@ "send": "^0.16.1", |
@@ -33,3 +33,3 @@ # [](https://github.com/catdad/canvas-confetti/) | ||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.8.0/dist/confetti.browser.min.js"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.0/dist/confetti.browser.min.js"></script> | ||
``` | ||
@@ -76,3 +76,3 @@ | ||
- `colors` _Array<String>_: An array of color strings, in the HEX format... you know, like `#bada55`. | ||
- `shapes` _Array<String|Shape>_: An array of shapes for the confetti. There are 3 built-in values of `square`, `circle`, and `star`. The default is to use both squares and circles in an even mix. To use a single shape, you can provide just one shape in the array, such as `['star']`. You can also change the mix by providing a value such as `['circle', 'circle', 'square']` to use two third circles and one third squares. You can also create your own shapes using the `confetti.shapeFromPath` helper method. | ||
- `shapes` _Array<String|Shape>_: An array of shapes for the confetti. There are 3 built-in values of `square`, `circle`, and `star`. The default is to use both squares and circles in an even mix. To use a single shape, you can provide just one shape in the array, such as `['star']`. You can also change the mix by providing a value such as `['circle', 'circle', 'square']` to use two third circles and one third squares. You can also create your own shapes using the [`confetti.shapeFromPath`](#confettishapefrompath-path-matrix---shape) or [`confetti.shapeFromText`](#confettishapefromtext-text-scalar-color-fontfamily---shape) helper methods. | ||
- `scalar` _Number (default: 1)_: Scale factor for each confetti particle. Use decimals to make the confetti smaller. Go on, try teeny tiny confetti, they are adorable! | ||
@@ -82,3 +82,3 @@ - `zIndex` _Integer (default: 100)_: The confetti should be on top, after all. But if you have a crazy high page, you can set it even higher. | ||
### `confetti.shapeFromPath({ path, matrix? })` -> `Shape` | ||
### `confetti.shapeFromPath({ path, matrix? })` → `Shape` | ||
@@ -104,2 +104,27 @@ This helper method lets you create a custom confetti shape using an [SVG Path string](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d). Any valid path should work, though there are a few caveats: | ||
### `confetti.shapeFromText({ text, scalar?, color?, fontFamily? })` → `Shape` | ||
This is the highly anticipated feature to render emoji confetti! Use any standard unicode emoji. Or other text, but... maybe don't use other text. | ||
While any text should work, there are some caveats: | ||
- For flailing confetti, something that is mostly square works best. That is, a single character, especially an emoji. | ||
- Rather than rendering text every time a confetti is drawn, this helper actually rasterizes the text. Therefore, it does not scale well after it is created. If you plan to use the `scalar` value to scale your confetti, use the same `scalar` value here when creating the shape. This will make sure the confetti are not blurry. | ||
The options for this method are: | ||
- `options` _`Object`_: | ||
- `text` _`String`_: the text to be rendered as a confetti. If you can't make up your mind, I suggest "🐈". | ||
- `scalar` _`Number, optional, default: 1`_: a scale value relative to the default size. It matches the `scalar` value in the confetti options. | ||
- `color` _`String, optional, default: #000000`_: the color used to render the text. | ||
- `fontFamily` _`String, optional, default: native emoji`_: the font family name to use when rendering the text. The default follows [best practices for rendring the native OS emoji of the device](https://nolanlawson.com/2022/04/08/the-struggle-of-using-native-emoji-on-the-web/), falling back to `sans-serif`. If using a web font, make sure this [font is loaded](https://developer.mozilla.org/en-US/docs/Web/API/FontFace/load) before rendering your confetti. | ||
```javascript | ||
var scalar = 2; | ||
var pineapple = confetti.shapeFromText({ text: '🍍', scalar }); | ||
confetti({ | ||
shapes: [pineapple], | ||
scalar | ||
}); | ||
``` | ||
### `confetti.create(canvas, [globalOptions])` → `function` | ||
@@ -106,0 +131,0 @@ |
@@ -359,2 +359,33 @@ (function main(global, module, isWorker, workerSize) { | ||
)); | ||
} else if (fetti.shape.type === 'bitmap') { | ||
var rotation = Math.PI / 10 * fetti.wobble; | ||
var scaleX = Math.abs(x2 - x1) * 0.1; | ||
var scaleY = Math.abs(y2 - y1) * 0.1; | ||
var width = fetti.shape.bitmap.width * fetti.scalar; | ||
var height = fetti.shape.bitmap.height * fetti.scalar; | ||
var matrix = new DOMMatrix([ | ||
Math.cos(rotation) * scaleX, | ||
Math.sin(rotation) * scaleX, | ||
-Math.sin(rotation) * scaleY, | ||
Math.cos(rotation) * scaleY, | ||
fetti.x, | ||
fetti.y | ||
]); | ||
// apply the transform matrix from the confetti shape | ||
matrix.multiplySelf(new DOMMatrix(fetti.shape.matrix)); | ||
var pattern = context.createPattern(fetti.shape.bitmap, 'no-repeat'); | ||
pattern.setTransform(matrix); | ||
context.globalAlpha = (1 - progress); | ||
context.fillStyle = pattern; | ||
context.fillRect( | ||
fetti.x - (width / 2), | ||
fetti.y - (height / 2), | ||
width, | ||
height | ||
); | ||
context.globalAlpha = 1; | ||
} else if (fetti.shape === 'circle') { | ||
@@ -661,3 +692,3 @@ context.ellipse ? | ||
function createPathFetti(pathData) { | ||
function shapeFromPath(pathData) { | ||
if (!canUsePaths) { | ||
@@ -722,2 +753,48 @@ throw new Error('path confetti are not supported in this browser'); | ||
function shapeFromText(textData) { | ||
var text, | ||
scalar = 1, | ||
color = '#000000', | ||
// see https://nolanlawson.com/2022/04/08/the-struggle-of-using-native-emoji-on-the-web/ | ||
fontFamily = '"Twemoji Mozilla", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", "EmojiOne Color", "Android Emoji", "system emoji", sans-serif'; | ||
if (typeof textData === 'string') { | ||
text = textData; | ||
} else { | ||
text = textData.text; | ||
scalar = 'scalar' in textData ? textData.scalar : scalar; | ||
fontFamily = 'fontFamily' in textData ? textData.fontFamily : fontFamily; | ||
color = 'color' in textData ? textData.color : color; | ||
} | ||
// all other confetti are 10 pixels, | ||
// so this pixel size is the de-facto 100% scale confetti | ||
var fontSize = 10 * scalar; | ||
var font = '' + fontSize + 'px ' + fontFamily; | ||
var canvas = new OffscreenCanvas(fontSize, fontSize); | ||
var ctx = canvas.getContext('2d'); | ||
ctx.font = font; | ||
var size = ctx.measureText(text); | ||
var width = Math.floor(size.width); | ||
var height = Math.floor(size.fontBoundingBoxAscent + size.fontBoundingBoxDescent); | ||
canvas = new OffscreenCanvas(width, height); | ||
ctx = canvas.getContext('2d'); | ||
ctx.font = font; | ||
ctx.fillStyle = color; | ||
ctx.fillText(text, 0, fontSize); | ||
var scale = 1 / scalar; | ||
return { | ||
type: 'bitmap', | ||
// TODO these probably need to be transfered for workers | ||
bitmap: canvas.transferToImageBitmap(), | ||
matrix: [scale, 0, 0, scale, -width * scale / 2, -height * scale / 2] | ||
}; | ||
} | ||
module.exports = function() { | ||
@@ -730,3 +807,4 @@ return getDefaultFire().apply(this, arguments); | ||
module.exports.create = confettiCannon; | ||
module.exports.shapeFromPath = createPathFetti; | ||
module.exports.shapeFromPath = shapeFromPath; | ||
module.exports.shapeFromText = shapeFromText; | ||
}((function () { | ||
@@ -733,0 +811,0 @@ if (typeof window !== 'undefined') { |
Sorry, the diff of this file is not supported yet
87275
12.69%2052
10.5%250
11.11%