canvas-design

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Canvas Design

Canvas 设计

Overview

概述

Create performant, accessible, and visually compelling graphics using HTML Canvas 2D, SVG, and data visualization libraries. This skill covers everything from low-level pixel manipulation to high-level chart composition with D3.js, including generative art, interactive graphics, and animation.
使用HTML Canvas 2D、SVG和数据可视化库创建高性能、可访问且视觉效果出色的图形。本技能涵盖从底层像素操作到使用D3.js实现高阶图表组合的所有内容,包括生成艺术、交互式图形和动画。

Phase 1: Requirements Analysis

阶段1:需求分析

  1. Determine output type (static, animated, interactive, data-driven)
  2. Choose rendering technology (Canvas 2D, SVG, WebGL, hybrid)
  3. Identify data sources and update frequency
  4. Define accessibility requirements for the visualization
  5. Set performance budget (frame rate, element count)
STOP — Present technology recommendation with rationale before implementation.
  1. 确定输出类型(静态、动画、交互式、数据驱动)
  2. 选择渲染技术(Canvas 2D、SVG、WebGL、混合方案)
  3. 明确数据源和更新频率
  4. 定义可视化的可访问性要求
  5. 设定性能预算(帧率、元素数量)
停止 —— 实现前先给出技术选型建议及理由。

Technology Selection Decision Table

技术选型决策表

RequirementCanvas 2DSVGWebGL
< 1000 elementsMaybeYesNo
> 10,000 elementsYesNoYes
DOM event handling neededNoYesNo
Pixel manipulationYesNoYes
Text-heavy visualizationNoYesNo
3D renderingNoNoYes
Print qualityNoYesNo
Animation-heavyYesMaybeYes
Accessibility criticalNoYesNo
SEO-relevant contentNoYesNo
需求Canvas 2DSVGWebGL
元素数量<1000可选推荐不推荐
元素数量>10000推荐不推荐推荐
需要DOM事件处理不推荐推荐不推荐
需要像素操作推荐不推荐推荐
文本密集型可视化不推荐推荐不推荐
3D渲染不推荐不推荐推荐
打印质量要求不推荐推荐不推荐
动画密集型推荐可选推荐
可访问性为核心要求不推荐推荐不推荐
内容需要SEO不推荐推荐不推荐

When to Use Each Technology

各技术适用场景

Use CaseRecommendedWhy
Dashboard charts (< 500 data points)SVG + D3.jsDOM events, accessibility, print
Real-time data stream (1000+ points)Canvas 2DPerformance at scale
Interactive map with tooltipsSVGHover events, accessible
Particle system / generative artCanvas 2DPixel-level control, performance
3D data visualizationWebGL (Three.js)GPU acceleration
Infographic for blog postSVGScalable, accessible, printable
Game or simulationCanvas 2D or WebGLFrame rate, pixel control
使用场景推荐技术原因
仪表板图表(<500个数据点)SVG + D3.js支持DOM事件、可访问性好、可打印
实时数据流(1000+个数据点)Canvas 2D大规模场景下性能优异
带提示框的交互式地图SVG支持悬停事件、可访问性好
粒子系统/生成艺术Canvas 2D像素级控制、性能优异
3D数据可视化WebGL (Three.js)GPU加速支持
博客信息图SVG可缩放、可访问性好、可打印
游戏或模拟程序Canvas 2D 或 WebGL帧率有保障、支持像素控制

Phase 2: Implementation

阶段2:实现

  1. Set up responsive canvas/SVG container
  2. Implement rendering pipeline (clear, update, draw)
  3. Add interaction handlers (hover, click, drag, zoom)
  4. Optimize render loop (requestAnimationFrame, dirty rectangles)
  5. Add accessibility layer (ARIA, screen reader descriptions)
STOP — Verify rendering works correctly at target frame rate before adding polish.
  1. 搭建响应式Canvas/SVG容器
  2. 实现渲染管线(清空、更新、绘制)
  3. 添加交互处理逻辑(悬停、点击、拖拽、缩放)
  4. 优化渲染循环(requestAnimationFrame、脏矩形优化)
  5. 添加可访问层(ARIA、屏幕阅读器描述)
停止 —— 添加优化内容前先确认渲染在目标帧率下运行正常。

Canvas 2D API Patterns

Canvas 2D API 常用模式

Responsive Canvas Setup

响应式Canvas搭建

javascript
function createResponsiveCanvas(container) {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  const dpr = window.devicePixelRatio || 1;

  function resize() {
    const rect = container.getBoundingClientRect();
    canvas.width = rect.width * dpr;
    canvas.height = rect.height * dpr;
    canvas.style.width = `${rect.width}px`;
    canvas.style.height = `${rect.height}px`;
    ctx.scale(dpr, dpr);
  }

  const observer = new ResizeObserver(resize);
  observer.observe(container);
  container.appendChild(canvas);
  resize();

  return { canvas, ctx, destroy: () => observer.disconnect() };
}
javascript
function createResponsiveCanvas(container) {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  const dpr = window.devicePixelRatio || 1;

  function resize() {
    const rect = container.getBoundingClientRect();
    canvas.width = rect.width * dpr;
    canvas.height = rect.height * dpr;
    canvas.style.width = `${rect.width}px`;
    canvas.style.height = `${rect.height}px`;
    ctx.scale(dpr, dpr);
  }

  const observer = new ResizeObserver(resize);
  observer.observe(container);
  container.appendChild(canvas);
  resize();

  return { canvas, ctx, destroy: () => observer.disconnect() };
}

Animation Loop Pattern

动画循环模式

javascript
function createAnimationLoop(drawFn) {
  let rafId = null;
  let lastTime = 0;

  function loop(timestamp) {
    const deltaTime = timestamp - lastTime;
    lastTime = timestamp;
    drawFn(deltaTime, timestamp);
    rafId = requestAnimationFrame(loop);
  }

  return {
    start: () => { rafId = requestAnimationFrame(loop); },
    stop: () => { cancelAnimationFrame(rafId); rafId = null; },
    isRunning: () => rafId !== null,
  };
}
javascript
function createAnimationLoop(drawFn) {
  let rafId = null;
  let lastTime = 0;

  function loop(timestamp) {
    const deltaTime = timestamp - lastTime;
    lastTime = timestamp;
    drawFn(deltaTime, timestamp);
    rafId = requestAnimationFrame(loop);
  }

  return {
    start: () => { rafId = requestAnimationFrame(loop); },
    stop: () => { cancelAnimationFrame(rafId); rafId = null; },
    isRunning: () => rafId !== null,
  };
}

Dirty Rectangle Optimization

脏矩形优化

javascript
class DirtyRectRenderer {
  constructor(ctx, width, height) {
    this.ctx = ctx;
    this.dirtyRects = [];
    this.objects = [];
  }

  markDirty(x, y, w, h) {
    this.dirtyRects.push({ x, y, w, h });
  }

  render() {
    for (const rect of this.dirtyRects) {
      this.ctx.clearRect(rect.x, rect.y, rect.w, rect.h);
      for (const obj of this.objects) {
        if (this.intersects(obj.bounds, rect)) {
          obj.draw(this.ctx);
        }
      }
    }
    this.dirtyRects = [];
  }
}
javascript
class DirtyRectRenderer {
  constructor(ctx, width, height) {
    this.ctx = ctx;
    this.dirtyRects = [];
    this.objects = [];
  }

  markDirty(x, y, w, h) {
    this.dirtyRects.push({ x, y, w, h });
  }

  render() {
    for (const rect of this.dirtyRects) {
      this.ctx.clearRect(rect.x, rect.y, rect.w, rect.h);
      for (const obj of this.objects) {
        if (this.intersects(obj.bounds, rect)) {
          obj.draw(this.ctx);
        }
      }
    }
    this.dirtyRects = [];
  }
}

SVG Patterns

SVG 常用模式

Programmatic SVG Creation

程序化创建SVG

javascript
function createSVG(width, height, viewBox) {
  const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  svg.setAttribute('width', '100%');
  svg.setAttribute('height', '100%');
  svg.setAttribute('viewBox', viewBox || `0 0 ${width} ${height}`);
  svg.setAttribute('role', 'img');
  return svg;
}
javascript
function createSVG(width, height, viewBox) {
  const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  svg.setAttribute('width', '100%');
  svg.setAttribute('height', '100%');
  svg.setAttribute('viewBox', viewBox || `0 0 ${width} ${height}`);
  svg.setAttribute('role', 'img');
  return svg;
}

SVG Accessibility

SVG可访问性实现

xml
<svg role="img" aria-labelledby="chart-title chart-desc">
  <title id="chart-title">Monthly Revenue Chart</title>
  <desc id="chart-desc">Bar chart showing revenue from Jan to Dec 2025</desc>
  <!-- chart content -->
</svg>
xml
<svg role="img" aria-labelledby="chart-title chart-desc">
  <title id="chart-title">Monthly Revenue Chart</title>
  <desc id="chart-desc">Bar chart showing revenue from Jan to Dec 2025</desc>
  <!-- chart content -->
</svg>

D3.js Integration Patterns

D3.js 集成模式

Data Join Pattern (D3 v7)

数据关联模式(D3 v7)

javascript
function updateBars(svg, data) {
  const bars = svg.selectAll('.bar')
    .data(data, d => d.id);

  bars.exit()
    .transition().duration(300)
    .attr('opacity', 0)
    .remove();

  bars.enter()
    .append('rect')
    .attr('class', 'bar')
    .attr('opacity', 0)
    .merge(bars)
    .transition().duration(500)
    .attr('x', d => xScale(d.label))
    .attr('y', d => yScale(d.value))
    .attr('width', xScale.bandwidth())
    .attr('height', d => height - yScale(d.value))
    .attr('opacity', 1);
}
javascript
function updateBars(svg, data) {
  const bars = svg.selectAll('.bar')
    .data(data, d => d.id);

  bars.exit()
    .transition().duration(300)
    .attr('opacity', 0)
    .remove();

  bars.enter()
    .append('rect')
    .attr('class', 'bar')
    .attr('opacity', 0)
    .merge(bars)
    .transition().duration(500)
    .attr('x', d => xScale(d.label))
    .attr('y', d => yScale(d.value))
    .attr('width', xScale.bandwidth())
    .attr('height', d => height - yScale(d.value))
    .attr('opacity', 1);
}

Scales and Axes

比例尺和坐标轴

javascript
// Linear scale for continuous data
const yScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => d.value)])
  .range([height, 0])
  .nice();

// Band scale for categorical data
const xScale = d3.scaleBand()
  .domain(data.map(d => d.label))
  .range([0, width])
  .padding(0.2);

// Color scale
const colorScale = d3.scaleOrdinal(d3.schemeTableau10);
javascript
// 连续数据的线性比例尺
const yScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => d.value)])
  .range([height, 0])
  .nice();

// 分类数据的带状比例尺
const xScale = d3.scaleBand()
  .domain(data.map(d => d.label))
  .range([0, width])
  .padding(0.2);

// 颜色比例尺
const colorScale = d3.scaleOrdinal(d3.schemeTableau10);

Responsive D3 Chart

响应式D3图表

javascript
function responsiveChart(container, renderFn) {
  const observer = new ResizeObserver(entries => {
    const { width, height } = entries[0].contentRect;
    const margin = { top: 20, right: 20, bottom: 40, left: 50 };
    renderFn(container, {
      width: width - margin.left - margin.right,
      height: height - margin.top - margin.bottom,
      margin,
    });
  });
  observer.observe(container);
  return () => observer.disconnect();
}
javascript
function responsiveChart(container, renderFn) {
  const observer = new ResizeObserver(entries => {
    const { width, height } = entries[0].contentRect;
    const margin = { top: 20, right: 20, bottom: 40, left: 50 };
    renderFn(container, {
      width: width - margin.left - margin.right,
      height: height - margin.top - margin.bottom,
      margin,
    });
  });
  observer.observe(container);
  return () => observer.disconnect();
}

Phase 3: Polish

阶段3:优化打磨

  1. Add transitions and easing
  2. Implement responsive resizing
  3. Test across devices and browsers
  4. Add fallback content for unsupported environments
STOP — Verify accessibility and performance targets are met.
  1. 添加过渡动画和缓动效果
  2. 实现响应式缩放
  3. 跨设备和浏览器测试
  4. 为不支持的环境添加降级内容
停止 —— 确认可访问性和性能指标均达标。

Generative Art Techniques

生成艺术技术

TechniqueCategoryUse Case
Perlin/Simplex noiseNoise-basedOrganic shapes, terrain
Fractal Brownian MotionNoise-basedTerrain-like textures
Domain warpingNoise-basedFluid-like effects
Particle systemsSimulationFire, water, swarms
L-systemsAlgorithmicPlant-like structures
Voronoi diagramsAlgorithmicCell-like partitions
Delaunay triangulationAlgorithmicMesh generation
Flow fieldsAlgorithmicDirectional patterns
技术类别使用场景
Perlin/Simplex 噪声噪声类有机形状、地形
分形布朗运动噪声类类地形纹理
域扭曲噪声类流体类效果
粒子系统模拟类火焰、水流、群集
L-系统算法类类植物结构
Voronoi 图算法类类细胞分区
Delaunay 三角剖分算法类网格生成
流场算法类方向性图案

Accessibility for Visualizations

可视化可访问性要求

RequirementImplementation
Text alternatives
<title>
and
<desc>
in SVG, ARIA labels on Canvas
Data table fallbackHidden table with same data for screen readers
Keyboard interactionTab to elements, arrow keys for navigation
Color-blind safeUse shape/pattern in addition to color
High contrast modeDetect and adjust colors
Reduced motionSimplify or disable animations with
prefers-reduced-motion
要求实现方式
文本替代内容SVG中添加
<title>
<desc>
,Canvas上添加ARIA标签
数据表格降级为屏幕阅读器隐藏存储相同数据的表格
键盘交互支持Tab选中元素、方向键导航
色弱友好除颜色外额外使用形状/图案区分内容
高对比度模式支持检测模式并调整颜色
减少动画通过
prefers-reduced-motion
简化或关闭动画

Performance Guidelines

性能指南

TechnologyOptimization
CanvasBatch draw calls, minimize state changes (fill/stroke/font)
SVGLimit to < 1000 DOM nodes, use
<use>
for repeated elements
WorkerOffscreenCanvas for web worker rendering
EventsThrottle mousemove handlers to 16ms (60fps)
CSSUse
will-change: transform
for CSS-animated SVG elements
CleanupDispose of observers, animation frames on unmount
技术优化方案
Canvas批量绘制调用,减少状态变更(填充/描边/字体)
SVG限制DOM节点数量<1000,重复元素使用
<use>
Worker使用OffscreenCanvas在Web Worker中渲染
事件将mousemove处理程序节流到16ms(60fps)
CSSCSS动画的SVG元素添加
will-change: transform
清理卸载时销毁观察者、取消动画帧

Anti-Patterns / Common Mistakes

反模式/常见错误

Anti-PatternWhy It Is WrongWhat to Do Instead
Canvas for text-heavy contentPoor text rendering, no accessibilityUse SVG for text-heavy visualizations
Full canvas redraw every frameWastes CPU when nothing changedUse dirty rectangle optimization
Creating new SVG elements instead of updatingMemory leaks, poor performanceUse D3 data join pattern
Forgetting devicePixelRatioBlurry on Retina/HiDPI displaysScale canvas by
window.devicePixelRatio
No fallback content for CanvasScreen readers get nothingAdd
aria-label
and hidden data table
Inline event handlers on 1000+ SVG elementsMemory and performance overheadUse event delegation on parent
Not cleaning up animation framesMemory leaks on unmount
cancelAnimationFrame
in cleanup
Using D3 for simple static chartsOver-engineeringUse SVG directly or Chart.js
反模式问题替代方案
文本密集内容使用Canvas文本渲染效果差、无访问性文本密集可视化使用SVG
每帧全量重绘Canvas无内容变更时浪费CPU使用脏矩形优化
频繁新建SVG元素而非更新内存泄漏、性能差使用D3数据关联模式
忽略devicePixelRatioRetina/高DPI屏幕下显示模糊
window.devicePixelRatio
缩放Canvas
Canvas无降级内容屏幕阅读器无法识别添加
aria-label
和隐藏数据表格
1000+个SVG元素绑定内联事件内存和性能开销大父元素使用事件委托
未清理动画帧卸载时内存泄漏清理逻辑中调用
cancelAnimationFrame
简单静态图表使用D3过度设计直接使用SVG或Chart.js

Integration Points

集成点

SkillIntegration
ui-ux-pro-max
Chart type selection and color palettes
ui-design-system
Design tokens for chart theming
artifacts-builder
Self-contained visualization artifacts
senior-frontend
Component integration in React/Vue/Svelte
performance-optimization
Frame rate and rendering optimization
mobile-design
Touch interaction for mobile charts
技能集成场景
ui-ux-pro-max
图表类型选择和调色板
ui-design-system
图表主题的设计令牌
artifacts-builder
独立可视化产物
senior-frontend
React/Vue/Svelte中的组件集成
performance-optimization
帧率和渲染优化
mobile-design
移动端图表的触摸交互

Skill Type

技能类型

FLEXIBLE — Choose the rendering technology and library that best fits the use case. SVG for accessibility-critical and interactive charts, Canvas for performance-critical and animation-heavy visuals, WebGL for 3D and massive datasets.
灵活适配 —— 选择最适合场景的渲染技术和库。可访问性要求高、交互式的图表使用SVG,性能要求高、动画密集的视觉内容使用Canvas,3D和超大规模数据集使用WebGL。