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>

关键说明

  • widthheight:定义画布的实际像素尺寸(默认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();

八、注意事项与最佳实践

  1. 坐标系统:牢记Canvas左上角为(0,0),y轴向下递增(与数学坐标系不同,容易混淆)。

  2. 路径管理:每次绘制新图形前,务必用beginPath()开始新路径,否则新路径会与旧路径连接,导致描边/填充异常。

  3. 清除画布:动画或动态更新图形时,需用clearRect(0,0,width,height)清除整个画布(或局部区域),避免上一帧残留。

  4. 图片加载:绘制图片必须在img.onload回调中执行,确保图片加载完成,否则会绘制空白。

  5. 性能优化

    • 避免频繁重绘(如复杂动画控制帧率);
    • 大尺寸画布可分区域绘制,只更新变化的部分;
    • 避免在动画循环中执行复杂计算(提前计算好参数)。
  6. 兼容性:几乎所有现代浏览器(Chrome、Firefox、Edge、Safari)都支持Canvas,但旧版本IE(IE8及以下)不支持,需提供替代方案。

九、总结

HTML5 Canvas是网页动态绘图的核心工具,通过<canvas>元素和CanvasRenderingContext2D API,可实现从简单图形到复杂动画的全场景绘制。核心知识点包括:

  • 画布初始化与上下文获取;
  • 基础图形(直线、矩形、圆形、路径)的绘制;
  • 样式设置(颜色、渐变、阴影、文本);
  • 图像绘制与裁剪;
  • 动画实现(连续重绘与帧更新)。

学习Canvas的关键是“多动手实践”:从绘制简单图形开始,逐步尝试组合图形、添加样式,最终实现交互动画(如鼠标控制图形移动)。掌握Canvas后,你可以开发签名板、简易游戏、数据可视化图表等有趣的应用,为网页增添丰富的动态效果。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值