在本教程中,我们将探讨 canvas
的高级用法,包括复杂的绘图 API、坐标系统和变换操作、平滑动画技术以及复杂应用和游戏开发的实践。
quadraticCurveTo
)二次贝塞尔曲线需要两个点:一个控制点和一个结束点。
// 获取 canvas 元素和 2d 上下文
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
// 开始绘制路径
ctx.beginPath();
ctx.moveTo(50, 50); // 起点
ctx.quadraticCurveTo(200, 100, 50, 200); // 控制点(200,100),结束点(50,200)
ctx.strokeStyle = 'blue';
ctx.stroke(); // 绘制路径
bezierCurveTo
)三次贝塞尔曲线需要三个点:两个控制点和一个结束点。
// 开始绘制路径
ctx.beginPath();
ctx.moveTo(50, 250); // 起点
ctx.bezierCurveTo(150, 200, 200, 300, 300, 250); // 控制点1(150,200),控制点2(200,300),结束点(300,250)
ctx.strokeStyle = 'red';
ctx.stroke(); // 绘制路径
通过 translate
方法可以移动 canvas 的坐标系统。
// 平移坐标系
ctx.translate(100, 100);
// 在新的坐标系中绘制矩形
ctx.fillStyle = 'green';
ctx.fillRect(0, 0, 50, 50);
通过 rotate
方法可以旋转 canvas 的坐标系统。
// 重置变换矩阵
ctx.resetTransform();
// 平移到旋转中心
ctx.translate(150, 150);
// 旋转45度(弧度制,45度=PI/4)
ctx.rotate(Math.PI / 4);
// 绘制旋转后的矩形
ctx.fillStyle = 'purple';
ctx.fillRect(-25, -25, 50, 50); // 以旋转中心为原点绘制
通过 scale
方法可以缩放 canvas 的坐标系统。
// 重置变换矩阵
ctx.resetTransform();
// 平移到缩放中心
ctx.translate(250, 250);
// 缩放
ctx.scale(2, 2); // 宽高都缩放2倍
// 绘制缩放后的矩形
ctx.fillStyle = 'orange';
ctx.fillRect(-25, -25, 50, 50); // 以缩放中心为原点绘制
通过 requestAnimationFrame
方法可以实现平滑动画。
var x = 0;
function draw() {
// 清除 canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制一个移动的矩形
ctx.fillStyle = 'blue';
ctx.fillRect(x, 50, 50, 50);
// 更新 x 坐标
x += 1;
// 请求下一帧
requestAnimationFrame(draw);
}
// 启动动画
draw();
在游戏开发中,碰撞检测是一个重要的概念。这里是一个简单的碰撞检测示例。
var ballRadius = 10;
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
// 碰撞检测
if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if (y + dy > canvas.height - ballRadius || y + dy < ballRadius) {
dy = -dy;
}
x += dx;
y += dy;
requestAnimationFrame(draw);
}
draw();
通过结合键盘事件处理,可以开发简单的键盘控制游戏。
var paddleHeight = 10;
var paddleWidth = 75;
var paddleX = (canvas.width - paddleWidth) / 2;
var rightPressed = false;
var leftPressed = false;
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if (e.key == "Right" || e.key == "ArrowRight") {
rightPressed = true;
} else if (e.key == "Left" || e.key == "ArrowLeft") {
leftPressed = true;
}
}
function keyUpHandler(e) {
if (e.key == "Right" || e.key == "ArrowRight") {
rightPressed = false;
} else if (e.key == "Left" || e.key == "ArrowLeft") {
leftPressed = false;
}
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPaddle();
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 7;
} else if (leftPressed && paddleX > 0) {
paddleX -= 7;
}
requestAnimationFrame(draw);
}
draw();