'<canvas>'标签的基本使用
<canvas>
是 HTML5 引入的一个强大元素,允许通过 JavaScript 动态绘制图形、动画和交互式内容。它提供了一种像素级的绘图方式,适用于游戏开发、数据可视化、图像处理等场景。
<canvas>
的基本语法
<canvas>
标签的语法非常简单,只需在 HTML 中声明即可:
<canvas id="myCanvas" width="500" height="300"></canvas>
id
属性用于在 JavaScript 中引用该元素。width
和height
属性定义画布的尺寸(单位为像素)。如果不设置,默认宽度为 300px,高度为 150px。
获取绘图上下文
要在 <canvas>
上绘图,必须先获取其绘图上下文(rendering context)。目前主要支持 2D 和 WebGL(3D)两种上下文。以下是获取 2D 上下文的示例:
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
getContext('2d')
返回一个 CanvasRenderingContext2D
对象,提供了丰富的绘图方法。
绘制基本形状
绘制矩形
CanvasRenderingContext2D
提供了三种绘制矩形的方法:
// 填充矩形(填充色由 fillStyle 决定)
ctx.fillStyle = 'blue';
ctx.fillRect(50, 50, 100, 75);
// 描边矩形(边框色由 strokeStyle 决定)
ctx.strokeStyle = 'red';
ctx.lineWidth = 3;
ctx.strokeRect(200, 50, 100, 75);
// 清除矩形区域(变为透明)
ctx.clearRect(80, 80, 40, 20);
绘制路径
路径可以绘制任意形状,基本步骤是:
- 调用
beginPath()
开始新路径 - 使用路径方法(如
moveTo()
,lineTo()
)绘制 - 调用
stroke()
或fill()
渲染
// 绘制三角形
ctx.beginPath();
ctx.moveTo(100, 100); // 起点
ctx.lineTo(150, 50); // 第二条边
ctx.lineTo(200, 100); // 第三条边
ctx.closePath(); // 闭合路径(可选)
ctx.stroke(); // 描边
// 绘制圆形
ctx.beginPath();
ctx.arc(300, 200, 50, 0, Math.PI * 2); // (x, y, 半径, 起始角, 结束角)
ctx.fillStyle = 'green';
ctx.fill();
样式和颜色
颜色设置
ctx.fillStyle = 'orange'; // 颜色名称
ctx.fillStyle = '#FFA500'; // 十六进制
ctx.fillStyle = 'rgb(255,165,0)'; // RGB
ctx.fillStyle = 'rgba(255,165,0,0.5)'; // 带透明度
线型样式
ctx.lineWidth = 5; // 线宽
ctx.lineCap = 'round'; // 线端样式(butt|round|square)
ctx.lineJoin = 'bevel'; // 转角样式(miter|round|bevel)
ctx.setLineDash([10, 5]); // 虚线模式(实线长度, 间隙长度)
绘制文本
ctx.font = '30px Arial'; // 字体样式
ctx.fillStyle = 'black';
ctx.fillText('Hello Canvas', 50, 50); // 填充文本
ctx.strokeStyle = 'blue';
ctx.strokeText('Hello Canvas', 50, 100); // 描边文本
文本对齐方式可以通过 textAlign
和 textBaseline
属性调整:
ctx.textAlign = 'center'; // left|right|center|start|end
ctx.textBaseline = 'middle'; // top|hanging|middle|alphabetic|ideographic|bottom
图像操作
绘制图像
const img = new Image();
img.src = 'example.jpg';
img.onload = function() {
// 绘制原始尺寸
ctx.drawImage(img, 50, 50);
// 缩放绘制
ctx.drawImage(img, 200, 50, 100, 80);
// 裁剪并绘制
ctx.drawImage(img,
10, 10, 100, 100, // 源图像裁剪区域 (sx, sy, sw, sh)
300, 50, 150, 150 // 画布绘制区域 (dx, dy, dw, dh)
);
};
像素操作
可以直接操作像素数据:
// 获取像素数据
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data; // Uint8ClampedArray
// 修改像素(RGBA格式)
for (let i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i]; // R
data[i+1] = 255 - data[i+1]; // G
data[i+2] = 255 - data[i+2]; // B
// Alpha通道保持不变
}
// 写回修改后的像素
ctx.putImageData(imageData, 0, 0);
变换和状态管理
坐标变换
ctx.translate(100, 100); // 移动原点
ctx.rotate(Math.PI / 4); // 旋转45度
ctx.scale(1.5, 1.5); // 缩放
// 绘制一个旋转的矩形
ctx.fillStyle = 'purple';
ctx.fillRect(0, 0, 50, 30);
保存和恢复状态
save()
和 restore()
方法可以保存/恢复当前的绘图状态(包括样式、变换等):
ctx.fillStyle = 'red';
ctx.save(); // 保存当前状态
ctx.fillStyle = 'blue';
ctx.translate(100, 100);
ctx.fillRect(0, 0, 50, 50); // 蓝色矩形
ctx.restore(); // 恢复之前的状态
ctx.fillRect(50, 50, 50, 50); // 红色矩形
动画实现
通过 requestAnimationFrame
可以实现流畅的动画效果:
let x = 0;
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'red';
ctx.fillRect(x, 100, 50, 50);
x += 2;
if (x > canvas.width) x = -50;
requestAnimationFrame(animate);
}
animate();
事件交互
<canvas>
本身是一个 DOM 元素,可以添加事件监听器:
canvas.addEventListener('click', function(event) {
const rect = canvas.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
ctx.beginPath();
ctx.arc(x, y, 10, 0, Math.PI * 2);
ctx.fillStyle = 'blue';
ctx.fill();
});
性能优化技巧
- 分层渲染:使用多个
<canvas>
叠加,将静态内容和动态内容分开 - 避免频繁状态改变:将相同样式的绘制操作集中处理
- 离屏渲染:先在内存中的 canvas 绘制复杂图形,再复制到主 canvas
- 合理使用
clearRect()
:只清除需要更新的区域
// 离屏渲染示例
const offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = 100;
offscreenCanvas.height = 100;
const offscreenCtx = offscreenCanvas.getContext('2d');
// 在离屏canvas上绘制复杂图形
offscreenCtx.beginPath();
offscreenCtx.arc(50, 50, 40, 0, Math.PI * 2);
offscreenCtx.fillStyle = 'rgba(255,0,0,0.5)';
offscreenCtx.fill();
// 复制到主canvas
ctx.drawImage(offscreenCanvas, 50, 50);
实际应用示例
绘制图表
// 简单柱状图
const data = [30, 60, 90, 40, 70];
const barWidth = 50;
const spacing = 20;
let x = 50;
ctx.fillStyle = 'steelblue';
data.forEach(value => {
const height = value * 2;
ctx.fillRect(x, canvas.height - height, barWidth, height);
x += barWidth + spacing;
});
// 添加坐标轴
ctx.beginPath();
ctx.moveTo(30, 30);
ctx.lineTo(30, canvas.height - 30);
ctx.lineTo(canvas.width - 30, canvas.height - 30);
ctx.strokeStyle = 'black';
ctx.stroke();
简单画板实现
<canvas id="drawingCanvas" width="600" height="400"></canvas>
<script>
const canvas = document.getElementById('drawingCanvas');
const ctx = canvas.getContext('2d');
let isDrawing = false;
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseout', stopDrawing);
function startDrawing(e) {
isDrawing = true;
draw(e);
}
function draw(e) {
if (!isDrawing) return;
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.strokeStyle = '#000';
ctx.lineTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(e.clientX - canvas.offsetLeft, e.clientY - canvas.offsetTop);
}
function stopDrawing() {
isDrawing = false;
ctx.beginPath();
}
</script>
浏览器兼容性注意事项
虽然现代浏览器都支持 <canvas>
,但需要注意:
- 始终提供后备内容:
<canvas>
<p>您的浏览器不支持Canvas,请升级浏览器</p>
</canvas>
-
IE9 以下版本不支持,可以使用 ExplorerCanvas 作为 polyfill
-
移动端需要注意触控事件和高分辨率屏幕适配:
// 处理高DPI屏幕
function setupCanvas(canvas) {
const dpr = window.devicePixelRatio || 1;
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
const ctx = canvas.getContext('2d');
ctx.scale(dpr, dpr);
return ctx;
}
const ctx = setupCanvas(document.getElementById('myCanvas'));
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:流媒体与自适应比特率技术