Canvas是HTML5引入的一个用于动态绘制图形的元素,配合JavaScript API可创建图表、游戏图形、数据可视化等。本文将系统地总结Canvas的关键知识点,包括基本绘图、路径、曲线、文本、图像、变换、状态管理、渐变、模式、动画及性能优化,并提供可直接运行的代码示例。
一、Canvas基础与绘图上下文
在HTML中声明Canvas元素时,需指定宽高并通过JavaScript获取2D上下文:- <canvas id="myCanvas" width="500" height="400">您的浏览器不支持canvas元素。</canvas>
- <script>
- var canvas = document.getElementById('myCanvas');
- var ctx = canvas.getContext('2d');
- </script>
复制代码
二、矩形绘制
Canvas提供三种矩形方法:
- fillRect(x, y, w, h):绘制填充矩形。
- strokeRect(x, y, w, h):绘制矩形边框。
- clearRect(x, y, w, h):清除指定区域使其透明。
示例:- ctx.fillStyle = 'green';
- ctx.fillRect(10, 10, 100, 100);
- ctx.strokeStyle = 'blue';
- ctx.lineWidth = 5;
- ctx.strokeRect(120, 10, 100, 100);
- ctx.clearRect(50, 50, 60, 60);
复制代码
三、路径绘制
路径绘制需遵循以下步骤:beginPath()开始新路径,moveTo()移动画笔,lineTo()绘制线段,closePath()闭合路径,最后用fill()或stroke()填充/描边。例如绘制一个矩形边框:- ctx.beginPath();
- ctx.moveTo(50, 50);
- ctx.lineTo(200, 50);
- ctx.lineTo(200, 200);
- ctx.lineTo(50, 200);
- ctx.closePath();
- ctx.stroke();
复制代码
四、贝塞尔曲线与弧线
1)二次贝塞尔曲线:quadraticCurveTo(cpx, cpy, x, y),一个控制点。
2)三次贝塞尔曲线:bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y),两个控制点。
3)弧线:arc(x, y, radius, startAngle, endAngle, anticlockwise),角度用弧度表示。绘制完整圆:- ctx.beginPath();
- ctx.arc(150, 150, 75, 0, Math.PI * 2, true);
- ctx.stroke();
复制代码
五、文本绘制
两种方法:fillText(text, x, y, maxWidth)填充文本,strokeText(text, x, y, maxWidth)描边文本。可通过font、fillStyle、strokeStyle设置样式:- ctx.font = '30px Arial';
- ctx.fillStyle = 'black';
- ctx.fillText('Hello, Canvas!', 50, 50);
- ctx.strokeStyle = 'red';
- ctx.strokeText('Hello, Canvas!', 50, 100);
复制代码
六、图像绘制
drawImage方法有三种重载:
- drawImage(img, dx, dy) 在指定位置绘制完整图像。
- drawImage(img, dx, dy, dWidth, dHeight) 缩放到指定尺寸。
- drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) 截取源图像部分区域绘制。
注意图像需onload后才可绘制:- var img = new Image();
- img.onload = function() {
- ctx.drawImage(img, 10, 10);
- ctx.drawImage(img, 10, 150, 100, 100);
- ctx.drawImage(img, 50, 50, 100, 100, 150, 150, 100, 100);
- };
- img.src = 'path/to/image.jpg';
复制代码
七、变换操作
1)平移:translate(x, y)移动原点。
2)旋转:rotate(angle)按弧度旋转。
3)缩放:scale(x, y)按倍数缩放。变换影响后续所有绘制,常与save/restore配合使用。- ctx.translate(50, 50);
- ctx.fillRect(0, 0, 100, 100); // 实际绘制在(50,50)位置
- ctx.rotate(Math.PI / 4);
- ctx.fillRect(0, 0, 100, 100); // 旋转后矩形
复制代码
八、状态保存与恢复
save()保存当前状态(变换、裁剪、样式等),restore()恢复上一次保存的状态。适合做复杂变换而不影响后续绘制。
九、渐变与模式
1)线性渐变:createLinearGradient(x0,y0,x1,y1),addColorStop(offset, color)添加色标。
2)径向渐变:createRadialGradient(x0,y0,r0,x1,y1,r1),同理。
3)模式:createPattern(image, repetition)创建重复图案,repetition可为'repeat'/'repeat-x'/'repeat-y'/'no-repeat'。- var linearGradient = ctx.createLinearGradient(0, 0, 200, 0);
- linearGradient.addColorStop(0, 'red');
- linearGradient.addColorStop(1, 'blue');
- ctx.fillStyle = linearGradient;
- ctx.fillRect(10, 10, 200, 100);
- var radialGradient = ctx.createRadialGradient(100, 100, 20, 100, 100, 100);
- radialGradient.addColorStop(0, 'white');
- radialGradient.addColorStop(1, 'black');
- ctx.fillStyle = radialGradient;
- ctx.fillRect(50, 50, 200, 200);
- var img = new Image();
- img.onload = function() {
- var pattern = ctx.createPattern(img, 'repeat');
- ctx.fillStyle = pattern;
- ctx.fillRect(10, 10, 200, 100);
- };
- img.src = 'path/to/image.jpg';
复制代码
十、动画实现
推荐使用requestAnimationFrame代替setTimeout/setInterval,它会在浏览器重绘时调用,节省资源且后台标签页自动暂停。典型的动画循环:- var x = 0;
- function draw() {
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.fillRect(x, 50, 50, 50);
- x += 2;
- requestAnimationFrame(draw);
- }
- draw();
复制代码
十一、性能优化
1)使用requestAnimationFrame而不是定时器,减少不必要的CPU消耗。
2)合并绘图操作,避免频繁清除和重绘。
3)利用离屏Canvas预渲染复杂图形:创建临时canvas并绘制,再用drawImage一次性绘制到主Canvas上。- var offscreenCanvas = document.createElement('canvas');
- var offscreenCtx = offscreenCanvas.getContext('2d');
- offscreenCanvas.width = 500;
- offscreenCanvas.height = 400;
- offscreenCtx.fillStyle = 'green';
- offscreenCtx.fillRect(0, 0, 100, 100);
- ctx.drawImage(offscreenCanvas, 0, 0);
复制代码
总结上述知识点,Canvas为前端图形开发提供了丰富而灵活的API,掌握这些基础操作、变换、动画及优化技巧,可以有效构建高性能的网页图形应用。 |