Keyframes
Keyframe schemas, easing, track interpolation, and animated element resolution.
Types
AnimatableProperty
type AnimatableProperty = z.infer<typeof animatablePropertySchema>An animatable property name as inferred from animatablePropertySchema.
Easing
type Easing = z.infer<typeof easingSchema>An easing as inferred from easingSchema.
Keyframe
type Keyframe = z.infer<typeof keyframeSchema>A keyframe as inferred from keyframeSchema.
KeyframeMap
type KeyframeMap = z.infer<typeof keyframesSchema>A keyframe map as inferred from keyframesSchema.
Schemas
ANIMATABLE_PROPERTIES
const ANIMATABLE_PROPERTIES = animatablePropertySchema.optionsThe options of animatablePropertySchema as a readonly array.
animatablePropertySchema
const animatablePropertySchema = z.enum([
'position.x',
'position.y',
'scale.x',
'scale.y',
'rotation',
'opacity',
'blur',
'volume',
'letterSpacing',
])Zod schema for the nine keyframeable properties, position, scale, rotation, opacity, blur, volume, and letter spacing.
easingSchema
const easingSchema = z.union([
z.enum(['linear', 'hold', 'easeIn', 'easeOut', 'easeInOut', 'easeInExpo', 'easeOutExpo', 'easeInOutExpo']),
z.object({ cubicBezier: z.tuple([z.number(), z.number(), z.number(), z.number()]) }),
])Zod schema for the interpolation toward the next keyframe, a named easing or a cubicBezier tuple, where hold steps.
keyframeSchema
const keyframeSchema = z.object({
timeMs: z.number().int().nonnegative(),
value: z.number(),
easing: easingSchema.optional(),
})Zod schema for one keyframe, an integer element-local time, a value, and an optional outgoing easing.
keyframesSchema
const keyframesSchema = z.partialRecord(animatablePropertySchema, z.array(keyframeSchema))Zod schema for a keyframe map, one keyframe track per animatable property.
Functions
animatableProperties
function animatableProperties(element: TimelineElement): AnimatableProperty[]Returns the animatable properties for the element's kind, motion properties plus volume for video and multicam, volume alone for audio, motion for images, motion plus letterSpacing for text, and none for captions.
cubicBezierAt
function cubicBezierAt(points: readonly [number, number, number, number], x: number): numberReturns the y value of a CSS-style cubic bezier timing curve at progress x, solving for the curve parameter with Newton steps and a bisection fallback.
elementSupportsProperty
function elementSupportsProperty(
element: TimelineElement,
property: AnimatableProperty,
): booleanReturns true when the element's type declares the property as keyframeable.
evaluateEasing
function evaluateEasing(easing: Easing | undefined, t: number): numberReturns eased progress for linear progress t, where linear and undefined pass through, hold returns 0, and other easings evaluate their bezier.
getAnimatedValue
function getAnimatedValue(
element: TimelineElement,
property: AnimatableProperty,
timelineMs: number,
): numberReturns the property value at a timeline time, interpolated from its keyframe track when one exists and static otherwise.
getKeyframes
function getKeyframes(
element: TimelineElement,
property: AnimatableProperty,
): Keyframe[]Returns the keyframe track for a property, or an empty array.
getStaticValue
function getStaticValue(element: TimelineElement, property: AnimatableProperty): numberReturns the unanimated value of a property from the element's fields, 0 for blur, or NaN when the element has no such field.
hasKeyframes
function hasKeyframes(element: TimelineElement, property?: AnimatableProperty): booleanReturns true when the element has a non-empty track for the property, or for any property when none is given.
interpolateTrack
function interpolateTrack(track: readonly Keyframe[], localMs: number): numberReturns the value of a keyframe track at an element-local time, holding the first value before the track and the last value after it, or NaN for an empty track.
isOnKeyframe
function isOnKeyframe(
element: TimelineElement,
property: AnimatableProperty,
timelineMs: number,
toleranceMs = 1,
): booleanReturns true when a keyframe on the property lies within toleranceMs of the timeline time.
resolveAnimatedElement
function resolveAnimatedElement<E extends TimelineElement>(
element: E,
timelineMs: number,
): EReturns a copy of the element with every keyframed property resolved at the timeline time, appending an animated blur as an effect, or the same element when it has no keyframes.
splitKeyframes
function splitKeyframes(
keyframes: KeyframeMap | undefined,
offsetMs: number,
): { left: KeyframeMap | undefined; right: KeyframeMap | undefined }Splits a keyframe map at an element-local offset into maps for both halves, adding boundary keyframes with the interpolated value so motion stays continuous across the cut.
upsertKeyframe
function upsertKeyframe(track: readonly Keyframe[], keyframe: Keyframe): Keyframe[]Returns the track with the keyframe inserted or replaced at its time, kept sorted.