js实现投球
实现投球动画的步骤
使用Canvas绘制球体
创建一个Canvas元素,通过arc()方法绘制圆形球体。设置填充颜色和描边样式,使球体具有立体感。
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
function drawBall(x, y, radius) {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
}
定义球的运动轨迹 使用抛物线公式模拟投球轨迹。水平方向匀速运动,垂直方向受重力加速度影响。
let ball = {
x: 50,
y: canvas.height - 30,
radius: 10,
dx: 5, // 水平速度
dy: -15, // 初始垂直速度
gravity: 0.4
};
function updateBallPosition() {
ball.x += ball.dx;
ball.y += ball.dy;
ball.dy += ball.gravity; // 重力影响
}
动画循环实现
通过requestAnimationFrame创建动画循环,每帧清除画布并重绘球体。

function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall(ball.x, ball.y, ball.radius);
updateBallPosition();
if (ball.y + ball.radius < canvas.height) {
requestAnimationFrame(animate);
}
}
animate();
添加碰撞检测
边界碰撞检测 当球碰到画布底部时,模拟反弹效果,通过减少垂直速度实现能量损失。
function checkCollision() {
// 底部碰撞
if (ball.y + ball.radius > canvas.height) {
ball.y = canvas.height - ball.radius;
ball.dy = -ball.dy * 0.7; // 反弹系数
}
// 右侧碰撞
if (ball.x + ball.radius > canvas.width) {
ball.x = canvas.width - ball.radius;
ball.dx = -ball.dx * 0.7;
}
}
交互控制投球
鼠标/触摸事件监听 通过事件监听获取投球起始点,计算投掷力度和角度。

let isDragging = false;
let startPos = {};
canvas.addEventListener('mousedown', (e) => {
isDragging = true;
startPos = { x: e.clientX, y: e.clientY };
});
canvas.addEventListener('mouseup', (e) => {
if (isDragging) {
const endPos = { x: e.clientX, y: e.clientY };
const dx = (endPos.x - startPos.x) / 10;
const dy = (endPos.y - startPos.y) / 10;
ball.x = startPos.x;
ball.y = startPos.y;
ball.dx = dx;
ball.dy = dy;
animate();
isDragging = false;
}
});
性能优化建议
使用双缓冲技术 创建离屏Canvas进行预渲染,减少画面闪烁。
节流动画帧率 通过时间戳控制帧率,避免过度消耗资源。
let lastTime = 0;
function animate(timestamp) {
if (timestamp - lastTime > 16) { // ~60fps
// 更新和绘制逻辑
lastTime = timestamp;
}
requestAnimationFrame(animate);
}
添加运动衰减 随时间减少球体速度,最终停止运动,避免无限反弹。
function applyFriction() {
ball.dx *= 0.99;
if (Math.abs(ball.dx) < 0.1) ball.dx = 0;
if (Math.abs(ball.dy) < 0.1) ball.dy = 0;
}






