Add patterngen-oss: pattern animations, blender pipeline, deterministic generation

This commit is contained in:
Neo committed 2026-06-20 17:30:26 +05:00
1 parent 2b42a76d6d
commit c7f0be809b
4 files changed
+726 -3

No files matched your search

+8 -3
View File
@@ -1,7 +1,7 @@
--- ---
title: Premium Design Wiki — Overview title: Premium Design Wiki — Overview
description: Central index for all 79 design patterns, LLM prompts, and assets. description: Central index for all 82 design patterns, LLM prompts, and assets.
version: 2.1.0 version: 2.2.0
date: 2026-06-20 date: 2026-06-20
--- ---
@@ -22,7 +22,9 @@ Encode premium web design taste into reusable patterns so LLMs can generate prof
| 🎨 Systems | 6 patterns | ✅ Complete | | 🎨 Systems | 6 patterns | ✅ Complete |
| 🌐 Mobile | 21 token systems | ✅ Complete | | 🌐 Mobile | 21 token systems | ✅ Complete |
| 🎯 Landing | 25 patterns | ✅ Complete | | 🎯 Landing | 25 patterns | ✅ Complete |
| **Total** | **79 patterns** | **✅ Complete** | | 🎬 Blender Pipeline | 1 pipeline spec | ✅ Complete |
| ⚙️ Deterministic Gen | 1 methodology | ✅ Complete |
| **Total** | **82 patterns + assets** | **✅ Complete** |
## 📁 Structure ## 📁 Structure
@@ -48,6 +50,7 @@ wow-design-wiki/
│ ├── magnetic-button.md │ ├── magnetic-button.md
│ ├── page-transitions.md │ ├── page-transitions.md
│ ├── parallax-scroll.md │ ├── parallax-scroll.md
│ ├── pattern-animations.md
│ ├── procedural-patterns.md │ ├── procedural-patterns.md
│ └── staggered-reveal.md │ └── staggered-reveal.md
├── typography/ ├── typography/
@@ -56,6 +59,7 @@ wow-design-wiki/
│ └── kinetic-text.md │ └── kinetic-text.md
├── media/ ├── media/
│ ├── animated-illustration.md │ ├── animated-illustration.md
│ ├── blender-pipeline.md
│ ├── image-parallax.md │ ├── image-parallax.md
│ ├── svg-animation.md │ ├── svg-animation.md
│ └── video-mask.md │ └── video-mask.md
@@ -68,6 +72,7 @@ wow-design-wiki/
│ ├── component-patterns.md │ ├── component-patterns.md
│ ├── css-architecture.md │ ├── css-architecture.md
│ ├── design-tokens.md │ ├── design-tokens.md
│ ├── deterministic-generation.md
│ ├── glassmorphism.md │ ├── glassmorphism.md
│ ├── noise-texture.md │ ├── noise-texture.md
│ └── responsive-patterns.md │ └── responsive-patterns.md
+222
View File
@@ -0,0 +1,222 @@
# Blender Pipeline — Figma → PatternGen → 3D Compositing
> Полный конвейер от Figma-дизайна до 3D-compositing в Blender.
> Основано на [patterngen-oss](https://github.com/halfof8/patterngen-oss) workflow.
## Обзор
```
Figma (artboard 1920×1080)
↓ Plugin "PatternGen Scene Export"
Scene JSON (titles as 2× PNG data URLs + colors + seed)
↓ Load в PatternGen web app
Procedural pattern generation (Canvas 2D)
↓ EXPORT (JSZip + FileSaver)
ZIP: scene_titles/*.png, scene_patterns/*.png, scene_dots/*.png
↓ Blender addon "PatternGen Importer"
3 emissive planes с alpha-blending → Cycles/Eevee render
```
---
## Этап 1: Figma → Scene JSON
### Подготовка артборда
- Frame размер: **1920×1080 px** (Full HD)
- Grid: **20 px** (Layout Grid → Grid → 20 px)
- Каждый title — top-level child frame, размеры кратны 20
- Название фрейма = `sceneName` (префикс для экспорта)
- Цвета: любые (плагин сканирует fills/strokes)
### Экспорт
1. Выбрать один или несколько фреймов 1920×1080
2. **Plugins → Development → PatternGen Scene Export**
3. **Export Selected Frames**
4. Результат: `<frameName>_patterngen.json`
### Структура JSON
```json
{
"sceneName": "My Title",
"seed": 123456789, // 31-bit integer, determinism
"colors": ["#FF0000", "#00FF00", "#0000FF"], // detected colors
"titles": [
{
"id": "title_1",
"x": 100, // snapped to 20px grid
"y": 200,
"w": 400,
"h": 100,
"img": "data:image/png;base64,..." // 2× retina PNG
}
],
"defaults": {
"durationMs": 6000,
"density": 10,
"proximity": 2,
"stagger": 3,
"theme": "dark"
}
}
```
### Что экспортируется
- **Titles**: 2× PNG (retina), data URL, позиции snapped к сетке
- **Color set**: уникальные цвета fills/strokes (кроме #000 и #FFF)
- **Seed**: 31-bit integer — детерминированная генерация паттернов
- **Scene defaults**: продолжительность, плотность, proximity, stagger, тема
---
## Этап 2: PatternGen Web App
### Загрузка
1. Открыть PatternGen (localhost:5173)
2. Кнопка **LOAD** → выбрать `*_patterngen.json`
3. Паттерны генерируются **детерминированно по seed**
4. Сцена сразу готова к **PLAY**
### Ручное редактирование
- **Drag & Drop** PNG/JPG изображений на canvas (snap to 20 px grid)
- **Drag** для перемещения, drag off canvas для удаления
- **+ ADD COLOR** — до 3 кастомных цветов (color picker)
- Клик по swatch — toggle on/off
### Параметры
| Параметр | Диапазон | Описание |
|-------------|---------|----------|
| **Density** | 1–20 | Количество паттерн-элементов |
| **Proximity** | 1–20 | Минимальное расстояние от titles |
| **Stagger** | 0–5 | Разброс animation delay |
| **Grid** | toggle | 20 px reference grid |
| **Theme** | dark/light | UI theme |
---
## Этап 3: Экспорт PNG-секвенций
### Формат ZIP
```
scene_pattern_gen.zip
├── titles/
│ scene_titles_00000.png
│ scene_titles_000001.png
│ ...
├── patterns/
│ scene_patterns_00000.png
│ ...
└── dots/
scene_dots_00000.png
...
```
### Параметры экспорта
- **Scale**: 4× (EXPORT_SCALE = 4 → 7680×4320px)
- **FPS**: 24
- **Фон**: прозрачный (RGBA)
- **Слои**: 3 отдельных (titles, patterns, dots)
### Фазы рендера
```
titles: durationMs (1×) — plays once
patterns: durationMs (1×) — plays once
dots: 4000ms loop — infinite loop
```
### Easing при экспорте
Выбирается один из 7 типов:
`linear`, `easeIn`, `easeOut`, `easeInOut`, `easeInCubic`, `easeOutCubic`, `easeInOutCubic`
---
## Этап 4: Blender Import
### Установка
1. Blender → **Edit → Preferences → Add-ons → Install…**
2. Выбрать `patterngen_importer.py`
3. Поставить галочку для активации
4. Открыть N-panel → вкладка **PatternGen**
### Импорт сцены
1. Установить **Scene Folder** на распакованную папку
2. Кнопка **Import Scene Folders**
3. Три planes создаются в origin
### Конфигурация слоёв
| Layer | Cyclic | Location (m) | Rotation | Scale |
|-------|--------|-------------|----------|-------|
| titles | off | (0, 0, 0) | 90° на X | 6×6×6 |
| patterns | off | (0, 0.1, 0) | 90° на X | 6×6×6 |
| dots | **on** | (0, 0.2, 0) | 90° на X | 6×6×6 |
### Node Tree материалов
```
Image Texture (SEQUENCE, auto-refresh ON)
Color ─┬─► Principled BSDF › Base Color
└─► Principled BSDF › Emission Color (strength = 1)
Alpha ───► Principled BSDF › Alpha
```
### Image Sequence настройки
- **Start Frame**: 0
- **Frames**: количество PNG в папке
- **Offset**: 0
- **Auto Refresh**: ON
- **Cyclic**: ON для `dots`, OFF для `titles`/`patterns`
### Sync Start Frame
1. Выбрать plane(s) (Shift+click или A для всех)
2. В секции **Sync Start Frame** ввести новое значение
3. **Apply to Selected** — все image-sequence текстуры обновлены
### Замечания
- **Blend Method**: `BLEND` (alpha renders clean в Eevee/Cycles)
- При артефактах сортировки переключить на `HASHED`
- Повторный импорт создаёт дубликаты (`.001`, `.002`) — удалить вручную
- Отступ 0.1m между слоями — только для предотвращения z-fighting
- Plane scale настроен по aspect ratio изображения (16:9)
---
## Полный конвейер в цифрах
| Параметр | Значение |
|----------|---------|
| Canvas | 1920×1080 |
| Export Scale | 4× (7680×4320) |
| FPS | 24 |
| Grid | 20 px |
| Duration | 6000ms (default) |
| Dots Loop | 4000ms |
| Cycle | 4× duration = 24s |
| Patterns | 7 animation types |
| Colors | 2 fixed + 3 custom max |
| Export Layers | 3 (titles, patterns, dots) |
---
## Референсы кода
- `figma-plugin/README.md` — Figma plugin setup, export format
- `blender-addon/README.md` — Blender addon installation, node tree
- `src/export/exporter.ts` — PNG sequence export, JSZip, FileSaver
- `src/engine/timeline.ts` — Phase 1/2/3 timing, dots loop
- `src/types.ts` — CANVAS_W/H, EXPORT_SCALE, FPS, GRID_SIZE
+213
View File
@@ -0,0 +1,213 @@
# Pattern Animations — 7 типов процедурных анимаций
> Основано на реализациях из [patterngen-oss](https://github.com/halfof8/patterngen-oss).
> 7 анимационных типов для SVG-паттернов, рендерящихся через Canvas 2D с таймлайном.
## Обзор
Каждый паттерн — это SVG-файл 40×40 px, который анимируется одним из 7 типов.
Рендер происходит на Canvas 2D с 4× масштабированием (EXPORT_SCALE = 4).
Базовый кадр 1920×1080, сетка 20 px, FPS = 24.
## Таймлайн
```
Фаза 1 (0 — durationMs): Title reveal (half-reveal с easing)
Фаза 2 (durationMs — 2×): Patterns reveal + squares reveal (staggered)
Фаза 3 (2× — 4× durationMs): Patterns hold + dots pulsation (loop 4s)
Цикл: repeat cycle = 4 × durationMs
```
---
## 1. Dots — fade-in с stagger
Каждый SVG-элемент проявляется индивидуально с рандомной задержкой.
**Механика:**
```
dotP = max(0, min(1, (progress - stagger * 0.6) / 0.4))
globalAlpha = dotP
```
**Использование:**
- Мягкое проявление множества мелких элементов
- Звёздные/точечные паттерны, частицы, текстуры
- Элементы с `stagger` из SVG (случайный при парсинге)
**Параметры:**
- `stagger` определяет задержку: 0 = мгновенно, 5 = максимальный разброс
- Визуально: элементы появляются поочерёдно, создавая «волну»
---
## 2. Capsule — рост из центра по длинной оси
Каждый элемент масштабируется от центра вдоль своей более длинной оси.
**Механика:**
```
elP = max(0, min(1, (progress - stagger * 0.3) / 0.7))
if (w >= h) {
// горизонтальный: ширина растёт, высота стоит
animW = w * elP
animX = cx - animW / 2
} else {
// вертикальный: высота растёт, ширина стоит
animH = h * elP
animY = cy - animH / 2
}
```
**Использование:**
- Анимация линий, полос, разделителей
- Эффект «заполнения» вдоль направления
- Элементы с rotation поддерживаются (через rotate transform)
---
## 3. Circle — pie-fill clockwise reveal
Полное SVG-изображение проявляется секторально, как таймер.
**Механика:**
```
cx = size / 2
cy = size / 2
startAngle = -PI / 2
endAngle = startAngle + PI * 2 * progress
ctx.arc(cx, cy, size, startAngle, endAngle)
ctx.drawImage(img, 0, 0, size, size)
```
**Использование:**
- Круговые паттерны, диаграммы, радары
- Прогресс-индикаторы, loading-анимации
- Полное изображение, не по-элементно
---
## 4. Arrow — slide up снизу
Полное изображение физически сдвигается вверх из-за нижнего края.
**Механика:**
```
offset = size * (1 - progress)
ctx.drawImage(img, 0, offset, size, size)
```
**Использование:**
- Элементы «влетают» снизу
- Эффект подъёма, выдвижения
- Подходит для контрастных паттернов на тёмном фоне
---
## 5. Square — scale down 1.6× → 1×
Изображение масштабируется от 1.6× до 1× (на 60% больше до нормального).
**Механика:**
```
s = 1 + (1 - progress) * 0.6
cx = size / 2
cy = size / 2
ctx.translate(cx, cy)
ctx.scale(s, s)
ctx.translate(-cx, -cy)
ctx.drawImage(img, 0, 0, size, size)
```
**Использование:**
- Резкий акцент, «взрывное» проявление
- Привлечение внимания к паттерну
- Квадратные/крестообразные элементы
---
## 6. Stripes — slide-in слева направо
Каждая полоса (элемент) сдвигается сверху вниз, сортировка по X.
**Механика:**
```
sorted = shapes.sort((a, b) => a.x - b.x)
stripeStart = (i / n) * 0.5
stripeP = max(0, min(1, (progress - stripeStart) / 0.5))
slideOffset = (1 - stripeP) * -size
ctx.translate(0, slideOffset)
```
**Использование:**
- Полосатые паттерны, штрих-код текстуры
- Горизонтальные линии, решётки
- Эффект «сканирования» слева направо
---
## 7. Cross — scale down 1.6× → 1×
Тот же алгоритм, что и `square`, но для крестообразных элементов.
Разница исключительно в семантике и визуальном контексте.
**Механика:**
```
// identical to square
s = 1 + (1 - progress) * 0.6
ctx.scale(s, s)
```
---
## Easing функции
| Название | Формула |
|---------------|---------|
| `linear` | `t` |
| `easeIn` | `t²` |
| `easeOut` | `t(2-t)` |
| `easeInOut` | `2t²` при t<0.5, `-1+(4-2t)t` при t≥0.5 |
| `easeInCubic` | `t³` |
| `easeOutCubic`| `1-(1-t)³` |
| `easeInOutCubic` | `4t³` при t<0.5, `1-(-2t+2)³/2` при t≥0.5 |
---
## SVG Spec
Каждый SVG-паттерн должен соответствовать формату:
```xml
<svg width="40" height="40" viewBox="0 0 40 40" fill="none">
<rect width="40" height="40" fill="white"/>
<!-- foreground shapes -->
<circle cx="20" cy="20" r="14" fill="black"/>
<rect x="10" y="10" width="20" height="20" rx="4" fill="black" stroke="black"/>
</svg>
```
**Правила:**
1. Размер: 40×40 px (viewBox 0 0 40 40)
2. Фон: `<rect width="40" height="40" fill="white"/>` (переокрашивается в runtime)
3.Foreground: `fill="black"` и/или `stroke="black"` (переокрашивается)
4. Тег `<defs>` игнорируется при парсинге
5. Вложенные `<g>` обрабатываются рекурсивно
6. Анимация определяется типом анимации, не структурой SVG
**Поддерживаемые теги:** `<rect>`, `<circle>`, `<path>`
**Transform:** `rotate(angle, ox, oy)` — угол поворота и точка вращения.
---
## Референсы кода
- `src/engine/animations.ts` — 7 switch-касов для каждого animType
- `src/engine/timeline.ts` — фаза titles → patterns → dots (цикл 4× duration)
- `src/engine/easing.ts` — 7 easing функций
- `src/core/patterns.ts` — парсинг SVG, colorizeSvg, svgToImage
- `src/export/exporter.ts` — экспорт PNG-секвенций (titles, patterns, dots)
- `src/types.ts` — PatternAnimType, SvgShapeInfo, PatternDef
+283
View File
@@ -0,0 +1,283 @@
# Deterministic Generation — Seed-Based Layout Methodology
> Детерминированная генерация паттернов с использованием seeded PRNG.
> Основано на [patterngen-oss](https://github.com/halfof8/patterngen-oss).
## Обзор
Каждая генерация паттернов **детерминирована** — одинаковый seed всегда даёт
идентичный layout. Это позволяет:
- Повторно воспроизводить удачные комбинации
- Синхронизировать дизайн между Figma и PatternGen
- Кэшировать результаты генерации
- Делиться сценами через JSON с seed
---
## Seeded PRNG
### Алгоритм
```typescript
class SeededRNG {
private seed: number;
constructor(seed: number) {
this.seed = seed & 0x7FFFFFFF; // 31-bit positive
}
next(): number {
// LCG: Linear Congruential Generator
this.seed = (this.seed * 1103515245 + 12345) & 0x7FFFFFFF;
return this.seed / 0x7FFFFFFF; // range [0, 1)
}
nextInt(min: number, max: number): number {
return Math.floor(this.next() * (max - min + 1)) + min;
}
pick<T>(array: T[]): T {
return array[this.nextInt(0, array.length - 1)];
}
}
```
### Seed из Figma
```json
{
"seed": 123456789
}
```
31-bit integer генерируется плагином Figma. Значение зашито в JSON
и передается в PatternGen.
---
## Placement Engine
### Input parameters
| Параметр | Тип | Диапазон | Описание |
|----------|-----|----------|----------|
| `seed` | int | 0–2³¹-1 | Seed для PRNG |
| `density` | int | 1–20 | Количество элементов |
| `proximity` | int | 1–20 | Мин. расстояние до title (20 px grid units) |
### Placement algorithm
```
1. Создать RNG из seed
2. Для каждого элемента:
a. Сгенерировать случайную позицию (x, y)
b. Проверить proximity к существующим элементам и title
c. Если too close → пересадить с тем же RNG state
d. Иначе → записать позицию
3. Для каждого элемента:
a. Выбрать случайный pattern из доступных
b. Выбрать случайную clipSide (top/bottom/left/right)
c. Выбрать случайную анимацию
d. Сгенерировать stagger delay
```
### Stagger calculation
```typescript
const staggerWindow = Math.max(0, Math.min(0.85, (stagger / 5) * 0.8));
const staggeredStart = element.animDelay * staggerWindow * durationMs;
const elemDur = durationMs * (1 - staggerWindow);
const localMs = cycleMs - staggeredStart;
const p = Math.max(0, Math.min(1, localMs / elemDur));
```
---
## Animation Timeline
### Фаза 1: Title Reveal (0 — durationMs)
Title проявляется из центра по горизонтали (если wider) или вертикали (if taller).
```typescript
const titleT = min(1, max(0, elapsedMs / durationMs));
const titleEased = applyEasing(titleT, easing);
if (title.w >= title.h) {
// wide title: half-reveal horizontally
halfReveal = (title.w / 2) * titleEased;
revealBox = {
x: cx - halfReveal,
y: title.y,
w: halfReveal * 2,
h: title.h
};
} else {
// tall title: half-reveal vertically
halfReveal = (title.h / 2) * titleEased;
revealBox = {
x: title.x,
y: cy - halfReveal,
w: title.w,
h: halfReveal * 2
};
}
```
### Фаза 2: Pattern Reveal (durationMs — 2× durationMs)
Паттерны проявляются с stagger-задержкой.
### Фаза 3: Dots Loop (2× durationMs — 4× durationMs)
Точки пульсируют синусоидой 4000ms цикл.
```typescript
const fadeIn = min(1, loopMs / 800);
const wave = 0.5 + 0.5 * sin(2 * PI * dot.blinkSpeed * (loopMs / 1000) + dot.blinkPhase * 2 * PI);
const pulse = 0.15 + 0.85 * wave;
opacity = pulse * fadeIn;
```
---
## Color System
### Fixed Colors
```typescript
const FIXED_COLORS = ['#000000', '#FFFFFF'];
```
Черный и белый всегда доступны.
### Custom Colors
До 3 кастомных цветов добавляются через color picker.
Color pairs для паттернов генерируются алгоритмически:
```typescript
// Для каждого pair custom_color:
bg = customColor;
fg = generateComplementary(customColor);
```
### SVG Colorization
```typescript
function colorizeSvg(svgText: string, colors: ColorPair): string {
return svgText
.replace(/fill="white"/g, `fill="${colors.bg}"`)
.replace(/fill="black"/g, `fill="${colors.fg}"`)
.replace(/stroke="black"/g, `stroke="${colors.fg}"`);
}
```
SVG-паттерны хранят только `white` (фон) и `black` (foreground).
Окрашивание происходит в runtime.
---
## Image Caching
```typescript
const imageCache = new Map<string, HTMLImageElement>();
export function svgToImage(svgText: string): Promise<HTMLImageElement> {
if (imageCache.has(svgText)) return Promise.resolve(imageCache.get(svgText)!);
return new Promise((resolve, reject) => {
const img = new Image();
const blob = new Blob([svgText], { type: 'image/svg+xml;charset=utf-8' });
const url = URL.createObjectURL(blob);
img.onload = () => {
URL.revokeObjectURL(url);
imageCache.set(svgText, img);
resolve(img);
};
img.onerror = () => {
URL.revokeObjectURL(url);
reject(new Error('Failed to load SVG image'));
};
img.src = url;
});
}
export function clearImageCache() {
imageCache.clear();
}
```
---
## Export Pipeline
### Layer structure
```
titles: durationMs (1×) — plays once
patterns: durationMs (1×) — plays once
dots: 4000ms loop — infinite loop
```
### Export scale
- Canvas: 1920×1080
- Export Scale: 4× → 7680×4320
- FPS: 24
- Format: PNG (RGBA, transparent background)
### Frame calculation
```typescript
const totalFrames = Math.ceil((layerDuration / 1000) * FPS);
const frameRatio = totalFrames > 1 ? frame / (totalFrames - 1) : 1;
```
### Naming convention
```
<sceneName>_<layer>_<frame>.png
Пример:
MyTitle_titles_00000.png
MyTitle_titles_00001.png
MyTitle_patterns_00000.png
MyTitle_dots_00000.png
```
---
## Использование determinism в дизайне
### Scenario 1: Figma → PatternGen sync
1. Экспортировать сцену из Figma (содержит seed)
2. Загрузить в PatternGen
3. Паттерны генерируются точно так же каждый раз
4. Можно итерировать параметры и снова генерировать тот же layout
### Scenario 2: A/B testing
1. Создать базовую сцену с seed
2. Экспортировать 10 раз с разными параметрами density/stagger
3. Каждый раз layout идентичен, но timing разный
4. Сравнить конверсию/визуальное впечатление
### Scenario 3: Team collaboration
1. Дизайнер делится scene JSON
2. Коллега загружает и видит ту же генерацию
3. Может менять цвета, паттерны, параметры
4. Seed остаётся — layout predictable
---
## Референсы кода
- `src/core/rng.ts` — SeededRNG класс, LCG algorithm
- `src/core/placement.ts` — Placement engine, proximity check
- `src/engine/timeline.ts` — Phase 1/2/3, dots loop
- `src/export/exporter.ts` — PNG export, frame calculation
- `src/export/renderer.ts` — Canvas rendering per frame
- `src/types.ts` — AnimationState, PatternAnimType