JavaScript游戏中更新Canvas图片源时如何消除闪烁?
解决Canvas图片切换时的闪烁问题
问题根源
你现在的代码存在两个核心问题导致闪烁:
- 每次
gameLoop都会重复设置img.src,哪怕玩家生命值状态没变化,这会反复触发图片重新加载 - 图片加载是异步操作,还没加载完成就调用
drawImage,会出现空白/旧图交替的闪烁现象;而且你没有预加载图片,切换时才开始加载,延迟更明显
解决办法
1. 预加载所有图片
提前把需要用到的两张图片加载完成,避免切换时临时加载导致的延迟
2. 仅在状态变化时切换图片
只有当生命值的状态(高于/低于50)发生改变时,才切换要显示的图片,避免重复设置src
3. 确保图片加载完成后再绘制
修改后的代码
HTML(无需改动)
<canvas id="canvas" width="200px" height="200px"></canvas>
JavaScript
let canvas; let ctx; let player; // 存储预加载好的两张图片 const images = { healthy: new Image(), hurt: new Image() }; // 记录当前显示的图片状态,避免重复切换 let currentImageState = 'healthy'; window.onload = function () { canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); player = { x: 0, y: 0, width: 20, height: 20, color: "#000000", health: 100 } // 预加载图片,所有图片加载完成后再启动游戏循环 let loadedCount = 0; const totalImages = Object.keys(images).length; // 图片加载完成的回调 function onImageLoad() { loadedCount++; if (loadedCount === totalImages) { // 所有图片加载完成后启动游戏 requestAnimationFrame(gameLoop); } } images.healthy.src = "img2"; images.healthy.onload = onImageLoad; images.hurt.src = "img1"; images.hurt.onload = onImageLoad; function draw() { // 每次绘制前先清空画布(避免残留旧内容) ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = player.color; ctx.fillRect(player.x, player.y, player.width, player.height); // 根据当前状态绘制对应的已加载图片 const currentImg = currentImageState === 'healthy' ? images.healthy : images.hurt; ctx.drawImage(currentImg, 0, 0); } function gameLoop() { // 判断当前应该显示的图片状态 const targetState = player.health < 50 ? 'hurt' : 'healthy'; // 只有状态变化时才切换,避免重复操作 if (targetState !== currentImageState) { currentImageState = targetState; } draw(); requestAnimationFrame(gameLoop); } }
关键改动说明
- 新增
images对象存储两张预加载的图片,确保绘制时用的是已经加载完成的资源 - 用
currentImageState记录当前显示状态,只有当生命值状态真的改变时才更新,避免每次循环重复触发图片加载 - 绘制前调用
clearRect清空画布,避免旧画面残留 - 所有图片加载完成后才启动游戏循环,确保第一次绘制就有可用的图片
内容的提问来源于stack exchange,提问作者Charles Masgalas
相关产品推荐
相关产品推荐

