Programmatic API
Declarative animation covers the common case: describe the state, let the change drive the
motion. Some things do not fit that shape - a timeline whose steps overlap, a value that is not
a DOM property, an animation you need to pause halfway. BmotionAnimateService
is the imperative half of the library: animate by CSS selector or ElementReference,
with no <Bmotion> wrapper anywhere in sight, and get back playback controls
you can hold on to.
Animating by selector
AnimateAsync(selector, target, transition, stagger) resolves every matching
element and animates them together, with the optional stagger spreading
their start times. The call returns BmAnimationControls: awaitable for
completion, and holding Pause, Play, SetSpeed,
Stop (freeze where it is) and Complete (jump to the end). Start
the slow run below and then interfere with it.
Animating a number
Nothing about the engine requires a DOM element. AnimateAsync(from, to, onUpdate,
transition) interpolates a bare double and hands you every value on the
way - which is how you get a counter that eases rather than ticks, and equally how you
would drive a canvas, an audio gain or anything else outside the render tree.
Sequences
A BmSequence is a timeline: each step names its own target, and
at places it relative to what came before. "+0.2" and
"-0.1" are offsets from the previous step's end (so a negative value
overlaps it), "<" aligns with the previous step's start, a bare
number is absolute, and Label marks a position several later steps can share.
That is what lets a sequence overlap without you hand-computing a single delay.
The whole timeline runs on one playhead, driven by the animation clock
rather than by wall-clock timers. So the controls it returns govern the gaps between the
steps as well as the steps themselves: pause it mid-run and the sequence genuinely holds
instead of quietly starting its later steps on time, and SetSpeed(3) compresses
the silences by the same factor it compresses the movement.
Motion values
A motion value is a number that other things can watch. Bind one with the
Values parameter and it writes to the DOM every frame without re-rendering the
component; derive from it with Transform and the derived value updates in
lockstep; wrap it in Motion.Spring and you get a follower that lags behind with
physics rather than tracking exactly. The slider below sets one value - everything else on
the row is downstream of it.
Driving one element by reference
When the element is a <Bmotion>, a @ref gives you
the same controls without a selector. AnimateAsync plays a one-off target,
Set applies one instantly with no animation, Pause /
Resume / SetPlaybackRate control whatever is currently running,
and Stop freezes it where it stands.
Global defaults
BmotionConfig cascades defaults to everything beneath it, which is the
cheapest way to change the feel of a whole surface at once. TransitionSpeed is
a playback multiplier - 0.25 is the slow-motion switch every animation
developer wants while tuning, and 0 makes every transition instant.
It also carries ReduceMotion, the prefers-reduced-motion policy for
its subtree — covered in full on the Accessibility page.