在前端开发中,Canvas 和 SVG 是两种强大的绘图技术。本文将深入探讨如何在实际应用中使用 Canvas 和 SVG 绘制基本图形、添加交互事件、实现动画效,特别是如何优化性能和实现高级功能。
实际应用
如何在 Canvas 上绘制一个矩形?
使用 getContext('2d')
获取 2D 绘图上下文,然后使用 fillRect(x, y, width, height)
方法绘制矩形。
示例代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas Rectangle</title>
<style>
#myCanvas {
border: 1px solid black;
}
</style>
</head>
<body>
<h1>Canvas Rectangle</h1>
<canvas id="myCanvas" width="200" height="200"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
ctx.fillRect(10, 10, 100, 50);
</script>
</body>
</html>
效果:
如何在 SVG 中绘制一个圆形?
使用 <circle cx="50" cy="50" r="40" />
元素,其中 cx
和 cy
定义圆心坐标,r
定义半径。
示例代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG Circle</title>
</head>
<body>
<h1>SVG Circle</h1>
<svg width="200" height="200">
<circle cx="50" cy="50" r="40" fill="blue" />
</svg>
</body>
</html>
效果:
如何在 Canvas 上绘制文本?
使用 fillText(text, x, y)
方法,其中 text
是要绘制的文本,x
和 y
是文本的起始坐标。
示例代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas Text</title>
</head>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #000000;"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'black';
ctx.font = '20px Arial';
ctx.fillText('Hello Canvas', 50, 200);
</script>
</body>
</html>
如何在 SVG 中添加交互事件?
可以直接在 SVG 元素上添加事件监听器,例如 <rect onclick="handleClick()" />
。
示例代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG Interaction</title>
<script>
function handleClick() {
alert('Rectangle clicked!');
}
</script>
</head>
<body>
<svg width="400" height="400" style="border:1px solid #000000;">
<rect x="50" y="50" width="150" height="100" fill="blue" onclick="handleClick()" />
</svg>
</body>
</html>
效果:
性能优化
如何优化 Canvas 的绘图性能?
- 使用离屏 Canvas:进行复杂图形的预渲染,减少重绘次数。
- 使用
requestAnimationFrame
,而不是SetInterval
等:进行动画更新,提供更平滑的动画效果。 - 减少重绘区域:只重绘需要更新的区域,而不是整个画布。
- 批量绘制:将多个绘图操作合并为一个批量操作,减少绘图调用的开销。
示例代码
javascript
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制图形
// ...
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
其他例子在这里有讲:juejin.cn/post/744071...
如何优化 SVG 的渲染性能?
- 减少 DOM 元素的数量:尽量减少 SVG 中的元素数量。
- 使用
<use>
元复用图形:避免重复定义相同的图形。 - 避免频繁的 DOM 操作:尽量减少对 SVG DOM 的频繁操作。
- 使用 CSS 动画代替 JavaScript 动画:提高动画性能。
示例代码
html
<svg width="400" height="400" style="border:1 solid #000000;">
<defs>
<circle id="myCircle" cx="50" cy="50" r="40" fill="red" />
</defs>
<use xlink:href="#myCircle" x="0" y="0" />
<use xlink:href="#myCircle" x="100" y="100" />
</svg>
高级使用场景
如何在 Canvas 上实现动画效果?
使用 requestAnimationFrame
方法进行动画帧的更新,在每一帧中清除画布并重新绘制图形。
示例代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas Animation</title>
</head>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #000000;"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
let x = 0;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'blue';
ctx.fillRect(x, 50, 50, 50);
x += 1;
if (x > canvas.width) x = 0;
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
</script>
</body>
</html>
如何在 SVG 中实现渐变效果?
使用 <linearGradient>
或 <radialGradient>
元素定义渐变,然后在图形元素中使用 fill="url(#gradientId)"
应用渐变。
示例代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG Gradient</title>
</head>
<body>
<h1>SVG Gradient</h1>
<svg width="200" height="200">
<defs>
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
</defs>
<rect width="200" height="200" fill="url(#grad1)" />
</svg>
</body>
</html>
效果:
如何在 Canvas 上处理图像?
使用 drawImage(image, x, y, width, height)
方法绘制图像,可以进行裁剪、缩放等操作。
示例代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas Image</title>
</head>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #000000;"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
const img = new Image();
img.onload = function() {
ctx.drawImage(img, 50, 50, 300, 300);
};
img.src = 'https://example.com/image.jpg';
</script>
</body>
</html>
如何在 SVG 中使用滤镜效果?
使用 <filter>
元素定义滤镜效果,然后在图形元素中使用 filter="url(#filterId)"
应用滤镜。
示例代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SVG Filter</title>
</head>
<body>
<h1>SVG Filter</h1>
<svg width="200" height="200">
<defs>
<filter id="blurFilter">
<feGaussianBlur in="SourceGraphic" stdDeviation="5" />
</filter>
</defs>
<rect width="200" height="200" fill="blue" filter="url(#blurFilter)" />
</svg>
</body>
</html>
效果: