Animation Manager
window.lcards.core.animationManager: Central anime.js v4 coordinator for card and overlay animations.
Overview
AnimationManager extends BaseService. It manages animation scopes per overlay, integrates with DataSourceManager for reactive value-driven animations, with RulesEngine for rule-triggered animations, and provides a full runtime/debug API surface.
Key Classes
| Class | File | Role |
|---|---|---|
AnimationManager | core/animation/AnimationManager.js | Scope management, trigger coordination, lifecycle |
AnimationRegistry | core/animation/AnimationRegistry.js | Caches compiled anime.js instances; avoids re-parsing |
TriggerManager | core/animation/TriggerManager.js | Manages trigger subscriptions (entity_change, datasource) |
AnimationPerformanceMonitor | core/animation/PerformanceMonitor.js | Tracks active animation count and frame budget |
resolveAnimations | core/animation/resolveAnimations.js | Merges preset defaults with overlay animation config |
resolveTimelines | core/animation/resolveTimelines.js | Resolves timeline steps from config or preset |
Architecture
AnimationManager
├─ scopes Map (overlayId → scope)
│ ├─ scope.triggerManager (TriggerManager per overlay)
│ └─ scope.activeAnimations (Set<anime instance>)
│
├─ AnimationRegistry (shared, caches anime instances by key)
├─ datasourceSubscriptions (datasource_id → cleanup fn)
└─ timelines Map (timelineId → createTimeline() instance)Trigger Types
| Trigger | When fires |
|---|---|
on_load | Once on card initialisation |
on_tap | When the card is tapped/clicked |
on_hold | When the card is held (long press) |
on_hover | When the mouse enters the card |
on_leave | When the mouse leaves the card |
on_entity_change | When a watched entity changes state |
on_datasource_change | When a DataSource value crosses a threshold or changes |
on_rule | Internally-synthesized: never set this directly via trigger: in your own config. It's applied automatically when an animation is executed via a rule's apply.animations targeting; author rule-driven animations through the Rules Engine, not by hand-setting this trigger. |
anime.js v4 Note
LCARdS uses anime.js v4. The timeline API (anime.createTimeline(), renamed from v3's anime.timeline()) changed from v3. Always pass targets as CSS selectors or DOM element references resolved at runtime, not stale references cached at config time.
Preset Animations
Presets are named animation parameter bundles distributed via packs. Built-in presets include:
| Preset | Effect |
|---|---|
pulse | Scale + brightness breathing (use for alert emphasis) |
glow | Animated drop-shadow bloom |
slide | Slide in from a direction |
fade | Opacity transition |
bounce | Elastic scale bounce |
Custom presets are registered via animation_presets in pack definitions.
Public API
| Method | Returns | Description |
|---|---|---|
playAnimation(overlayId, animDef) | Promise<Object|null> | Resolve and play one animation definition against an overlay's scope; returns the resolved animDef or null on failure |
triggerAnimations(overlayId, trigger) | Promise<void> | Fire every animation registered for an overlay + trigger pair (used internally by ActionHandler on tap/hold/hover/etc.) |
stopAnimation(overlayId) | void | Revert the overlay's entire anime.js scope (all running instances) |
stopAnimations(overlayId, trigger?) | void | Stop animations for one overlay, optionally filtered to a single trigger |
pauseOverlay(overlayId) / resumeOverlay(overlayId) | void | Pause/resume the anime.js scope for an overlay |
getActiveAnimations() | Object | { [overlayId]: [{ preset, trigger, duration }, ...] }: only overlays with running animations |
getAllAnimationDefinitions() | Array | Every registered animation definition, each tagged with its overlayId |
inspectOverlay(overlayId) | Object|null | Debug snapshot: { overlayId, hasScope, activeAnimations, registeredAnimations, hasTriggerManager } |
dispose() | void | Tear down the manager and all scopes |
scopes | Map | Internal scope registry keyed by overlay ID |
Custom animation presets are registered via animation_presets in pack definitions (see Pack System). ScreenEffectManager has its own, unrelated registerPreset() for full-screen effect presets; don't confuse the two.
Console Access
window.lcards.debug.singleton('animationManager')
// → { type: 'AnimationManager', initialized: true, scopesCount: 4, customPresetsCount: 0,
// timelinesCount: 0, activeAnimationsCount: 1, registeredAnimationsCount: 3,
// hasMountEl: true, hasSystemsManager: true }const am = window.lcards.core.animationManager
await am.playAnimation('my-overlay', { trigger: 'on_tap', preset: 'pulse' })
am.stopAnimation('my-overlay')
am.stopAnimations('my-overlay', 'on_tap')
am.getActiveAnimations() // { overlayId: [{ preset, trigger, duration }, ...] }
am.getAllAnimationDefinitions() // all registered animation defs, tagged with overlayId
am.inspectOverlay('my-overlay') // { overlayId, hasScope, activeAnimations, ... }
am.scopes // Map<overlayId, scopeData>