Skip to content

Commit b48767d

Browse files
authored
docs: add 1600-style brutalist motion template (#101)
* fix(fonts): resolve declared custom and Google fonts in text rendering Custom/Google fonts declared in a scenario's `fonts` were downloaded and handed to Skia via `FontMgr::new_from_data`, but that call returns a detached Typeface and never exposes it to `match_family_style` — Skia's default FontMgr only name-resolves installed system fonts. So every `font-family` pointing at a declared font silently rendered in the Helvetica/Arial fallback (e.g. Anton came out as a generic sans-serif). Keep the raw bytes in a global family->bytes registry when loading, and have `typeface_with_fallback` resolve custom families from it first — building and caching the Typeface per render thread (the FontMgr is thread-local, so system-thread registration alone never reached the rayon render workers). One weight per custom family via this path; multi-weight custom families are follow-up. Tests: registry stores first-wins + serves bytes; a registered family resolves to its own typeface over the system fallback (uses the cached Anton TTF when present, skips on a cold cache). * docs: add 1600-style brutalist motion template A 21s, 6-scene reference scenario (examples/1600-style.json) in the style of motion studios like 1600.agency: full-bleed saturated colour blocks that hard-cut between scenes, oversized Anton grotesque type, kinetic entrances (slide/scale with stagger), animated counters, and directional wipe transitions. Plus a skill rule documenting the visual language so the look can be reproduced on any content. Depends on the custom-font fix (declared Anton must actually render). * docs: add spatial depth to 1600-style template Address the '2D slideshow' feel: every scene now plays on space instead of being a flat panel. - continuous camera per scene (keyframed zoom + focal origin drift, and a subtle roll on two scenes) — no more static frames - three parallax planes via style.depth on scene direct children: a deep tone-on-tone ghost word (~0.4), the content (1.0), floating foreground accents (~1.75) — planes separate as the camera moves - 3D rotational entrances (flip_in_x/y, tilt_in with perspective and a hinge transform-origin) instead of flat slides; they resolve face-on so the type stays legible - camera-roll bleed avoided by keeping a covering zoom during rotation (documented in the style rule) Rule updated with the depth/camera layer.
1 parent b4603f9 commit b48767d

2 files changed

Lines changed: 268 additions & 0 deletions

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Style "1600" — motion brutalist à blocs de couleur
2+
3+
Recette pour produire des vidéos dans l'esprit des studios de motion design type [1600.agency](https://www.1600.agency/) : typographie massive, blocs de couleur saturés plein cadre, kinetic typography, transitions franches. Exemple de référence : `examples/1600-style.json`.
4+
5+
## Langage visuel
6+
7+
- **Typographie** : une seule grotesque condensée ultra-bold en `UPPERCASE`, partout. Anton (Google Font) est le choix canonique. Déclarer au niveau racine :
8+
```json
9+
"fonts": [{ "family": "Anton", "source": "google", "weights": [400] }]
10+
```
11+
puis `"font-family": "Anton"` sur chaque texte. `line-height` serré (0.92–1.02) pour empiler les lignes, `letter-spacing` 1–2 sur les gros titres, 4–8 sur les petits kickers.
12+
- **Tailles (16:9, 1920×1080)** : hero 240–300px, titres 120–200px, chiffres 190px, kicker/label 32–56px. On cherche le texte qui remplit la largeur.
13+
- **Palette — blocs saturés alternés** : chaque scène est un aplat plein cadre qui bascule brutalement. Un seul aplat par scène, texte en noir `#0A0A0A` ou crème `#F5F0E8` selon le fond.
14+
- Jaune `#FFE500`, cobalt `#1A1AE5`, corail `#FF4A32`, vert acide `#00E676`, noir `#0A0A0A`.
15+
- Accent sur un mot : réutiliser une des couleurs de bloc (ex. jaune sur fond noir).
16+
- **Fond de scène** : un `shape` `rounded_rect` (border-radius 0) plein cadre `1920×1080` en `position: absolute` posé en **premier** enfant ; le contenu passe en flow centré au-dessus.
17+
18+
## Animation
19+
20+
- **Kinetic entrances** : `slide_in_up` (lignes empilées, stagger 0.12s), `slide_in_left` (listes de services), `scale_in` avec `overshoot` (mots accent, CTA). Jamais de fondu mou.
21+
- **Transitions entre scènes** : franches et directionnelles — `wipe_up` / `wipe_left` / `wipe_right` / `wipe_down` / `slide`, durée 0.35s. Alterner les directions pour le rythme.
22+
- **Chiffres** : `counter` (`from`/`to`, `prefix`), il monte sur la durée de la scène. Réserver sa hauteur (`"height"` ≈ font-size + 10) et un `gap` ≥ 24 avec son label, sinon le label remonte sur le chiffre (le counter hors `card` n'a pas de correction de baseline).
23+
24+
## Profondeur & caméra — jouer sur l'espace
25+
26+
Sans ça, le style est un diaporama 2D. Trois leviers, cumulés sur chaque scène :
27+
28+
1. **Caméra en mouvement continu** (`scene.camera.keyframes`, propriétés `zoom` / `origin.x` / `origin.y` / `rotation`) : un push-in ou pull-out lent (zoom 1.0↔1.14) + une dérive du point focal (`origin`) donne une vie permanente. Alterner push-in / pull-out d'une scène à l'autre.
29+
2. **Plans de profondeur** (`style.depth` sur les enfants **directs** de la scène, qui deviennent les plans de parallaxe) : structurer chaque scène en 3 plans absolus plein cadre —
30+
- **fond profond** `depth ~0.4` : un mot/chiffre géant ton-sur-ton (`overflow: hidden` sur le plan pour le clipper au cadre) ;
31+
- **contenu** `depth 1.0` : la typo principale ;
32+
- **avant-plan** `depth ~1.75` : petites formes d'accent avec `float_3d` en boucle.
33+
Au mouvement caméra, les plans se séparent → vraie profondeur.
34+
3. **Entrées en rotation 3D** sur la ligne clé : `flip_in_x` / `flip_in_y` / `tilt_in` (+ `perspective` 900–1400 sur l'élément, `transform-origin` pour pivoter sur une charnière), qui se résolvent face caméra → lisible une fois posé.
35+
36+
**Piège du bleed** : une `rotation` caméra (ou un zoom < 1.0) révèle le `video.background` aux coins. Garder un zoom couvrant pendant toute la rotation (`zoom ≥ ~1.06` pour ±2°), ou fixer `video.background` à la couleur de la scène. Un `origin` qui dérive à zoom 1.0 ne bleede pas (l'origin n'a d'effet qu'avec du zoom).
37+
38+
## Structure d'une scène type
39+
40+
```json
41+
{
42+
"duration": 3.4,
43+
"transition": { "type": "wipe_up", "duration": 0.35 },
44+
"layout": { "direction": "column", "align_items": "center", "justify_content": "center", "gap": 6 },
45+
"children": [
46+
{ "type": "shape", "shape": "rounded_rect", "fill": "#0A0A0A", "position": "absolute", "x": 0, "y": 0, "style": { "width": 1920, "height": 1080, "border-radius": 0 } },
47+
{ "type": "text", "content": "STUDIO DE", "style": { "font-family": "Anton", "font-size": 150, "color": "#F5F0E8", "line-height": 0.95, "animation": [{ "name": "slide_in_up", "duration": 0.55 }] } },
48+
{ "type": "text", "content": "MOTION DESIGN", "style": { "font-family": "Anton", "font-size": 200, "color": "#FFE500", "line-height": 0.95, "animation": [{ "name": "scale_in", "delay": 0.18, "duration": 0.6, "overshoot": 0.12 }] } }
49+
]
50+
}
51+
```
52+
53+
## Pour dupliquer sur un autre contenu
54+
55+
Garder le squelette (aplat + typo Anton + entrées kinetic + transitions franches), remplacer les textes/chiffres/palette. Rythme : 3–4s par scène, une idée par scène. Réutiliser une couleur d'accent cohérente d'un bout à l'autre.

0 commit comments

Comments
 (0)