You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

JavaScript帧率时序操作咨询:小游戏帧动画实现方案优化建议

优化帧率动画的实现方案

嘿,你的加载动画思路是对的,但原代码确实有几个可以改进的地方,不管是代码维护性还是动画流畅度都能提升不少。先说说原代码里的小问题:

  • 随着帧数量增加,switch语句会变得无比冗长,新增或修改帧都要改一堆case,维护起来特别麻烦
  • clearInterval()没传定时器引用,这根本停不了定时器,会导致不必要的性能浪费
  • 逻辑里的loadCount >=6ticks的判断可以更简洁,没必要绕这么多弯

下面给你两种更优的实现方式,按需选择:

方式一:用数组简化setInterval版本

把所有帧的图片路径存到数组里,直接通过索引切换帧,代码瞬间清爽很多:

// 把所有帧的路径统一存到数组,新增/删除帧直接改数组就行
const framePaths = [
    "src/images/cenario/img004.png",
    "src/images/cenario/img005.png",
    "src/images/cenario/img006.png",
    // 继续添加其他帧的路径...
];

let currentFrameIndex = 0;
const frameInterval = 500; // 每帧停留的毫秒数
let animationTimer; // 保存定时器ID,方便停止

function updateLoadingFrame() {
    // 更新图片资源
    $("#img").attr("src", framePaths[currentFrameIndex]);
    currentFrameIndex++;

    // 播放到最后一帧时停止动画
    if (currentFrameIndex >= framePaths.length) {
        clearInterval(animationTimer);
        console.log("加载动画播放完成");
    }
}

// 启动动画,记得保存定时器ID
animationTimer = setInterval(updateLoadingFrame, frameInterval);

方式二:更推荐的requestAnimationFrame版本

requestAnimationFrame是浏览器专门为动画设计的API,它会和浏览器的刷新频率同步,比setInterval更流畅,还能避免后台标签页浪费性能:

const framePaths = [
    "src/images/cenario/img004.png",
    "src/images/cenario/img005.png",
    "src/images/cenario/img006.png",
    // 其他帧路径...
];

let currentFrameIndex = 0;
const frameDuration = 500; // 每帧显示的毫秒数
let lastFrameTime = 0;

function loadingAnimation(timestamp) {
    // 初始化首次执行的时间
    if (!lastFrameTime) lastFrameTime = timestamp;

    // 计算距离上一帧的时间差
    const elapsed = timestamp - lastFrameTime;

    // 时间差达标就切换帧
    if (elapsed >= frameDuration) {
        $("#img").attr("src", framePaths[currentFrameIndex]);
        currentFrameIndex++;
        lastFrameTime = timestamp; // 更新上一帧时间
    }

    // 没播完就继续请求下一帧
    if (currentFrameIndex < framePaths.length) {
        requestAnimationFrame(loadingAnimation);
    } else {
        console.log("加载动画播放完成");
    }
}

// 启动动画
requestAnimationFrame(loadingAnimation);

额外优化小技巧

  • 预加载图片:如果不想切换帧时出现空白,可以提前加载所有图片,比如用Image对象批量加载,等所有图片加载完成后再启动动画
  • 循环播放:如果需要循环动画,只需要在currentFrameIndex >= framePaths.length时把currentFrameIndex重置为0即可

内容的提问来源于stack exchange,提问作者zoshida

火山引擎 最新活动