animation-composition
v2.2.0
Published
Compose Sprite Animation Layers
Downloads
4
Maintainers
Readme
Animation
Opts
canvas
: The canvas element for the animation to uselayers
: An Array of Layers composed however you'd likeloop
(optional default: true)ticksPerFrame
(optional default: 0): How many frame delay you would like in each 60 frame/sec call. e.g. 1 ticksPerFrame is ~30fpsdebug
(optional default: false): If you'd like to offset Layers or receive console logsdebugOffset
(optional default: 0): This only takes effect ifdebug
is true. This is the amount of pixels to offset the layers for debugging.paused
(optional default: false): Do not play animation. Allows manual step through usinganimation.next()
. If trueticksPerFrame
is always set to0
onerror
(optional): If there is an error this function will be called
Methods
instance.destroy
: Destroy instance and stop RAF timerinstance.next
: If paused, render next frame
Layers
BaseLayer
This is a base class that can be extended. This base class is the base for all Layer Types included in this library.
Opts
name
(optional): this can be used for debugging
Interface Methods are:
render(canvas, frameIndex)
You will use this to manipulate the Canvas in any way you'd like. Be aware this canvas could have data in it based on previous layers in the animation.
Preset Default Methods:
getFrames() { return 0; }
preload() { return Promise.resolve(); }
ColorLayer
(extends BaseLayer)
Color Layer will give a flat full canvas color fill. I built this for my use with MaskLayer to color fill a mask image.
Opts
color
: aCanvasRenderingContext2D.fillStyle
EXAMPLE:
const colorLayer = new ColorLayer({ color: 'rgba(51, 170, 51, .7)' });
Layer
(extends BaseLayer)
Layer is an image layer. This is used as an animation layer base for animating across multiple images.
Opts
One of the following are required:
images
: An array of one or more image URLs to be usedsprite
: An object to describe the sprite sheetsheet
: The URL to the sprite sheetsize
: width of a frame (only with is supported right now)frames
: Number of frames in the animation (this allows a sheet to have empty frames)
sizeRef
(optional): an optional reference to a Layer type to be used
EXAMPLE:
const border = new Layer({
images: [ '/ripple-web/border/ripple_border_00.png', '/ripple-web/border/ripple_border_01.png' ]
});
MaskLayer
(extends BaseLayer)
MaskLayer is used to cleverly compose global canvas masking to apply masks to certain layers. This does have some hard limitations;
- Mask layers must be grouped together if there is more than one. Example:
OK: [ shapeLayer1, mask1, mask2, shapeLayer2 ]
NOT VALID: [ mask1, shapeLayer1, mask2, shapeLayer2 ]
Technical explanation. Canvas only allows global mask composition, this means that any layer data already written to the canvas will affect the mask. To work around that we first find all the mask layers in the animation and render those first (top to bottom, writing new data below existing data). After masks we write nonmask layers to the canvas being careful to place data correctly below or above. If needed we could allow nongrouped mask layers, but it was not needed for my usage.
Opts
mask
: A Layer that will be used as the mask source. This can be an animation.layers
: An array of Layers to be masked using the source.
EXAMPLE:
const avatarMask = new Layer({
images: [ '/ripple-web/mask/ripple_00.png', '/ripple-web/mask/ripple_01.png' ],
});
const avatarImageLayer = new Layer({ images: [ '/ripple-web/avatar.png' ], sizeRef: avatarMask });
const avatarLayer = new MaskLayer({ mask: avatarMask, layers: [ avatarImageLayer ]});
Utils
imageStringIterator(path, startNumber, endNumber)
This Util is used to iterate over a number of images at a specific path.
Arguments
- path: Path with
XX
representing the number to be replaced - startNumber: what to start at
- endNumber: what to end at
EXAMPLE:
import AnimationComposition from 'animation-composition';
const { Utils } = AnimationComposition;
const { imageStringIterator } = Utils;
console.log(
imageStringIterator(`/ripple/border/ripple_XX_xhdpi.png`, 0, 29)
);
// [
// '/ripple/border/ripple_00_xhdpi.png',
// '/ripple/border/ripple_01_xhdpi.png',
// ...
// '/ripple/border/ripple_29_xhdpi.png',
// ]
Library Example
import AnimationComposition from 'animation-composition';
const { Animation, Layer, MaskLayer, ColorLayer, Utils } = AnimationComposition;
const { imageStringIterator } = Utils;
const PATH = '/FAKE/PATH/';
const color = '#c0ffee';
const avatarImage = `${PATH}/myAvatar.png`;
const canvas = document.querySelector('canvas');
const border = new Layer({
images: imageStringIterator(`${PATH}ripple-web/border/ripple_border_XX_xhdpi.png`, 0, 29)
});
const colorLayer = new ColorLayer({ color });
const fill = new Layer({
images: imageStringIterator(`${PATH}ripple-web/fill/ripple_fill_XX_xhdpi.png`, 0, 29)
});
const participantLayer = new MaskLayer({ name: 'participantLayer', mask: fill, layers: [ colorLayer ]});
const avatarMask = new Layer({ images: imageStringIterator(`${PATH}ripple-web/mask/ripple_mask_XX_xhdpi.png`, 0, 29) });
const avatarImageLayer = new Layer({ images: [ avatarImage ], sizeRef: avatarMask });
const avatarLayer = new MaskLayer({ mask: avatarMask, layers: [ avatarImageLayer ]});
new Animation({
ticksPerFrame: 1,
canvas,
layers: [ border, participantLayer, avatarLayer ],
});