85453da49f
CodeQL / Analyze (javascript-typescript) (push) Waiting to run
Docs / Validate docs (push) Waiting to run
CodeQL / Analyze (actions) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Sync skills to ClawHub / Publish changed skills (push) Waiting to run
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
135 lines
5.8 KiB
Plaintext
135 lines
5.8 KiB
Plaintext
---
|
|
title: GSAP Animation
|
|
description: "Add animations to your Hyperframes compositions with GSAP."
|
|
---
|
|
|
|
Hyperframes uses [GSAP](https://gsap.com/) for animation. Timelines are paused and controlled by the runtime — you define the animations, the framework handles playback. For background on how animation runtimes plug into Hyperframes, see [Frame Adapters](/concepts/frame-adapters).
|
|
|
|
## Setup
|
|
|
|
Include GSAP and create a paused timeline:
|
|
|
|
```html index.html
|
|
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
|
|
<script>
|
|
// 1. Create a paused timeline — the framework controls playback
|
|
const tl = gsap.timeline({ paused: true });
|
|
|
|
// 2. Add animations using the position parameter (3rd arg) for absolute timing
|
|
tl.to("#title", { opacity: 1, duration: 0.5 }, 0);
|
|
|
|
// 3. Initialize the global timelines registry (if not already present)
|
|
window.__timelines = window.__timelines || {};
|
|
|
|
// 4. Register the timeline using the data-composition-id as the key
|
|
window.__timelines["root"] = tl;
|
|
</script>
|
|
```
|
|
|
|
<Note>
|
|
The key you use in `window.__timelines` must match the `data-composition-id` attribute on your composition's root element. See [Compositions](/concepts/compositions) for how the root element is structured.
|
|
</Note>
|
|
|
|
## Key Rules
|
|
|
|
1. **Always create timelines with `{ paused: true }`** — the framework controls playback via [deterministic seeking](/concepts/determinism)
|
|
2. **Register timelines on `window.__timelines`** with the [`data-composition-id`](/concepts/data-attributes#composition-attributes) as key
|
|
3. **Use the position parameter** (3rd argument) for absolute timing: `tl.to(el, vars, 1.5)`
|
|
4. **Only animate visual properties** — never control media playback in scripts
|
|
|
|
## Supported Methods
|
|
|
|
| Method | Description |
|
|
|--------|-------------|
|
|
| `tl.to(target, vars, position)` | Animate to values |
|
|
| `tl.from(target, vars, position)` | Animate from values |
|
|
| `tl.fromTo(target, fromVars, toVars, position)` | Animate from/to values |
|
|
| `tl.set(target, vars, position)` | Set values instantly |
|
|
|
|
## Supported Properties
|
|
|
|
`opacity`, `x`, `y`, `scale`, `scaleX`, `scaleY`, `rotation`, `color`, `backgroundColor`, and other CSS-animatable transform/color properties. Do **not** animate `visibility`, `width`, or `height` — these break deterministic rendering.
|
|
|
|
## Timeline Duration and Composition Duration
|
|
|
|
A composition's duration equals its GSAP timeline duration. The two are directly linked:
|
|
|
|
```javascript compositions/intro-anim.html
|
|
// Your last animation ends at 3 seconds...
|
|
tl.from("#title", { opacity: 0, y: -50, duration: 1 }, 0);
|
|
tl.to("#title", { opacity: 0, duration: 1 }, 2);
|
|
// ...so this composition is exactly 3 seconds long.
|
|
```
|
|
|
|
If your composition contains a video clip that is 283 seconds long, but your last GSAP animation ends at 8 seconds, the composition will be only 8 seconds long and the video will be cut short. To extend the timeline to match the video:
|
|
|
|
```javascript index.html
|
|
// All your visual animations
|
|
tl.to("#lower-third", { left: -640, duration: 0.6 }, 7.2);
|
|
|
|
// Extend the timeline to 283 seconds to match the video length.
|
|
// This adds a zero-duration tween at 283s without affecting any elements.
|
|
tl.set({}, {}, 283);
|
|
```
|
|
|
|
<Warning>
|
|
This is one of the most common mistakes in Hyperframes. If your video cuts off early, the timeline is too short. See [Common Mistakes: Composition Duration Shorter Than Video](/guides/common-mistakes) for more details.
|
|
</Warning>
|
|
|
|
## What NOT to Do
|
|
|
|
These patterns will break your composition or cause sync issues:
|
|
|
|
```javascript index.html
|
|
// WRONG: Playing media in scripts — the framework owns media playback
|
|
document.getElementById("el-video").play();
|
|
document.getElementById("el-audio").currentTime = 5;
|
|
|
|
// WRONG: Creating a non-paused timeline
|
|
const tl = gsap.timeline(); // missing { paused: true }!
|
|
|
|
// WRONG: Animating dimensions directly on a <video> element
|
|
tl.to("#el-video", { width: 500, height: 280 }, 5);
|
|
|
|
// WRONG: Manually nesting sub-timelines
|
|
const masterTL = window.__timelines["root"];
|
|
masterTL.add(window.__timelines["intro-anim"], 0);
|
|
```
|
|
|
|
The framework automatically manages [media playback](/reference/html-schema#framework-managed-behavior), [clip lifecycle](/concepts/compositions#two-layers-primitives-and-scripts), and [sub-composition nesting](#sub-composition-timelines). Scripts that duplicate this behavior will conflict.
|
|
|
|
## Sub-Composition Timelines
|
|
|
|
Each [nested composition](/concepts/compositions#nested-compositions) registers its own timeline. The framework automatically nests sub-composition timelines into the parent based on [`data-start`](/concepts/data-attributes#timing-attributes):
|
|
|
|
```javascript compositions/intro-anim.html
|
|
// In compositions/intro-anim.html
|
|
const tl = gsap.timeline({ paused: true });
|
|
tl.from(".title", { opacity: 0, y: -50, duration: 1 });
|
|
window.__timelines["intro-anim"] = tl;
|
|
|
|
// DO NOT manually add sub-timelines to the master:
|
|
// masterTL.add(window.__timelines["intro-anim"], 0); // UNNECESSARY
|
|
```
|
|
|
|
<Warning>
|
|
Don't animate `width`, `height`, `top`, or `left` directly on `<video>` elements — this can cause the browser to stop rendering frames. Wrap the video in a `<div>` and animate the wrapper instead. See [Common Mistakes](/guides/common-mistakes) for a detailed explanation.
|
|
</Warning>
|
|
|
|
## Next Steps
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Compositions" icon="layer-group" href="/concepts/compositions">
|
|
Understand the building blocks that timelines animate
|
|
</Card>
|
|
<Card title="Frame Adapters" icon="plug" href="/concepts/frame-adapters">
|
|
Learn how GSAP plugs into the render pipeline
|
|
</Card>
|
|
<Card title="Common Mistakes" icon="triangle-exclamation" href="/guides/common-mistakes">
|
|
Avoid pitfalls that break animations
|
|
</Card>
|
|
<Card title="HTML Schema Reference" icon="code" href="/reference/html-schema">
|
|
Full reference for composition attributes
|
|
</Card>
|
|
</CardGroup>
|