HTML5 Canvas 是一种在网页上进行图形绘制的强大技术。它允许开发者使用 JavaScript 在网页上绘制图形、动画等,非常适合制作网页游戏、数据可视化等。本文将带你从入门到精通,通过实战案例教学,轻松掌握 HTML5 Canvas 动画制作。
一、HTML5 Canvas 基础知识
1.1 Canvas 元素
Canvas 元素是 HTML5 中新增的一个元素,用于在网页上绘制图形。它的基本属性是 width 和 height,分别表示画布的宽度和高度。
<canvas id="myCanvas" width="200" height="100"></canvas>
1.2 2D 上下文
Canvas 元素创建后,可以通过 getContext('2d') 方法获取到 2D 上下文对象。2D 上下文提供了一系列绘制图形的 API。
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
二、Canvas 基本绘制
2.1 绘制线条
使用 lineTo() 和 moveTo() 方法可以绘制直线。lineTo() 方法用于指定直线的终点,而 moveTo() 方法用于指定起点。
ctx.moveTo(0, 0);
ctx.lineTo(100, 100);
ctx.stroke();
2.2 绘制矩形
使用 rect() 方法可以绘制矩形。该方法需要指定矩形的四个顶点坐标。
ctx.rect(0, 0, 100, 100);
ctx.stroke();
2.3 绘制圆形
使用 arc() 方法可以绘制圆形。该方法需要指定圆的半径、圆心坐标以及圆弧的角度。
ctx.arc(50, 50, 40, 0, Math.PI * 2);
ctx.stroke();
三、Canvas 动画制作
3.1 requestAnimationFrame 方法
requestAnimationFrame() 方法用于创建动画,它会在浏览器准备好绘制下一帧时调用指定的函数。该方法返回一个请求 ID,可以用于取消动画。
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.arc(50, 50, 5, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.arc(50 + Math.sin(Date.now() / 1000) * 50, 50 + Math.cos(Date.now() / 1000) * 50, 5, 0, Math.PI * 2);
ctx.stroke();
requestAnimationFrame(animate);
}
animate();
3.2 动画帧率控制
为了使动画流畅,可以使用 frameRate() 方法控制动画帧率。该方法接受一个帧率参数,单位为每秒帧数。
function frameRate(fps) {
var frames = Math.floor(1000 / fps);
return frames;
}
四、实战案例:制作简单的弹球游戏
4.1 游戏设计
本案例将制作一个简单的弹球游戏,玩家控制弹球撞击墙壁,游戏过程中,弹球速度逐渐加快。
4.2 代码实现
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var ballRadius = 10;
var ballX = canvas.width / 2;
var ballY = canvas.height - 30;
var ballSpeedX = 5;
var ballSpeedY = -5;
var paddleHeight = 10;
var paddleWidth = 75;
var paddleX = (canvas.width - paddleWidth) / 2;
var rightPressed = false;
var leftPressed = false;
var brickRowCount = 3;
var brickColumnCount = 5;
var brickWidth = 75;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 25;
var bricks = [];
for (var c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for (var r = 0; r < brickRowCount; r++) {
bricks[c][r] = { x: 0, y: 0, status: 1 };
}
}
document.addEventListener('keydown', keyDownHandler, false);
document.addEventListener('keyup', keyUpHandler, false);
document.addEventListener('mousemove', mouseMoveHandler, false);
function keyDownHandler(e) {
if (e.keyCode == 39) {
rightPressed = true;
}
else if (e.keyCode == 37) {
leftPressed = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 39) {
rightPressed = false;
}
else if (e.keyCode == 37) {
leftPressed = false;
}
}
function mouseMoveHandler(e) {
var relativeX = e.clientX - canvas.offsetLeft;
if (relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth / 2;
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.beginPath();
ctx.arc(ballX, ballY, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = '#0095DD';
ctx.fill();
ctx.closePath();
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 5;
}
else if (leftPressed && paddleX > 0) {
paddleX -= 5;
}
ballX += ballSpeedX;
ballY += ballSpeedY;
if (ballX + ballRadius > canvas.width || ballX - ballRadius < 0) {
ballSpeedX = -ballSpeedX;
}
if (ballY + ballRadius > canvas.height || ballY - ballRadius < 0) {
ballSpeedY = -ballSpeedY;
}
var collision = checkCollision(ballX, ballY, ballRadius);
if (collision) {
ballSpeedY = -ballSpeedY;
}
for (var c = 0; c < brickColumnCount; c++) {
for (var r = 0; r < brickRowCount; r++) {
var b = bricks[c][r];
if (b.status == 1) {
var brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft;
var brickY = (r * (brickHeight + brickPadding)) + brickOffsetTop;
ctx.beginPath();
ctx.rect(brickX, brickY, brickWidth, brickHeight);
ctx.fillStyle = '#0095DD';
ctx.fill();
ctx.closePath();
}
}
}
requestAnimationFrame(draw);
}
function checkCollision(x, y, radius) {
for (var c = 0; c < brickColumnCount; c++) {
for (var r = 0; r < brickRowCount; r++) {
var b = bricks[c][r];
if (b.status == 1) {
var brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft;
var brickY = (r * (brickHeight + brickPadding)) + brickOffsetTop;
if (x > brickX && x < brickX + brickWidth &&
y > brickY && y < brickY + brickHeight) {
return true;
}
}
}
}
return false;
}
draw();
五、总结
通过本文的学习,相信你已经掌握了 HTML5 Canvas 动画制作的基础知识和实战技巧。在实际应用中,你可以根据自己的需求对动画进行优化和扩展。希望这篇文章能对你有所帮助,祝你学习愉快!