关于 canvas-design
使用 HTML Canvas 2D、SVG、WebGL 及 D3.js 等可视化库制作图形和数据可视化的设计技能。它帮助开发者选择合适的渲染方式,并在实现中处理交互、无障碍、响应式布局和性能。
主要功能
- 01按需求选择 Canvas、SVG 或 WebGL
- 02运用 D3.js 模式制作图表
- 03添加交互和响应式尺寸调整
- 04规划无障碍支持与备用内容
- 05优化渲染和动画性能
适用场景
- 01为可视化选择渲染方式
- 02构建交互式图表和地图
- 03制作生成艺术或动画图形
- 04改善无障碍体验和渲染性能
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ pixel-process-ug/ superkit-agents --skill canvas-design安装后在 Claude Code 中输入/canvas-design确认已加载。
详细介绍
Canvas 设计
概述
使用 HTML Canvas 2D、SVG 和数据可视化库,创建高性能、易访问且视觉效果出色的图形。本技能涵盖从底层像素操作到使用 D3.js 进行高级图表组合的所有内容,包括生成艺术、交互式图形和动画。
阶段 1:需求分析
- 确定输出类型(静态、动画、交互式、数据驱动)
- 选择渲染技术(Canvas 2D、SVG、WebGL、混合方案)
- 确定数据源和更新频率
- 定义可视化的无障碍要求
- 设定性能预算(帧率、元素数量)
停止——在开始实现前,提供技术建议并说明理由。
技术选择决策表
| 需求 | Canvas 2D | SVG | WebGL |
|---|---|---|---|
| 少于 1000 个元素 | 可能 | 是 | 否 |
| 多于 10,000 个元素 | 是 | 否 | 是 |
| 需要处理 DOM 事件 | 否 | 是 | 否 |
| 像素操作 | 是 | 否 | 是 |
| 以文本为主的可视化 | 否 | 是 | 否 |
| 3D 渲染 | 否 | 否 | 是 |
| 印刷质量 | 否 | 是 | 否 |
| 动画密集型 | 是 | 可能 | 是 |
| 无障碍至关重要 | 否 | 是 | 否 |
| 与 SEO 相关的内容 | 否 | 是 | 否 |
各技术的适用场景
| 使用场景 | 推荐方案 | 原因 |
|---|---|---|
| 仪表盘图表(少于 500 个数据点) | SVG + D3.js | DOM 事件、无障碍、打印 |
| 实时数据流(1000 个以上数据点) | Canvas 2D | 大规模数据下的性能 |
| 带工具提示的交互式地图 | SVG | 悬停事件、易访问 |
| 粒子系统 / 生成艺术 | Canvas 2D | 像素级控制、高性能 |
| 3D 数据可视化 | WebGL (Three.js) | GPU 加速 |
| 博客文章信息图 | SVG | 可缩放、易访问、可打印 |
| 游戏或模拟 | Canvas 2D 或 WebGL | 帧率、像素控制 |
阶段 2:实现
- 设置响应式 Canvas/SVG 容器
- 实现渲染管线(清除、更新、绘制)
- 添加交互处理器(悬停、点击、拖动、缩放)
- 优化渲染循环(requestAnimationFrame、脏矩形)
- 添加无障碍层(ARIA、屏幕阅读器描述)
停止——在添加润色效果前,确认渲染在目标帧率下正常运行。
Canvas 2D API 模式
响应式 Canvas 设置
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() };
}
动画循环模式
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,
};
}
脏矩形优化
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 模式
以编程方式创建 SVG
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 无障碍
<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>
</svg>
D3.js 集成模式
数据连接模式(D3 v7)
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);
}
比例尺和坐标轴
// 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);
响应式 D3 图表
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();
}
阶段 3:润色
- 添加过渡效果和缓动
- 实现响应式调整大小
- 在不同设备和浏览器上测试
- 为不支持的环境添加备用内容
停止——确认已达到无障碍和性能目标。
生成艺术技巧
| 技巧 | 类别 | 使用场景 |
|---|---|---|
| Perlin/Simplex 噪声 | 基于噪声 | 有机形状、地形 |
| 分形布朗运动 | 基于噪声 | 类地形纹理 |
| 域扭曲 | 基于噪声 | 流体效果 |
| 粒子系统 | 模拟 | 火焰、水、群集 |
| L 系统 | 算法 | 植物状结构 |
| Voronoi 图 | 算法 | 单元状分区 |
| Delaunay 三角剖分 | 算法 | 网格生成 |
| 流场 | 算法 | 方向性图案 |
可视化的无障碍设计
| 需求 | 实现方式 |
|---|---|
| 文本替代内容 | 在 SVG 中使用 <title> 和 <desc>,在 Canvas 上添加 ARIA 标签 |
| 数据表格备用方案 | 提供包含相同数据的隐藏表格,供屏幕阅读器读取 |
| 键盘交互 | 使用 Tab 键定位元素,使用方向键导航 |
| 适合色盲用户 | 除颜色外,同时使用形状 / 图案 |
| 高对比度模式 | 检测并调整颜色 |
| 减少动态效果 | 使用 prefers-reduced-motion 简化或禁用动画 |
性能指南
| 技术 | 优化 |
|---|---|
| Canvas | 批量执行绘制调用,尽量减少状态变更(填充/描边/字体) |
| SVG | 将 DOM 节点限制在 1000 个以内,重复元素使用 <use> |
| Worker | 使用 OffscreenCanvas 在 web worker 中渲染 |
| Events | 将 mousemove 处理程序节流至 16ms(60fps) |
| CSS | 对使用 CSS 动画的 SVG 元素使用 will-change: transform |
| 清理 | 卸载时释放观察器和动画帧 |
反模式/常见错误
| 反模式 | 错误原因 | 替代做法 |
|---|---|---|
| 使用 Canvas 展示文字密集型内容 | 文字渲染效果差,且不具备无障碍支持 | 文字密集型可视化使用 SVG |
| 每帧都重绘整个画布 | 内容没有变化时也会浪费 CPU | 使用脏矩形优化 |
| 创建新的 SVG 元素,而不是更新已有元素 | 会导致内存泄漏、性能不佳 | 使用 D3 数据联结模式 |
| 忘记 devicePixelRatio | 在 Retina/HiDPI 显示屏上显示模糊 | 按 window.devicePixelRatio 缩放画布 |
| Canvas 没有备用内容 | 屏幕阅读器无法读取任何内容 | 添加 aria-label 和隐藏的数据表格 |
| 在 1000 多个 SVG 元素上使用内联事件处理程序 | 增加内存和性能开销 | 在父元素上使用事件委托 |
| 未清理动画帧 | 卸载时会导致内存泄漏 | 在清理逻辑中调用 cancelAnimationFrame |
| 对简单的静态图表使用 D3 | 过度设计 | 直接使用 SVG 或 Chart.js |
集成点
| 技能 | 集成方式 |
|---|---|
ui-ux-pro-max | 图表类型选择和调色板 |
ui-design-system | 用于图表主题的设计令牌 |
artifacts-builder | 独立的可视化产物 |
senior-frontend | 在 React/Vue/Svelte 中集成组件 |
performance-optimization | 帧率和渲染优化 |
mobile-design | 移动端图表的触控交互 |
技能类型
FLEXIBLE — 根据具体使用场景选择最合适的渲染技术和库。对无障碍支持至关重要且需要交互的图表使用 SVG;对性能要求高且动画密集的视觉内容使用 Canvas;对 3D 和海量数据集使用 WebGL。
评论
支持 Markdown