文章目录
- HTML5 Canvas基础
HTML5 Canvas基础
HTML5 Canvas是HTML5新增的核心元素之一,它提供了一块“画布”,允许通过JavaScript在网页上动态绘制图形、文字、图像甚至动画。从简单的几何图形到复杂的游戏场景、数据可视化图表,Canvas都能胜任。本文从零基础角度,详解Canvas的核心概念、绘图API、实战案例及注意事项,帮你快速掌握“网页绘图”的核心技能。
一、Canvas是什么?为什么需要它?
- 定义:Canvas是一个HTML元素(
<canvas>),本质是一块“像素画布”,通过JavaScript的Canvas API可以直接操作像素,实现动态绘图。 - 特点:
- 像素级控制:直接操作画布上的每个像素,灵活性极高;
- 动态交互:可通过JavaScript响应用户操作(如鼠标、键盘),实时更新图形;
- 轻量高效:相比图片或SVG,Canvas绘制的图形更省资源,适合动态场景(如动画、游戏)。
- 应用场景:网页游戏、数据可视化(图表)、图像编辑工具、电子签名板、实时视频处理等。
二、Canvas基本结构:创建你的第一块画布
使用Canvas的第一步是在HTML中定义<canvas>元素,然后通过JavaScript获取“绘图上下文”(context)——这是所有绘图操作的入口。
1. 基本HTML结构
<!-- 定义Canvas元素:width和height是画布的像素尺寸(必须在标签内设置,而非CSS) -->
<canvas id="myCanvas" width="600" height="400" style="border: 1px solid #000;">
<!-- 浏览器不支持Canvas时显示的替代文本 -->
您的浏览器不支持Canvas元素,请升级浏览器。
</canvas>
关键说明:
width和height:定义画布的实际像素尺寸(默认300x150),必须在<canvas>标签内设置(若通过CSS设置,会导致图形拉伸变形);border:仅用于可视化画布边界(非必需);- 替代文本:当浏览器不支持Canvas时显示,提升兼容性。
2. 获取绘图上下文(核心步骤)
Canvas本身只是一块“空白画布”,所有绘图操作都需通过“2D渲染上下文”(CanvasRenderingContext2D)完成。通过JavaScript获取上下文:
<canvas id="myCanvas" width="600" height="400"></canvas>
<script>
// 1. 获取Canvas元素
const canvas = document.getElementById("myCanvas");
// 2. 获取2D绘图上下文(核心对象,所有绘图API都在这个对象上)
const ctx = canvas.getContext("2d");
// 现在可以通过ctx调用绘图方法了
</script>
getContext("2d"):返回2D绘图上下文,支持2D图形绘制(本文重点);- 若要绘制3D图形,需使用
getContext("webgl")(WebGL,基于OpenGL ES,适合3D场景)。
三、核心绘图API:从基础图形到路径
Canvas的绘图核心是“路径(path)”——通过一系列点连接形成的线条或形状,再通过“描边(stroke)”或“填充(fill)”使其可见。
1. 绘制直线
直线是最基础的图形,通过moveTo()(起点)和lineTo()(终点)定义路径,再用stroke()描边。
// 绘制一条从(50,50)到(300,50)的直线
ctx.beginPath(); // 开始一条新路径(必须调用,避免与之前的路径混淆)
ctx.moveTo(50, 50); // 移动画笔到起点(50,50)(x坐标, y坐标)
ctx.lineTo(300, 50); // 从起点绘制直线到终点(300,50)
ctx.stroke(); // 描边路径(让直线可见)
坐标系统:Canvas的坐标原点(0,0)在左上角,x轴向右递增,y轴向下递增(与数学坐标系的y轴方向相反)。
2. 绘制矩形
矩形是少数不需要路径即可直接绘制的图形,提供了3个专用方法:
| 方法 | 作用 | 示例 |
|---|---|---|
strokeRect(x,y,w,h) | 描边矩形(空心) | ctx.strokeRect(50,100,200,100) |
fillRect(x,y,w,h) | 填充矩形(实心) | ctx.fillRect(50,100,200,100) |
clearRect(x,y,w,h) | 清除矩形区域(变为透明) | ctx.clearRect(80,130,140,40) |
x,y:矩形左上角坐标;w,h:宽度和高度。
示例:绘制带镂空的矩形
// 绘制实心矩形
ctx.fillStyle = "lightblue"; // 设置填充颜色
ctx.fillRect(50, 100, 200, 100);
// 清除中间部分(镂空效果)
ctx.clearRect(80, 130, 140, 40);
// 绘制矩形边框(描边)
ctx.strokeStyle = "blue"; // 设置描边颜色
ctx.lineWidth = 3; // 设置线条宽度(默认1px)
ctx.strokeRect(50, 100, 200, 100);
3. 绘制圆形与弧线
圆形通过arc()方法定义,属于路径的一种,需配合beginPath()和stroke()/fill()使用。
arc()语法:
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);
x,y:圆心坐标;radius:半径;startAngle/endAngle:起始/结束角度(弧度制,0为x轴正方向,π为180°,2π为360°);anticlockwise:是否逆时针绘制(true为逆时针,false为顺时针)。
示例:绘制实心圆和空心圆
// 1. 绘制实心圆
ctx.beginPath();
ctx.arc(150, 300, 50, 0, 2 * Math.PI); // 0到2π弧度(完整圆形)
ctx.fillStyle = "red"; // 填充颜色
ctx.fill(); // 填充路径
// 2. 绘制空心圆(同心圆)
ctx.beginPath(); // 必须重新开始路径,否则会与前一个圆连接
ctx.arc(150, 300, 70, 0, 2 * Math.PI);
ctx.strokeStyle = "green"; // 描边颜色
ctx.lineWidth = 4; // 线条宽度
ctx.stroke(); // 描边路径
4. 绘制任意路径(多边形)
通过lineTo()连续定义线段,配合closePath()闭合路径,可绘制三角形、多边形等任意形状。
示例:绘制三角形
ctx.beginPath();
// 定义三角形的三个顶点
ctx.moveTo(350, 100); // 顶点1
ctx.lineTo(450, 200); // 顶点2(从顶点1连线到顶点2)
ctx.lineTo(250, 200); // 顶点3(从顶点2连线到顶点3)
ctx.closePath(); // 闭合路径(从顶点3连线回顶点1)
// 填充与描边
ctx.fillStyle = "yellow";
ctx.fill();
ctx.strokeStyle = "orange";
ctx.lineWidth = 2;
ctx.stroke();
四、样式与特效:让图形更丰富
Canvas提供了多种样式设置,包括颜色、渐变、阴影等,让图形更具视觉效果。
1. 颜色设置
fillStyle:设置填充颜色(适用于fill()、fillRect()等);strokeStyle:设置描边颜色(适用于stroke()、strokeRect()等)。
颜色值支持多种格式:
ctx.fillStyle = "red"; // 颜色名
ctx.fillStyle = "#ff0000"; // 十六进制
ctx.fillStyle = "rgb(255, 0, 0)"; // RGB值
ctx.fillStyle = "rgba(255, 0, 0, 0.5)"; // RGBA(最后一位是透明度,0-1)
2. 线条样式
lineWidth:线条宽度(像素);lineCap:线条端点样式(butt默认、round圆形、square方形);lineJoin:线条拐角样式(miter默认、round圆角、bevel斜角)。
示例:线条样式对比
// 线条1:默认样式
ctx.beginPath();
ctx.moveTo(50, 350);
ctx.lineTo(200, 350);
ctx.lineWidth = 10;
ctx.stroke();
// 线条2:圆形端点+圆角拐角
ctx.beginPath();
ctx.moveTo(250, 350);
ctx.lineTo(350, 350);
ctx.lineTo(350, 400);
ctx.lineWidth = 10;
ctx.lineCap = "round"; // 端点圆形
ctx.lineJoin = "round"; // 拐角圆角
ctx.stroke();
3. 渐变效果
Canvas支持线性渐变和径向渐变,通过createLinearGradient()和createRadialGradient()创建,再用addColorStop()添加颜色节点。
(1)线性渐变
从一个点到另一个点的颜色过渡:
// 创建线性渐变(x0,y0:起点;x1,y1:终点)
const linearGrad = ctx.createLinearGradient(400, 100, 550, 250);
// 添加颜色节点(位置0-1,0是起点,1是终点)
linearGrad.addColorStop(0, "pink"); // 起点颜色
linearGrad.addColorStop(0.5, "purple"); // 中间颜色
linearGrad.addColorStop(1, "blue"); // 终点颜色
// 用渐变填充矩形
ctx.fillStyle = linearGrad;
ctx.fillRect(400, 100, 150, 150);
(2)径向渐变
从一个圆到另一个圆的颜色过渡:
// 创建径向渐变(x0,y0,r0:内圆;x1,y1,r1:外圆)
const radialGrad = ctx.createRadialGradient(500, 300, 10, 500, 300, 80);
// 添加颜色节点
radialGrad.addColorStop(0, "yellow"); // 内圆颜色
radialGrad.addColorStop(1, "orange"); // 外圆颜色
// 用渐变填充圆形
ctx.beginPath();
ctx.arc(500, 300, 80, 0, 2 * Math.PI);
ctx.fillStyle = radialGrad;
ctx.fill();
4. 阴影效果
通过设置阴影属性,为图形添加阴影:
// 阴影设置(需在绘制图形前定义)
ctx.shadowColor = "rgba(0,0,0,0.5)"; // 阴影颜色(半透明黑色)
ctx.shadowBlur = 10; // 阴影模糊程度(值越大越模糊)
ctx.shadowOffsetX = 5; // 阴影水平偏移
ctx.shadowOffsetY = 5; // 阴影垂直偏移
// 绘制带阴影的矩形
ctx.fillStyle = "lightgreen";
ctx.fillRect(350, 300, 150, 100);
// 重置阴影(避免影响后续图形)
ctx.shadowColor = "transparent";
五、文本绘制:在画布上写字
Canvas支持绘制文本,通过fillText()(填充文本)和strokeText()(描边文本)实现,配合字体样式设置,可控制文本的大小、字体等。
1. 基本文本绘制
// 填充文本(实心文字)
ctx.font = "30px SimHei"; // 设置字体(大小 字体名,需先设置)
ctx.fillStyle = "darkblue";
ctx.fillText("Hello Canvas!", 50, 450); // 文本内容,x,y(文本基线位置)
// 描边文本(空心文字)
ctx.font = "24px Arial";
ctx.strokeStyle = "red";
ctx.strokeText("HTML5 绘图", 300, 450);
2. 文本对齐与基线
textAlign:水平对齐方式(start默认、center居中、end右对齐);textBaseline:垂直基线(alphabetic默认、middle居中、top顶部)。
示例:居中对齐文本
// 绘制一个矩形作为参考
ctx.strokeRect(50, 500, 200, 50);
// 文本水平居中(相对于矩形中心)
ctx.font = "20px SimHei";
ctx.textAlign = "center"; // 水平居中
ctx.textBaseline = "middle"; // 垂直居中
ctx.fillText("居中对齐", 50 + 100, 500 + 25); // 矩形中心坐标
六、图像绘制:在画布上插入图片
通过drawImage()方法,可在Canvas上绘制外部图片(本地或网络图片),支持缩放、裁剪等操作。
1. 基本图像绘制
// 创建Image对象
const img = new Image();
// 设置图片源(网络图片需注意跨域问题,本地图片无限制)
img.src = "image.jpg"; // 替换为实际图片路径
// 图片加载完成后绘制(必须在onload中,否则图片未加载会绘制失败)
img.onload = function() {
// 绘制图片(x,y:绘制位置;可选参数:width,height:绘制尺寸,用于缩放)
ctx.drawImage(img, 350, 500, 150, 100); // 缩放到150x100像素
};
2. 图片裁剪(从大图中截取部分)
drawImage()支持裁剪模式,语法:
ctx.drawImage(img,
sx, sy, sWidth, sHeight, // 源图片裁剪区域(sx,sy:裁剪起点;sWidth,sHeight:裁剪尺寸)
dx, dy, dWidth, dHeight // 目标画布绘制区域(dx,dy:绘制起点;dWidth,dHeight:绘制尺寸)
);
示例:裁剪图片的一部分并绘制
img.onload = function() {
// 从源图片(50,50)位置裁剪100x100的区域,绘制到画布(350,500)位置,缩放为150x150
ctx.drawImage(img, 50, 50, 100, 100, 350, 500, 150, 150);
};
七、动画基础:让图形“动”起来
Canvas动画的核心是“连续重绘”——通过定时器或帧动画API,不断清除画布并重新绘制图形,形成动画效果。
1. 用requestAnimationFrame实现动画
requestAnimationFrame是浏览器提供的专门用于动画的API,会根据浏览器刷新率自动调整帧率(通常60帧/秒),比setInterval更流畅。
示例:移动的小球
// 小球初始位置和速度
let x = 50; // x坐标
let y = 100; // y坐标
let dx = 2; // x方向速度(每帧移动2px)
let dy = 2; // y方向速度
const radius = 20; // 半径
// 动画函数
function animate() {
// 1. 清除画布(每次重绘前清除上一帧)
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 2. 绘制小球
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.fillStyle = "blue";
ctx.fill();
// 3. 边界检测(碰到画布边缘反弹)
if (x + radius > canvas.width || x - radius < 0) {
dx = -dx; // x方向反转
}
if (y + radius > canvas.height || y - radius < 0) {
dy = -dy; // y方向反转
}
// 4. 更新位置
x += dx;
y += dy;
// 5. 请求下一帧动画
requestAnimationFrame(animate);
}
// 启动动画
animate();
八、注意事项与最佳实践
-
坐标系统:牢记Canvas左上角为(0,0),y轴向下递增(与数学坐标系不同,容易混淆)。
-
路径管理:每次绘制新图形前,务必用
beginPath()开始新路径,否则新路径会与旧路径连接,导致描边/填充异常。 -
清除画布:动画或动态更新图形时,需用
clearRect(0,0,width,height)清除整个画布(或局部区域),避免上一帧残留。 -
图片加载:绘制图片必须在
img.onload回调中执行,确保图片加载完成,否则会绘制空白。 -
性能优化:
- 避免频繁重绘(如复杂动画控制帧率);
- 大尺寸画布可分区域绘制,只更新变化的部分;
- 避免在动画循环中执行复杂计算(提前计算好参数)。
-
兼容性:几乎所有现代浏览器(Chrome、Firefox、Edge、Safari)都支持Canvas,但旧版本IE(IE8及以下)不支持,需提供替代方案。
九、总结
HTML5 Canvas是网页动态绘图的核心工具,通过<canvas>元素和CanvasRenderingContext2D API,可实现从简单图形到复杂动画的全场景绘制。核心知识点包括:
- 画布初始化与上下文获取;
- 基础图形(直线、矩形、圆形、路径)的绘制;
- 样式设置(颜色、渐变、阴影、文本);
- 图像绘制与裁剪;
- 动画实现(连续重绘与帧更新)。
学习Canvas的关键是“多动手实践”:从绘制简单图形开始,逐步尝试组合图形、添加样式,最终实现交互动画(如鼠标控制图形移动)。掌握Canvas后,你可以开发签名板、简易游戏、数据可视化图表等有趣的应用,为网页增添丰富的动态效果。

1508

被折叠的 条评论
为什么被折叠?



