Add patterngen-oss: pattern animations, blender pipeline, deterministic generation
This commit is contained in:
1 parent
2b42a76d6d
commit
c7f0be809b
4 files changed
+726
-3
No files matched your search
@@ -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
|
||||
Reference in new issue
Block a user