以下是 Canvas 和 SVG 的实用案例对比及实现代码,涵盖核心特性和典型应用场景:
一、Canvas 动态时钟(位图绘制)
<canvas id="clock" width="300" height="300"></canvas>
<script>
const canvas = document.getElementById('clock');
const ctx = canvas.getContext('2d');
function drawClock() {
// 清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制表盘
ctx.beginPath();
ctx.arc(150, 150, 140, 0, Math.PI * 2);
ctx.strokeStyle = '#333';
ctx.lineWidth = 4;
ctx.stroke();
// 绘制刻度
for (let i = 0; i < 60; i++) {
ctx.beginPath();
const angle = (i * Math.PI) / 30;
const length = i % 5 === 0 ? 15 : 5;
ctx.moveTo(150 + Math.cos(angle) * 125, 150 + Math.sin(angle) * 125);
ctx.lineTo(150 + Math.cos(angle) * (125 - length), 150 + Math.sin(angle) * (125 - length));
ctx.stroke();
}
// 获取时间
const now = new Date();
const hours = now.getHours() % 12;
const minutes = now.getMinutes();
const seconds = now.getSeconds();
// 绘制时针
ctx.save();
ctx.translate(150, 150);
ctx.rotate((hours * 30 + minutes * 0.5) * Math.PI / 180);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(0, -60);
ctx.lineWidth = 6;
ctx.stroke();
ctx.restore();
// 动画循环
requestAnimationFrame(drawClock);
}
drawClock();
</script>
核心要点:
- 使用
getContext('2d')
获取绘图上下文 - 通过
clearRect
实现画面刷新 - 数学计算实现坐标定位
requestAnimationFrame
优化动画性能
二、SVG 可交互柱状图(矢量图形)
<svg width="400" height="300" id="chart">
<!-- X轴 -->
<path d="M50 250 H350" stroke="#999" />
<!-- 数据列 -->
<rect x="70" y="150" width="40" height="100" fill="#4CAF50" class="bar">
<title>销售额: ¥12000</title>
</rect>
<rect x="150" y="100" width="40" height="150" fill="#2196F3" class="bar">
<title>销售额: ¥18000</title>
</rect>
<rect x="230" y="50" width="40" height="200" fill="#FF9800" class="bar">
<title>销售额: ¥24000</title>
</rect>
<!-- 文字标签 -->
<text x="90" y="270" text-anchor="middle">Q1</text>
<text x="170" y="270" text-anchor="middle">Q2</text>
<text x="250" y="270" text-anchor="middle">Q3</text>
</svg>
<style>
.bar {
transition: all 0.3s;
cursor: pointer;
}
.bar:hover {
opacity: 0.8;
transform: translateY(-2px);
}
</style>
核心要点:
- 原生 SVG 标签声明式绘图
- CSS 直接控制样式和动画
- 内置
<title>
实现 Tooltip - 矢量特性保证缩放不失真
三、技术选型对比表
特性 | Canvas | SVG |
---|---|---|
图像类型 | 位图(像素操作) | 矢量图(XML描述) |
渲染方式 | 立即模式(需手动刷新) | 保留模式(自动管理) |
交互实现 | 需手动计算坐标区域 | 原生支持DOM事件 |
性能表现 | 大数据量渲染更优(游戏/可视化) | 复杂图形渲染更高效 |
典型应用 | 动态图表/图像处理 | 可缩放图标/数据可视化 |
学习曲线 | 需要图形API知识 | 类似HTML的声明式语法 |
动画实现 | 通过JS逐帧绘制 | CSS动画/SMIL |
四、混合使用场景
地图可视化方案:
- 使用 SVG 绘制基础地图轮廓
- Canvas 叠加实时热力图
- WebGL 处理3D地形
// 获取SVG路径数据
const paths = document.querySelectorAll('svg path');
// Canvas叠加绘制
ctx.globalCompositeOperation = 'multiply';
paths.forEach(path => {
const points = getPathPoints(path); // 解析SVG路径
drawHeatmap(points); // Canvas绘制热力
});
五、现代框架集成
-
React + Canvas
useEffect(() => { const ctx = canvasRef.current.getContext('2d'); // 使用requestAnimationFrame驱动动画 }, []);
-
Vue + SVG
<template> <svg> <circle v-for="(item, i) in data" :cx="i * 50 + 30" :cy="100" :r="item.value / 10" /> </svg> </template>
关键决策建议:
-
选择 Canvas 当需要:
- 处理图像像素(滤镜/合成)
- 高频更新动画(游戏)
- 大数据量绘制(10k+元素)
-
选择 SVG 当需要:
- 可访问性(屏幕阅读器支持)
- 精细交互(hover/click事件)
- 响应式缩放(高分辨率设备)
掌握两者的核心差异,根据具体场景选择最佳方案,亦可结合使用实现互补优势。