Animation
PinePaper supports both simple loop animations and complex keyframe-based animations.
Simple Animations
animate(item, params)
Apply a predefined animation to an item.
Parameters:
item: Item to animateparams(object): Animation settings
Animation Types:
pulse- Scale up/down rhythmicallyrotate- Continuous rotationbounce- Vertical bouncing motionfade- Opacity cyclingwobble- Side-to-side wobblingslide- Horizontal slidingtypewriter- Character-by-character reveal (text only)
// Pulsing animation
app.animate(circle, {
animationType: 'pulse',
animationSpeed: 1.0 // Speed multiplier
});
// Rotating animation
app.animate(star, {
animationType: 'rotate',
animationSpeed: 0.5
});
// Bouncing text
app.animate(text, {
animationType: 'bounce',
animationSpeed: 1.5
});
// Typewriter effect
app.animate(text, {
animationType: 'typewriter',
animationSpeed: 10 // Characters per second
});
stopAnimation(item)
Stop and remove animation from an item.
app.stopAnimation(circle);
Keyframe Animations
For complex, multi-property animations over time.
Adding Keyframes
app.modify(sun, {
animationType: 'keyframe',
keyframes: [
{
time: 0,
properties: { position: [100, 400], fillColor: '#fbbf24' },
easing: 'linear'
},
{
time: 2,
properties: { position: [400, 100], fillColor: '#f97316' },
easing: 'easeInOut'
},
{
time: 4,
properties: { position: [700, 400], fillColor: '#ef4444' },
easing: 'easeOut'
}
]
});
Keyframe Properties
| Property | Description |
|---|---|
position |
Array [x, y] or separate x, y |
scale |
Uniform scale, or scaleX/scaleY |
rotation |
Rotation in degrees |
opacity |
Transparency (0-1) |
fillColor |
Fill color (hex, rgb, named) |
strokeColor |
Stroke color |
fontSize |
Text size |
Easing Functions
linear- Constant speedeaseIn- Slow starteaseOut- Slow endeaseInOut- Slow start and endbounce- Bounce effectelastic- Elastic overshoot
Playback Control
// Start playback
app.playKeyframeTimeline(duration, loop);
// Stop playback
app.stopKeyframeTimeline();
// Scrub to specific time
app.setPlaybackTime(2.5); // Jump to 2.5 seconds
// Check playback state
if (app.isPlayingKeyframes) {
console.log('Playing at:', app.playbackTime);
}
Example: Day/Night Cycle
// Create sky
const sky = app.create('rectangle', {
x: 400, y: 300, width: 800, height: 600,
color: '#1e3a5f'
});
// Create sun
const sun = app.create('circle', {
x: 100, y: 500, radius: 60,
color: '#fbbf24'
});
// Animate sky color
app.modify(sky, {
animationType: 'keyframe',
keyframes: [
{ time: 0, properties: { fillColor: '#1e3a5f' }, easing: 'easeInOut' },
{ time: 2, properties: { fillColor: '#fb923c' }, easing: 'easeInOut' },
{ time: 4, properties: { fillColor: '#38bdf8' }, easing: 'easeInOut' },
{ time: 6, properties: { fillColor: '#f97316' }, easing: 'easeInOut' },
{ time: 8, properties: { fillColor: '#1e3a5f' }, easing: 'easeInOut' }
]
});
// Animate sun position
app.modify(sun, {
animationType: 'keyframe',
keyframes: [
{ time: 0, properties: { position: [100, 600], opacity: 0 } },
{ time: 2, properties: { position: [200, 100], opacity: 1 } },
{ time: 4, properties: { position: [400, 50], opacity: 1 } },
{ time: 6, properties: { position: [600, 100], opacity: 1 } },
{ time: 8, properties: { position: [700, 600], opacity: 0 } }
]
});
// Play looping
app.playKeyframeTimeline(8, true);
OnFrame Callbacks
For custom per-frame animation logic:
// Add custom animation
app.addOnFrameCallback('myAnimation', (event) => {
// event.delta - Time since last frame
// event.time - Total elapsed time
// event.count - Frame count
myItem.rotate(event.delta * 30); // 30 degrees per second
}, {
throttleMs: 16, // Minimum ms between calls
priority: 0 // Execution order
});
// Remove callback
app.removeOnFrameCallback('myAnimation');
Animated Items Tracking
PinePaper optimizes performance by tracking only animated items:
// Get count of animated items
const count = app.getAnimatedItemCount();
// Rebuild tracking after scene changes
app.rebuildAnimatedItemsSet();