canvas 基础绘图与性能优化技巧

Canvas 是 HTML5 提供的一个强大的绘图 API,它允许开发者通过 JavaScript 在网页上绘制图形、动画和游戏等。本文将介绍 Canvas 的基础绘图功能,并分享一些性能优化的实用技巧。

一、Canvas 基础绘图

1. 初始化 Canvas

首先需要在 HTML 中创建 canvas 元素:

html 复制代码
<canvas id="myCanvas" width="800" height="600"></canvas>

然后通过 JavaScript 获取上下文:

javascript 复制代码
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

2. 基本绘图方法

绘制矩形

javascript 复制代码
// 填充矩形
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 100, 50);

// 描边矩形
ctx.strokeStyle = 'blue';
ctx.lineWidth = 2;
ctx.strokeRect(150, 10, 100, 50);

绘制路径

javascript 复制代码
ctx.beginPath();
ctx.moveTo(50, 50);    // 起点
ctx.lineTo(150, 50);   // 第一条线
ctx.lineTo(100, 150);  // 第二条线
ctx.closePath();       // 闭合路径
ctx.stroke();          // 描边

绘制圆形/圆弧

javascript 复制代码
ctx.beginPath();
ctx.arc(200, 200, 50, 0, Math.PI * 2); // 圆心(x,y), 半径, 起始角, 结束角
ctx.fillStyle = 'green';
ctx.fill();

3. 文本绘制

javascript 复制代码
ctx.font = '30px Arial';
ctx.fillStyle = 'black';
ctx.fillText('Hello Canvas', 50, 300);

ctx.strokeStyle = 'purple';
ctx.strokeText('Stroke Text', 50, 350);

二、性能优化技巧

1. 减少绘制操作

Canvas 性能的关键在于减少绘制操作:

  • 合并相似的绘制操作
  • 避免在动画循环中频繁创建路径
  • 使用 requestAnimationFrame 替代 setIntervalsetTimeout

2. 分层 Canvas

对于复杂场景,可以使用多个叠加的 canvas 元素:

html 复制代码
<div class="canvas-container">
  <canvas id="bgCanvas" width="800" height="600"></canvas>
  <canvas id="gameCanvas" width="800" height="600"></canvas>
  <canvas id="uiCanvas" width="800" height="600"></canvas>
</div>

这样可以将静态背景、动态游戏元素和UI界面分开绘制,避免不必要的重绘。

3. 离屏 Canvas

对于需要重复绘制的复杂图形,可以使用离屏 Canvas:

javascript 复制代码
// 创建离屏canvas
const offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = 100;
offscreenCanvas.height = 100;
const offscreenCtx = offscreenCanvas.getContext('2d');

// 在离屏canvas上绘制复杂图形
drawComplexGraphic(offscreenCtx);

// 在主canvas上绘制离屏内容
ctx.drawImage(offscreenCanvas, 0, 0);

4. 合理使用 clearRect

避免清除整个画布,只清除需要更新的区域:

javascript 复制代码
// 不好 - 清除整个画布
ctx.clearRect(0, 0, canvas.width, canvas.height);

// 更好 - 只清除需要更新的区域
ctx.clearRect(x, y, width, height);

5. 优化图像绘制

  • 预加载所有图像资源
  • 使用合适的图像尺寸(不要绘制大图然后缩小)
  • 对于重复的图像,使用 createPattern 方法
javascript 复制代码
const img = new Image();
img.onload = function() {
  const pattern = ctx.createPattern(img, 'repeat');
  ctx.fillStyle = pattern;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
};
img.src = 'texture.png';

6. 减少状态改变

Canvas 的状态改变(如样式、变换等)是昂贵的操作:

javascript 复制代码
// 不好 - 频繁改变状态
for (let i = 0; i < 100; i++) {
  ctx.fillStyle = colors[i];
  ctx.fillRect(x[i], y[i], 10, 10);
}

// 更好 - 按状态分组绘制
ctx.fillStyle = 'red';
for (let i = 0; i < redItems.length; i++) {
  ctx.fillRect(redItems[i].x, redItems[i].y, 10, 10);
}

ctx.fillStyle = 'blue';
for (let i = 0; i < blueItems.length; i++) {
  ctx.fillRect(blueItems[i].x, blueItems[i].y, 10, 10);
}

三、高级技巧

1. 使用 WebGL

对于需要3D或更复杂图形的应用,可以考虑使用 WebGL(通过 canvas.getContext('webgl'))。

2. 硬件加速

确保浏览器启用了硬件加速,可以通过 CSS 开启:

css 复制代码
canvas {
  transform: translateZ(0);
}

3. 性能监控

使用 performance.now() 来测量绘制时间:

javascript 复制代码
const start = performance.now();
// 绘制操作
const duration = performance.now() - start;
console.log(`绘制耗时: ${duration}ms`);

结语

Canvas 提供了强大的绘图能力,但要实现高性能的绘图应用需要掌握这些优化技巧。通过减少绘制操作、合理分层、使用离屏渲染等方法,可以显著提升 Canvas 应用的性能表现。在实际开发中,应根据具体场景选择合适的优化策略。