Html5学习教程,从入门到精通, HTML5 Canvas 全攻略:从入门到精通(19)
HTML5 Canvas 全攻略:从入门到精通
一、Canvas 基础
1.1 什么是 Canvas
Canvas 是 HTML5 中的一个绘图元素,允许通过 JavaScript 绘制图形、图像和动画。它提供了一个空白的绘图区域,开发者可以使用其 API 进行各种绘图操作。
1.2 创建 Canvas 元素
在 HTML 中,通过 <canvas>
标签创建 Canvas 元素,并为其指定 id
、width
和 height
属性。
<canvas id="myCanvas" width="500" height="500"></canvas>
1.3 获取绘图上下文
在 JavaScript 中,通过 getContext()
方法获取 Canvas 的绘图上下文,通常使用 2D 上下文进行绘图。
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
二、绘图基础
2.1 设置线条样式
可以使用 lineWidth
、strokeStyle
等属性设置线条的宽度和颜色。
ctx.lineWidth = 5; // 设置线条宽度
ctx.strokeStyle = 'blue'; // 设置线条颜色
2.2 绘制路径
使用 beginPath()
开始绘制路径,moveTo()
移动到起始点,lineTo()
绘制直线,最后使用 stroke()
绘制路径。
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(200, 50);
ctx.stroke();
2.3 填充路径
使用 fillStyle
设置填充颜色,fill()
方法填充路径。
ctx.fillStyle = 'red';
ctx.fillRect(50, 100, 100, 50); // 绘制并填充矩形
三、绘制图形
3.1 矩形
使用 rect()
方法绘制矩形路径,再结合 stroke()
或 fill()
绘制边框或填充。
ctx.beginPath();
ctx.rect(50, 150, 100, 50);
ctx.stroke(); // 绘制矩形边框
3.2 圆形
使用 arc()
方法绘制圆形,参数包括圆心坐标、半径、起始角和结束角。
ctx.beginPath();
ctx.arc(150, 250, 40, 0, Math.PI * 2);
ctx.stroke();
3.3 椭圆
使用 ellipse()
方法绘制椭圆,参数包括圆心坐标、长轴半径、短轴半径、旋转角度、起始角和结束角。
ctx.beginPath();
ctx.ellipse(250, 250, 50, 30, 0, 0, Math.PI * 2);
ctx.stroke();
四、文本绘制
4.1 设置文本样式
使用 font
设置字体,textAlign
设置文本对齐方式。
ctx.font = '20px Arial';
ctx.textAlign = 'center';
4.2 绘制文本
使用 fillText()
绘制填充文本,strokeText()
绘制描边文本。
ctx.fillText('Hello Canvas!', 150, 300);
ctx.strokeText('Hello Canvas!', 150, 350);
五、图像绘制
5.1 绘制图像
使用 drawImage()
方法绘制图像,可以绘制整个图像或部分图像。
const img = new Image();
img.src = 'image.jpg';
img.onload = function() {
ctx.drawImage(img, 50, 50, 100, 100); // 绘制图像到指定区域
};
六、变换
6.1 平移
使用 translate()
方法平移绘图上下文的原点。
ctx.translate(50, 50);
ctx.fillRect(0, 0, 50, 50); // 相对于平移后的原点绘制矩形
6.2 旋转
使用 rotate()
方法旋转绘图上下文。
ctx.rotate(Math.PI / 4); // 旋转 45 度
ctx.fillRect(0, 0, 50, 50);
6.3 缩放
使用 scale()
方法缩放绘图上下文。
ctx.scale(2, 2); // 水平和垂直方向各缩放 2 倍
ctx.fillRect(0, 0, 50, 50);
七、动画
7.1 创建动画
使用 requestAnimationFrame()
方法创建动画,不断更新绘图内容。
let x = 0;
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
ctx.fillRect(x, 50, 50, 50); // 绘制矩形
x++; // 更新位置
if (x < canvas.width) {
requestAnimationFrame(animate); // 请求下一帧动画
}
}
animate();
八、事件处理
8.1 监听鼠标事件
可以为 Canvas 元素添加鼠标事件监听器,实现与用户的交互。
canvas.addEventListener('click', function(event) {
const rect = canvas.getBoundingClientRect();
const clickX = event.clientX - rect.left;
const clickY = event.clientY - rect.top;
ctx.beginPath();
ctx.arc(clickX, clickY, 10, 0, Math.PI * 2);
ctx.fill(); // 在点击位置绘制圆形
});
九、高级技巧
9.1 阴影效果
使用 shadowColor
和 shadowBlur
等属性添加阴影效果。
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
ctx.shadowBlur = 10;
ctx.fillRect(50, 50, 100, 50); // 绘制带有阴影的矩形
9.2 渐变和图案填充
创建线性渐变或径向渐变,用于填充图形。
const gradient = ctx.createLinearGradient(0, 0, 200, 0);
gradient.addColorStop(0, 'red');
gradient.addColorStop(1, 'blue');
ctx.fillStyle = gradient;
ctx.fillRect(50, 100, 100, 50); // 使用渐变填充矩形
9.3 复合操作
使用 globalCompositeOperation
属性设置图形的合成方式。
ctx.globalCompositeOperation = 'destination-over';
ctx.fillStyle = 'green';
ctx.fillRect(100, 100, 100, 50); // 使用复合操作绘制矩形
以上是 HTML5 Canvas 的全面知识点及案例代码,涵盖了从基础到高级的各种功能和应用。通过这些示例,你可以深入理解并掌握 Canvas 的强大绘图能力,为你的 Web 开发项目增添丰富的视觉效果。
以下是HTML5 Canvas在实际开发中的一些具体案例,涵盖了不同应用场景,每个案例都附有详细代码和注释:
案例一:Flappy Bird 小游戏
实现思路:
- 使用Canvas绘制游戏背景、小鸟、管道等元素。
- 监听鼠标点击事件,更新小鸟的垂直速度。
- 通过物理模拟计算小鸟的运动轨迹,包括重力下降和空气阻力。
- 定时更新画面,检测小鸟与管道的碰撞,根据碰撞结果更新游戏状态。
核心代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flappy Bird</title>
<style>
canvas {
display: block;
margin: auto;
background-color: #70c5ce;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="400" height="600"></canvas>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// 游戏变量
let bird = {
x: 50,
y: 300,
width: 40,
height: 30,
speed: 0,
gravity: 0.5,
jump: -8
};
let pipes = [];
let score = 0;
let gameRunning = true;
// 创建管道
function createPipe() {
let gapPosition = Math.random() * (canvas.height - 200) + 100;
pipes.push({
x: canvas.width,
y: gapPosition,
width: 50,
height: gapPosition - 100,
passed: false
});
pipes.push({
x: canvas.width,
y: gapPosition + 100,
width: 50,
height: canvas.height - gapPosition - 100,
passed: false
});
}
// 绘制小鸟
function drawBird() {
ctx.fillStyle = 'yellow';
ctx.fillRect(bird.x, bird.y, bird.width, bird.height);
}
// 绘制管道
function drawPipes() {
ctx.fillStyle = 'green';
pipes.forEach(pipe => {
ctx.fillRect(pipe.x, pipe.y, pipe.width, pipe.height);
});
}
// 更新游戏状态
function update() {
// 更新小鸟位置
bird.speed += bird.gravity;
bird.y += bird.speed;
// 创建新管道
if (pipes.length === 0 || pipes[pipes.length - 1].x < canvas.width - 200) {
createPipe();
}
// 更新管道位置
for (let i = 0; i < pipes.length; i++) {
pipes[i].x -= 2;
// 检测碰撞
if (pipes[i].x + pipes[i].width > bird.x && pipes[i].x < bird.x + bird.width &&
(pipes[i].y > bird.y && pipes[i].y < bird.y + bird.height || pipes[i].y + pipes[i].height > bird.y && pipes[i].y + pipes[i].height < bird.y + bird.height)) {
gameRunning = false;
}
// 更新得分
if (!pipes[i].passed && pipes[i].x + pipes[i].width < bird.x) {
pipes[i].passed = true;
score++;
}
// 移除超出屏幕的管道
if (pipes[i].x + pipes[i].width < 0) {
pipes.splice(i, 1);
i--;
}
}
// 检测地面碰撞
if (bird.y + bird.height > canvas.height) {
gameRunning = false;
}
}
// 游戏主循环
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (gameRunning) {
update();
}
drawBird();
drawPipes();
ctx.fillStyle = 'black';
ctx.font = '20px Arial';
ctx.fillText('Score: ' + score, 10, 30);
requestAnimationFrame(gameLoop);
}
// 事件监听
canvas.addEventListener('click', function() {
if (gameRunning) {
bird.speed = bird.jump;
} else {
// 重置游戏
bird.y = 300;
bird.speed = 0;
pipes = [];
score = 0;
gameRunning = true;
}
});
// 启动游戏
gameLoop();
</script>
</body>
</html>
案例二:动态烟花秀
实现思路:
- 使用Canvas绘制烟花粒子。
- 通过定时器控制烟花的生成和爆炸效果。
- 每个烟花由多个粒子组成,粒子的颜色和速度随机生成。
- 粒子在爆炸后逐渐消失,形成自然的烟花效果。
核心代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fireworks Show</title>
<style>
canvas {
display: block;
background-color: black;
}
</style>
</head>
<body>
<canvas id="fireworksCanvas" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById('fireworksCanvas');
const ctx = canvas.getContext('2d');
// 烟花数组
let fireworks = [];
// 烟花类
class Firework {
constructor() {
this.x = Math.random() * canvas.width;
this.y = canvas.height;
this.speed = Math.random() * 2 + 2;
this.angle = Math.random() * Math.PI / 2;
this.particles = [];
this.exploded = false;
}
// 更新烟花状态
update() {
if (!this.exploded) {
this.y -= this.speed * Math.sin(this.angle);
this.x += this.speed * Math.cos(this.angle);
// 检测爆炸条件
if (this.y < Math.random() * canvas.height / 2) {
this.explode();
}
} else {
// 更新粒子状态
for (let i = 0; i < this.particles.length; i++) {
this.particles[i].update();
}
// 移除消失的粒子
this.particles = this.particles.filter(particle => !particle.fadeOut);
}
}
// 爆炸效果
explode() {
this.exploded = true;
// 创建粒子
for (let i = 0; i < 100; i++) {
let angle = Math.random() * Math.PI * 2;
let speed = Math.random() * 3 + 1;
let radius = Math.random() * 2 + 1;
let red = Math.floor(Math.random() * 256);
let green = Math.floor(Math.random() * 256);
let blue = Math.floor(Math.random() * 256);
this.particles.push({
x: this.x,
y: this.y,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed,
radius: radius,
red: red,
green: green,
blue: blue,
fadeOut: false
});
}
}
// 绘制烟花
draw() {
if (!this.exploded) {
ctx.beginPath();
ctx.arc(this.x, this.y, 2, 0, Math.PI * 2);
ctx.fillStyle = 'white';
ctx.fill();
} else {
// 绘制粒子
this.particles.forEach(particle => {
ctx.beginPath();
ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2);
ctx.fillStyle = `rgba(${particle.red}, ${particle.green}, ${particle.blue}, ${particle.radius / 3})`;
ctx.fill();
});
}
}
}
// 粒子更新方法
Firework.prototype.particles.update = function() {
this.x += this.vx;
this.y += this.vy;
this.vy += 0.1; // 重力加速度
this.radius -= 0.05; // 缩小粒子
// 判断粒子是否消失
if (this.radius <= 0) {
this.fadeOut = true;
}
};
// 创建烟花
function createFirework() {
fireworks.push(new Firework());
}
// 游戏主循环
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 更新烟花
fireworks.forEach(firework => {
firework.update();
firework.draw();
});
// 移除已经爆炸且粒子消失的烟花
fireworks = fireworks.filter(firework => !firework.exploded || firework.particles.length > 0);
// 随机生成新烟花
if (Math.random() < 0.02) {
createFirework();
}
requestAnimationFrame(gameLoop);
}
// 启动游戏
gameLoop();
</script>
</body>
</html>
案例三:绘制图表
实现思路:
- 使用Canvas绘制各种类型的图表,如柱状图、折线图、饼图等。
- 通过数据数组生成图表的坐标点。
- 使用不同的颜色和样式区分不同的数据系列。
- 添加图例和标签,使图表更易读。
核心代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chart Example</title>
<style>
canvas {
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas id="chartCanvas" width="600" height="400"></canvas>
<script>
const canvas = document.getElementById('chartCanvas');
const ctx = canvas.getContext('2d');
// 数据
const data = [12, 19, 3, 5, 2, 3];
const labels = ['January', 'February', 'March', 'April', 'May', 'June'];
const colors = ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40'];
// 绘制柱状图
function drawBarChart() {
// 绘制背景
ctx.fillStyle = '#f8f9fa';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制坐标轴
ctx.beginPath();
ctx.moveTo(50, 350);
ctx.lineTo(550, 350); // X轴
ctx.lineTo(50, 50); // Y轴
ctx.strokeStyle = '#6c757d';
ctx.stroke();
// 绘制刻度
for (let i = 0; i <= 7; i++) {
ctx.beginPath();
ctx.moveTo(50, 350 - i * 50);
ctx.lineTo(55, 350 - i * 50);
ctx.strokeStyle = '#6c757d';
ctx.stroke();
ctx.fillStyle = '#6c757d';
ctx.font = '12px Arial';
ctx.fillText((7 - i) * 2, 30, 350 - i * 50 + 5);
}
// 绘制柱状图
for (let i = 0; i < data.length; i++) {
ctx.fillStyle = colors[i];
ctx.fillRect(80 + i * 80, 350 - data[i] * 30, 60, data[i] * 30);
// 绘制标签
ctx.fillStyle = '#6c757d';
ctx.font = '12px Arial';
ctx.fillText(labels[i], 80 + i * 80, 370);
}
// 绘制图例
for (let i = 0; i < data.length; i++) {
ctx.fillStyle = colors[i];
ctx.fillRect(570, 50 + i * 25, 15, 15);
ctx.fillStyle = '#6c757d';
ctx.font = '12px Arial';
ctx.fillText(labels[i], 590, 65 + i * 25);
}
}
// 绘制折线图
function drawLineChart() {
// 绘制背景
ctx.fillStyle = '#f8f9fa';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制坐标轴
ctx.beginPath();
ctx.moveTo(50, 350);
ctx.lineTo(550, 350); // X轴
ctx.lineTo(50, 50); // Y轴
ctx.strokeStyle = '#6c757d';
ctx.stroke();
// 绘制刻度
for (let i = 0; i <= 7; i++) {
ctx.beginPath();
ctx.moveTo(50, 350 - i * 50);
ctx.lineTo(55, 350 - i * 50);
ctx.strokeStyle = '#6c757d';
ctx.stroke();
ctx.fillStyle = '#6c757d';
ctx.font = '12px Arial';
ctx.fillText((7 - i) * 2, 30, 350 - i * 50 + 5);
}
// 绘制数据点和连线
ctx.beginPath();
ctx.moveTo(80, 350 - data[0] * 30);
for (let i = 1; i < data.length; i++) {
ctx.lineTo(80 + i * 80, 350 - data[i] * 30);
}
ctx.strokeStyle = '#36A2EB';
ctx.lineWidth = 2;
ctx.stroke();
// 绘制数据点圆圈
for (let i = 0; i < data.length; i++) {
ctx.beginPath();
ctx.arc(80 + i * 80, 350 - data[i] * 30, 4, 0, Math.PI * 2);
ctx.fillStyle = '#36A2EB';
ctx.fill();
}
// 绘制标签
for (let i = 0; i < data.length; i++) {
ctx.fillStyle = '#6c757d';
ctx.font = '12px Arial';
ctx.fillText(labels[i], 80 + i * 80, 370);
}
// 绘制图例
ctx.fillStyle = '#36A2EB';
ctx.fillRect(570, 50, 15, 15);
ctx.fillStyle = '#6c757d';
ctx.font = '12px Arial';
ctx.fillText('Data', 590, 65);
}
// 绘制饼图
function drawPieChart() {
// 绘制背景
ctx.fillStyle = '#f8f9fa';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制饼图
let total = data.reduce((sum, value) => sum + value, 0);
let startAngle = 0;
for (let i = 0; i < data.length; i++) {
let endAngle = startAngle + (data[i] / total) * Math.PI * 2;
ctx.beginPath();
ctx.moveTo(300, 200);
ctx.arc(300, 200, 150, startAngle, endAngle);
ctx.fillStyle = colors[i];
ctx.fill();
startAngle = endAngle;
}
// 绘制图例
for (let i = 0; i < data.length; i++) {
ctx.fillStyle = colors[i];
ctx.fillRect(570, 50 + i * 30, 15, 15);
ctx.fillStyle = '#6c757d';
ctx.font = '12px Arial';
ctx.fillText(labels[i], 590, 65 + i * 30);
}
}
// 绘制柱状图
drawBarChart();
// 绘制折线图
// drawLineChart();
// 绘制饼图
// drawPieChart();
</script>
</body>
</html>
以上案例展示了HTML5 Canvas在游戏开发、动画效果和数据可视化等实际开发场景中的应用,通过这些示例,你可以深入理解Canvas的强大功能,并将其应用于自己的项目中。
案例四:绘制动态时钟
描述
使用 Canvas 绘制一个动态更新的时钟,显示当前时间,包括时针、分针和秒针。
代码
<canvas id="clockCanvas" width="300" height="300"></canvas>
<script>
var canvas = document.getElementById("clockCanvas");
var ctx = canvas.getContext("2d");
var radius = canvas.height / 2;
// 将原点移动到画布中心
ctx.translate(radius, radius);
radius = radius * 0.90;
// 每秒更新一次时钟
setInterval(drawClock, 1000);
function drawClock() {
// 清空画布
ctx.clearRect(-radius, -radius, canvas.width, canvas.height);
// 绘制时钟外框
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.strokeStyle = "black";
ctx.lineWidth = 5;
ctx.stroke();
// 绘制时钟数字
ctx.font = radius * 0.15 + "px Arial";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
for (var i = 1; i <= 12; i++) {
var angle = (i * Math.PI) / 6;
ctx.rotate(angle);
ctx.translate(0, -radius * 0.85);
ctx.rotate(-angle);
ctx.fillText(i.toString(), 0, 0);
ctx.rotate(angle);
ctx.translate(0, radius * 0.85);
ctx.rotate(-angle);
}
// 获取当前时间
var now = new Date();
var hour = now.getHours();
var minute = now.getMinutes();
var second = now.getSeconds();
// 绘制时针
hour = hour % 12;
drawHand((hour * Math.PI) / 6 + (minute * Math.PI) / 360, radius * 0.5, radius * 0.07);
// 绘制分针
drawHand((minute * Math.PI) / 30, radius * 0.8, radius * 0.07);
// 绘制秒针
drawHand((second * Math.PI) / 30, radius * 0.9, radius * 0.02);
}
// 绘制时钟指针
function drawHand(angle, length, width) {
ctx.beginPath();
ctx.lineWidth = width;
ctx.lineCap = "round";
ctx.moveTo(0, 0);
ctx.rotate(angle);
ctx.lineTo(0, -length);
ctx.stroke();
ctx.rotate(-angle);
}
</script>
案例 五:绘制动态粒子效果
描述
使用 Canvas 绘制随机运动的粒子,粒子之间会连接成线,形成动态背景效果。
代码
<canvas id="particleCanvas" width="800" height="600"></canvas>
<script>
var canvas = document.getElementById("particleCanvas");
var ctx = canvas.getContext("2d");
var particles = [];
var particleCount = 100;
// 创建粒子对象
function Particle() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.vx = Math.random() * 2 - 1;
this.vy = Math.random() * 2 - 1;
this.radius = Math.random() * 3 + 1;
}
// 初始化粒子数组
for (var i = 0; i < particleCount; i++) {
particles.push(new Particle());
}
// 绘制粒子
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 更新粒子位置并绘制
for (var i = 0; i < particles.length; i++) {
var p = particles[i];
// 更新位置
p.x += p.vx;
p.y += p.vy;
// 边界检测
if (p.x < 0 || p.x > canvas.width) p.vx *= -1;
if (p.y < 0 || p.y > canvas.height) p.vy *= -1;
// 绘制粒子
ctx.beginPath();
ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);
ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
ctx.fill();
// 绘制粒子之间的连线
for (var j = i + 1; j < particles.length; j++) {
var p2 = particles[j];
var dx = p.x - p2.x;
var dy = p.y - p2.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 100) {
ctx.beginPath();
ctx.moveTo(p.x, p.y);
ctx.lineTo(p2.x, p2.y);
ctx.strokeStyle = "rgba(255, 255, 255, " + (1 - dist / 100) + ")";
ctx.lineWidth = 1;
ctx.stroke();
}
}
}
requestAnimationFrame(draw);
}
draw();
</script>
案例 六:绘制简单的柱状图
描述
使用 Canvas 绘制一个动态柱状图,展示随机生成的数据。
代码
<canvas id="barChartCanvas" width="600" height="400"></canvas>
<script>
var canvas = document.getElementById("barChartCanvas");
var ctx = canvas.getContext("2d");
var data = [30, 80, 120, 60, 150, 90, 180]; // 示例数据
var barWidth = 50;
var barSpacing = 20;
var startX = 50;
var startY = canvas.height - 50;
// 绘制柱状图
function drawBarChart() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < data.length; i++) {
var x = startX + i * (barWidth + barSpacing);
var y = startY - data[i];
// 绘制柱状条
ctx.fillStyle = "rgba(75, 192, 192, 0.8)";
ctx.fillRect(x, y, barWidth, data[i]);
// 绘制数据标签
ctx.fillStyle = "black";
ctx.font = "14px Arial";
ctx.fillText(data[i], x + barWidth / 2 - 10, y - 10);
}
}
drawBarChart();
</script>
案例 七:绘制简单的游戏(小球碰撞)
描述
使用 Canvas 实现一个简单的小球碰撞游戏,小球在画布内反弹。
代码
<canvas id="gameCanvas" width="600" height="400"></canvas>
<script>
var canvas = document.getElementById("gameCanvas");
var ctx = canvas.getContext("2d");
var ball = {
x: 100,
y: 100,
radius: 20,
vx: 4,
vy: 4,
color: "red"
};
// 绘制小球
function drawBall() {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fillStyle = ball.color;
ctx.fill();
ctx.closePath();
}
// 更新小球位置
function updateBall() {
ball.x += ball.vx;
ball.y += ball.vy;
// 边界检测
if (ball.x + ball.radius > canvas.width || ball.x - ball.radius < 0) {
ball.vx *= -1;
}
if (ball.y + ball.radius > canvas.height || ball.y - ball.radius < 0) {
ball.vy *= -1;
}
}
// 主循环
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
updateBall();
requestAnimationFrame(gameLoop);
}
gameLoop();
</script>
总结
以上案例展示了 HTML5 Canvas 在实际开发中的应用,包括动态时钟、粒子效果、数据可视化以及简单游戏开发。通过这些案例,您可以更好地理解 Canvas 的强大功能,并将其应用到自己的项目中。