The base concept for a constraint: an effect that continuously computes an object's properties from live scene state, instead of holding fixed values.
Base class — has no declarative element of its own; subclasses inherit its members.
A constraint is the shared idea behind the whole constraint family. Where a keyframe animation plays a fixed track, a constraint recomputes its result every frame from the current state of the scene — so the constrained target keeps tracking whatever it is bound to, even as that changes.
What it constrains. A constraint has one constrained target — the
object whose properties it drives — and may read from other objects it
references, such as a spline to follow, a node to look at, or a field to sample.
The target can be any SkenraAnimatable (a scene node, a material, or
another animatable), and referenced inputs are resolved by id against the scene
and re-resolved if the referenced object changes.
Member behaviours. Each concrete member computes a different result:
position and orient a node along a spline path
(sk-align-to-spline-constraint); rotate a node so a chosen axis points
at another node (sk-target-at-constraint); bind one object's property to
another animatable's property value, optionally remapped
(sk-follow-constraint); revolve a node around a pivot at a fixed radius
(sk-orbit-constraint); pin a node to a screen-space anchor regardless of
camera motion (sk-viewport-position-constraint); and write a field's
sampled weight into a target property (sk-field-constraint).
Effect model. Every constraint exposes a constrained target and a
priority, and participates in the unified effect model shared with animations:
effects are ordered by priority and combined with composite
operations. Constraints default to priority 100 so they take precedence over
animations (which default to 0); a constraint's result applies on the next frame
via the compositor, giving deterministic ordering when several effects touch the
same property. While a constraint is bound it writes to its target; once it is
removed the target reverts to its base values.
Related. The GPU-parallel sibling PointConstraint applies the same
idea to many points at once inside a Cloner, rather than to a single
node's properties.
The example below composes three constraints into a tiny solar system: a
planet orbits the sun (sk-orbit-constraint); a satellite flies a
spline parented to the planet, so its path travels with it
(sk-align-to-spline-constraint); and a center cone keeps pointing at
the moving planet (sk-target-at-constraint). Each constraint is a child
of the node it drives, and its #id attributes name its by-id inputs.
Abstract base class — not instantiated directly. Construct one of its concrete subclasses; this class contributes the members below to them.
Inherited from: SkenraAnimatable
— see those pages for inherited members.
| Property | Type | Default | Description | Declared by |
|---|---|---|---|---|
targetread-only |
SkenraAnimatable | null |
— | The node this constraint modifies. | Constraint |
priority |
number |
— | Gets the priority for this modifier in the effect stack. | Constraint |
sceneread-only |
any |
— | Gets the Scene this animatable belongs to, if any. | SkenraAnimatable |
animationsread-only |
SkenraAnimation[] |
— | Public getter for the animations affecting this target. | SkenraAnimatable |
| Method | Description | Declared by |
|---|---|---|
animate(firstArg: TypedKeyframe<this>[] | TypedPropertyIndexedKeyframes<this> | Record<string, any> | globalThis.Keyframe[] | globalThis.PropertyIndexedKeyframes | null, secondArg?: number | KeyframeAnimationOptions | globalThis.KeyframeAnimationOptions): SkenraAnimation & Animation |
Creates a new SkenraAnimation for this target per Web Animations API. | SkenraAnimatable |
removeAnimation(animation: SkenraAnimation): boolean |
Removes a specific animation from this object. | SkenraAnimatable |
constrain(type: K, config: ConstraintConfigMap[K]): ConstraintReturnMap[K] |
Creates a constraint on this Animatable using a fluent API. | SkenraAnimatable |
Serve these docs to run the live example.
WebGPU needs a secure context — open this page via grunt serve
rather than double-clicking the file. The Markup tab works from disk.
<sk-scene>
<sk-directional-light p="-0.9rad" h="0.4rad" intensity="1.0"></sk-directional-light>
<sk-ambient-light intensity="0.35"></sk-ambient-light>
<sk-plain-material id="sun-mat" base-color="#e0a030"></sk-plain-material>
<sk-plain-material id="planet-mat" base-color="#4f86c6"></sk-plain-material>
<sk-plain-material id="sat-mat" base-color="#c65f5f"></sk-plain-material>
<sk-plain-material id="cone-mat" base-color="#9fc98a"></sk-plain-material>
<sk-plain-material id="path-mat" base-color="#8899aa"></sk-plain-material>
<!-- A faint static ring at the orbit radius, so the auto-fit camera
frames the whole system (the planet's position is computed each frame). -->
<sk-cloner mode="vertex">
<sk-disc-points-source inner-radius="6" outer-radius="6.001"
radial-segments="1" rotation-segments="48" orientation="+y"></sk-disc-points-source>
<sk-sphere radius="0.05"><sk-surface-paint material="#path-mat"></sk-surface-paint></sk-sphere>
</sk-cloner>
<!-- The sun: a fixed pivot at the origin. -->
<sk-sphere id="sun" radius="1.2">
<sk-surface-paint material="#sun-mat"></sk-surface-paint>
</sk-sphere>
<!-- A center cone that keeps pointing at the planet. -->
<sk-cone id="cone" bottom-radius="0.5" top-radius="0" height="1.4" y="2.6">
<sk-surface-paint material="#cone-mat"></sk-surface-paint>
<sk-target-at-constraint target="#planet" axis="+y"></sk-target-at-constraint>
</sk-cone>
<!-- The planet orbits the sun; its spline path and satellite are its children. -->
<sk-sphere id="planet" radius="0.6">
<sk-surface-paint material="#planet-mat"></sk-surface-paint>
<sk-orbit-constraint radius="6" azimuth="0rad" elevation="0.2rad">
<sk-animation duration="8000ms" iterations="Infinity" easing="linear">
<sk-keyframe offset="0" azimuth="0rad"></sk-keyframe>
<sk-keyframe offset="1" azimuth="6.28318rad"></sk-keyframe>
</sk-animation>
</sk-orbit-constraint>
<sk-spline id="sat-path">
<sk-svg-spline-source path="M -1.6,0 C -1.6,-0.88 -0.88,-1.6 0,-1.6 C 0.88,-1.6 1.6,-0.88 1.6,0 C 1.6,0.88 0.88,1.6 0,1.6 C -0.88,1.6 -1.6,0.88 -1.6,0 Z"
coordinate-space="x-z"></sk-svg-spline-source>
<sk-stroke-paint material="#path-mat" width="1.5"></sk-stroke-paint>
</sk-spline>
<sk-sphere id="satellite" radius="0.22">
<sk-surface-paint material="#sat-mat"></sk-surface-paint>
<sk-align-to-spline-constraint spline="#sat-path" progress="0" tangential>
<sk-animation duration="2500ms" iterations="Infinity" easing="linear">
<sk-keyframe offset="0" progress="0"></sk-keyframe>
<sk-keyframe offset="1" progress="1"></sk-keyframe>
</sk-animation>
</sk-align-to-spline-constraint>
</sk-sphere>
</sk-sphere>
</sk-scene>