Streamlined sprite animation packing for webpack.
Implementing sprite based animations usually requires the use of a locally installed tool like TexturePacker
, necessitating additional setup steps, making things inconvenient to upgrade and cumbersome to integrate with an existing webpack setup. @bsmth/sequence-loader
attempts to solve this by fully integrating the packing step with webpack, passing the atlas images off to your existing image loader.
Instead of importing sequence info and generated atlas images seperately, you'll import a single .sequence.json
file, pointing to your image sequence and containing instructions on how to generate the atlas. Based on this, @bsmth/sequence-loader
then generates atlas images and sequence info automatically on the fly.
yarn add --dev @bsmth/sequence-loader @bsmth/loader-cache
npm i --save-dev @bsmth/sequence-loader @bsmth/loader-cache
You'll need to add the loader and its cache management plugin to your webpack config.
import { CachePlugin } from "@bsmth/loader-cache";
export default {
module: {
rules: [
// ...
{
test: /\.sequence\.json$/i,
type: "javascript/auto",
use: [
{
loader: "@bsmth/sequence-loader",
options: {
// ...
},
},
],
},
],
},
plugins: [
// ...
new CachePlugin({
// ...
}),
],
};
Inside your project you can now create a .sequence.json
file, pointing to your image sequence:
("$schema"
is entirely optional, but it'll give you autocomplete and inline validation support. You can also use https://bit.ly/2SXgtdE
as the URL)
{
"$schema": "https://unpkg.com/@bsmth/[email protected]/schema/SequenceOptions.json",
"files": "./path/to/my/sequence/*.png"
}
See .sequence.json
options for more options.
Now, you can import that JSON:
import mySequence from "./my.sequence.json";
By default, mySequence
will give you the following object:
{
width: number, // size of sequence
height: number,
pages: [
{
width: number, // size of page
height: number,
img: unknown, // whatever your image loader outputs
},
// ...
],
frames: [
{
frame: number, // frame index
x: number, // position on page
y: number,
width: number, // size of frame on page
height: number,
page: number, // index of page including ths frame
padding: { // amount of 'whitespace' trimmed
top: number,
right: number,
bottom: number,
left: number,
},
},
// ...
],
}
You can also get the info in the same format used by TexturePacker
, by adding "format": "TexturePacker"
to your .sequence.json
:
[
{
meta: {
version: string,
format: string,
image: unknown, // whatever your image loader outputs
scale: number,
size: {
w: number,
h: number,
},
},
frames: {
"frame-000": {
rotated: boolean,
trimmed: boolean,
frame: {
w: number,
h: number,
x: number,
y: number,
},
spriteSourceSize: {
w: number,
h: number,
x: number,
y: number,
},
sourceSize: {
w: number,
h: number,
},
},
// ...
},
},
// ...
];
Note that you'll receive an array of pages, since TexturePacker
would create a separate JSON file for each.
Name | Type | Default | Description |
---|---|---|---|
files |
string |
'./*.{png,jpg}' |
A glob pattern pointing to your sequence frames. This is relative to the .json you're importing. |
scale |
number |
1 |
A scalar applied to your frames before being packed. Useful if the frames are at a higher resolution than the final animation. |
padding |
number |
0 |
Amout of pixels in between the packed frames. Useful if you see bleeding at the frame edges. |
trim |
boolean |
true |
Whether to trim 'uninteresting' pixels off the frame edges. This reduces file size, but you'll need to reconstruct the trimmed areas manually. |
trimThreshold |
number |
1 |
The threshold below which a pixel will be considered 'uninteresting'. This represents the maximum difference from the top-left pixel of the image. |
relative |
boolean |
false |
Whether to output coordinates relative to the page instead of pixel coordinates. Useful if the output image is being resized. |
pageMaxWidth |
number |
4096 |
Maximum width in pixels a page image (atlas) may be. Note that multiple pages may be created to fit all frames. |
pageMaxHeight |
number |
4096 |
Maximum height in pixels a page image (atlas) may be. Note that multiple pages may be created to fit all frames. |
format |
'default' | 'TexturePacker' |
'default' |
The format in which you'll receive the sequence. Choosing 'TexturePacker' gives you an array of objects that match the output of running TexturePacker with --format json |
imageQuery |
string |
'' |
Query string appended to the generated image imports. Useful if you want to pass info to your image loader. |
You can also add the above options as loader options. The'll act as defaults. Additionally loader-specific options are:
Name | Type | Default | Description |
---|---|---|---|
generateDeclarations |
boolean |
false |
Whether to output a .d.ts files next to imported JSONs. This provides correct types based on your settings. |
output |
'esm' | 'commonjs' |
'esm' |
What module format the JS output should be generated in. |
logLevel |
'pretty' | 'simple' | 'off' |
'pretty' |
How progress updates are displayed in the console.'pretty' may conflict with existing progress UIs, set to 'simple' or 'off' in that case. |
@bsmth/sequence-loader
can auto-generate declarations for your sequences!
By setting generateDeclarations
to true
in the loader config, @bsmth/sequence-loader
will emit a .d.ts
file next to each .sequence.json
file you're importing, containing types for that specific sequence. Image import types are mapped to whatever the type of *.png
is in your setup.
@bsmth/sequence-loader
will cache all processed images and intermediates on disk. This is handled by the CachePlugin
exported by @bsmth/loader-cache
, which accepts some options.
Without an up to date cache, @bsmth/sequence-loader
will create all atlases on startup. This can lead to insanely long build- and startup times. To circumvent this, it may be desirable to push the entire cache directory (.bsmth-loader-cache
) to git LFS. While this is not ideal, all renditions will only be created once and reused on subsequent runs.
- better documentation
- examples
- tests
© 2021 the project bismuth authors, licensed under MIT.