Canvas元素允许在页面上使用JavaScript绘制图形和动画
一、Canvas绘图四步曲
<canvas id="myCanvas" width="300" height="200"></canvas>
<script>
// 1. 获取Canvas元素
const canvas = document.getElementById('myCanvas');
// 2. 获取2D渲染上下文(相当于拿到画笔)
const ctx = canvas.getContext('2d');
// 3. 设置绘图样式
ctx.fillStyle = '#FF0000'; // 填充颜色
ctx.strokeStyle = '#00FF00'; // 边框颜色
ctx.lineWidth = 3; // 边框粗细
// 4. 绘制图形
ctx.fillRect(50, 50, 100, 100); // 填充矩形
ctx.strokeRect(50, 50, 100, 100);// 边框矩形
</script>
二、常见图形绘制API(表格速查)
| 图形 | 方法 | 示例代码 | 关键参数说明 |
|---|---|---|---|
| 矩形 | fillRect(x,y,w,h) | ctx.fillRect(10,10,100,50) | x,y起点坐标,w,h宽高 |
| 圆形 | arc(x,y,r,sAngle,eAngle) | ctx.arc(150,100,50,0, Math.PI*2) | 半径r,起始和结束弧度 |
| 直线 | lineTo(x,y) | ctx.moveTo(0,0); ctx.lineTo(200,100) | 需要先moveTo设置起点 |
| 文本 | fillText(text,x,y) | ctx.fillText('Hello', 50, 50) | 可设置font属性定义字体样式 |
| 路径 | beginPath() + closePath() | ctx.beginPath(); ...; ctx.closePath() | 清除旧路径,创建新路径 |
三、完整绘制流程示例(画笑脸)
<canvas id="face" width="200" height="200"></canvas>
<script>
const canvas = document.getElementById('face');
const ctx = canvas.getContext('2d');
// 画脸(黄色圆形)
ctx.beginPath();
ctx.arc(100, 100, 80, 0, Math.PI * 2);
ctx.fillStyle = 'yellow';
ctx.fill();
ctx.strokeStyle = 'black';
ctx.stroke();
// 左眼(黑色圆形)
ctx.beginPath();
ctx.arc(60, 70, 15, 0, Math.PI * 2);
ctx.fillStyle = 'black';
ctx.fill();
// 右眼
ctx.beginPath();
ctx.arc(140, 70, 15, 0, Math.PI * 2);
ctx.fill();
// 嘴巴(半圆弧线)
ctx.beginPath();
ctx.arc(100, 100, 50, 0, Math.PI);
ctx.stroke();
</script>
四、高频面试题精讲
1. Canvas和SVG的区别?
- Canvas:基于像素,适合游戏/图表,通过JS操作
- SVG:基于矢量,适合图标/地图,通过DOM操作
- 性能:Canvas更适合频繁重绘,SVG适合静态图形
2. 如何实现动画?
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空画布
// 更新绘制逻辑
requestAnimationFrame(animate);
}
animate();
3. 解决Canvas模糊问题
<!-- 通过CSS设置大小时会拉伸,应该用属性设置 -->
<canvas id="c" width="300" height="150"></canvas>
<style>
#c {
width: 600px; /* 实际渲染放大2倍会模糊 */
height: 300px;
}
</style>
五、记忆口诀
"四步走:拿画布,取画笔,设样式,绘图形
矩形圆和线,路径要清空,动画需循环清"
面试时如果被要求手写Canvas代码,按照四步曲结构:
- 获取canvas元素
- 获取context对象
- 设置颜色/线宽等样式
- 调用绘制方法(记得beginPath区分不同图形)