mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
docs: add runtime adapter skills (#572)
* docs: add runtime adapter skills * docs: address adapter skill review comments
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
---
|
||||
name: animejs
|
||||
description: Anime.js adapter patterns for HyperFrames. Use when writing Anime.js animations or timelines inside HyperFrames compositions, registering animations on window.__hfAnime, making Anime.js seek-driven and deterministic, or translating Anime.js examples into render-safe HyperFrames HTML.
|
||||
---
|
||||
|
||||
# Anime.js for HyperFrames
|
||||
|
||||
HyperFrames can seek Anime.js instances through its `animejs` runtime adapter. The composition owns the animation objects; HyperFrames owns the clock.
|
||||
|
||||
## Contract
|
||||
|
||||
- Create animations or timelines synchronously during composition initialization.
|
||||
- Set `autoplay: false` so Anime.js does not advance on its own clock.
|
||||
- Register every returned animation or timeline on `window.__hfAnime`.
|
||||
- Use finite durations and loop counts.
|
||||
- Avoid callbacks that mutate DOM based on wall-clock time, network state, or unseeded randomness.
|
||||
|
||||
The adapter seeks every registered instance with `instance.seek(timeMs)`, where `timeMs` is HyperFrames time in milliseconds.
|
||||
|
||||
## Basic Pattern
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/animejs@4.0.2/lib/anime.iife.min.js"></script>
|
||||
<script>
|
||||
const anim = anime({
|
||||
targets: ".mark",
|
||||
translateX: 280,
|
||||
rotate: "1turn",
|
||||
opacity: [0, 1],
|
||||
duration: 1200,
|
||||
easing: "easeOutExpo",
|
||||
autoplay: false,
|
||||
});
|
||||
|
||||
window.__hfAnime = window.__hfAnime || [];
|
||||
window.__hfAnime.push(anim);
|
||||
</script>
|
||||
```
|
||||
|
||||
## Timeline Pattern
|
||||
|
||||
```html
|
||||
<script>
|
||||
const tl = anime.timeline({
|
||||
autoplay: false,
|
||||
easing: "easeOutCubic",
|
||||
});
|
||||
|
||||
tl.add({
|
||||
targets: ".title",
|
||||
translateY: [40, 0],
|
||||
opacity: [0, 1],
|
||||
duration: 650,
|
||||
}).add(
|
||||
{
|
||||
targets: ".accent",
|
||||
scaleX: [0, 1],
|
||||
duration: 450,
|
||||
},
|
||||
250,
|
||||
);
|
||||
|
||||
window.__hfAnime = window.__hfAnime || [];
|
||||
window.__hfAnime.push(tl);
|
||||
</script>
|
||||
```
|
||||
|
||||
## Module Builds
|
||||
|
||||
If you use an ES module build, the adapter does not care how the instance was created. It only needs the returned object to expose `seek()`, `pause()`, and preferably `play()`:
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import { animate } from "https://cdn.jsdelivr.net/npm/animejs/+esm";
|
||||
|
||||
const anim = animate(".chip", {
|
||||
x: "18rem",
|
||||
duration: 900,
|
||||
autoplay: false,
|
||||
});
|
||||
|
||||
window.__hfAnime = window.__hfAnime || [];
|
||||
window.__hfAnime.push(anim);
|
||||
</script>
|
||||
```
|
||||
|
||||
## Good Uses
|
||||
|
||||
- Small SVG and DOM flourishes where Anime.js syntax is compact.
|
||||
- Imported Anime.js examples that can be made seek-driven.
|
||||
- Multiple independent micro-animations pushed into the same registry.
|
||||
|
||||
Use GSAP for complex scene sequencing unless the user specifically asks for Anime.js. GSAP is still the primary HyperFrames authoring path.
|
||||
|
||||
## Avoid
|
||||
|
||||
- Leaving `autoplay` at the Anime.js default.
|
||||
- Depending on `anime.running` auto-discovery instead of explicit `window.__hfAnime.push(...)`.
|
||||
- Infinite loops. Compute a finite repeat count from the composition duration.
|
||||
- Building animations in timers, promises, event handlers, or after async asset loads.
|
||||
|
||||
## Validation
|
||||
|
||||
After editing a composition that uses Anime.js:
|
||||
|
||||
```bash
|
||||
npx hyperframes lint
|
||||
npx hyperframes validate
|
||||
```
|
||||
|
||||
## Credits And References
|
||||
|
||||
- HyperFrames adapter source: `packages/core/src/runtime/adapters/animejs.ts`.
|
||||
- Anime.js documentation for `autoplay`, `pause()`, and `seek()`: https://animejs.com/documentation/
|
||||
@@ -0,0 +1,124 @@
|
||||
---
|
||||
name: css-animations
|
||||
description: CSS animation adapter patterns for HyperFrames. Use when authoring CSS keyframes, animation-delay based timing, animation-fill-mode, animation-play-state, or CSS-only motion that HyperFrames must seek deterministically during preview and rendering.
|
||||
---
|
||||
|
||||
# CSS Animations for HyperFrames
|
||||
|
||||
HyperFrames can seek CSS keyframe animations through its `css` runtime adapter. Use this for simple repeated motifs, background motion, shimmer, glow, masks, and non-sequenced decoration.
|
||||
|
||||
For scene choreography, GSAP is usually clearer. CSS animations work best when the motion belongs to one element and has a fixed duration.
|
||||
|
||||
## Contract
|
||||
|
||||
- Put the animated element in the DOM before runtime initialization finishes.
|
||||
- Give timed elements a `data-start` value so local animation time matches the clip.
|
||||
- Use finite `animation-duration` and `animation-iteration-count` because the negative-delay fallback cannot represent unbounded duration in environments without WAAPI-backed CSS animations.
|
||||
- Prefer `animation-fill-mode: both` so seeked states hold before and after active motion.
|
||||
- Avoid wall-clock JavaScript, hover-triggered state, and class toggles that depend on user events.
|
||||
|
||||
The adapter discovers elements with computed `animation-name`, seeks their browser `Animation` handles when available, and falls back to pausing with negative `animation-delay`.
|
||||
|
||||
## Basic Pattern
|
||||
|
||||
```html
|
||||
<div
|
||||
id="pulse-ring"
|
||||
class="clip pulse-ring"
|
||||
data-start="0"
|
||||
data-duration="4"
|
||||
data-track-index="2"
|
||||
></div>
|
||||
|
||||
<style>
|
||||
.pulse-ring {
|
||||
width: 280px;
|
||||
height: 280px;
|
||||
border: 4px solid rgba(255, 255, 255, 0.7);
|
||||
border-radius: 50%;
|
||||
animation-name: pulse-ring;
|
||||
animation-duration: 1200ms;
|
||||
animation-timing-function: cubic-bezier(0.2, 0, 0, 1);
|
||||
animation-iteration-count: 3;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
@keyframes pulse-ring {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.82);
|
||||
}
|
||||
35% {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: scale(1.18);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## Stagger Pattern
|
||||
|
||||
Use CSS custom properties to avoid duplicating keyframes:
|
||||
|
||||
```html
|
||||
<div class="clip dots" data-start="1" data-duration="3" data-track-index="3">
|
||||
<span style="--i: 0"></span>
|
||||
<span style="--i: 1"></span>
|
||||
<span style="--i: 2"></span>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.dots span {
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 10px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
animation: dot-pop 900ms ease-out both;
|
||||
animation-delay: calc(var(--i) * 120ms);
|
||||
}
|
||||
|
||||
@keyframes dot-pop {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(18px) scale(0.75);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## Good Uses
|
||||
|
||||
- Decorative loops with a known repeat count.
|
||||
- Mask, glow, shimmer, grain, and subtle parallax layers.
|
||||
- Simple one-element entrances where a full JS timeline would be excessive.
|
||||
|
||||
## Avoid
|
||||
|
||||
- Infinite CSS animations unless you have verified the browser exposes seekable WAAPI-backed CSS animation handles. Prefer a finite iteration count covering the visible duration.
|
||||
- Animating layout properties like `top`, `left`, `width`, or `height` when transforms work.
|
||||
- Relying on hover, focus, scroll, or media queries to trigger render-critical motion.
|
||||
- Changing animation classes after startup unless another deterministic timeline controls that change.
|
||||
|
||||
## Validation
|
||||
|
||||
After editing CSS animation compositions:
|
||||
|
||||
```bash
|
||||
npx hyperframes lint
|
||||
npx hyperframes validate
|
||||
```
|
||||
|
||||
## Credits And References
|
||||
|
||||
- HyperFrames adapter source: `packages/core/src/runtime/adapters/css.ts`.
|
||||
- MDN CSS animation documentation: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/animation
|
||||
- MDN `animation-fill-mode`: https://developer.mozilla.org/en-US/docs/Web/CSS/animation-fill-mode
|
||||
+30
-1
@@ -5,6 +5,28 @@ description: GSAP animation reference for HyperFrames. Covers gsap.to(), from(),
|
||||
|
||||
# GSAP
|
||||
|
||||
## HyperFrames Contract
|
||||
|
||||
HyperFrames controls GSAP through its `gsap` runtime adapter. Create a paused timeline synchronously, register it on `window.__timelines` with the exact `data-composition-id`, and let HyperFrames seek it.
|
||||
|
||||
```html
|
||||
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
||||
<script>
|
||||
window.__timelines = window.__timelines || {};
|
||||
const tl = gsap.timeline({ paused: true });
|
||||
|
||||
tl.from(".title", { y: 48, opacity: 0, duration: 0.6, ease: "power3.out" }, 0);
|
||||
tl.to(".accent", { scaleX: 1, duration: 0.5, ease: "power2.out" }, 0.25);
|
||||
|
||||
window.__timelines["main"] = tl; // key must equal data-composition-id on the composition root
|
||||
</script>
|
||||
```
|
||||
|
||||
- The registry key must match the composition root's `data-composition-id`.
|
||||
- Do not call `tl.play()` for render-critical motion.
|
||||
- Do not build timelines inside async code, timers, or event handlers.
|
||||
- Keep loops finite. HyperFrames renders finite video durations.
|
||||
|
||||
## Core Tween Methods
|
||||
|
||||
- **gsap.to(targets, vars)** — animate from current state to `vars`. Most common.
|
||||
@@ -21,7 +43,7 @@ Always use **camelCase** property names (e.g. `backgroundColor`, `rotationX`).
|
||||
- **ease** — `"power1.out"` (default), `"power3.inOut"`, `"back.out(1.7)"`, `"elastic.out(1, 0.3)"`, `"none"`.
|
||||
- **stagger** — number `0.1` or object: `{ amount: 0.3, from: "center" }`, `{ each: 0.1, from: "random" }`.
|
||||
- **overwrite** — `false` (default), `true`, or `"auto"`.
|
||||
- **repeat** — number or `-1` for infinite. **yoyo** — alternates direction with repeat.
|
||||
- **repeat** — finite number; never `-1` in HyperFrames. Compute repeats from the visible duration. **yoyo** — alternates direction with repeat.
|
||||
- **onComplete**, **onStart**, **onUpdate** — callbacks.
|
||||
- **immediateRender** — default `true` for from()/fromTo(). Set `false` on later tweens targeting the same property+element to avoid overwrite.
|
||||
|
||||
@@ -209,3 +231,10 @@ Pause or kill off-screen animations.
|
||||
- Chain animations with delay when a timeline can sequence them.
|
||||
- Create tweens before the DOM exists.
|
||||
- Skip cleanup — always kill tweens when no longer needed.
|
||||
- Use infinite repeat values in HyperFrames compositions. Use finite repeat counts computed from the visible duration.
|
||||
|
||||
## Credits And References
|
||||
|
||||
- HyperFrames adapter source: `packages/core/src/runtime/adapters/gsap.ts`.
|
||||
- GSAP documentation: https://gsap.com/docs/v3/
|
||||
- GSAP timeline pause and seek behavior: https://gsap.com/docs/v3/GSAP/Timeline/pause%28%29/
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
---
|
||||
name: lottie
|
||||
description: Lottie and dotLottie adapter patterns for HyperFrames. Use when embedding lottie-web JSON animations, .lottie files, @lottiefiles/dotlottie-web players, registering instances on window.__hfLottie, or making After Effects exports deterministic in HyperFrames.
|
||||
---
|
||||
|
||||
# Lottie for HyperFrames
|
||||
|
||||
HyperFrames can seek both `lottie-web` and dotLottie players through its `lottie` runtime adapter. Lottie is a strong fit because the animation timeline is already encoded in the asset; HyperFrames only needs a player object it can seek.
|
||||
|
||||
## Contract
|
||||
|
||||
- Load assets from local project files, usually under `assets/`.
|
||||
- Set `autoplay: false`.
|
||||
- Prefer `loop: false` unless the user explicitly wants a loop.
|
||||
- Register every returned animation or player on `window.__hfLottie`.
|
||||
- Keep the Lottie container dimensions stable with CSS.
|
||||
|
||||
The adapter seeks `lottie-web` with `goToAndStop(timeMs, false)` and dotLottie with frame or percentage APIs depending on player shape.
|
||||
|
||||
## lottie-web Pattern
|
||||
|
||||
```html
|
||||
<div id="logo-lottie" class="lottie-layer"></div>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.12.2/lottie.min.js"></script>
|
||||
<script>
|
||||
const anim = lottie.loadAnimation({
|
||||
container: document.getElementById("logo-lottie"),
|
||||
renderer: "svg",
|
||||
loop: false,
|
||||
autoplay: false,
|
||||
path: "assets/logo-reveal.json",
|
||||
});
|
||||
|
||||
window.__hfLottie = window.__hfLottie || [];
|
||||
window.__hfLottie.push(anim);
|
||||
</script>
|
||||
```
|
||||
|
||||
```css
|
||||
.lottie-layer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
```
|
||||
|
||||
## dotLottie Pattern
|
||||
|
||||
```html
|
||||
<canvas id="product-lottie" class="lottie-canvas"></canvas>
|
||||
<script src="https://unpkg.com/@lottiefiles/dotlottie-web"></script>
|
||||
<script>
|
||||
const player = new DotLottie({
|
||||
canvas: document.getElementById("product-lottie"),
|
||||
src: "assets/product-flow.lottie",
|
||||
autoplay: false,
|
||||
loop: false,
|
||||
});
|
||||
|
||||
window.__hfLottie = window.__hfLottie || [];
|
||||
window.__hfLottie.push(player);
|
||||
</script>
|
||||
```
|
||||
|
||||
```css
|
||||
.lottie-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
```
|
||||
|
||||
## Multiple Animations
|
||||
|
||||
Push each player into the same registry:
|
||||
|
||||
```js
|
||||
window.__hfLottie = window.__hfLottie || [];
|
||||
window.__hfLottie.push(backgroundAnim);
|
||||
window.__hfLottie.push(iconAnim);
|
||||
window.__hfLottie.push(confettiAnim);
|
||||
```
|
||||
|
||||
HyperFrames seeks them all to the same composition time.
|
||||
|
||||
## Good Uses
|
||||
|
||||
- After Effects exports that are already known to render correctly in lottie-web.
|
||||
- Logo reveals, icon loops, decorative accents, and product UI motion.
|
||||
- Translating Remotion Lottie usage into plain HyperFrames HTML.
|
||||
|
||||
## Avoid
|
||||
|
||||
- Relying on remote `path` URLs at render time.
|
||||
- Starting playback with `play()`.
|
||||
- Assuming unsupported After Effects effects will survive export. Test the JSON or `.lottie` file in a browser first.
|
||||
- Loading a player asynchronously and registering it after HyperFrames validation has already inspected the page.
|
||||
|
||||
## Validation
|
||||
|
||||
After editing a Lottie composition:
|
||||
|
||||
```bash
|
||||
npx hyperframes lint
|
||||
npx hyperframes validate
|
||||
```
|
||||
|
||||
## Credits And References
|
||||
|
||||
- HyperFrames adapter source: `packages/core/src/runtime/adapters/lottie.ts`.
|
||||
- lottie-web by Airbnb: https://github.com/airbnb/lottie-web
|
||||
- lottie-web `loadAnimation` options: https://github.com/airbnb/lottie-web/wiki/loadAnimation-options
|
||||
- dotLottie web player methods by LottieFiles: https://developers.lottiefiles.com/docs/dotlottie-player/dotlottie-web/methods
|
||||
@@ -0,0 +1,106 @@
|
||||
---
|
||||
name: three
|
||||
description: Three.js and WebGL adapter patterns for HyperFrames. Use when creating deterministic Three.js scenes, WebGL canvas layers, AnimationMixer timelines, camera motion, shader-driven visuals, or canvas renders that respond to HyperFrames hf-seek events.
|
||||
---
|
||||
|
||||
# Three.js for HyperFrames
|
||||
|
||||
HyperFrames supports Three.js through its `three` runtime adapter. The adapter does not own your scene. It publishes HyperFrames time and dispatches a seek event so your composition can render the exact frame.
|
||||
|
||||
## Contract
|
||||
|
||||
- Create the scene, camera, renderer, materials, and assets synchronously when possible.
|
||||
- Render from HyperFrames time, not wall-clock time.
|
||||
- Listen for the `hf-seek` event and render exactly that time.
|
||||
- Load models, textures, and HDRIs before render-critical seeking. Do not fetch them at seek time.
|
||||
- Avoid `requestAnimationFrame` or `renderer.setAnimationLoop` as the source of truth for render-critical motion.
|
||||
|
||||
The adapter sets `window.__hfThreeTime` and dispatches `new CustomEvent("hf-seek", { detail: { time } })` on each seek.
|
||||
|
||||
## Basic Pattern
|
||||
|
||||
```html
|
||||
<canvas id="three-layer"></canvas>
|
||||
<script type="module">
|
||||
import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.181.2/+esm";
|
||||
|
||||
const canvas = document.getElementById("three-layer");
|
||||
const renderer = new THREE.WebGLRenderer({ canvas, alpha: true, antialias: true });
|
||||
// Match these to your composition's frame size.
|
||||
renderer.setSize(1920, 1080, false);
|
||||
renderer.setPixelRatio(1);
|
||||
|
||||
const scene = new THREE.Scene();
|
||||
const camera = new THREE.PerspectiveCamera(35, 1920 / 1080, 0.1, 100);
|
||||
camera.position.set(0, 0, 6);
|
||||
|
||||
const mesh = new THREE.Mesh(
|
||||
new THREE.IcosahedronGeometry(1.4, 4),
|
||||
new THREE.MeshStandardMaterial({ color: 0x64d2ff, roughness: 0.38 }),
|
||||
);
|
||||
scene.add(mesh);
|
||||
scene.add(new THREE.HemisphereLight(0xffffff, 0x223344, 2));
|
||||
|
||||
function renderAt(time) {
|
||||
mesh.rotation.y = time * 0.7;
|
||||
mesh.rotation.x = Math.sin(time * 0.6) * 0.16;
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
window.addEventListener("hf-seek", (event) => {
|
||||
renderAt(event.detail.time);
|
||||
});
|
||||
|
||||
renderAt(window.__hfThreeTime || 0);
|
||||
</script>
|
||||
```
|
||||
|
||||
```css
|
||||
#three-layer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
```
|
||||
|
||||
## AnimationMixer Pattern
|
||||
|
||||
For GLTF or authored clip animation, seek the mixer directly:
|
||||
|
||||
```js
|
||||
function renderAt(time) {
|
||||
mixer.setTime(time);
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
```
|
||||
|
||||
If several mixers exist, seek all of them from the same `time`.
|
||||
|
||||
## Good Uses
|
||||
|
||||
- Deterministic 3D objects, product spins, particles with seeded data, and shader plates.
|
||||
- Camera moves derived from `time`.
|
||||
- GLTF animation clips when assets are local and loaded before validation completes.
|
||||
|
||||
## Avoid
|
||||
|
||||
- Using `Date.now()`, `performance.now()`, or clock deltas to update scene state.
|
||||
- Leaving render-critical work inside a free-running animation loop.
|
||||
- Loading remote models or textures at render time.
|
||||
- Device-pixel-ratio dependent output. Pin renderer size and pixel ratio for video renders.
|
||||
- Post-processing passes that depend on previous frame history unless you can reconstruct state from time.
|
||||
|
||||
## Validation
|
||||
|
||||
After editing a Three.js composition:
|
||||
|
||||
```bash
|
||||
npx hyperframes lint
|
||||
npx hyperframes validate
|
||||
```
|
||||
|
||||
## Credits And References
|
||||
|
||||
- HyperFrames adapter source: `packages/core/src/runtime/adapters/three.ts`.
|
||||
- Three.js `WebGLRenderer` docs: https://threejs.org/docs/pages/WebGLRenderer.html
|
||||
- Three.js `AnimationMixer.setTime()` docs: https://threejs.org/docs/pages/AnimationMixer.html
|
||||
@@ -0,0 +1,94 @@
|
||||
---
|
||||
name: waapi
|
||||
description: Web Animations API adapter patterns for HyperFrames. Use when authoring element.animate() motion, Animation currentTime seeking, document.getAnimations(), KeyframeEffect timing, fill modes, or native browser animations that must render deterministically in HyperFrames.
|
||||
---
|
||||
|
||||
# Web Animations API for HyperFrames
|
||||
|
||||
HyperFrames can seek Web Animations API animations through its `waapi` runtime adapter. WAAPI is useful when you want native browser keyframes with JavaScript-created timing and no GSAP dependency.
|
||||
|
||||
## Contract
|
||||
|
||||
- Create animations synchronously during composition initialization.
|
||||
- Use `element.animate(...)` with finite `duration` and `iterations`.
|
||||
- Use `fill: "both"` so seeked states persist.
|
||||
- Pause animations after creation or let the adapter pause them on first seek.
|
||||
- Avoid callbacks and promises for render-critical state.
|
||||
|
||||
The adapter calls `document.getAnimations()`, sets each animation's `currentTime` to HyperFrames time in milliseconds, then pauses it.
|
||||
|
||||
## Basic Pattern
|
||||
|
||||
```html
|
||||
<div id="orb" class="clip orb" data-start="2" data-duration="3" data-track-index="2"></div>
|
||||
|
||||
<script>
|
||||
const orb = document.getElementById("orb");
|
||||
const animation = orb.animate(
|
||||
[
|
||||
{ transform: "translate3d(-160px, 0, 0) scale(0.8)", opacity: 0 },
|
||||
{ transform: "translate3d(0, 0, 0) scale(1)", opacity: 1, offset: 0.35 },
|
||||
{ transform: "translate3d(120px, 0, 0) scale(1.08)", opacity: 1 },
|
||||
],
|
||||
{
|
||||
duration: 3000,
|
||||
delay: 2000,
|
||||
easing: "cubic-bezier(0.2, 0, 0, 1)",
|
||||
fill: "both",
|
||||
iterations: 1,
|
||||
},
|
||||
);
|
||||
|
||||
animation.pause();
|
||||
</script>
|
||||
```
|
||||
|
||||
## Stagger Pattern
|
||||
|
||||
```js
|
||||
document.querySelectorAll(".token").forEach((token, index) => {
|
||||
const animation = token.animate(
|
||||
[
|
||||
{ transform: "translateY(24px)", opacity: 0 },
|
||||
{ transform: "translateY(0)", opacity: 1 },
|
||||
],
|
||||
{
|
||||
duration: 620,
|
||||
delay: index * 80,
|
||||
easing: "cubic-bezier(0.2, 0, 0, 1)",
|
||||
fill: "both",
|
||||
iterations: 1,
|
||||
},
|
||||
);
|
||||
animation.pause();
|
||||
});
|
||||
```
|
||||
|
||||
## Good Uses
|
||||
|
||||
- Lightweight DOM motion where CSS keyframes are too rigid and GSAP is unnecessary.
|
||||
- Generated animations from structured data.
|
||||
- Simple timelines that can be represented as keyframes, delays, and offsets.
|
||||
|
||||
## Avoid
|
||||
|
||||
- Infinite `iterations`.
|
||||
- Depending on `animation.finished` to mutate render-critical DOM.
|
||||
- Running separate clocks with `requestAnimationFrame`, timers, or `performance.now()`.
|
||||
- Animating layout properties when transforms and opacity can express the motion.
|
||||
- Assuming clip-local start time is automatic. WAAPI adapter seeks document-level animation time; model clip offsets with `delay` or create the animation on an element whose visibility is controlled by HyperFrames timing.
|
||||
|
||||
## Validation
|
||||
|
||||
After editing a WAAPI composition:
|
||||
|
||||
```bash
|
||||
npx hyperframes lint
|
||||
npx hyperframes validate
|
||||
```
|
||||
|
||||
## Credits And References
|
||||
|
||||
- HyperFrames adapter source: `packages/core/src/runtime/adapters/waapi.ts`.
|
||||
- MDN Web Animations API guide: https://developer.mozilla.org/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API
|
||||
- MDN `Animation.currentTime`: https://developer.mozilla.org/en-US/docs/Web/API/Animation/currentTime
|
||||
Reference in New Issue
Block a user