使用 Javascript 制作计数器动画

发布于 2024-11-26 02:39:42 字数 1971 浏览 0 评论 0原文

我有几个相当简单的 JavaScript 函数,它们可以根据用户操作对数字的转换进行动画处理,上下移动。页面上有许多滑块,它们在回调中调用 recalculateDiscount() ,根据它们的选择将数字向上或向下动画化。

var animationTimeout;

// Recalculate discount
function recalculateDiscount() {
    // Get the previous total from global variable
    var previousDiscount = totalDiscount;
    // Calculate new total
    totalDiscount = calculateDiscount().toFixed(0);
    // Calculate difference
    var difference = previousDiscount - totalDiscount;
    // If difference is negative, count up to new total
    if (difference < 0) {
        updateDiscount(true, totalDiscount);
    }
    // If difference is positive, count down to new total
    else if (difference > 0) {
        updateDiscount(false, totalDiscount);
    }
}

function updateDiscount(countUp, newValue) {
    // Clear previous timeouts
    clearTimeout(animationTimeout);
    // Get value of current count
    var currentValue = parseInt($(".totalSavingsHeader").html().replace("$", ""));
    // If we've reached desired value, end
    if (currentValue === newValue) { return; }
    // If counting up, increase value by one and recursively call with slight delay
    if (countUp) {
        $(".totalSavingsHeader").html("$" + (currentValue + 1));
        animationTimeout = setTimeout("updateDiscount(" + countUp + "," + totalDiscount + ")", 1);
    }
    // Otherwise assume we're counting down, decrease value by one and recursively call with slight delay
    else {
        $(".totalSavingsHeader").html("$" + (currentValue - 1));
        animationTimeout = setTimeout("updateDiscount(" + countUp + "," + totalDiscount + ")", 1);
    }
}

该脚本在大多数情况下都运行良好,但存在一些问题。首先,较旧的浏览器动画速度较慢(IE6 和 7),并且如果用户在滑块仍在动画内时再次移动滑块,则会感到困惑。

较新的浏览器工作得很好,除了在某些情况下,如果用户在动画中移动滑块,它似乎开始朝错误的方向前进。因此, updateDiscount() 会被调用,并带有一个新值和一个向上计数而不是向下计数的指令。因此,动画在无限循环中走向错误的方向,因为当它以错误的方向计数时,它永远不会达到正确的值。

我很困惑为什么会发生这种情况,我的 setTimeout() 经验非常低,这可能是问题所在。如果我没有提供足够的信息,请告诉我。

谢谢 :)

I have a couple of fairly simple javascript functions which animate the transition of a number, going up and down based on user actions. There are a number of sliders on the page which within their callback they call recalculateDiscount() which animates the number up or down based on their selection.

var animationTimeout;

// Recalculate discount
function recalculateDiscount() {
    // Get the previous total from global variable
    var previousDiscount = totalDiscount;
    // Calculate new total
    totalDiscount = calculateDiscount().toFixed(0);
    // Calculate difference
    var difference = previousDiscount - totalDiscount;
    // If difference is negative, count up to new total
    if (difference < 0) {
        updateDiscount(true, totalDiscount);
    }
    // If difference is positive, count down to new total
    else if (difference > 0) {
        updateDiscount(false, totalDiscount);
    }
}

function updateDiscount(countUp, newValue) {
    // Clear previous timeouts
    clearTimeout(animationTimeout);
    // Get value of current count
    var currentValue = parseInt($(".totalSavingsHeader").html().replace("$", ""));
    // If we've reached desired value, end
    if (currentValue === newValue) { return; }
    // If counting up, increase value by one and recursively call with slight delay
    if (countUp) {
        $(".totalSavingsHeader").html("$" + (currentValue + 1));
        animationTimeout = setTimeout("updateDiscount(" + countUp + "," + totalDiscount + ")", 1);
    }
    // Otherwise assume we're counting down, decrease value by one and recursively call with slight delay
    else {
        $(".totalSavingsHeader").html("$" + (currentValue - 1));
        animationTimeout = setTimeout("updateDiscount(" + countUp + "," + totalDiscount + ")", 1);
    }
}

The script works really well for the most part however there are a couple of problems. Firstly, older browsers animate more slowly (IE6 & 7) and get confused if the user moves the slider again whilst it is still within the animation.

Newer browsers work great EXCEPT for on some occasions, if the user moves the slider mid-animation, it seems that it starts progressing in the wrong direction. So for updateDiscount() gets called with a new value and a directive to count up instead of down. As a result the animation goes the wrong direction on an infinite loop as it will never reach the correct value when it's counting in the wrong direction.

I'm stumped as to why this happens, my setTimeout() experience is quite low which may be the problem. If I haven't provided enough info, just let me know.

Thank you :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

没有心的人 2024-12-03 02:39:42

以下是如何有效地使用 setTimeout

animationTimeout = setTimeout(function {
   updateDiscount(countUp,totalDiscount);
},20);

传递匿名函数来帮助您避免使用 eval。

另外:使用 1 毫秒,这太快了,有时会冻结旧的浏览器。因此,使用用户甚至不会注意到的更高的值可以更好地工作。

让我知道这是否适合您

Here is how you use setTimeout efficiently

animationTimeout = setTimeout(function {
   updateDiscount(countUp,totalDiscount);
},20);

passing an anonymous function help you avoid using eval.

Also: using 1 millisecond, which is too fast and will freeze older browsers sometimes. So using a higher which will not even be noticed by the user can work better.

Let me know if this works out for you

断肠人 2024-12-03 02:39:42

好吧,认为它已经修复了......

稍微重构了代码,这是最终产品,看起来已经解决了错误:

var animationTimeout;

function recalculateDiscount() {
    var previousDiscount = parseInt(totalDiscount);
    totalDiscount = parseInt(calculateDiscount());
    if (($.browser.msie && parseFloat($.browser.version) < 9) || $.browser.opera) {
        $(".totalSavingsHeader").html("$" + totalDiscount);
    }
    else {
        if (previousDiscount != totalDiscount) {
            clearTimeout(animationTimeout);
            updateDiscount(totalDiscount);
        }
    }
}

function updateDiscount(newValue) {
    var currentValue = parseInt($(".totalSavingsHeader").html().replace("$", ""));
    if (parseInt(currentValue) === parseInt(newValue)) {
        clearTimeout(animationTimeout);
        return;
    }
    var direction = (currentValue < newValue) ? "up" : "down";
    var htmlValue = direction === "up" ? (currentValue + 1) : (currentValue - 1);
    $(".totalSavingsHeader").html("$" + htmlValue);
    animationTimeout = setTimeout(function () { updateDiscount(newValue); }, 5);
}

将为 Ibu 和 Ibu 提供积分。 prodigitalson,谢谢您的帮助:)

OK think it's fixed...

Refactored code a little bit, here's final product which looks to have resolved bug:

var animationTimeout;

function recalculateDiscount() {
    var previousDiscount = parseInt(totalDiscount);
    totalDiscount = parseInt(calculateDiscount());
    if (($.browser.msie && parseFloat($.browser.version) < 9) || $.browser.opera) {
        $(".totalSavingsHeader").html("$" + totalDiscount);
    }
    else {
        if (previousDiscount != totalDiscount) {
            clearTimeout(animationTimeout);
            updateDiscount(totalDiscount);
        }
    }
}

function updateDiscount(newValue) {
    var currentValue = parseInt($(".totalSavingsHeader").html().replace("$", ""));
    if (parseInt(currentValue) === parseInt(newValue)) {
        clearTimeout(animationTimeout);
        return;
    }
    var direction = (currentValue < newValue) ? "up" : "down";
    var htmlValue = direction === "up" ? (currentValue + 1) : (currentValue - 1);
    $(".totalSavingsHeader").html("$" + htmlValue);
    animationTimeout = setTimeout(function () { updateDiscount(newValue); }, 5);
}

Will give points to both Ibu & prodigitalson, thank you for your help :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文