К основному содержанию
скилл CX Codex

canvas-generative — скилл для Claude Code: генеративное искусство

Скилл для алгоритмической графики на Canvas 2D: частицы, flow fields, шум, фракталы и L-системы. Пригодится, когда нужна анимация или генеративная картинка в браузере.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add AThevon/genjutsu --skill canvas-generative -a claude-code
Открыть на GitHub

Что делает canvas-generative

Скилл задаёт агенту правила работы с Canvas 2D: как настроить буфер под Retina, как пересчитывать размер при ресайзе, как крутить цикл на requestAnimationFrame с ограничением дельты. Дальше идут готовые рецепты — пул частиц фиксированного размера, чтобы не давить на сборщик мусора, сетка углов для flow fields, фрактальный шум через октавы, L-системы со строковыми правилами и черепашьей графикой.

Внутри есть раздел с антипаттернами. Например, clearRect каждый кадр убивает шлейф — вместо него полупрозрачная заливка. А getImageData в цикле анимации читает данные обратно с GPU и тормозит всё; автор советует не трогать его без нужды. Двойная буферизация через offscreen-канвас убирает мерцание.

Скилл помечен как version-sensitive: имена API и утверждения о поддержке в браузерах сверялись по первоисточникам, дата проверки лежит в _jutsu/VERSIONS.md. Если она старая, версию стоит перепроверить перед тем, как на неё опираться.

Какие задачи решает

  • настроить canvas под Retina, чтобы картинка не мылилась
  • сделать поток частиц без просадок по кадрам
  • построить flow field из шума и пустить по нему частицы
  • сгенерировать фрактал или растение через L-систему
  • добавить шлейф за движущимися объектами без мерцания

Примеры запросов агенту

  • сделай генеративную анимацию на canvas: flow field из шума и частицы по нему
  • настрой canvas под devicePixelRatio и перерисовку при ресайзе
  • нарисуй фрактальное дерево через L-систему с правилами и углом поворота

Как установить canvas-generative

1Через Skills CLI (Vercel)

npx skills add AThevon/genjutsu --skill canvas-generative -a claude-code

2Вручную: положить файлы

~/.claude/skills/canvas-generative/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/canvas-generative/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о canvas-generative

Как установить canvas-generative в Claude?

Выполните npx skills add AThevon/genjutsu --skill canvas-generative -a claude-code. После этого файл скилла появится по пути ~/.claude/skills/canvas-generative/SKILL.md.

Что делает canvas-generative?

Даёт агенту правила и примеры для алгоритмической графики на Canvas 2D: частицы, flow fields, шум Перлина и Симплекса, фракталы, L-системы. Плюс разбор типичных ошибок вроде чтения пикселей внутри цикла анимации.

Почему скилл называет себя version-sensitive?

Имена API и данные о поддержке в браузерах сверялись по первоисточникам на конкретную дату, она указана в _jutsu/VERSIONS.md. Если дата старая, проверьте версии заново, прежде чем полагаться на них.

Исходный текст

SKILL.md · MIT
---
name: canvas-generative
description: "Algorithmic and generative art with Canvas 2D - particles, flow fields, noise, fractals, L-systems."
metadata:
  internal: true
---

> **Version-sensitive.** Every API name, SDK gate and browser-support claim below was
> verified on **2026-09-08** against primary sources. What against, and when, is in
> `_jutsu/VERSIONS.md`. If that date is old, re-verify before acting on a version number.

# Canvas Generative

> Algorithmic and generative art with Canvas 2D.
> Concise rules here. Deep-dive and reference implementations in `references/`.

---

## Canvas 2D Setup

### DPR-Aware Sizing

Every canvas must be sharp on Retina/HiDPI displays. Set the buffer size to the physical pixel size, scale down with CSS.

```js
function setupCanvas(canvas, width, height) {
  const dpr = window.devicePixelRatio || 1;
  canvas.width = width * dpr;
  canvas.height = height * dpr;
  canvas.style.width = `${width}px`;
  canvas.style.height = `${height}px`;
  const ctx = canvas.getContext('2d');
  ctx.scale(dpr, dpr);
  return ctx;
}
```

### Resize Handler

```js
function handleResize(canvas, ctx, draw) {
  const ro = new ResizeObserver(([entry]) => {
    const { width, height } = entry.contentRect;
    const dpr = window.devicePixelRatio || 1;
    canvas.width = width * dpr;
    canvas.height = height * dpr;
    ctx.scale(dpr, dpr);
    draw(); // re-render after resize
  });
  ro.observe(canvas.parentElement);
  return () => ro.disconnect();
}
```

### Animation Loop (RAF)

```js
let animId;
let prevTime = 0;

function loop(time) {
  const dt = Math.min((time - prevTime) / 1000, 0.1); // cap delta to avoid spiral of death
  prevTime = time;

  update(dt);
  render(ctx);

  animId = requestAnimationFrame(loop);
}

// Start
animId = requestAnimationFrame(loop);
// Stop
cancelAnimationFrame(animId);
```

---

## Noise

| Type | Characteristics | Best For |
|---|---|---|
| Perlin | Smooth, grid-aligned bias, cheaper | Terrain, clouds, gentle organic textures |
| Simplex | No grid artifacts, better gradients, slightly costlier | Flow fields, organic motion, seamless tiling |
| Worley (Cellular) | Distance-to-nearest-point, cell-like | Voronoi patterns, caustics, cracks, cell textures |

**Usage rules:**
- Always scale input coordinates (divide by a `noiseScale` factor) -- raw pixel coords produce visual noise
- Use octaves (fractal Brownian motion) for detail: sum multiple noise calls at increasing frequency and decreasing amplitude
- Seed your noise for reproducibility

```js
// fBm pattern
function fbm(x, y, octaves = 4, lacunarity = 2, gain = 0.5) {
  let value = 0, amplitude = 1, frequency = 1, maxAmp = 0;
  for (let i = 0; i < octaves; i++) {
    value += amplitude * noise2D(x * frequency, y * frequency);
    maxAmp += amplitude;
    amplitude *= gain;
    frequency *= lacunarity;
  }
  return value / maxAmp; // normalize to [-1, 1]
}
```

---

## Particle Systems

### Pool Pattern (No GC Pressure)

Pre-allocate a fixed array. Never `new` or `splice` at runtime.

```js
const POOL_SIZE = 10000;
const particles = new Array(POOL_SIZE);
let aliveCount = 0;

// Init pool
for (let i = 0; i < POOL_SIZE; i++) {
  particles[i] = { x: 0, y: 0, vx: 0, vy: 0, life: 0, maxLife: 0, active: false };
}

function spawn(x, y) {
  if (aliveCount >= POOL_SIZE) return;
  const p = particles[aliveCount++];
  p.x = x; p.y = y;
  p.vx = (Math.random() - 0.5) * 2;
  p.vy = (Math.random() - 0.5) * 2;
  p.life = 0; p.maxLife = 60 + Math.random() * 60;
  p.active = true;
}

function update() {
  for (let i = aliveCount - 1; i >= 0; i--) {
    const p = particles[i];
    p.x += p.vx; p.y += p.vy;
    p.life++;
    if (p.life >= p.maxLife) {
      // Swap with last alive, shrink pool
      particles[i] = particles[--aliveCount];
      particles[aliveCount] = p;
      p.active = false;
    }
  }
}
```

---

## Flow Fields

Grid of angle vectors that steer particles. The classic generative recipe.

1. **Build grid:** Divide canvas into cells, compute an angle per cell (from noise)
2. **Lookup:** Particle position maps to grid cell, retrieve angle
3. **Steer:** Apply angle as velocity, accumulate over frames

```js
const cols = Math.ceil(width / cellSize);
const rows = Math.ceil(height / cellSize);
const field = new Float32Array(cols * rows);

// Fill with noise-based angles
for (let y = 0; y < rows; y++) {
  for (let x = 0; x < cols; x++) {
    field[y * cols + x] = noise2D(x * 0.05, y * 0.05) * Math.PI * 2;
  }
}

// Particle follow
function followField(p) {
  const col = Math.floor(p.x / cellSize);
  const row = Math.floor(p.y / cellSize);
  if (col >= 0 && col < cols && row >= 0 && row < rows) {
    const angle = field[row * cols + col];
    p.vx += Math.cos(angle) * force;
    p.vy += Math.sin(angle) * force;
  }
  // Damping to prevent runaway velocity
  p.vx *= 0.98;
  p.vy *= 0.98;
}
```

---

## Fractals & L-Systems

An L-system encodes recursive structure as string rewriting + turtle graphics.

| Component | Role |
|---|---|
| Axiom | Starting string (e.g. `"F"`) |
| Rules | Production rules (e.g. `"F" -> "F[+F]F[-F]F"`) |
| Angle | Turtle turn angle per `+`/`-` |
| Iterations | How many times to apply rules |

```js
function lsystem(axiom, rules, iterations) {
  let current = axiom;
  for (let i = 0; i < iterations; i++) {
    current = current.split('').map(c => rules[c] || c).join('');
  }
  return current;
}

function drawLSystem(ctx, commands, len, angle) {
  const stack = [];
  for (const c of commands) {
    switch (c) {
      case 'F': ctx.lineTo(ctx._x += Math.cos(ctx._a) * len, ctx._y += Math.sin(ctx._a) * len); break;
      case '+': ctx._a += angle; break;
      case '-': ctx._a -= angle; break;
      case '[': stack.push({ x: ctx._x, y: ctx._y, a: ctx._a }); break;
      case ']': { const s = stack.pop(); ctx._x = s.x; ctx._y = s.y; ctx._a = s.a; ctx.moveTo(s.x, s.y); } break;
    }
  }
}
```

---

## Double Buffer Pattern

Render to an offscreen canvas, then blit to the visible one. Eliminates flicker and enables trail effects.

```js
const offscreen = document.createElement('canvas');
offscreen.width = canvas.width;
offscreen.height = canvas.height;
const offCtx = offscreen.getContext('2d');

function render() {
  // Draw to offscreen
  offCtx.fillStyle = 'rgba(0, 0, 0, 0.05)'; // trail fade
  offCtx.fillRect(0, 0, offscreen.width, offscreen.height);
  drawParticles(offCtx);

  // Blit to screen
  ctx.drawImage(offscreen, 0, 0);
}
```

---

## Do Not

### 1. Never clearRect every frame for trail effects

Clearing destroys the trail. Use a semi-transparent fill instead.

```js
// BAD -- kills trails
ctx.clearRect(0, 0, w, h);

// GOOD -- fades previous frame
ctx.fillStyle = 'rgba(0, 0, 0, 0.02)';
ctx.fillRect(0, 0, w, h);
```

### 2. Never getImageData in the animation loop

`getImageData` reads back from GPU -- extremely slow. Avoid unless absolutely required (e.g. one-time color sampling).

```js
// BAD -- 60fps GPU readback
function loop() {
  const data = ctx.getImageData(0, 0, w, h); // blocks rendering pipeline
  processPixels(data);
  requestAnimationFrame(loop);
}

// GOOD -- sample once, cache
const colorMap = ctx.getImageData(0, 0, w, h);
function getColor(x, y) {
  const i = (y * w + x) * 4;
  return [colorMap.data[i], colorMap.data[i+1], colorMap.data[i+2]];
}
```

### 3. Always respect DPR for sharpness

A canvas without DPR scaling looks blurry on Retina displays. See setup section above.

```js
// BAD
canvas.width = 800;
canvas.height = 600;

// GOOD
const dpr = window.devicePixelRatio || 1;
canvas.width = 800 * dpr;
canvas.height = 600 * dpr;
canvas.style.width = '800px';
canvas.style.height = '600px';
ctx.scale(dpr, dpr);
```

### 4. Never allocate in the hot loop

No `new`, no object spread, no array creation inside `update()` or `render()`. Pre-allocate everything.

```js
// BAD
function update() {
  particles.forEach(p => {
    const force = { x: Math.cos(a), y: Math.sin(a) }; // new object every frame per particle
    p.vx += force.x;
  });
}

// GOOD
let fx = 0, fy = 0; // reuse
function update() {
  for (let i = 0; i < aliveCount; i++) {
    fx = Math.cos(a); fy = Math.sin(a);
    particles[i].vx += fx;
  }
}
```

---

## Quick Reference: Loading Sub-skills

| Need | Load |
|---|---|
| Noise implementations, particle pool, flow field, L-system, attractors | `references/algorithms.md` |
| Timing and easing for animated transitions | `../motion-principles/SKILL.md` |
| 3D generative (shaders, GPU particles) | `../threejs-r3f/SKILL.md` |

© AThevon · MIT · AThevon/genjutsu

Похожие скиллы

Всё по теме «Фронтенд и UI» →
pointer-trail-emitter MengTo Скилл учит агента строить шлейф за курсором, который держит одинаковый шаг между частицами при любой скорости руки. CX Codex +1 1 200установок javascript-animation iart-ai Скилл собирает короткий анимационный ролик, где каждый кадр нарисован кодом на HTML canvas, и рендерит его в MP4. Пригодится, когда нет ни картинок, ни шрифтов под рукой. CX Codex +1 532установок p5js SHL0MS, Hermes Agent Создаёт браузерные скетчи на p5.js: генеративное искусство, интерактивные визуализации, 3D-сцены с WebGL, audio-reactive графика. Экспорт в PNG, GIF, MP4 или SVG. CX Codex +1 534установок component-canvas ibelick Собирает полноэкранный канвас, где компоненты проекта показаны как есть: с панорамированием, зумом и сравнением вариантов. Пригодится, когда нужно разом увидеть, что уже есть в дизайн-системе. CX Codex +1 685установок create-canvas ibelick Скилл собирает в проекте свободный холст, где варианты интерфейса или контента живут рядом, двигаются и сравниваются без перезагрузки страницы. CX Codex +1 381установок frontend-dev nexu-io Скилл для создания современных фронтенда с плавными анимациями, AI-генерируемым контентом через MiniMax API и генеративным искусством. Подходит для героев-страниц и портфолио-сайтов. CX Codex +1 2 800установок

Из того же набора17

design-audit Проверяет код фронтенда на проблемы с анимацией, доступностью и дизайн-токенами. Находит визуальные штампы ИИ и ошибки вёрстки перед сдачей проекта. CX Codex +1 1 000установок threejs-r3f Скилл по Three.js и React Three Fiber: правила сцен, хуков, постобработки и производительности. Пригодится, когда агент пишет 3D на React. CX Codex +1 1 000установок css-native Скилл для ИИ-агента, который подсказывает, как делать анимации и визуальные эффекты на нативном CSS без библиотек. CX Codex +1 1 100установок gsap Скилл помогает агенту писать анимации GSAP: таймлайны, каскадные эффекты и ScrollTrigger. Нужен для сложных движений и прокрутки. CX Codex +1 997установок framer-motion Подсказывает агенту правила работы с Framer Motion и Motion в React: анимации раскладки, жесты и хуки без лишних ререндеров. CX Codex +1 990установок desktop-principles Скилл с правилами десктопного UX: ховеры, точность указателя, горячие клавиши, несколько окон. Пригодится, когда интерфейс делают под macOS, Windows или Linux. CX Codex +1 982установок mobile-principles Набор правил для мобильного интерфейса: размеры тап-зон, отказ от hover, зоны большого пальца, safe area и жесты. Подключается, когда агент видит мобильную платформу. CX Codex +1 974установок compose-multiplatform Скилл помогает писать кроссплатформенный интерфейс на Compose Multiplatform для Android, iOS, Desktop и Web. Пригодится при переносе общих компонентов в commonMain. CX Codex +1 951установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой