
Canvas是即时模式绘图系统,fillRect()仅在调用时绘制一次;修改x/y变量后未重新调用该方法,图形位置自然不会更新。解决方法是在每次按键响应后清空画布并重绘矩形。
canvas是即时模式绘图系统,fillrect()仅在调用时绘制一次;修改x/y变量后未重新调用该方法,图形位置自然不会更新。解决方法是在每次按键响应后清空画布并重绘矩形。
Canvas不同于SVG等保留模式图形系统——它不维护场景树,也不自动追踪状态变化。你声明了 let x = 735, y = 360 并首次调用 ctx.fillRect(x, y, 100, 100),这确实在画布上画出了一个方块;但此后无论 x 和 y 如何改变,只要不再执行新的绘图指令,画布内容就永远停留在初始帧。
✅ 正确做法是:将绘图逻辑封装为可重复调用的函数,并在每次状态更新后主动重绘。同时,必须在重绘前清除旧图像,否则会留下移动残影。Canvas 提供 ctx.clearRect(0, 0, canvas.width, canvas.height) 实现高效清屏。
以下是修复后的核心代码(已优化键控逻辑、修复上下方向反向问题,并增强可读性):
const canvas = document.getElementById("canvasSpace");
const ctx = canvas.getContext("2d");
let x = 735, y = 360;
// 封装重绘逻辑
function render() {
// 清空整个画布(关键!)
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制当前坐标下的方块
ctx.fillRect(x, y, 100, 100);
}
// 修正方向:键盘↑应减y(向上移动),↓应加y(向下移动)
function moveLeft() { x -= 10; }
function moveUp() { y -= 10; } // 原代码中 moveUp 加 y 是错误的
function moveRight() { x += 10; }
function moveDown() { y += 10; }
document.addEventListener('keydown', function(event) {
switch(event.keyCode) {
case 37: moveLeft(); break;
case 38: moveUp(); break;
case 39: moveRight(); break;
case 40: moveDown(); break;
case 13: console.log(`x = ${x}, y = ${y}`); break; // 改用 console 更友好
}
render(); // 每次按键后立即重绘 —— 核心修复点
});
// 首帧渲染(避免依赖初始 fillRect)
render();⚠️ 注意事项:
-
方向坐标系:Canvas 的原点 (0,0) 在左上角,y 值增大表示向下移动,因此 ↑ 键应减少 y,↓ 键应增加 y(原代码中
moveUp错误地使用了y += 10); -
清屏时机:务必在
fillRect之前调用clearRect,否则会叠加绘制; -
性能提示:对于更复杂的动画,建议使用
requestAnimationFrame替代事件驱动重绘,以获得平滑帧率; -
现代替代:keyCode 已废弃,推荐改用
event.key(如'ArrowLeft')或event.code进行跨浏览器兼容判断。
总结:Canvas 的“无状态”本质决定了——变量变 ≠ 图像变,只有调用绘图 API 才能产生视觉反馈。掌握“清屏 → 更新状态 → 重绘”这一三步范式,是驾驭 Canvas 动画的基础能力。


















