You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js场景在浏览器标签页闲置后冻结,角色动画停止运行

Three.js场景在浏览器标签页闲置后冻结,角色动画停止运行

这个问题我之前做Three.js互动项目时也踩过坑!控制台没报错但场景假死,核心原因其实是浏览器的后台资源节流机制在搞鬼,给你拆解下:

问题根源

浏览器为了节省CPU和GPU资源,当标签页处于后台时,会把requestAnimationFrame的触发频率从平时的60次/秒,直接降到1次/秒甚至更低。看你Time.js里的delta计算逻辑:

this.delta = (currentTime - this.current) / 1000

如果标签页后台待个几分钟,切回前台的第一次tick计算时,currentTime - this.current会是一个超级大的数值——比如后台5分钟,这个差值就是300000毫秒,换算成delta就是300秒!

当这么夸张的deltaTime传给Three.js的AnimationMixer.update()时,mixer会尝试一次性处理这几百秒的动画:要么直接把动画跳到最后一帧(之后没有新的动画触发,看起来就像冻结),要么瞬间处理海量动画数据导致浏览器主线程阻塞,表现为场景完全假死,而且控制台不会抛出语法错误,因为这属于逻辑异常。

修复方案(两种思路,可单独用也可组合)

方案1:给deltaTime加上限(最直接的快速修复)

修改Time.js里的delta计算逻辑,强制给它设置一个最大值,比如限制为0.1秒(相当于10帧/秒的上限,既不影响正常动画流畅度,又能避免后台切回时的超大delta):

tick() {
    const currentTime = Date.now()
    // 限制delta最大值为0.1秒,彻底避免后台切回时的异常大值
    this.delta = Math.min((currentTime - this.current) / 1000, 0.1) 
    this.current = currentTime
    this.elapsed = (this.current - this.start) / 1000

    this.trigger('tick')

    window.requestAnimationFrame(() => {
        this.tick()
    })
}

如果不想修改全局的Time类,也可以在每个调用mixer.update的地方单独做限制,比如Box.js和TamagotchiController.js:

update(deltaTime) {
    if (this.mixer) {
        const safeDelta = Math.min(deltaTime, 0.1)
        this.mixer.update(safeDelta)
    }
}

方案2:监听页面可见性,切回时重置时间

给Time.js加上页面可见性监听,当页面从后台切回前台时,直接重置current时间,从根源避免超大delta的计算:

constructor() {
    super()

    // Setup
    this.start = Date.now()
    this.current = this.start
    this.elapsed = 0
    this.delta = 0.016

    // 监听页面前后台切换事件
    document.addEventListener('visibilitychange', () => {
        if (!document.hidden) {
            // 切回前台时,把current重置为当前时间,避免计算出异常大的delta
            this.current = Date.now()
        }
    })

    window.requestAnimationFrame(() => {
        this.tick()
    })
}

个人建议

最好把两个方案组合起来用:既限制delta的最大值,又监听页面可见性重置时间,双重保险下,不管标签页后台待多久,切回前台时动画都能正常运行。我之前用这个组合方案修复过类似的Tamagotchi风格项目,后台挂半小时再切回,动画依然丝滑,你可以试试!

备注:内容来源于stack exchange,提问作者cconsta1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 10:43:02