@editframe/create 0.43.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/index.js +16 -28
- package/dist/index.js.map +1 -1
- package/dist/skills/editframe-brand-video-generator/README.md +155 -0
- package/dist/skills/editframe-brand-video-generator/SKILL.md +207 -0
- package/dist/skills/editframe-brand-video-generator/references/brand-examples.md +178 -0
- package/dist/skills/editframe-brand-video-generator/references/color-psychology.md +227 -0
- package/dist/skills/editframe-brand-video-generator/references/composition-patterns.md +383 -0
- package/dist/skills/editframe-brand-video-generator/references/editing.md +66 -0
- package/dist/skills/editframe-brand-video-generator/references/emotional-arcs.md +496 -0
- package/dist/skills/editframe-brand-video-generator/references/genre-selection.md +135 -0
- package/dist/skills/editframe-brand-video-generator/references/transition-styles.md +611 -0
- package/dist/skills/editframe-brand-video-generator/references/typography-personalities.md +326 -0
- package/dist/skills/editframe-brand-video-generator/references/video-archetypes.md +86 -0
- package/dist/skills/editframe-brand-video-generator/references/video-fundamentals.md +169 -0
- package/dist/skills/editframe-brand-video-generator/references/visual-metaphors.md +50 -0
- package/dist/skills/editframe-composition/SKILL.md +169 -0
- package/dist/skills/editframe-composition/references/audio.md +483 -0
- package/dist/skills/editframe-composition/references/captions.md +844 -0
- package/dist/skills/editframe-composition/references/composition-model.md +73 -0
- package/dist/skills/editframe-composition/references/configuration.md +403 -0
- package/dist/skills/editframe-composition/references/css-parts.md +105 -0
- package/dist/skills/editframe-composition/references/css-variables.md +640 -0
- package/dist/skills/editframe-composition/references/entry-points.md +810 -0
- package/dist/skills/editframe-composition/references/events.md +499 -0
- package/dist/skills/editframe-composition/references/getting-started.md +259 -0
- package/dist/skills/editframe-composition/references/hooks.md +234 -0
- package/dist/skills/editframe-composition/references/image.md +241 -0
- package/dist/skills/editframe-composition/references/r3f.md +580 -0
- package/dist/skills/editframe-composition/references/render-api.md +484 -0
- package/dist/skills/editframe-composition/references/render-strategies.md +119 -0
- package/dist/skills/editframe-composition/references/render-to-video.md +1101 -0
- package/dist/skills/editframe-composition/references/scripting.md +606 -0
- package/dist/skills/editframe-composition/references/sequencing.md +116 -0
- package/dist/skills/editframe-composition/references/server-rendering.md +753 -0
- package/dist/skills/editframe-composition/references/surface.md +329 -0
- package/dist/skills/editframe-composition/references/text.md +627 -0
- package/dist/skills/editframe-composition/references/time-model.md +99 -0
- package/dist/skills/editframe-composition/references/timegroup-modes.md +102 -0
- package/dist/skills/editframe-composition/references/timegroup.md +457 -0
- package/dist/skills/editframe-composition/references/timeline-root.md +398 -0
- package/dist/skills/editframe-composition/references/transcription.md +47 -0
- package/dist/skills/editframe-composition/references/transitions.md +608 -0
- package/dist/skills/editframe-composition/references/use-media-info.md +357 -0
- package/dist/skills/editframe-composition/references/video.md +506 -0
- package/dist/skills/editframe-composition/references/waveform.md +327 -0
- package/dist/skills/editframe-editor-gui/SKILL.md +152 -0
- package/dist/skills/editframe-editor-gui/references/active-root-temporal.md +657 -0
- package/dist/skills/editframe-editor-gui/references/canvas.md +947 -0
- package/dist/skills/editframe-editor-gui/references/controls.md +366 -0
- package/dist/skills/editframe-editor-gui/references/dial.md +756 -0
- package/dist/skills/editframe-editor-gui/references/editor-toolkit.md +587 -0
- package/dist/skills/editframe-editor-gui/references/filmstrip.md +460 -0
- package/dist/skills/editframe-editor-gui/references/fit-scale.md +772 -0
- package/dist/skills/editframe-editor-gui/references/focus-overlay.md +561 -0
- package/dist/skills/editframe-editor-gui/references/hierarchy.md +544 -0
- package/dist/skills/editframe-editor-gui/references/overlay-item.md +634 -0
- package/dist/skills/editframe-editor-gui/references/overlay-layer.md +429 -0
- package/dist/skills/editframe-editor-gui/references/pan-zoom.md +568 -0
- package/dist/skills/editframe-editor-gui/references/pause.md +397 -0
- package/dist/skills/editframe-editor-gui/references/play.md +370 -0
- package/dist/skills/editframe-editor-gui/references/preview.md +391 -0
- package/dist/skills/editframe-editor-gui/references/resizable-box.md +749 -0
- package/dist/skills/editframe-editor-gui/references/scrubber.md +588 -0
- package/dist/skills/editframe-editor-gui/references/thumbnail-strip.md +566 -0
- package/dist/skills/editframe-editor-gui/references/time-display.md +492 -0
- package/dist/skills/editframe-editor-gui/references/timeline-ruler.md +489 -0
- package/dist/skills/editframe-editor-gui/references/timeline.md +604 -0
- package/dist/skills/editframe-editor-gui/references/toggle-loop.md +618 -0
- package/dist/skills/editframe-editor-gui/references/toggle-play.md +526 -0
- package/dist/skills/editframe-editor-gui/references/transform-handles.md +924 -0
- package/dist/skills/editframe-editor-gui/references/trim-handles.md +725 -0
- package/dist/skills/editframe-editor-gui/references/workbench.md +453 -0
- package/dist/skills/editframe-motion-design/SKILL.md +101 -0
- package/dist/skills/editframe-motion-design/references/0-editframe.md +299 -0
- package/dist/skills/editframe-motion-design/references/1-intent.md +201 -0
- package/dist/skills/editframe-motion-design/references/2-physics-model.md +405 -0
- package/dist/skills/editframe-motion-design/references/3-attention.md +350 -0
- package/dist/skills/editframe-motion-design/references/4-process.md +418 -0
- package/dist/skills/editframe-vite-plugin/SKILL.md +75 -0
- package/dist/skills/editframe-vite-plugin/references/file-api.md +111 -0
- package/dist/skills/editframe-vite-plugin/references/getting-started.md +96 -0
- package/dist/skills/editframe-vite-plugin/references/jit-transcoding.md +91 -0
- package/dist/skills/editframe-vite-plugin/references/local-assets.md +75 -0
- package/dist/skills/editframe-vite-plugin/references/visual-testing.md +136 -0
- package/dist/skills/editframe-webhooks/SKILL.md +126 -0
- package/dist/skills/editframe-webhooks/references/events.md +382 -0
- package/dist/skills/editframe-webhooks/references/getting-started.md +232 -0
- package/dist/skills/editframe-webhooks/references/security.md +418 -0
- package/dist/skills/editframe-webhooks/references/testing.md +409 -0
- package/dist/skills/editframe-webhooks/references/troubleshooting.md +457 -0
- package/dist/templates/html/AGENTS.md +13 -0
- package/dist/templates/react/AGENTS.md +13 -0
- package/dist/utils.js +15 -16
- package/dist/utils.js.map +1 -1
- package/package.json +2 -2
- package/tsdown.config.ts +4 -0
- package/dist/detectAgent.js +0 -89
- package/dist/detectAgent.js.map +0 -1
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Implementing Motion in Editframe
|
|
3
|
+
description: How the motion design principles map to Editframe syntax — CSS animations, --ef-progress, text splitting, addFrameTask, and transitions.
|
|
4
|
+
type: explanation
|
|
5
|
+
order: 0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Implementing Motion in Editframe
|
|
9
|
+
|
|
10
|
+
The motion design principles in this skill apply directly to Editframe's composition system. This reference maps each concept to the specific Editframe tools that implement it.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Easing and Physics → CSS `animation-timing-function`
|
|
15
|
+
|
|
16
|
+
The material physics model translates directly to CSS easing curves. Apply them to the `animation` shorthand on any element.
|
|
17
|
+
|
|
18
|
+
```html
|
|
19
|
+
<!-- Glass: clean entrance, minimal overshoot -->
|
|
20
|
+
<ef-text style="animation: 400ms title-enter both; animation-timing-function: cubic-bezier(0, 0.55, 0.45, 1)">
|
|
21
|
+
Professional Title
|
|
22
|
+
</ef-text>
|
|
23
|
+
|
|
24
|
+
<!-- Rubber: bouncy entrance for playful brands -->
|
|
25
|
+
<ef-text style="animation: 600ms logo-bounce both; animation-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55)">
|
|
26
|
+
Fun Brand
|
|
27
|
+
</ef-text>
|
|
28
|
+
|
|
29
|
+
@keyframes title-enter {
|
|
30
|
+
from { transform: translateY(20px); opacity: 0; }
|
|
31
|
+
to { transform: translateY(0); opacity: 1; }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@keyframes logo-bounce {
|
|
35
|
+
from { transform: scale(0.8); opacity: 0; }
|
|
36
|
+
to { transform: scale(1); opacity: 1; }
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Add a new section after the material reference table:
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Rhythm Through Variation
|
|
45
|
+
|
|
46
|
+
**Anti-pattern:** All animations using identical duration and easing creates mechanical, monotonous motion.
|
|
47
|
+
|
|
48
|
+
**Rule:** Within any scene, vary at least ONE of: duration, easing, or delay pattern.
|
|
49
|
+
|
|
50
|
+
**For keyboard/command-driven products (Linear, Raycast, etc.):**
|
|
51
|
+
- Primary actions: 200-300ms, sharp easing (`cubic-bezier(0.55, 0, 1, 0.45)`) — feels responsive
|
|
52
|
+
- State transitions: 400-500ms, smooth easing — shows the system working
|
|
53
|
+
- Reveals/entrances: 500-600ms, gentle easing — gives content room to land
|
|
54
|
+
|
|
55
|
+
```html
|
|
56
|
+
<!-- Wrong: monotonous -->
|
|
57
|
+
<ef-text style="animation: 0.6s enter ease-out">Action</ef-text>
|
|
58
|
+
<ef-text style="animation: 0.6s enter ease-out">Result</ef-text>
|
|
59
|
+
|
|
60
|
+
<!-- Right: rhythm through variation -->
|
|
61
|
+
<ef-text style="animation: 0.25s snap cubic-bezier(0.55, 0, 1, 0.45)">⌘K</ef-text>
|
|
62
|
+
<ef-text style="animation: 0.5s reveal ease-out 0.15s">Issue created</ef-text>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Stagger → `ef-text` `split` and `--ef-word-index`
|
|
68
|
+
|
|
69
|
+
The attention sequencing principle — one focus at a time — is implemented through text splitting and CSS variable stagger delays.
|
|
70
|
+
|
|
71
|
+
```html
|
|
72
|
+
<!-- Word-by-word reveal with stagger -->
|
|
73
|
+
<ef-text
|
|
74
|
+
split="word"
|
|
75
|
+
class="text-white text-4xl"
|
|
76
|
+
style="animation: 0.5s word-in both; animation-delay: calc(var(--ef-word-index) * 80ms)"
|
|
77
|
+
>Your message builds word by word</ef-text>
|
|
78
|
+
|
|
79
|
+
<!-- Character-by-character (typewriter style) -->
|
|
80
|
+
<ef-text
|
|
81
|
+
split="char"
|
|
82
|
+
class="text-white text-3xl font-mono"
|
|
83
|
+
style="animation: 0.1s char-in both; animation-delay: calc(var(--ef-char-index) * 40ms)"
|
|
84
|
+
>LOADING...</ef-text>
|
|
85
|
+
|
|
86
|
+
<!-- Line-by-line with organic variation using --ef-seed -->
|
|
87
|
+
<ef-text
|
|
88
|
+
split="line"
|
|
89
|
+
class="text-white text-2xl"
|
|
90
|
+
style="animation: 0.6s line-in both; animation-delay: calc(var(--ef-line-index) * 150ms); animation-timing-function: cubic-bezier(0, 0.55, calc(0.45 + var(--ef-seed) * 0.1), 1)"
|
|
91
|
+
>First line
|
|
92
|
+
Second line
|
|
93
|
+
Third line</ef-text>
|
|
94
|
+
|
|
95
|
+
@keyframes word-in { from { transform: translateY(18px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
|
|
96
|
+
@keyframes char-in { from { opacity: 0; } to { opacity: 1; } }
|
|
97
|
+
@keyframes line-in { from { transform: translateY(12px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Available CSS variables on split elements:**
|
|
101
|
+
|
|
102
|
+
- `--ef-word-index` — 0-based index of this word in its parent
|
|
103
|
+
- `--ef-char-index` — 0-based index of this character
|
|
104
|
+
- `--ef-line-index` — 0-based index of this line
|
|
105
|
+
- `--ef-stagger-offset` — total number of siblings (for inverse stagger: `calc((var(--ef-stagger-offset) - var(--ef-word-index)) * 80ms)`)
|
|
106
|
+
- `--ef-seed` — stable random value per element, useful for organic variation
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Progress-Driven Animation → `--ef-progress`
|
|
111
|
+
|
|
112
|
+
`--ef-progress` updates every frame to the current playback position (0–1) of its timegroup. This drives any CSS property as a continuous function of time.
|
|
113
|
+
|
|
114
|
+
```html
|
|
115
|
+
<!-- Bar that fills with time -->
|
|
116
|
+
<ef-timegroup mode="fixed" duration="10s" class="w-full h-2 bg-slate-700">
|
|
117
|
+
<div class="h-full bg-blue-400" style="width: calc(var(--ef-progress) * 100%)"></div>
|
|
118
|
+
</ef-timegroup>
|
|
119
|
+
|
|
120
|
+
<!-- Color that shifts from cool to warm -->
|
|
121
|
+
<ef-timegroup mode="fixed" duration="8s" class="w-full h-full"
|
|
122
|
+
style="background: hsl(calc(220 - var(--ef-progress) * 150), 70%, 50%)">
|
|
123
|
+
</ef-timegroup>
|
|
124
|
+
|
|
125
|
+
<!-- Counter that counts up -->
|
|
126
|
+
<ef-timegroup mode="fixed" duration="5s" id="counter-scene">
|
|
127
|
+
<div id="count" class="text-white text-6xl font-bold">0</div>
|
|
128
|
+
</ef-timegroup>
|
|
129
|
+
<script>
|
|
130
|
+
const scene = document.getElementById('counter-scene');
|
|
131
|
+
const count = document.getElementById('count');
|
|
132
|
+
scene.addFrameTask((ownCurrentTimeMs, durationMs) => {
|
|
133
|
+
const progress = ownCurrentTimeMs / durationMs;
|
|
134
|
+
count.textContent = Math.floor(progress * 1000000).toLocaleString();
|
|
135
|
+
});
|
|
136
|
+
</script>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Other available time variables:**
|
|
140
|
+
|
|
141
|
+
- `--ef-duration` — element's total duration as a CSS time value (e.g., `"8s"`)
|
|
142
|
+
- `--ef-transition-duration` — overlap duration for scene transitions
|
|
143
|
+
- `--ef-transition-out-start` — when fade-out should start (use as `animation-delay` for exits)
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Per-Frame Procedural Animation → `addFrameTask`
|
|
148
|
+
|
|
149
|
+
For animations that can't be expressed with CSS — particle systems, generative graphics, data visualization, physics simulations — `addFrameTask` runs a callback every frame with the current time.
|
|
150
|
+
|
|
151
|
+
```html
|
|
152
|
+
<ef-timegroup mode="fixed" duration="6s" id="scene" class="w-full h-full bg-slate-900">
|
|
153
|
+
<canvas id="canvas" class="absolute inset-0 size-full"></canvas>
|
|
154
|
+
</ef-timegroup>
|
|
155
|
+
|
|
156
|
+
<script>
|
|
157
|
+
const scene = document.getElementById('scene');
|
|
158
|
+
const canvas = document.getElementById('canvas');
|
|
159
|
+
const ctx = canvas.getContext('2d');
|
|
160
|
+
|
|
161
|
+
scene.addFrameTask((ownCurrentTimeMs, durationMs) => {
|
|
162
|
+
canvas.width = canvas.offsetWidth;
|
|
163
|
+
canvas.height = canvas.offsetHeight;
|
|
164
|
+
const progress = ownCurrentTimeMs / durationMs;
|
|
165
|
+
|
|
166
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
167
|
+
|
|
168
|
+
// Example: lines connecting to a center point, growing with progress
|
|
169
|
+
const cx = canvas.width / 2;
|
|
170
|
+
const cy = canvas.height / 2;
|
|
171
|
+
const count = Math.floor(progress * 60);
|
|
172
|
+
|
|
173
|
+
for (let i = 0; i < count; i++) {
|
|
174
|
+
const angle = (i / 60) * Math.PI * 2;
|
|
175
|
+
const radius = 200 + Math.sin(i * 0.5 + ownCurrentTimeMs * 0.001) * 40;
|
|
176
|
+
ctx.beginPath();
|
|
177
|
+
ctx.moveTo(cx, cy);
|
|
178
|
+
ctx.lineTo(cx + Math.cos(angle) * radius, cy + Math.sin(angle) * radius);
|
|
179
|
+
ctx.strokeStyle = `rgba(99, 179, 237, ${0.2 + progress * 0.5})`;
|
|
180
|
+
ctx.lineWidth = 1;
|
|
181
|
+
ctx.stroke();
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
</script>
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Key rules for `addFrameTask`:**
|
|
188
|
+
|
|
189
|
+
- The callback receives `(ownCurrentTimeMs, durationMs)` — local time, not global
|
|
190
|
+
- Always resize the canvas inside the callback (`canvas.width = canvas.offsetWidth`) — this clears it
|
|
191
|
+
- The callback runs on every frame during rendering, so it must be a pure function of `ownCurrentTimeMs`
|
|
192
|
+
- No `Date.now()`, `Math.random()`, or any non-deterministic values — renders must be reproducible
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Overlapping Attention Choreography → `overlap` and CSS Delays
|
|
197
|
+
|
|
198
|
+
Sequence elements with partially overlapping animations to create natural rhythm. The `overlap` attribute on `ef-timegroup` creates shared time between adjacent scenes; staggered `animation-delay` sequences elements within a scene.
|
|
199
|
+
|
|
200
|
+
```html
|
|
201
|
+
<!-- Within-scene sequencing: logo → headline → subhead -->
|
|
202
|
+
<ef-timegroup mode="contain" duration="4s" class="absolute w-full h-full">
|
|
203
|
+
<!-- Logo arrives first -->
|
|
204
|
+
<ef-image src="logo.png" class="absolute top-8 left-8 w-32"
|
|
205
|
+
style="animation: 0.5s enter-down both 0s"></ef-image>
|
|
206
|
+
|
|
207
|
+
<!-- Headline starts before logo finishes (overlap 60%) -->
|
|
208
|
+
<ef-text class="absolute top-1/3 left-8 text-white text-5xl font-bold"
|
|
209
|
+
style="animation: 0.6s enter-up both 0.3s"></ef-text>
|
|
210
|
+
|
|
211
|
+
<!-- Subhead follows headline -->
|
|
212
|
+
<ef-text class="absolute top-1/2 left-8 text-white/70 text-2xl"
|
|
213
|
+
style="animation: 0.5s enter-up both 0.7s">Supporting text</ef-text>
|
|
214
|
+
</ef-timegroup>
|
|
215
|
+
|
|
216
|
+
@keyframes enter-down { from { transform: translateY(-16px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
|
|
217
|
+
@keyframes enter-up { from { transform: translateY(16px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Between-scene sequencing using `overlap`:**
|
|
221
|
+
|
|
222
|
+
```html
|
|
223
|
+
<!-- 1s overlap between scenes creates shared time for crossfade -->
|
|
224
|
+
<ef-timegroup mode="sequence" overlap="1s">
|
|
225
|
+
<ef-timegroup mode="contain" class="absolute w-full h-full"
|
|
226
|
+
style="animation: 1s fade-out var(--ef-transition-out-start) both">
|
|
227
|
+
<!-- Scene A content -->
|
|
228
|
+
</ef-timegroup>
|
|
229
|
+
<ef-timegroup mode="contain" class="absolute w-full h-full"
|
|
230
|
+
style="animation: 1s fade-in both">
|
|
231
|
+
<!-- Scene B content -->
|
|
232
|
+
</ef-timegroup>
|
|
233
|
+
</ef-timegroup>
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Exit Animations → `--ef-transition-out-start`
|
|
239
|
+
|
|
240
|
+
Exits should be shorter than entrances (30–40% shorter). Use `--ef-transition-out-start` to trigger exit animations at precisely the right moment, regardless of scene duration.
|
|
241
|
+
|
|
242
|
+
```html
|
|
243
|
+
<ef-timegroup mode="contain" duration="6s" class="absolute w-full h-full"
|
|
244
|
+
style="animation: 1s fade-out var(--ef-transition-out-start) both">
|
|
245
|
+
|
|
246
|
+
<!-- Elements exit before the scene ends (staggered out) -->
|
|
247
|
+
<ef-text class="absolute bottom-8 text-white text-4xl"
|
|
248
|
+
style="animation: 0.4s exit-down var(--ef-transition-out-start) both">Headline</ef-text>
|
|
249
|
+
<ef-text class="absolute bottom-4 text-white/70 text-xl"
|
|
250
|
+
style="animation: 0.4s exit-down calc(var(--ef-transition-out-start) - 0.1s) both">Subhead</ef-text>
|
|
251
|
+
</ef-timegroup>
|
|
252
|
+
|
|
253
|
+
@keyframes exit-down { from { transform: translateY(0); opacity: 1; } to { transform: translateY(16px); opacity: 0; } }
|
|
254
|
+
@keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
`--ef-transition-out-start` is set automatically when `overlap` is used on the parent sequence. For scenes without a sequence parent, it equals `--ef-duration - <overlap>`.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## React Implementation
|
|
262
|
+
|
|
263
|
+
In React, apply animations as inline `style` props:
|
|
264
|
+
|
|
265
|
+
```tsx
|
|
266
|
+
import { Timegroup, Text } from "@editframe/react";
|
|
267
|
+
|
|
268
|
+
// Word stagger
|
|
269
|
+
<Text
|
|
270
|
+
split="word"
|
|
271
|
+
className="text-white text-4xl font-bold"
|
|
272
|
+
style={{
|
|
273
|
+
animation: "0.5s word-in both",
|
|
274
|
+
animationDelay: "calc(var(--ef-word-index) * 80ms)"
|
|
275
|
+
}}
|
|
276
|
+
>
|
|
277
|
+
Your message here
|
|
278
|
+
</Text>
|
|
279
|
+
|
|
280
|
+
// Progress-driven via addFrameTask on ref
|
|
281
|
+
import { useRef, useEffect } from "react";
|
|
282
|
+
|
|
283
|
+
const ProgressBar = () => {
|
|
284
|
+
const ref = useRef<HTMLElement>(null);
|
|
285
|
+
useEffect(() => {
|
|
286
|
+
const el = ref.current;
|
|
287
|
+
if (!el) return;
|
|
288
|
+
const bar = el.querySelector('.bar') as HTMLElement;
|
|
289
|
+
el.addFrameTask((t, d) => {
|
|
290
|
+
bar.style.width = `${(t / d) * 100}%`;
|
|
291
|
+
});
|
|
292
|
+
}, []);
|
|
293
|
+
return (
|
|
294
|
+
<Timegroup ref={ref} mode="fixed" duration="5s" className="w-full h-2 bg-slate-700">
|
|
295
|
+
<div className="bar h-full bg-blue-400 transition-none" />
|
|
296
|
+
</Timegroup>
|
|
297
|
+
);
|
|
298
|
+
};
|
|
299
|
+
```
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Intent
|
|
3
|
+
description: Define motion intent by mapping message and emotional goal to specific motion characteristics before choosing timing or easing.
|
|
4
|
+
type: explanation
|
|
5
|
+
order: 1
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Intent → Strategy
|
|
9
|
+
|
|
10
|
+
## Core Concept
|
|
11
|
+
|
|
12
|
+
**Message + Emotion → Motion Characteristics**
|
|
13
|
+
|
|
14
|
+
Every animation starts with intent. Before choosing timing or easing, determine what the viewer should feel and remember.
|
|
15
|
+
|
|
16
|
+
## The Intent Framework
|
|
17
|
+
|
|
18
|
+
### 1. Extract the Core Message
|
|
19
|
+
|
|
20
|
+
What's the single most important thing?
|
|
21
|
+
|
|
22
|
+
**Good intent statements:**
|
|
23
|
+
- "User action succeeded, continue with confidence"
|
|
24
|
+
- "This content is important, pay attention"
|
|
25
|
+
- "Loading is happening, please wait briefly"
|
|
26
|
+
- "These items are related and sequential"
|
|
27
|
+
|
|
28
|
+
**Bad intent statements:**
|
|
29
|
+
- "Make it look cool" (no communication goal)
|
|
30
|
+
- "Add some animation" (no purpose)
|
|
31
|
+
- "Fade in the elements" (mechanism, not intent)
|
|
32
|
+
|
|
33
|
+
### 2. Determine Target Emotion
|
|
34
|
+
|
|
35
|
+
The emotion directly maps to motion characteristics:
|
|
36
|
+
|
|
37
|
+
| Emotion | Timing | Easing | Material | Exaggeration |
|
|
38
|
+
|---------|--------|--------|----------|--------------|
|
|
39
|
+
| Playful | Fast (250ms) | Bounce | Rubber | High (120%) |
|
|
40
|
+
| Confident | Medium (400ms) | Smooth | Metal/Glass | Low (102%) |
|
|
41
|
+
| Calm | Slow (800ms) | Gentle | Paper/Wood | Minimal (101%) |
|
|
42
|
+
| Urgent | Very fast (200ms) | Sharp | Stone/Metal | None |
|
|
43
|
+
| Premium | Slow (600ms) | Fluid | Leather/Glass | Subtle (103%) |
|
|
44
|
+
| Friendly | Medium (350ms) | Slight bounce | Plastic | Moderate (105%) |
|
|
45
|
+
|
|
46
|
+
### 3. Context Modifiers
|
|
47
|
+
|
|
48
|
+
**Viewing Context:**
|
|
49
|
+
- Social media (mobile): Fast (200-400ms), attention-grabbing
|
|
50
|
+
- Explainer video: Medium (500-800ms), clear and readable
|
|
51
|
+
- Cinematic: Slow (1000-1600ms), dramatic
|
|
52
|
+
- Ads: Fast to medium, hook within 3 seconds
|
|
53
|
+
|
|
54
|
+
**Content Type:**
|
|
55
|
+
- Tutorial: Slower, more explanatory
|
|
56
|
+
- Entertainment: Fast-paced, energetic
|
|
57
|
+
- Documentary: Medium, measured
|
|
58
|
+
- Promotional: Fast, exciting
|
|
59
|
+
|
|
60
|
+
**Viewing Frequency:**
|
|
61
|
+
- One-time narrative: Can be longer, more detailed
|
|
62
|
+
- Looping content: Must loop seamlessly, can't become annoying
|
|
63
|
+
- Repeated branding: Very brief, memorable
|
|
64
|
+
- Background ambient: Subtle, non-distracting
|
|
65
|
+
|
|
66
|
+
### 4. Communication vs Decoration Test
|
|
67
|
+
|
|
68
|
+
**Ask:** If I remove this animation, does the message weaken?
|
|
69
|
+
|
|
70
|
+
**Communication** (keep):
|
|
71
|
+
- Directs viewer attention to key information
|
|
72
|
+
- Shows relationships between concepts
|
|
73
|
+
- Emphasizes important moments
|
|
74
|
+
- Guides narrative flow
|
|
75
|
+
- Clarifies transitions between ideas
|
|
76
|
+
|
|
77
|
+
**Decoration** (remove):
|
|
78
|
+
- Makes things "look pretty" without purpose
|
|
79
|
+
- Distracts from core message
|
|
80
|
+
- Adds time without adding clarity
|
|
81
|
+
- Becomes tiresome on repeated viewing
|
|
82
|
+
|
|
83
|
+
## Mapping Intent to Physics Model
|
|
84
|
+
|
|
85
|
+
Once intent is clear, it determines material selection:
|
|
86
|
+
|
|
87
|
+
**Intent:** User succeeded, feel confident and rewarded
|
|
88
|
+
→ **Emotion:** Confident + slight celebration
|
|
89
|
+
→ **Material:** Glass with slight rubber (mostly rigid, tiny bounce)
|
|
90
|
+
→ **Physics:** 400ms, 5% overshoot, ease-out
|
|
91
|
+
|
|
92
|
+
**Intent:** Loading in progress, maintain attention without anxiety
|
|
93
|
+
→ **Emotion:** Calm, patient
|
|
94
|
+
→ **Material:** Liquid (continuous, flowing)
|
|
95
|
+
→ **Physics:** 1400ms loop, ease-in-out, smooth
|
|
96
|
+
|
|
97
|
+
**Intent:** Error occurred, immediate attention needed
|
|
98
|
+
→ **Emotion:** Urgent, alerting
|
|
99
|
+
→ **Material:** Metal (sharp, immediate)
|
|
100
|
+
→ **Physics:** 400ms, sharp shake, no bounce
|
|
101
|
+
|
|
102
|
+
## Output Format
|
|
103
|
+
|
|
104
|
+
Before implementing any animation, write:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
Intent: [What should viewer remember/feel/do?]
|
|
108
|
+
Emotion: [Target feeling]
|
|
109
|
+
Material: [Physical metaphor]
|
|
110
|
+
Exaggeration: [Subtle/Moderate/High]
|
|
111
|
+
Context: [Platform, frequency, user state]
|
|
112
|
+
|
|
113
|
+
Result: [Concrete motion characteristics]
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Example:**
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
Intent: Emphasize key statistic in explainer video
|
|
120
|
+
Emotion: Confident, clear
|
|
121
|
+
Material: Glass with 5% rubber bounce
|
|
122
|
+
Exaggeration: Subtle (103%)
|
|
123
|
+
Context: Explainer video, one-time viewing, general audience
|
|
124
|
+
|
|
125
|
+
Result:
|
|
126
|
+
- Duration: 600ms (18 frames at 30fps)
|
|
127
|
+
- Scale: 1 → 1.03 → 1
|
|
128
|
+
- Position: Slide in from right (60px)
|
|
129
|
+
- Easing: ease-out
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Common Intent Patterns for Video
|
|
133
|
+
|
|
134
|
+
### Narrative Flow Intents
|
|
135
|
+
|
|
136
|
+
**"Introducing new section"**
|
|
137
|
+
→ Clear transition (500-800ms), wipe or dissolve
|
|
138
|
+
→ Material: Paper or glass (clean, professional)
|
|
139
|
+
|
|
140
|
+
**"Key point emphasis"**
|
|
141
|
+
→ Scale + position (400-600ms), draws eye
|
|
142
|
+
→ Material: Stone (substantial) or metal (sharp)
|
|
143
|
+
|
|
144
|
+
**"Supporting information"**
|
|
145
|
+
→ Subtle fade-in (300-400ms), doesn't steal focus
|
|
146
|
+
→ Material: Paper (light, secondary)
|
|
147
|
+
|
|
148
|
+
### Brand/Title Intents
|
|
149
|
+
|
|
150
|
+
**"Logo reveal"**
|
|
151
|
+
→ Memorable entrance (800-1200ms), can be playful or serious
|
|
152
|
+
→ Material: Rubber (playful) or glass (professional)
|
|
153
|
+
|
|
154
|
+
**"Title card"**
|
|
155
|
+
→ Clear, readable (600-1000ms), establishes hierarchy
|
|
156
|
+
→ Material: Depends on brand personality
|
|
157
|
+
|
|
158
|
+
**"End card/CTA"**
|
|
159
|
+
→ Attention-grabbing (500-800ms), clear next action
|
|
160
|
+
→ Material: Metal (urgent) or glass (confident)
|
|
161
|
+
|
|
162
|
+
### Transition Intents
|
|
163
|
+
|
|
164
|
+
**"Scene change, different context"**
|
|
165
|
+
→ Clear break (400-600ms), wipe or cut
|
|
166
|
+
→ Material: Metal (sharp) or stone (definitive)
|
|
167
|
+
|
|
168
|
+
**"Scene change, same context"**
|
|
169
|
+
→ Smooth flow (600-800ms), dissolve or fade
|
|
170
|
+
→ Material: Liquid (flowing) or paper (gentle)
|
|
171
|
+
|
|
172
|
+
**"Time passage"**
|
|
173
|
+
→ Dissolve or clock-like (800-1200ms)
|
|
174
|
+
→ Material: Liquid (smooth, continuous)
|
|
175
|
+
|
|
176
|
+
## Anti-Patterns
|
|
177
|
+
|
|
178
|
+
### Intent Drift
|
|
179
|
+
|
|
180
|
+
Starting with clear intent but adding motion that contradicts it:
|
|
181
|
+
|
|
182
|
+
**Intent:** "Quick confirmation without disrupting workflow"
|
|
183
|
+
**Bad implementation:** 2-second celebration animation with particles
|
|
184
|
+
|
|
185
|
+
The implementation violated the intent (quick, non-disruptive).
|
|
186
|
+
|
|
187
|
+
### Multiple Simultaneous Intents
|
|
188
|
+
|
|
189
|
+
Trying to communicate several things at once:
|
|
190
|
+
|
|
191
|
+
**Bad:** Sidebar slides in WHILE content fades in WHILE header animates
|
|
192
|
+
**Result:** Viewer doesn't know where to look, misses all three messages
|
|
193
|
+
|
|
194
|
+
**Fix:** Sequence them. One intent at a time.
|
|
195
|
+
|
|
196
|
+
### Implied vs Stated Intent
|
|
197
|
+
|
|
198
|
+
**Implied:** "Make the button feel more premium"
|
|
199
|
+
**Stated:** "User should feel confident their payment is secure"
|
|
200
|
+
|
|
201
|
+
Always state intent explicitly. Implied intents drift toward decoration.
|