在HTML5出现之前,想在网页里画一个简单图形并不轻松。有人用十几个div拼出三角形,有人依赖Flash插件,还有人在IE里写VML、在其他浏览器里写SVG,代码里到处是兼容性判断。HTML5引入的canvas元素彻底改变了这个局面,它提供了一个像素级的画布,配合JavaScript就能绘制任意图形。本文将围绕如何用canvas替代传统绘制方法展开,从基本流程讲到具体图形绘制,最后聊聊交互和性能方面的经验。

一、传统HTML绘图方式有哪些局限
早期的网页绘图手段主要有三类。第一类是利用CSS配合div模拟图形,比如用border技巧画三角形、用圆角属性画圆形。这种方式实现简单图形还可以,一旦涉及曲线组合、动态重绘,DOM节点数量会迅速膨胀,浏览器渲染负担也随之加重。
第二类是VML和SVG。VML是微软推出的矢量标记语言,只在IE浏览器中得到支持;SVG虽然标准一些,但在老旧浏览器上同样存在兼容问题。两套语法并存意味着开发者要写两份代码,维护成本翻倍。
第三类是Flash等插件方案。它功能强大,但依赖插件安装,移动端基本无法使用,而且插件崩溃、安全漏洞频发,最终被各大浏览器弃用。相比之下,canvas是浏览器原生支持的能力,不需要任何插件,一次编写即可在所有现代浏览器中运行,这正是替代传统方案的核心理由。
二、canvas绘图的基本流程与坐标体系
使用canvas绘图的第一步是在页面中放置一个<canvas>元素,并通过width和height属性指定画布尺寸。需要注意的是,直接用CSS设置宽高会导致画布被拉伸,图形变得模糊,这是新手最常踩的坑。正确的做法是写在标签属性里,或者在JavaScript中通过canvas.width赋值。
canvas采用二维直角坐标系,原点位于画布左上角,x轴向右延伸,y轴向下延伸,单位是像素。所有绘制操作都基于这套坐标系,理解它之后绘制复杂图形就有了基准。
绘制的一般流程分为四步:获取canvas元素、取得绘图上下文、设置绘图状态(颜色、线宽等)、调用绘图方法。下面是标准写法:
<canvas id="myCanvas" width="600" height="400">
您的浏览器不支持canvas,请升级浏览器。
</canvas>
<script>
// 第一步:获取画布元素
var canvas = document.getElementById('myCanvas');
// 第二步:获取二维绘图上下文
var ctx = canvas.getContext('2d');
// 第三步:设置填充颜色
ctx.fillStyle = '#4A90D9';
// 第四步:绘制一个矩形
ctx.fillRect(50, 50, 200, 120);
</script>其中getContext('2d')返回的上下文对象是所有绘图API的入口。除了2d,还有webgl用于三维渲染,本文聚焦二维场景。
三、常见图形的绘制方法与代码示例
1. 绘制矩形
矩形是最基础的图形,canvas提供了三个方法:fillRect绘制实心矩形,strokeRect绘制空心矩形,clearRect清除指定区域的像素。三个方法的参数依次为x、y、宽、高。
var ctx = document.getElementById('myCanvas').getContext('2d');
ctx.fillStyle = 'tomato';
ctx.fillRect(30, 30, 150, 100); // 实心矩形
ctx.strokeStyle = '#333';
ctx.lineWidth = 3;
ctx.strokeRect(30, 30, 150, 100); // 空心边框
ctx.clearRect(60, 60, 60, 40); // 在矩形中间挖一个透明洞2. 绘制路径与直线
更复杂的形状需要通过路径来完成。基本套路是beginPath开始新路径,用moveTo定位起点,用lineTo画线段,最后调用closePath闭合,再用fill或stroke上色。三角形可以这样画:
ctx.beginPath(); ctx.moveTo(300, 50); // 顶点 ctx.lineTo(250, 150); // 左下角 ctx.lineTo(350, 150); // 右下角 ctx.closePath(); // 自动闭合回顶点 ctx.fillStyle = 'seagreen'; ctx.fill();
3. 绘制圆形与圆弧
arc方法用于画圆和圆弧,参数依次为圆心x、圆心y、半径、起始角度、结束角度、是否逆时针。角度单位是弧度,一个完整圆就是0到2倍的Math.PI。
ctx.beginPath(); ctx.arc(480, 100, 60, 0, Math.PI * 2); // 完整的圆 ctx.fillStyle = 'gold'; ctx.fill(); ctx.beginPath(); ctx.arc(480, 100, 60, 0, Math.PI); // 下半圆弧 ctx.strokeStyle = 'darkorange'; ctx.lineWidth = 4; ctx.stroke();
4. 渐变与文字
渐变分线性渐变和径向渐变两种。以线性渐变为例,先创建渐变对象并添加色标,再赋值给fillStyle:
// 创建从左到右的线性渐变
var grad = ctx.createLinearGradient(0, 0, 600, 0);
grad.addColorStop(0, '#ff6b6b');
grad.addColorStop(1, '#4dabf7');
ctx.fillStyle = grad;
ctx.fillRect(0, 250, 600, 150);
// 绘制文字
ctx.fillStyle = '#fff';
ctx.font = 'bold 28px Microsoft YaHei';
ctx.textAlign = 'center';
ctx.fillText('HTML5 canvas 渐变效果', 300, 330);四、交互处理与性能优化建议
canvas本身是一块像素画布,画上去的图形不会成为DOM节点,因此无法直接给某个图形绑定点击事件。交互的通用做法是监听canvas的鼠标事件,通过getBoundingClientRect换算出画布内坐标,再判断该坐标落在哪个图形区域内。圆形判断只需计算点到圆心的距离是否小于半径,矩形判断更简单,直接比较边界即可。
canvas.addEventListener('click', function (e) {
var rect = canvas.getBoundingClientRect();
// 换算成画布内部坐标,注意canvas绘制尺寸与CSS显示尺寸可能不同
var x = (e.clientX - rect.left) * (canvas.width / rect.width);
var y = (e.clientY - rect.top) * (canvas.height / rect.height);
var dx = x - 480, dy = y - 100;
if (Math.sqrt(dx * dx + dy * dy) <= 60) {
alert('你点击了圆形');
}
});性能方面有几点值得注意。第一,canvas绘制不会自动清空,做动画时每帧开始前要调用clearRect清屏,否则图形会叠加残留。第二,频繁绘制静态背景是浪费,可以把静态部分画到一个离屏canvas上,主循环里用drawImage整体拷贝,速度远快于逐个重绘。第三,高分辨率屏幕上建议按设备像素比放大画布再缩小CSS尺寸,否则图形会发虚。
总结一下,用canvas替代传统绘图方法的核心优势在于:原生支持零依赖、像素级控制自由度高、绘制复杂图形不增加DOM负担、配合requestAnimationFrame可轻松实现流畅动画。把过去div拼图、双份VML和SVG代码的包袱丢掉,几行JavaScript就能搞定大部分网页图形需求,这也是HTML5给前端开发者带来的实实在在的便利。
canvas绘图HTML5JavaScript图形绘制修改时间:2026-09-09 01:28:47