最近收到私信,发现很多同学对Canvas标签非常不熟悉,甚至连听都没听过,这篇文章就带大家好好了解一下这个原生标签Canvas。
1.基础设置
<!-- 创建Canvas元素 -->
<!-- width和height设置画布大小,不要用CSS设置,会导致画面模糊 -->
<canvas id="myCanvas" width="500" height="300"></canvas><script>
// 获取Canvas元素
const canvas = document.getElementById('myCanvas');
// 获取绘图上下文,'2d'表示二维绘图
const ctx = canvas.getContext('2d');
</script>
2. 基础图形绘制
/*** 基础图形绘制类* 包含最常用的绘图方法*/
class BasicDrawing {constructor(canvasId) {// 初始化画布和上下文this.canvas = document.getElementById(canvasId);this.ctx = this.canvas.getContext('2d');}// 绘制矩形drawRectangle() {// 设置填充颜色this.ctx.fillStyle = 'red';// 绘制填充矩形// 参数含义:x坐标, y坐标, 宽度, 高度this.ctx.fillRect(10, 10, 100, 80);// 设置边框颜色this.ctx.strokeStyle = 'blue';// 设置边框宽度this.ctx.lineWidth = 2;// 绘制边框矩形this.ctx.strokeRect(130, 10, 100, 80);}// 绘制圆形drawCircle() {// 开始一个新的绘制路径this.ctx.beginPath();// 绘制圆形// 参数:圆心x, 圆心y, 半径, 开始角度, 结束角度this.ctx.arc(50, 50, 30, 0, Math.PI * 2);// 设置填充颜色this.ctx.fillStyle = 'green';// 填充this.ctx.fill();}// 绘制线条drawLine() {this.ctx.beginPath();// 移动到起点this.ctx.moveTo(10, 10);// 画线到终点this.ctx.lineTo(200, 200);// 设置线条颜色this.ctx.strokeStyle = 'black';// 设置线条宽度this.ctx.lineWidth = 2;// 绘制线条this.ctx.stroke();}
}// 使用示例
const drawing = new BasicDrawing('myCanvas');
drawing.drawRectangle();
3. 动画效果
/*** 简单动画示例* 展示如何制作移动的小球*/
class SimpleAnimation {constructor(canvasId) {this.canvas = document.getElementById(canvasId);this.ctx = this.canvas.getContext('2d');// 小球的初始位置和速度this.x = 50;this.y = 50;this.speed = 2;this.radius = 20;}// 绘制小球drawBall() {this.ctx.beginPath();this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);this.ctx.fillStyle = 'red';this.ctx.fill();}// 更新小球位置update() {// 移动小球this.x += this.speed;// 如果碰到边界就反弹if (this.x + this.radius > this.canvas.width || this.x - this.radius < 0) {this.speed = -this.speed;}}// 开始动画animate() {// 清除整个画布this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);// 绘制和更新this.drawBall();this.update();// 请求下一帧动画// requestAnimationFrame比setTimeout更适合动画requestAnimationFrame(() => this.animate());}
}// 使用示例
const animation = new SimpleAnimation('myCanvas');
animation.animate();
4.简单的画板功能
/*** 简单画板* 允许用户用鼠标在画布上绘画*/
class SimpleDrawingBoard {constructor(canvasId) {this.canvas = document.getElementById(canvasId);this.ctx = this.canvas.getContext('2d');// 是否正在绘制this.isDrawing = false;// 初始化画板设置this.initializeBoard();}// 初始化画板initializeBoard() {// 设置线条样式this.ctx.strokeStyle = 'black';this.ctx.lineWidth = 2;this.ctx.lineCap = 'round'; // 让线条末端圆润// 添加鼠标事件监听this.canvas.addEventListener('mousedown', (e) => this.startDrawing(e));this.canvas.addEventListener('mousemove', (e) => this.draw(e));this.canvas.addEventListener('mouseup', () => this.stopDrawing());this.canvas.addEventListener('mouseout', () => this.stopDrawing());}// 开始绘制startDrawing(e) {this.isDrawing = true;// 移动到鼠标位置this.ctx.beginPath();this.ctx.moveTo(e.clientX - this.canvas.offsetLeft,e.clientY - this.canvas.offsetTop);}// 绘制draw(e) {if (!this.isDrawing) return;// 画线到当前鼠标位置jthis.ctx.lineTo(e.clientX - this.canvas.offsetLeft,e.clientY - this.canvas.offsetTop);this.ctx.stroke();}// 停止绘制stopDrawing() {this.isDrawing = false;}// 清除画布clear() {this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);}
}// 使用示例
const drawingBoard = new SimpleDrawingBoard('myCanvas');// 添加清除按钮
const clearButton = document.createElement('button');
clearButton.textContent = '清除画布';
clearButton.onclick = () => drawingBoard.clear();
document.body.appendChild(clearButton);
5.图片处理
/*** 图片处理类* 展示如何在Canvas中处理图片*/
class ImageProcessor {constructor(canvasId) {this.canvas = document.getElementById(canvasId);this.ctx = this.canvas.getContext('2d');}// 加载并显示图片loadImage(imageUrl) {// 创建新的图片对象const img = new Image();// 图片加载完成后的处理img.onload = () => {// 将图片绘制到画布上this.ctx.drawImage(img, 0, 0, this.canvas.width, this.canvas.height);};// 设置图片源img.src = imageUrl;}// 添加简单的灰度效果applyGrayscale() {// 获取画布上的图像数据const imageData = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);const data = imageData.data;// 处理每个像素for (let i = 0; i < data.length; i += 4) {// 计算灰度值const gray = (data[i] + data[i + 1] + data[i + 2]) / 3;// 设置RGB值为灰度值data[i] = gray; // Rdata[i + 1] = gray; // Gdata[i + 2] = gray; // B// data[i + 3] 是透明度,保持不变}// 将处理后的图像数据放回画布this.ctx.putImageData(imageData, 0, 0);}
}// 使用示例
const processor = new ImageProcessor('myCanvas');
processor.loadImage('path/to/image.jpg');// 添加灰度效果按钮
const grayscaleButton = document.createElement('button');
grayscaleButton.textContent = '添加灰度效果';
grayscaleButton.onclick = () => processor.applyGrayscale();
document.body.appendChild(grayscaleButton);
使用建议:
1.性能优化
- 避免在循环中重复获取canvas和context
- 使用requestAnimationFrame而不是setInterval
- 适当使用缓存
2.常见问题解决
- 画布模糊:使用正确的尺寸设置
- 图片跨域:确保图片允许跨域访问
- 性能问题:控制重绘频率
3.适用场景
- 简单游戏开发
- 图表绘制
- 图片处理
- 签名板
- 动画效果
4. 初学者注意事项
- 先掌握基础图形绘制
- 理解坐标系统
- 多练习动画效果
- 从简单项目开始
5.进阶方向
- 复杂动画效果
- 碰撞检测
- 粒子效果
- 3D效果(使用WebGL)