jQuery计数器,数到数后倒数
jQuery counter, counting down after reaching the number
我正在使用 jQuery 代码来为我的网页显示动画统计信息。
数字动画成功,但在达到最大值几秒钟后开始倒计时回到 1!我该如何解决这个问题?
// Checks if any particular element is in viewport
$.fn.isInViewport = function() {
var elementTop = $(this).offset().top;
var elementBottom = elementTop + $(this).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
return elementTop < viewportBottom;
};
// Animate numbers when scrolled into view
$(window).scroll(function() {
var counters_triggered = false;
var $counter_animated = $('.stat-counters > .stat > .counter > span');
if ($('.stat-counters').isInViewport() && !counters_triggered) {
counters_triggered = true;
$.each($counter_animated, function() {
var $counter = $(this);
$counter.prop('Counter', 0).animate({
Counter: $counter.text()
}, {
duration: 5000,
easing: 'swing',
step: function(now) {
$counter.text(Math.ceil(now));
}
});
});
}
});
.padding { height: 1000px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Scroll down...
<div class="padding"></div>
<div class="stat-counters d-flex justify-content-between align-items-start">
<div class="stat col-md-4 px-0">
<div class="counter">
<span>10</span>+
</div>
<span class="text">Years of Experience</span>
</div>
</div>
问题是因为您防止动画在滚动时被多次触发的逻辑不太正确,实际上是多次排队事件处理程序。
您的 isInViewport()
函数需要针对每个单独的元素而不是集合调用。因此 if
条件应该在 $.each()
.
内
此外,您使用单个变量来管理所有可动画元素的状态。您可以通过对它们单独使用 data
属性来单独管理它们的状态。
话虽如此,试试这个:
// Checks if any particular element is in viewport
$.fn.isInViewport = function() {
var elementTop = $(this).offset().top;
var elementBottom = elementTop + $(this).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
return elementTop < viewportBottom;
};
// Animate numbers when scrolled into view
$(window).scroll(function() {
$('.stat-counters > .stat > .counter > span').each((i, el) => {
var $counter = $(el);
if (!$counter.isInViewport() || $counter.data('animation-started'))
return;
$counter.data('animation-started', true).prop('Counter', 0).animate({
Counter: $counter.text()
}, {
duration: 5000,
easing: 'swing',
step: function(now) {
$counter.text(Math.ceil(now));
}
});
});
});
.padding {
height: 1000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Scroll down...
<div class="padding"></div>
<div class="stat-counters d-flex justify-content-between align-items-start">
<div class="stat col-md-4 px-0">
<div class="counter">
<span>10</span>+
</div>
<span class="text">Years of Experience</span>
</div>
</div>
我正在使用 jQuery 代码来为我的网页显示动画统计信息。
数字动画成功,但在达到最大值几秒钟后开始倒计时回到 1!我该如何解决这个问题?
// Checks if any particular element is in viewport
$.fn.isInViewport = function() {
var elementTop = $(this).offset().top;
var elementBottom = elementTop + $(this).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
return elementTop < viewportBottom;
};
// Animate numbers when scrolled into view
$(window).scroll(function() {
var counters_triggered = false;
var $counter_animated = $('.stat-counters > .stat > .counter > span');
if ($('.stat-counters').isInViewport() && !counters_triggered) {
counters_triggered = true;
$.each($counter_animated, function() {
var $counter = $(this);
$counter.prop('Counter', 0).animate({
Counter: $counter.text()
}, {
duration: 5000,
easing: 'swing',
step: function(now) {
$counter.text(Math.ceil(now));
}
});
});
}
});
.padding { height: 1000px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Scroll down...
<div class="padding"></div>
<div class="stat-counters d-flex justify-content-between align-items-start">
<div class="stat col-md-4 px-0">
<div class="counter">
<span>10</span>+
</div>
<span class="text">Years of Experience</span>
</div>
</div>
问题是因为您防止动画在滚动时被多次触发的逻辑不太正确,实际上是多次排队事件处理程序。
您的 isInViewport()
函数需要针对每个单独的元素而不是集合调用。因此 if
条件应该在 $.each()
.
此外,您使用单个变量来管理所有可动画元素的状态。您可以通过对它们单独使用 data
属性来单独管理它们的状态。
话虽如此,试试这个:
// Checks if any particular element is in viewport
$.fn.isInViewport = function() {
var elementTop = $(this).offset().top;
var elementBottom = elementTop + $(this).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
return elementTop < viewportBottom;
};
// Animate numbers when scrolled into view
$(window).scroll(function() {
$('.stat-counters > .stat > .counter > span').each((i, el) => {
var $counter = $(el);
if (!$counter.isInViewport() || $counter.data('animation-started'))
return;
$counter.data('animation-started', true).prop('Counter', 0).animate({
Counter: $counter.text()
}, {
duration: 5000,
easing: 'swing',
step: function(now) {
$counter.text(Math.ceil(now));
}
});
});
});
.padding {
height: 1000px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Scroll down...
<div class="padding"></div>
<div class="stat-counters d-flex justify-content-between align-items-start">
<div class="stat col-md-4 px-0">
<div class="counter">
<span>10</span>+
</div>
<span class="text">Years of Experience</span>
</div>
</div>