如何分别对两个变量的计数进行动画处理

时间:2019-05-25 02:47:09

标签: javascript html

我正在尝试在滚动的同一页上设置两组数字的动画。以下代码有效,但我注意到启动速度较慢,并且完成动画所需的时间更长。我还认为代码可以优化和改进。

JS

// Animated numbers when scrolled to
var a = 0;
$(window).scroll(function() {
  var oTop1 = $('.counter-1').offset().top - window.innerHeight;
  var oTop2 = $('.counter-2').offset().top - window.innerHeight;
  if (a == 0 && $(window).scrollTop() > oTop1) {
    $('.animate-numbers-1').each(function() {
      var $this = $(this),
        countTo = $this.attr('data-target');
      $({
        countNum: $this.text()
      }).animate({
          countNum: countTo
        },
        {
          duration: 1000,
          easing: 'swing',
          step: function() {
            $this.text(Math.floor(this.countNum));
          },
          complete: function() {
            $this.text(this.countNum);
            //alert('finished');
          }
        });
    });
  }
  if (a == 0 && $(window).scrollTop() > oTop2) {
    $('.animate-numbers-2').each(function() {
      var $this = $(this),
        countTo = $this.attr('data-target');
      $({
        countNum: $this.text()
      }).animate({
          countNum: countTo
        },
        {
          duration: 2500,
          easing: 'swing',
          step: function() {
            $this.text(Math.floor(this.countNum));
          },
          complete: function() {
            $this.text(this.countNum);
            //alert('finished');
          }
        });
    });
  }
});

我们将不胜感激。

2 个答案:

答案 0 :(得分:1)

$(window).scroll()在很短的时间内就会产生数百个事件。

在您的代码中,每个动画事件(几秒钟内发生数百次)都指定持续时间为一秒。因此:数百个事件(每个事件需要一秒钟)都需要在几秒钟内发生。经济增长放缓并不令人惊讶。

如果有一种方法可以限制事件,以便每隔几毫秒就触发一个事件,那不是很好吗?还是这样,只有一个事件会触发,直到间隔了几毫秒?

去抖动器 可确保对于可能发生很多次的事件仅发送一个信号。 限制 限制了函数在固定时间间隔内收到的调用次数-例如,每500ms仅发生一个事件。)或者,如Chris Coyer explains the two:< / p>

限制功能可随时间推移强制调用函数的最大次数。就像“每100毫秒最多执行一次此功能”。

去抖强制执行一个函数,直到经过一定时间后才再次调用该函数。就像“只有在没有调用它的情况下经过100毫秒时才执行此函数。”

In this article,大卫·沃尔什(David Walsh)解释了此非常流行的去抖动功能,该功能来自underscore.js

function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

Walsh用来演示如何使用上述功能的示例是:

var myEfficientFn = debounce(function() {
    // All the taxing stuff you do
}, 250);

window.addEventListener('resize', myEfficientFn);

参考文献:

https://davidwalsh.name/javascript-debounce-function

https://css-tricks.com/the-difference-between-throttling-and-debouncing/

https://underscorejs.org/#debounce

答案 1 :(得分:1)

在我的第一个答案中,我可能误解了您代码的性质。当window.scroll到达适当元素的顶部时,可能只需要动画运行一次。如果是这样,那么您所需要的只是一个指示符,以跟踪动画的状态:在动画执行之前为false,之后为true。 仅当指示器为假时才运行动画。

您可以为此使用全局变量-或仅将类添加到触发元素。缺少类(false)表示该动画尚未运行,具有类的表示该动画已经运行。

// Animated numbers when scrolled to
var a = 0;
$(window).scroll(function() {
    var oTop1 = $('.counter-1').offset().top - window.innerHeight;
    var oTop2 = $('.counter-2').offset().top - window.innerHeight;
    var done1 = $('.counter-1').hasClass('ani-done');
    var done2 = $('.counter-2').hasClass('ani-done');
    if (!done1 && a == 0 && $(window).scrollTop() > oTop1) {
        $('.animate-numbers-1').each(function() {
            //animation goes here
        });
        $('.counter-1').addClass('ani-done');
    }
    if (!done2 && a == 0 && $(window).scrollTop() > oTop2) {
        $('.animate-numbers-2').each(function() {
            //animation goes here
        });
        $('.counter-2').addClass('ani-done');
    }
});