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

jQuery数字计数动画运行一段时间后失效,socket.io仍正常推送数据

数字动画运行一段时间后停止,Socket.io连接正常但无动画效果

我通过Socket.io与服务器建立了正常连接,当数据发生变化时,服务器会向脚本推送新数据,以此触发页面更新函数。但运行一段时间后,数字不再执行动画效果,Socket.io连接仍处于正常状态,控制台也能看到新数据推送——若移除动画相关逻辑,数字可及时显示。

相关代码

JavaScript代码

let obj = {
    values: {
        "number1": 200,
        "number2": 300
    }
}

Object.entries(obj.values).forEach(entry => {
    const [key, value] = entry;
    // Update corresponding ID
    if (value) {
        animateNumbers($('#' + key + "_value"), value);
    }
});

// Function for animating numbers
function animateNumbers(elm, value) {
    let nr = elm.text();
    let dcPlaces;
    let nrIsFloat = false;

    // Determine the type of Number
    if (!isNaN(nr) && nr.toString().indexOf('.') != -1) {
        nrIsFloat = true;
        dcPlaces = nr.split('.');
        dcPlaces = dcPlaces.length > 1 ? dcPlaces[1].length : 0;
    }

    elm.prop('Counter', nr).animate({
        Counter: value
    }, {
        duration: 1000,
        easing: "swing",
        step: function (now) {
            // Check added for decimal number
            elm.text(nrIsFloat ? now.toFixed(dcPlaces) : Math.ceil(now));
        }
    });
    console.log(`Present Number: ${nr} - New Number: ${value}`);
}

HTML代码

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span id="number1_value"></span><br/>
<span id="number2_value"></span><br/>

问题排查与解决方案

1. jQuery动画队列堆积冲突

多次触发动画时,jQuery会将动画加入元素的动画队列,如果前一个动画未完成就触发新动画,会导致队列堆积,甚至后续动画被阻塞。尤其是Socket推送频率较高时,这个问题会快速显现。

解决方法:启动新动画前,停止元素上的现有动画并清空队列:

// 修改animateNumbers函数中的动画启动代码
elm.stop(true, true).prop('Counter', nr).animate({
    Counter: value
}, {
    duration: 1000,
    easing: "swing",
    step: function (now) {
        elm.text(nrIsFloat ? now.toFixed(dcPlaces) : Math.ceil(now));
    }
});

stop(true, true)的作用:第一个true清空元素的动画队列,第二个true让当前动画直接跳转到结束状态,避免队列积压。

2. 初始值获取与类型判断异常

当元素文本为空或非有效数字时,nr = elm.text()会拿到空字符串或无效值,!isNaN(nr)的判断逻辑会出现偏差(比如空字符串转数字为0,!isNaN('')返回true),导致后续动画计算错误。

解决方法:强制转换并校验初始值的合法性:

function animateNumbers(elm, value) {
    // 转为数字,无效则设为0
    let nr = parseFloat(elm.text()) || 0;
    let nrIsFloat = Number.isFinite(nr) && !Number.isInteger(nr);
    let dcPlaces = nrIsFloat ? nr.toString().split('.')[1].length : 0;

    elm.stop(true, true).prop('Counter', nr).animate({
        Counter: value
    }, {
        duration: 1000,
        easing: "swing",
        step: function (now) {
            elm.text(nrIsFloat ? now.toFixed(dcPlaces) : Math.ceil(now));
        }
    });
    console.log(`Present Number: ${nr} - New Number: ${value}`);
}

3. 自定义动画属性Counter的隐式问题

jQuery对自定义DOM属性的动画处理可能存在兼容性或状态异常问题,多次赋值后可能导致属性值无法正确计算差值,进而动画失效。

解决方法:改用原生requestAnimationFrame实现动画,摆脱对jQuery动画队列的依赖:

function animateNumbers(elm, value) {
    let start = parseFloat(elm.text()) || 0;
    let isFloat = Number.isFinite(start) && !Number.isInteger(start);
    let decimals = isFloat ? start.toString().split('.')[1].length : 0;
    const duration = 1000;
    const startTime = Date.now();

    const update = () => {
        const elapsed = Date.now() - startTime;
        const progress = Math.min(elapsed / duration, 1);
        // 模拟jQuery的swing缓动效果
        const current = start + (value - start) * (1 - Math.cos(progress * Math.PI / 2));
        elm.text(isFloat ? current.toFixed(decimals) : Math.ceil(current));
        if (progress < 1) {
            requestAnimationFrame(update);
        }
    };
    update();
    console.log(`Present Number: ${start} - New Number: ${value}`);
}

4. 频繁触发导致的性能限制

如果Socket推送频率过高,短时间内重复触发动画会占用大量浏览器资源,浏览器可能会为了性能暂停动画执行。

解决方法:添加防抖函数,避免短时间内重复触发同一元素的动画:

// 防抖工具函数
function debounce(func, wait) {
    let timeout;
    return function(...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => func.apply(this, args), wait);
    };
}

// 包装动画函数,设置500ms防抖间隔
const debouncedAnimate = debounce(animateNumbers, 500);

// 在Socket回调中使用防抖后的函数
Object.entries(obj.values).forEach(entry => {
    const [key, value] = entry;
    if (value) {
        debouncedAnimate($('#' + key + "_value"), value);
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 09:45:01