1. Canvas简介
1.1 什么是Canvas
HTML5 Canvas是一个HTML元素,提供了一个通过JavaScript进行2D绘图的画布。它是一个基于像素的绘图API,允许开发者创建动态图形、动画、游戏和数据可视化应用。
<canvas id="myCanvas" width="800" height="600"></canvas>
1.2 Canvas的特点
- 基于像素的绘图:直接操作像素数据
- 即时模式:绘制后无法直接修改已绘制的内容
- 高性能:硬件加速支持
- 跨平台:所有现代浏览器都支持
- 灵活性:可以绘制任意形状和效果
1.3 Canvas vs SVG
特性 | Canvas | SVG |
---|---|---|
绘图方式 | 基于像素(位图) | 基于矢量 |
DOM集成 | 单个元素 | 每个图形都是DOM元素 |
交互性 | 需要手动实现 | 内置事件支持 |
性能 | 适合复杂动画 | 适合静态图形 |
可缩放性 | 像素化 | 无损缩放 |
2. 环境搭建
2.1 基础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>
canvas {
border: 1px solid #ccc;
display: block;
margin: 20px auto;
}
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
}
</style>
</head>
<body>
<h1>Canvas绘图示例</h1>
<canvas id="canvas" width="800" height="600"></canvas>
<script src="script.js"></script>
</body>
</html>
2.2 获取Canvas上下文
// 获取canvas元素
const canvas = document.getElementById('canvas');
// 获取2D渲染上下文
const ctx = canvas.getContext('2d');
// 检查浏览器支持
if (!ctx) {
console.error('浏览器不支持Canvas');
}
2.3 Canvas坐标系统
Canvas使用左上角为原点(0,0)的坐标系统: - X轴:从左到右递增 - Y轴:从上到下递增
// 坐标系统示例
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 50, 50); // 左上角
ctx.fillRect(750, 0, 50, 50); // 右上角
ctx.fillRect(0, 550, 50, 50); // 左下角
ctx.fillRect(750, 550, 50, 50); // 右下角
3. 开发工具与调试
3.1 推荐的开发工具
代码编辑器
- Visual Studio Code
- WebStorm
- Sublime Text
浏览器开发者工具
- Chrome DevTools
- Firefox Developer Tools
- Safari Web Inspector
在线工具
- CodePen
- JSFiddle
- JSBin
3.2 调试技巧
// 1. 使用console.log调试
function drawCircle(x, y, radius) {
console.log(`绘制圆形: x=${x}, y=${y}, radius=${radius}`);
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fill();
}
// 2. 绘制辅助线
function drawGrid(step = 50) {
ctx.strokeStyle = '#e0e0e0';
ctx.lineWidth = 1;
// 垂直线
for (let x = 0; x <= canvas.width; x += step) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
// 水平线
for (let y = 0; y <= canvas.height; y += step) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
}
// 3. 显示坐标信息
canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
console.log(`鼠标坐标: (${x}, ${y})`);
});
4. 第一个Canvas程序
4.1 Hello Canvas
// 获取canvas和上下文
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// 设置背景色
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制文本
ctx.fillStyle = '#333';
ctx.font = '48px Arial';
ctx.textAlign = 'center';
ctx.fillText('Hello Canvas!', canvas.width / 2, canvas.height / 2);
// 绘制装饰性图形
ctx.strokeStyle = '#007acc';
ctx.lineWidth = 3;
ctx.strokeRect(50, 50, canvas.width - 100, canvas.height - 100);
4.2 基础图形绘制
// 清除画布
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
// 绘制矩形
function drawRectangles() {
// 填充矩形
ctx.fillStyle = 'red';
ctx.fillRect(50, 50, 100, 80);
// 描边矩形
ctx.strokeStyle = 'blue';
ctx.lineWidth = 2;
ctx.strokeRect(200, 50, 100, 80);
// 清除矩形区域
ctx.clearRect(75, 75, 50, 30);
}
// 绘制圆形
function drawCircles() {
// 填充圆
ctx.fillStyle = 'green';
ctx.beginPath();
ctx.arc(400, 90, 40, 0, Math.PI * 2);
ctx.fill();
// 描边圆
ctx.strokeStyle = 'purple';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(550, 90, 40, 0, Math.PI * 2);
ctx.stroke();
}
// 绘制线条
function drawLines() {
ctx.strokeStyle = 'orange';
ctx.lineWidth = 4;
ctx.beginPath();
ctx.moveTo(50, 200);
ctx.lineTo(200, 250);
ctx.lineTo(350, 200);
ctx.stroke();
}
// 执行绘制
clearCanvas();
drawRectangles();
drawCircles();
drawLines();
5. Canvas属性与方法概览
5.1 Canvas元素属性
// 画布尺寸
console.log('宽度:', canvas.width);
console.log('高度:', canvas.height);
// 设置画布尺寸
canvas.width = 1200;
canvas.height = 800;
// 获取画布数据URL
const dataURL = canvas.toDataURL('image/png');
console.log('画布数据:', dataURL);
5.2 上下文基础方法
// 状态保存与恢复
ctx.save(); // 保存当前状态
ctx.restore(); // 恢复之前保存的状态
// 变换方法
ctx.translate(x, y); // 平移
ctx.rotate(angle); // 旋转
ctx.scale(scaleX, scaleY); // 缩放
ctx.transform(a, b, c, d, e, f); // 变换矩阵
// 路径方法
ctx.beginPath(); // 开始新路径
ctx.closePath(); // 闭合路径
ctx.moveTo(x, y); // 移动到指定点
ctx.lineTo(x, y); // 画线到指定点
// 绘制方法
ctx.fill(); // 填充
ctx.stroke(); // 描边
ctx.clip(); // 裁剪
6. 常见问题与解决方案
6.1 模糊问题
// 问题:Canvas在高DPI屏幕上显示模糊
// 解决方案:设备像素比适配
function setupHighDPI(canvas) {
const ctx = canvas.getContext('2d');
const devicePixelRatio = window.devicePixelRatio || 1;
// 设置实际尺寸
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width * devicePixelRatio;
canvas.height = rect.height * devicePixelRatio;
// 缩放上下文
ctx.scale(devicePixelRatio, devicePixelRatio);
// 设置CSS尺寸
canvas.style.width = rect.width + 'px';
canvas.style.height = rect.height + 'px';
}
6.2 性能优化基础
// 1. 避免频繁的状态改变
function efficientDrawing() {
// 批量设置相同样式的图形
ctx.fillStyle = 'red';
for (let i = 0; i < 100; i++) {
ctx.fillRect(i * 10, 100, 8, 8);
}
}
// 2. 使用离屏Canvas
function createOffscreenCanvas() {
const offscreen = document.createElement('canvas');
offscreen.width = 200;
offscreen.height = 200;
const offCtx = offscreen.getContext('2d');
// 在离屏canvas上绘制复杂图形
offCtx.fillStyle = 'blue';
offCtx.fillRect(0, 0, 200, 200);
// 将离屏canvas绘制到主canvas
ctx.drawImage(offscreen, 100, 100);
}
7. 小结
本章介绍了Canvas的基础概念和环境搭建:
- Canvas基础:了解了Canvas的特点和应用场景
- 环境搭建:学会了如何创建Canvas元素和获取绘图上下文
- 坐标系统:掌握了Canvas的坐标系统
- 开发工具:了解了常用的开发和调试工具
- 第一个程序:创建了简单的Canvas绘图示例
- 常见问题:学习了模糊问题和性能优化的基础知识
下一章我们将深入学习Canvas的基本绘图API,包括矩形、圆形、线条等基础图形的绘制方法。
8. 练习题
- 创建一个800x600的Canvas,绘制一个居中的”Hello World”文本
- 绘制一个简单的房子图形(矩形+三角形屋顶)
- 实现一个鼠标跟随的小圆点效果
- 创建一个网格背景的Canvas画布
- 实现Canvas的高DPI适配