PhaseAnimator and KeyframeAnimator under One.iOS, run by SwiftUI
One.iOS.PhaseAnimator and One.iOS.KeyframeAnimator are SwiftUI’s
PhaseAnimator and KeyframeAnimator. SwiftUI runs the timing,
interpolation, springs and interruption on the main thread; JavaScript does
not drive any frames.
children function. It returns native views,
as any other One.iOS container does.swiftStyle may change with the phase or value. Every other prop,
the element types and the children must come out the same.PhaseAnimator(_:trigger:content:animation:) without a trigger cycles through
phases while it is on screen. With trigger, each change (compared with
Object.is) runs every phase once and returns to the first. A change during a
run moves on to the next phase at once.
| Props | Type | Description |
|---|---|---|
phases (required)Iterable<Phase>The phases, in order. Must not be empty. | Iterable<Phase> | The phases, in order. Must not be empty. |
triggerunknownRuns the phases once each time it changes. Omit it to cycle. | unknown | Runs the phases once each time it changes. Omit it to cycle. |
animation(phase: Phase) => SDKAnimation | null = 'default'The animation into a phase, or null to change without one. | (phase: Phase) => SDKAnimation | null = 'default' | The animation into a phase, or null to change without one. |
children (required)(phase: Phase) => ReactNodeThe content closure. | (phase: Phase) => ReactNode | The content closure. |
<One.iOS.PhaseAnimator phases={[0, 1, 2]} trigger={likes} animation={(phase) => (phase === 1 ? 'bouncy' : 'easeInOut')}> {(phase) => ( <One.iOS.Image systemName="heart.fill" swiftStyle={{ scaleEffectWithSAndAnchor: { s: phase === 1 ? 1.4 : 1, anchor: 'center' } }} /> )}</One.iOS.PhaseAnimator>The closure runs once per phase during render, and SwiftUI animates from one
phase’s swiftStyle to the next. Colors that change by phase must be plain
colors; a platform color throws. animation returns one of the named
animations withAnimation takes.
KeyframeAnimator(initialValue:repeating:content:keyframes:) and
KeyframeAnimator(initialValue:trigger:content:keyframes:). The value is a
number or a record of up to eight numbers. With repeating (the default
without a trigger) the timeline loops; with trigger it plays once per
change, starting again from the current value when the change lands mid-run.
| Props | Type | Description |
|---|---|---|
initialValue (required)ValueA number, or a record of up to eight numbers. | Value | A number, or a record of up to eight numbers. |
repeatingboolean = trueLoops the timeline. Not allowed with trigger. | boolean = true | Loops the timeline. Not allowed with trigger. |
triggerunknownPlays the timeline once each time it changes. | unknown | Plays the timeline once each time it changes. |
keyframes (required)(value: Value) => readonly KeyframeTrack<Value>[] | readonly Keyframe<Value>[]Tracks, or keyframes for the whole value. | (value: Value) => readonly KeyframeTrack<Value>[] | readonly Keyframe<Value>[] | Tracks, or keyframes for the whole value. |
children (required)(value: Value) => ReactNodeThe content closure. | (value: Value) => ReactNode | The content closure. |
<One.iOS.KeyframeAnimator initialValue={{ scale: 1, lift: 0 }} trigger={count} keyframes={() => [ One.iOS.KeyframeTrack('scale', [ One.iOS.LinearKeyframe(1.2, { duration: 0.2 }), One.iOS.SpringKeyframe(1, { spring: 'bouncy' }), ]), One.iOS.KeyframeTrack('lift', [ One.iOS.CubicKeyframe(-30, { duration: 0.3 }), One.iOS.MoveKeyframe(0), ]), ]}> {(value) => ( <One.iOS.Text text="Done" swiftStyle={{ scaleEffectWithSAndAnchor: { s: value.scale, anchor: 'center' }, offset: { x: 0, y: value.lift } }} /> )}</One.iOS.KeyframeAnimator>KeyframeTrack(keyPath, keyframes) animates one field; KeyframeTrack(keyframes)
or a bare list of keyframes animates the whole value. A field takes one track.
| Keyframe | SwiftUI | Options |
|---|---|---|
LinearKeyframe(to, options) | LinearKeyframe | duration, timingCurve (a UnitCurve name or { startControlPoint, endControlPoint }) |
SpringKeyframe(to, options) | SpringKeyframe | duration, spring (smooth, snappy, bouncy or a Spring initializer), startVelocity |
CubicKeyframe(to, options) | CubicKeyframe | duration, startVelocity, endVelocity |
MoveKeyframe(to) | MoveKeyframe | none |
SwiftUI calls the content closure every frame, which JavaScript cannot do
without a frame loop. Instead the closure runs during render at the initial
value and at one step per field, and each swiftStyle number must follow the
value linearly, such as value.scale or 40 * value.width + 8. SwiftUI then
computes every frame’s numbers natively. A closure whose numbers curve with
the value, or whose strings or colors change with it, throws. The keyframes
function must not read its argument.
swiftStyle, element types and children cannot change with
the phase or value.PhaseAnimator animations are the named SDKAnimation values.KeyframeAnimator values have at most eight fields, and its content numbers
are linear in them.Edit this page on GitHub.