跳到主要内容

JavaScript Canvas基础

什么是Canvas?

Canvas是HTML5引入的元素,它允许我们使用JavaScript在网页上动态绘制图形、动画、游戏画面和其他视觉效果。Canvas提供了一个空白的矩形区域,我们可以通过JavaScript API控制其中的每个像素,从而创建各种各样的2D图形和动画。

提示

Canvas是一个非常强大的工具,它不仅可以用于数据可视化,还可以用于游戏开发、图像处理和交互式应用程序。

创建你的第一个Canvas

基本设置

要开始使用Canvas,首先需要在HTML中创建一个<canvas>元素:

html
<!DOCTYPE html>
<html>
<head>
<title>我的第一个Canvas</title>
<style>
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="500" height="300"></canvas>

<script>
// Canvas相关的JavaScript代码将在这里
</script>
</body>
</html>

获取绘图上下文

Canvas元素本身没有绘图能力,我们需要获取其"上下文"来进行绘制:

javascript
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');

getContext('2d')方法返回一个CanvasRenderingContext2D对象,它提供了所有的2D绘图功能。

警告

如果浏览器不支持Canvas,getContext()方法将返回null。最好在使用Canvas前检查浏览器兼容性。

javascript
if (canvas.getContext) {
const ctx = canvas.getContext('2d');
// 继续绘图操作
} else {
console.log('您的浏览器不支持Canvas');
}

Canvas坐标系统

在Canvas中,坐标系统的原点(0,0)位于画布的左上角。x轴向右延伸,y轴向下延伸:

(0,0) → x轴

y轴

基本绘图操作

绘制矩形

Canvas API提供了三种绘制矩形的方法:

javascript
// 绘制一个填充的矩形
ctx.fillStyle = 'blue'; // 设置填充颜色
ctx.fillRect(50, 50, 100, 75); // x, y, width, height

// 绘制一个矩形边框
ctx.strokeStyle = 'red'; // 设置边框颜色
ctx.lineWidth = 5; // 设置边框宽度
ctx.strokeRect(200, 50, 100, 75);

// 清除指定矩形区域
ctx.clearRect(75, 75, 50, 25);

绘制路径

路径是Canvas中更复杂图形的基础:

javascript
// 开始一条新路径
ctx.beginPath();

// 移动到起点
ctx.moveTo(75, 150);

// 绘制直线到指定点
ctx.lineTo(150, 200);
ctx.lineTo(200, 150);

// 闭合路径
ctx.closePath();

// 描边
ctx.strokeStyle = 'green';
ctx.stroke();

// 填充
// ctx.fillStyle = 'orange';
// ctx.fill();

绘制圆形和圆弧

使用arc()方法可以绘制圆形和圆弧:

javascript
ctx.beginPath();
// 参数: x, y, 半径, 开始角度(弧度), 结束角度(弧度), 是否逆时针
ctx.arc(300, 175, 50, 0, Math.PI * 2, false);
ctx.fillStyle = 'purple';
ctx.fill();

// 绘制半圆
ctx.beginPath();
ctx.arc(400, 175, 30, 0, Math.PI, false); // 半圆
ctx.stroke();

绘制文本

Canvas也可以绘制文本:

javascript
ctx.font = '24px Arial';
ctx.fillStyle = 'black';
ctx.fillText('Hello Canvas!', 150, 250);

// 带边框的文本
ctx.strokeStyle = 'blue';
ctx.lineWidth = 1;
ctx.strokeText('Outlined Text', 300, 250);

样式和颜色

填充和描边样式

javascript
// 使用CSS颜色
ctx.fillStyle = 'red';
ctx.strokeStyle = '#00ff00';

// 使用rgba
ctx.fillStyle = 'rgba(0, 0, 255, 0.5)'; // 半透明蓝色

// 线条样式
ctx.lineWidth = 5; // 线宽
ctx.lineCap = 'round'; // 线条端点: butt(默认), round, square
ctx.lineJoin = 'bevel'; // 线条连接点: miter(默认), round, bevel

渐变

javascript
// 线性渐变
const gradient = ctx.createLinearGradient(0, 0, 200, 0);
gradient.addColorStop(0, 'red');
gradient.addColorStop(0.5, 'green');
gradient.addColorStop(1, 'blue');

ctx.fillStyle = gradient;
ctx.fillRect(50, 300, 200, 75);

// 径向渐变
const radialGradient = ctx.createRadialGradient(350, 350, 10, 350, 350, 70);
radialGradient.addColorStop(0, 'white');
radialGradient.addColorStop(1, 'black');

ctx.fillStyle = radialGradient;
ctx.fillRect(300, 300, 100, 100);

图像操作

你可以在Canvas中绘制图像:

javascript
const img = new Image();
img.onload = function() {
ctx.drawImage(img, 50, 400);

// 缩放图像
// ctx.drawImage(img, 200, 400, 100, 75);

// 裁剪和缩放: 源图像(sx, sy, sWidth, sHeight), 目标位置(dx, dy, dWidth, dHeight)
// ctx.drawImage(img, 0, 0, img.width/2, img.height/2, 350, 400, 100, 75);
};
img.src = 'https://example.com/image.jpg'; // 替换为实际图像路径

变换

Canvas支持各种变换操作:

javascript
// 保存当前状态
ctx.save();

// 平移 - 移动原点
ctx.translate(100, 500);

// 旋转 (以弧度为单位)
ctx.rotate(Math.PI / 4); // 旋转45度

// 缩放
ctx.scale(1.5, 0.5); // x轴放大1.5倍,y轴缩小一半

// 在变换后的坐标系中绘制
ctx.fillStyle = 'orange';
ctx.fillRect(0, 0, 50, 50); // 这个矩形会受到上面所有变换的影响

// 恢复到之前保存的状态
ctx.restore();

// 恢复后绘制的矩形不受之前变换的影响
ctx.fillStyle = 'cyan';
ctx.fillRect(100, 500, 50, 50);

动画基础

Canvas最强大的功能之一是能够创建动画。基本步骤是:

  1. 清除Canvas
  2. 保存Canvas状态
  3. 绘制动画帧
  4. 恢复Canvas状态
  5. 重复以上步骤
javascript
let x = 0;

function draw() {
// 清除整个Canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);

// 绘制背景
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// 绘制移动的圆
ctx.beginPath();
ctx.arc(x, canvas.height/2, 20, 0, Math.PI * 2);
ctx.fillStyle = 'red';
ctx.fill();

// 更新位置
x += 2;
if (x > canvas.width + 20) {
x = -20;
}

// 请求下一帧
requestAnimationFrame(draw);
}

// 启动动画
draw();

实际案例:简单数据可视化

下面是一个简单的柱状图示例,展示如何使用Canvas进行数据可视化:

javascript
// 示例数据
const data = [50, 120, 180, 80, 140, 100];
const barWidth = 50;
const barSpacing = 20;
const chartHeight = 200;
const startX = 50;
const startY = 250;

// 绘制坐标轴
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(startX, startY - chartHeight - 20); // Y轴
ctx.moveTo(startX, startY);
ctx.lineTo(startX + (barWidth + barSpacing) * data.length + 20, startY); // X轴
ctx.strokeStyle = 'black';
ctx.stroke();

// 绘制柱状图
for (let i = 0; i < data.length; i++) {
const x = startX + i * (barWidth + barSpacing);
const barHeight = data[i];

// 绘制柱子
ctx.fillStyle = `hsl(${i * 50}, 70%, 50%)`;
ctx.fillRect(x, startY - barHeight, barWidth, barHeight);

// 添加数值标签
ctx.fillStyle = 'black';
ctx.font = '12px Arial';
ctx.textAlign = 'center';
ctx.fillText(data[i], x + barWidth/2, startY - barHeight - 5);

// 添加X轴标签
ctx.fillText(`项目${i+1}`, x + barWidth/2, startY + 15);
}

// 添加标题
ctx.font = '18px Arial';
ctx.textAlign = 'center';
ctx.fillText('简单柱状图示例', canvas.width/2, 30);

响应用户交互

可以为Canvas添加事件监听器,以响应用户交互:

javascript
// 创建一个可以拖动的圆
const circle = {
x: 200,
y: 200,
radius: 30,
isDragging: false
};

// 检查点是否在圆内
function isInCircle(x, y) {
return Math.sqrt((x - circle.x) ** 2 + (y - circle.y) ** 2) < circle.radius;
}

// 获取Canvas上的鼠标位置
function getMousePos(canvas, evt) {
const rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}

canvas.addEventListener('mousedown', function(evt) {
const mousePos = getMousePos(canvas, evt);
if (isInCircle(mousePos.x, mousePos.y)) {
circle.isDragging = true;
}
});

canvas.addEventListener('mousemove', function(evt) {
if (circle.isDragging) {
const mousePos = getMousePos(canvas, evt);
circle.x = mousePos.x;
circle.y = mousePos.y;

// 重绘Canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
ctx.fillStyle = 'blue';
ctx.fill();
}
});

canvas.addEventListener('mouseup', function() {
circle.isDragging = false;
});

// 初始绘制
ctx.beginPath();
ctx.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2);
ctx.fillStyle = 'blue';
ctx.fill();

总结

在本教程中,我们学习了:

  1. 如何创建和初始化Canvas
  2. 基本的绘图操作(矩形、路径、圆形、文本)
  3. 样式和颜色的应用(填充、描边、渐变)
  4. 图像操作
  5. 变换(平移、旋转、缩放)
  6. 动画基础
  7. 简单数据可视化示例
  8. 如何响应用户交互

Canvas提供了丰富的绘图功能,可以用于创建各种各样的可视化效果和交互式应用。熟练掌握Canvas API将使你能够实现复杂的数据可视化和自定义图形界面。

练习与进阶

为了巩固所学知识,尝试完成以下练习:

  1. 创建一个简单的时钟,显示当前时间,并且秒针可以动态转动。
  2. 实现一个折线图,显示一组随时间变化的数据。
  3. 创建一个简单的绘画应用,允许用户在Canvas上用鼠标绘制。
  4. 尝试实现一个简单的粒子系统,展示多个移动的圆点。

进阶学习资源

  1. MDN Canvas教程
  2. HTML5 Canvas图表库Chart.js
  3. Canvas高级动画技术
  4. WebGL - 当你准备好探索3D图形时

记住,学习Canvas最好的方式是实践。开始一个小项目,随着你的学习不断扩展它的功能和复杂性!