Skip to content

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

ClassFileRole
AnimationManagercore/animation/AnimationManager.jsScope management, trigger coordination, lifecycle
AnimationRegistrycore/animation/AnimationRegistry.jsCaches compiled anime.js instances; avoids re-parsing
TriggerManagercore/animation/TriggerManager.jsManages trigger subscriptions (entity_change, datasource)
AnimationPerformanceMonitorcore/animation/PerformanceMonitor.jsTracks active animation count and frame budget
resolveAnimationscore/animation/resolveAnimations.jsMerges preset defaults with overlay animation config
resolveTimelinescore/animation/resolveTimelines.jsResolves 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

TriggerWhen fires
on_loadOnce on card initialisation
on_tapWhen the card is tapped/clicked
on_holdWhen the card is held (long press)
on_hoverWhen the mouse enters the card
on_leaveWhen the mouse leaves the card
on_entity_changeWhen a watched entity changes state
on_datasource_changeWhen a DataSource value crosses a threshold or changes
on_ruleInternally-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:

PresetEffect
pulseScale + brightness breathing (use for alert emphasis)
glowAnimated drop-shadow bloom
slideSlide in from a direction
fadeOpacity transition
bounceElastic scale bounce

Custom presets are registered via animation_presets in pack definitions.


Public API

MethodReturnsDescription
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)voidRevert the overlay's entire anime.js scope (all running instances)
stopAnimations(overlayId, trigger?)voidStop animations for one overlay, optionally filtered to a single trigger
pauseOverlay(overlayId) / resumeOverlay(overlayId)voidPause/resume the anime.js scope for an overlay
getActiveAnimations()Object{ [overlayId]: [{ preset, trigger, duration }, ...] } — only overlays with running animations
getAllAnimationDefinitions()ArrayEvery registered animation definition, each tagged with its overlayId
inspectOverlay(overlayId)Object|nullDebug snapshot: { overlayId, hasScope, activeAnimations, registeredAnimations, hasTriggerManager }
dispose()voidTear down the manager and all scopes
scopesMapInternal 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

javascript
window.lcards.debug.singleton('animationManager')
// → { type: 'AnimationManager', initialized: true, scopesCount: 4, customPresetsCount: 0,
//      timelinesCount: 0, activeAnimationsCount: 1, registeredAnimationsCount: 3,
//      hasMountEl: true, hasSystemsManager: true }
javascript
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>

See Also