canvas 画布基础
HTML5 的 <canvas> 元素提供了一个可通过 JavaScript 绘制图形的画布。它可以用于绘制图表、游戏图形、数据可视化、图像处理等。本节将介绍 canvas 的基本概念、HTML 结构和 fallback 内容。
前置知识
阅读本节前,建议先了解:异步解码
基础概念
<canvas> 是 HTML5 引入的图形绘制元素。与 <img> 直接显示图片不同,<canvas> 本身只是一个空的矩形区域——所有图形内容都需要通过 JavaScript 的 Canvas API 来绘制。
canvas 提供了两种绘图上下文:2D Context(最常用,用于 2D 图形绘制)和 WebGL Context(用于 3D 图形)。本系列教程主要关注 2D Context。
语法
基本语法
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>canvas 基础</title>
</head>
<body>
<h1>canvas 基本语法</h1>
<!-- 最简单的 canvas -->
<canvas id="myCanvas" width="400" height="300">
您的浏览器不支持 canvas。
</canvas>
<hr>
<!-- 带样式的 canvas -->
<canvas id="styledCanvas"
width="600" height="400"
style="border: 1px solid #ccc; border-radius: 8px;">
您的浏览器不支持 canvas。
</canvas>
</body>
</html>详细说明
canvas 属性
| 属性 | 说明 | 示例 |
|---|---|---|
width | 画布宽度(像素) | width="400" |
height | 画布高度(像素) | height="300" |
canvas 尺寸的重要性
canvas 的 width 和 height 属性定义了绘图缓冲区的大小(即像素分辨率)。CSS 的 width/height 只影响 canvas 的显示尺寸,不改变缓冲区大小。如果 CSS 尺寸与属性尺寸不一致,图形会被缩放,可能导致模糊。
Fallback 内容
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>canvas Fallback</title>
</head>
<body>
<h1>canvas 回退内容</h1>
<canvas id="myCanvas" width="400" height="300">
<!--
canvas 标签内的内容只在浏览器不支持 canvas 时显示
支持 canvas 的浏览器会忽略这些内容
-->
<!-- 方式 1:纯文本提示 -->
您的浏览器不支持 canvas,请升级浏览器。
<!-- 方式 2:提供替代图片 -->
<!-- <img src="chart.png" alt="图表"> -->
<!-- 方式 3:提供下载链接 -->
<!-- <p>请 <a href="chrome.html">下载 Chrome</a></p> -->
</canvas>
<script>
// 检测浏览器是否支持 canvas
var canvas = document.getElementById('myCanvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#4285f4';
ctx.fillRect(50, 50, 300, 200);
ctx.fillStyle = '#fff';
ctx.font = '24px sans-serif';
ctx.fillText('Canvas 支持正常', 100, 160);
}
</script>
</body>
</html>canvas 尺寸 vs CSS 尺寸
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>canvas 尺寸</title>
<style>
.canvas-large {
/* CSS 尺寸:显示为 600x450 */
width: 600px;
height: 450px;
border: 2px solid #333;
}
</style>
</head>
<body>
<h1>canvas 尺寸 vs CSS 尺寸</h1>
<!--
属性尺寸:300x225 的绘图缓冲区
CSS 尺寸:600x450 的显示区域
结果:图形被放大 2 倍,可能模糊
-->
<canvas id="scaledCanvas"
class="canvas-large"
width="300" height="225">
不支持 canvas
</canvas>
<p>上面的 canvas 属性尺寸为 300x225,但 CSS 放大到了 600x450。</p>
<script>
var canvas = document.getElementById('scaledCanvas');
var ctx = canvas.getContext('2d');
// 绘制一个红色矩形
ctx.fillStyle = '#e74c3c';
ctx.fillRect(0, 0, 150, 112);
// 绘制一个蓝色矩形
ctx.fillStyle = '#3498db';
ctx.fillRect(150, 112, 150, 113);
// 文字会因放大而模糊
ctx.fillStyle = '#fff';
ctx.font = '14px sans-serif';
ctx.fillText('放大会模糊', 80, 120);
</script>
</body>
</html>2D 与 WebGL 上下文
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>canvas 上下文</title>
</head>
<body>
<h1>2D 与 WebGL 上下文</h1>
<!-- 2D 上下文画布 -->
<h2>2D Context</h2>
<canvas id="canvas2d" width="400" height="200"
style="border: 1px solid #ccc;"></canvas>
<br><br>
<!-- WebGL 上下文画布 -->
<h2>WebGL Context</h2>
<canvas id="canvasWebGL" width="400" height="200"
style="border: 1px solid #ccc;"></canvas>
<script>
// 获取 2D 上下文
var canvas2d = document.getElementById('canvas2d');
var ctx = canvas2d.getContext('2d');
ctx.fillStyle = '#2ecc71';
ctx.fillRect(0, 0, 400, 200);
ctx.fillStyle = '#fff';
ctx.font = '20px sans-serif';
ctx.fillText('2D Canvas', 150, 110);
// 获取 WebGL 上下文
var glCanvas = document.getElementById('canvasWebGL');
var gl = glCanvas.getContext('webgl');
if (gl) {
gl.clearColor(0.18, 0.52, 0.95, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
}
</script>
</body>
</html>实战示例
简单的 canvas 图形
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas 示例</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
text-align: center;
}
canvas {
border: 2px solid #ddd;
border-radius: 8px;
margin: 20px 0;
}
</style>
</head>
<body>
<h1>Canvas 图形绘制</h1>
<canvas id="demoCanvas" width="500" height="400">
您的浏览器不支持 canvas。
</canvas>
<script>
var canvas = document.getElementById('demoCanvas');
var ctx = canvas.getContext('2d');
// 背景
ctx.fillStyle = '#1a1a2e';
ctx.fillRect(0, 0, 500, 400);
// 蓝色矩形
ctx.fillStyle = '#4285f4';
ctx.fillRect(50, 50, 150, 100);
// 红色圆形
ctx.beginPath();
ctx.arc(350, 100, 50, 0, Math.PI * 2);
ctx.fillStyle = '#e74c3c';
ctx.fill();
// 绿色三角形
ctx.beginPath();
ctx.moveTo(250, 250);
ctx.lineTo(150, 380);
ctx.lineTo(350, 380);
ctx.closePath();
ctx.fillStyle = '#2ecc71';
ctx.fill();
// 文字
ctx.fillStyle = '#fff';
ctx.font = 'bold 20px sans-serif';
ctx.fillText('Canvas Demo', 170, 40);
</script>
</body>
</html>注意事项
- canvas 的
width/height属性定义绘图缓冲区,CSS 尺寸只影响显示 - canvas 标签内的文本是回退内容,仅在浏览器不支持时显示
- canvas 默认尺寸为 300x150 像素
- canvas 内容是像素数据,不会被搜索引擎索引
- canvas 不支持 DOM 事件绑定到绘制的内容上
- 高 DPI 屏幕需要手动处理像素比
最佳实践
- 始终设置 canvas 的
width/height属性 - 使用 CSS 控制显示尺寸,保持属性尺寸为实际像素大小
- 在 canvas 内提供回退内容
- 使用 JavaScript 检测
getContext支持情况 - 处理高 DPI 屏幕(使用
devicePixelRatio) - 对于简单的图形,考虑使用 SVG 替代
下一节
继续学习:canvas 绑定与上下文