Files
wow-design-wiki/motion/procedural-patterns.md
neo 76c4c5b4fe design-systems: add 74 brand DESIGN.md files (VoltAgent/awesome-design-md)
- 74 brands: airbnb, stripe, apple, figma, linear, vercel, etc.
- 147 files: DESIGN.md + README.md per brand (~2.1 MB)
- Each DESIGN.md contains structured brand analysis (colors, typography, components)
- Updated 00-overview.md with new design-systems directory
2026-06-21 20:40:35 +05:00

9.2 KiB
Raw Permalink Blame History

name, title, description, tags, source
name title description tags source
motion/procedural-patterns Procedural Pattern Generator Canvas-based procedural generation of animated patterns around title elements. Uses occupancy grid, BFS proximity map, and seeded RNG for deterministic layout.
motion
procedural
pattern
canvas
generation
animation
title-card
github.com/halfof8/patterngen-oss

Procedural Pattern Generator

Что это

Инструментарий для автоматического создания анимированных заставок с процедурно размещёнными паттернами вокруг заголовков. Состоит из трёх компонентов:

  1. Web App (React + Canvas 2D) — основной генератор
  2. Figma Plugin — импорт дизайна из Figma
  3. Blender Add-on — импорт PNG-последовательностей как emissive planes

Пайплайн: Figma → Web App (генерация) → PNG-последовательности → Blender (композиция).

Алгоритм размещения

1. Occupancy Grid

Сетка 20px на 1920×1080 (96×54 ячеек). Title-элементы занимают ячейки, помечая их как занятые.

class GridOccupancy {
  private cells: boolean[][]; // GRID_ROWS × GRID_COLS
  
  markRect(x, y, w, h) { /* occupy cells */ }
  isBlockFree(col, row, spanCols, spanRows) { /* collision check */ }
  findFreeBlocks(spanCols, spanRows, align) { /* find valid positions */ }
}

2. BFS Proximity Map

BFS от всех title-элементов к каждой ячейке сетки. Определяет «зону влияния» — где паттерны могут появляться относительно заголовка.

function buildProximityMap(titles): number[][] {
  const dist: number[][] = fill(Infinity);
  // BFS from all title edges
  while (queue.length > 0) {
    const [cx, cy] = queue.shift();
    for (const [dx, dy] of neighbors) {
      const nd = dist[cy+dy][cx+dx];
      if (nd > dist[cy][cx] + 1) {
        dist[cy+dy][cx+dx] = dist[cy][cx] + 1;
        queue.push([cx+dx, cy+dy]);
      }
    }
  }
}

3. Seeded Placement

Deterministic RNG (mulberry32). Same seed = identical layout.

function mulberry32(seed) {
  let state = seed >>> 0;
  return () => {
    state = (state + 0x6D2B79F5) >>> 0;
    let t = state;
    t = Math.imul(t ^ (t >>> 15), t | 1);
    t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

7 типов анимации паттернов

Тип Эффект CSS/Canvas
dots Поэлементный fade-in со stagger globalAlpha per shape
capsule Рост от центра по длинной оси Clip rect grow
circle Pie-fill по часовой Arc + clip
arrow Slide up снизу translateY offset
square Scale 1.6× → 1× scale() transform
stripes Полосы slide-in staggered Y-offset per stripe
cross Scale 1.6× → 1× scale() transform

Timeline: 3 фазы

0──────────→ durationMs ──────────→ 2×durationMs ──────────→ 4×durationMs (loop)
  │              ФАЗА 1              │           ФАЗА 2           │    ФАЗА 3     │
  │         Title reveal             │   Pattern reveal           │  Dots pulse   │
  │  half-reveal из центра           │   clip-side reveal          │  sin wave     │
// Фазовая логика timeline
function evaluate(elapsedMs, durationMs, titles, patterns, dots, easing) {
  // Phase 1: Title reveal (0→1×)
  const titleT = Math.min(1, elapsedMs / durationMs);
  const titleEased = applyEasing(titleT, easing); // half-reveal
  
  // Phase 2: Pattern reveal (1×→2×)
  const cycleMs = afterTitle % (4 * durationMs);
  
  // Phase 3: Dots pulse (2×→4×)
  const holdMs = cycleMs - durationMs;
  const pulse = 0.15 + 0.85 * (0.5 + 0.5 * Math.sin(2π * speed * t + phase));
}

Color System

function getPairsForColor(primary: string): ColorPair[] {
  const lum = luminance(r, g, b);
  const dark = mixRGB(primary, #000000, 0.45);
  const light = mixRGB(primary, #FFFFFF, 0.35);
  
  if (lum > 0.5) {
    return [
      { bg: primary, fg: '#000000' },
      { bg: dark, fg: primary },
      { bg: primary, fg: dark },
    ];
  }
  // inverted for dark colors
}

Конвенция SVG-паттернов (40×40): fill="white" = фон (перекрашивается runtime), fill="black" / stroke="black" = foreground.

Figma Plugin

Экспортирует фреймы 1920×1080 в JSON. Каждый слой экспортируется как 2× PNG, цвета автодетектятся.

// code.js — экспорт слоя
bytes = await child.exportAsync({
  format: 'PNG',
  constraint: { type: 'SCALE', value: 2 },
});

// Автодетект цветов
collectUsedColors(node, usedColors); // BFS по иерархии

Blender Add-on

Импорт ZIP с 3 PNG-последовательностями (titles, patterns, dots) как emissive planes:

# Создаёт plane с aspect-ratio из разрешения PNG
plane.scale = (6.0, 6.0, 6.0)
plane.rotation_euler = (90°, 0, 0)

# Emissive shader node graph
tex.image.source = 'SEQUENCE'
tex.image_user.use_cyclic = cyclic  # dots = True
nt.links.new(tex.outputs['Color'], bsdf.inputs['Emission'])
nt.links.new(tex.outputs['Alpha'], bsdf.inputs['Alpha'])

Ключевые параметры

Параметр Диапазон Описание
density 1–20 Количество паттернов (формула: 3 + 40 × (d/10)²)
proximity 1–20 Зона влияния от title (maxRadius = 2 + proximity × 2.5)
stagger 0–5 Stagger window: (stagger/5) × 0.8
durationMs 100–20000 Длительность фазы
EXPORT_SCALE 4 Рендер в 4× разрешении
FPS 24 Частота кадров

Anti-patterns

❌ Плохо ✅ Хорошо
Паттерны накладываются на title BFS proximity map ограничивает placement
Без collision detection Occupancy grid предотвращает наложения
Рандомная расстановка Seeded RNG — детерминизм для итераций
Паттерны без анимации 7 типов анимации с clip-side
Фиксированные цвета Алгоритмическая генерация color pairs
Рендер без bg/fg разделения white→bg, black→fg runtime colorize
1 кадр = 1 экспорт Layer export: titles/patterns/dots separately

Где используется

  • patterngen-oss (github.com/halfof8/patterngen-oss) — open-source референс
  • Title cards в motion design
  • Анимированные фоны лендингов
  • Procedural patterns для социальных сетей
  • Генерация фоновых текстур для 3D-композиций в Blender

CV Service Validation

Процедурные паттерны рендерятся на Canvas 2D — это клиентская генерация, не серверная. Для валидации дизайна страницы с pattern-генератором:

curl -X POST http://localhost:8001/design/full-analysis \
  -H "Content-Type: application/json" \
  -d '{"html": "<HTML>", "full_analysis": true}'

Особенности: Canvas-элементы не оцениваются по semantic HTML — паттерны — это визуальный слой. Оценивается обёртка (header, sidebar, controls).

Технические детали

Структура проекта:
├── src/store.ts          # Zustand store — 373 строки, вся бизнес-логика
├── src/core/
│   ├── patterns.ts       # Load SVG, colorize (white→bg, black→fg)
│   ├── colors.ts         # getPairsForColor, luminance-based
│   ├── grid.ts           # GridOccupancy + snapToGrid(20px)
│   ├── placement.ts      # generatePlacement — BFS + occupancy
│   └── rng.ts            # mulberry32 seeded RNG
├── src/engine/
│   ├── animations.ts     # 7 анимаций (drawAnimatedPattern)
│   ├── easing.ts         # 7 easing функций
│   └── timeline.ts       # evaluate() — фазовая логика
├── src/export/
│   ├── renderer.ts       # renderFrame() — canvas layer compositing
│   └── exporter.ts       # exportAll() → ZIP with 3 layers × 24fps
├── figma-plugin/
│   ├── code.js           # Figma sandbox export
│   └── ui.html           # Plugin UI
└── blender-addon/
    └── patterngen_importer.py  # Blender 3.4+ operator

Зависимости: React 18, Zustand 5, JSZip, FileSaver, Vite