animate() 在滚动停止之前不触发
animate() not firing until scrolling stops
目标:
我希望我的固定 header 元素在用户向下滚动时向上滑出屏幕(有效隐藏),并在用户向上滚动时向下移动。
问题:
实际的动画和逻辑工作正常,但动画直到用户停止滚动才开始,而不是在滚动仍在继续时开始。
这已在 Chrome 和 Firefox 上复制。然而,使用完全相同的代码,解决方案似乎在 JSFiddle 中正常工作:
https://jsfiddle.net/8cj7v6n5/
Javascript:
var lastScroll = 0;
var scrollDelta = 10;
var animating = false;
$(window).on('scroll', function() {
//if animation isn't currently taking place, begin animation
if (!animating) hasScrolled();
});
function hasScrolled() {
var st = $(window).scrollTop();
//if user hasn't scrolled past scrollDelta, do not animate yet
if(Math.abs(lastScroll - st) <= scrollDelta)
return;
animating = true;
if (st > lastScroll && st >= 0){ // Scroll Down
$('header').animate( { top: -80 }, { queue: false, duration: 500, complete: function() { animating = false; } });
}
else { // Scroll Up
$('header').animate( { top: 0 }, { queue: false, duration: 500, complete: function() { animating = false } });
}
lastScroll = st;
}
不使用动画标志,您可以只将动画排队并使用 stop() 和 animate() 到 运行 队列中的最后一个动画。
编辑:您可以使用方向标志来检测滚动方向是否发生变化。
JavaScript:
var lastScroll = 0;
var scrollDelta = 10;
var animationDirection = 0; // 0 for up direction, 1 for down direction
$(window).on('scroll', function () {
hasScrolled();
});
function hasScrolled() {
var st = $(window).scrollTop();
if (Math.abs(lastScroll - st) <= scrollDelta)
return;
if (st > lastScroll && st >= 0 && animationDirection == 0) { // Scroll Down
$('header').stop().animate({ top: -80 }, 500);
animationDirection = 1;
}
else if (st <= lastScroll && st >= 0 && animationDirection == 1) { // Scroll Up
animationDirection = 0;
$('header').stop().animate({ top: 0 }, 500);
}
lastScroll = st;
}
JSFiddle:https://jsfiddle.net/8cj7v6n5/27/
问题是您用于 lastscroll 的值仅在动画发生时更新。它应该始终更新,因为您可以在动画 运行 时滚动屏幕,并且 lastscroll 值将与真正的顶部滚动值不同,然后您再次比较这些值,系统认为是高于或低于确实如此。
示例:
- Window scrolltop 为 0 你向下滚动 -> 第一个动画
fires,Window此时scrolltop为100,赋值给
变量圣。
- 您继续向下滚动 -> 标志打开,动画打开
不火,Window scrolltop 此时是 200 但不是
分配。
- 第一个动画结束 -> st 分配给 lastscroll (100)
- 你向上滚动的下一个动作,lastscroll 是 100,real scroll top 是
实际上是 200。新滚动顶部是 190,但是当你与 lastscroll 比较时,系统认为你正在向下滚动。
这是更正后的代码:
var lastScroll = 0;
var scrollDelta = 10;
var animating = false;
$(window).on('scroll', function() {
//if animation isn't currently taking place, begin animation
if (!animating) {hasScrolled()}else{lastScroll = $(window).scrollTop();};
});
function hasScrolled() {
var st = $(window).scrollTop();
//if user hasn't scrolled past scrollDelta, do not animate yet
if(Math.abs(lastScroll - st) <= scrollDelta)
return;
animating = true;
if (st > lastScroll && st >= 0){ // Scroll Down
$('header').animate( { top: -80 }, { queue: false, duration: 500, complete: function() { animating = false; } });
}
else { // Scroll Up
$('header').animate( { top: 0 }, { queue: false, duration: 500, complete: function() { animating = false } });
}
lastScroll = st;
}
这是我用来调试控制台日志的 fiddle:
https://jsfiddle.net/8cj7v6n5/18/
编辑:
此代码在 fiddle 之外对我有效,请尝试如果有效,则问题出在页面的另一个组件中,未在此处发布。
也许是另一行代码或库覆盖了 .animate() 或滚动事件的行为。
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8">
var lastScroll = 0;
var scrollDelta = 10;
var animating = false;
var lastScroll = 0;
var scrollDelta = 10;
var animating = false;
$(window).on('scroll', function() {
//if animation isn't currently taking place, begin animation
if (!animating) {hasScrolled()}else{lastScroll = $(window).scrollTop();};
});
function hasScrolled() {
var st = $(window).scrollTop();
//if user hasn't scrolled past scrollDelta, do not animate yet
if(Math.abs(lastScroll - st) <= scrollDelta)
return;
animating = true;
if (st > lastScroll && st >= 0){ // Scroll Down
$('header').animate( { top: -80 }, { queue: false, duration: 500, complete: function() { animating = false; } });
}
else { // Scroll Up
$('header').animate( { top: 0 }, { queue: false, duration: 500, complete: function() { animating = false } });
}
lastScroll = st;
}
</script>
<style type="text/css">
body {
height: 2000px;
width: 100%;
background-image: url(http://static.tumblr.com/cc2l8yc/qa8nbkd68/2.jpg);
background-repeat: repeat;
}
header {
height: 80px;
width: 100%;
background-color: red;
position: fixed;
top: 0;
left: 0;
}
</style>
</head>
<body>
<header></header>
</body>
</html>
目标:
我希望我的固定 header 元素在用户向下滚动时向上滑出屏幕(有效隐藏),并在用户向上滚动时向下移动。
问题:
实际的动画和逻辑工作正常,但动画直到用户停止滚动才开始,而不是在滚动仍在继续时开始。
这已在 Chrome 和 Firefox 上复制。然而,使用完全相同的代码,解决方案似乎在 JSFiddle 中正常工作:
https://jsfiddle.net/8cj7v6n5/
Javascript:
var lastScroll = 0;
var scrollDelta = 10;
var animating = false;
$(window).on('scroll', function() {
//if animation isn't currently taking place, begin animation
if (!animating) hasScrolled();
});
function hasScrolled() {
var st = $(window).scrollTop();
//if user hasn't scrolled past scrollDelta, do not animate yet
if(Math.abs(lastScroll - st) <= scrollDelta)
return;
animating = true;
if (st > lastScroll && st >= 0){ // Scroll Down
$('header').animate( { top: -80 }, { queue: false, duration: 500, complete: function() { animating = false; } });
}
else { // Scroll Up
$('header').animate( { top: 0 }, { queue: false, duration: 500, complete: function() { animating = false } });
}
lastScroll = st;
}
不使用动画标志,您可以只将动画排队并使用 stop() 和 animate() 到 运行 队列中的最后一个动画。
编辑:您可以使用方向标志来检测滚动方向是否发生变化。
JavaScript:
var lastScroll = 0;
var scrollDelta = 10;
var animationDirection = 0; // 0 for up direction, 1 for down direction
$(window).on('scroll', function () {
hasScrolled();
});
function hasScrolled() {
var st = $(window).scrollTop();
if (Math.abs(lastScroll - st) <= scrollDelta)
return;
if (st > lastScroll && st >= 0 && animationDirection == 0) { // Scroll Down
$('header').stop().animate({ top: -80 }, 500);
animationDirection = 1;
}
else if (st <= lastScroll && st >= 0 && animationDirection == 1) { // Scroll Up
animationDirection = 0;
$('header').stop().animate({ top: 0 }, 500);
}
lastScroll = st;
}
JSFiddle:https://jsfiddle.net/8cj7v6n5/27/
问题是您用于 lastscroll 的值仅在动画发生时更新。它应该始终更新,因为您可以在动画 运行 时滚动屏幕,并且 lastscroll 值将与真正的顶部滚动值不同,然后您再次比较这些值,系统认为是高于或低于确实如此。
示例:
- Window scrolltop 为 0 你向下滚动 -> 第一个动画 fires,Window此时scrolltop为100,赋值给 变量圣。
- 您继续向下滚动 -> 标志打开,动画打开 不火,Window scrolltop 此时是 200 但不是 分配。
- 第一个动画结束 -> st 分配给 lastscroll (100)
- 你向上滚动的下一个动作,lastscroll 是 100,real scroll top 是 实际上是 200。新滚动顶部是 190,但是当你与 lastscroll 比较时,系统认为你正在向下滚动。
这是更正后的代码:
var lastScroll = 0;
var scrollDelta = 10;
var animating = false;
$(window).on('scroll', function() {
//if animation isn't currently taking place, begin animation
if (!animating) {hasScrolled()}else{lastScroll = $(window).scrollTop();};
});
function hasScrolled() {
var st = $(window).scrollTop();
//if user hasn't scrolled past scrollDelta, do not animate yet
if(Math.abs(lastScroll - st) <= scrollDelta)
return;
animating = true;
if (st > lastScroll && st >= 0){ // Scroll Down
$('header').animate( { top: -80 }, { queue: false, duration: 500, complete: function() { animating = false; } });
}
else { // Scroll Up
$('header').animate( { top: 0 }, { queue: false, duration: 500, complete: function() { animating = false } });
}
lastScroll = st;
}
这是我用来调试控制台日志的 fiddle: https://jsfiddle.net/8cj7v6n5/18/
编辑: 此代码在 fiddle 之外对我有效,请尝试如果有效,则问题出在页面的另一个组件中,未在此处发布。 也许是另一行代码或库覆盖了 .animate() 或滚动事件的行为。
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript" charset="utf-8">
var lastScroll = 0;
var scrollDelta = 10;
var animating = false;
var lastScroll = 0;
var scrollDelta = 10;
var animating = false;
$(window).on('scroll', function() {
//if animation isn't currently taking place, begin animation
if (!animating) {hasScrolled()}else{lastScroll = $(window).scrollTop();};
});
function hasScrolled() {
var st = $(window).scrollTop();
//if user hasn't scrolled past scrollDelta, do not animate yet
if(Math.abs(lastScroll - st) <= scrollDelta)
return;
animating = true;
if (st > lastScroll && st >= 0){ // Scroll Down
$('header').animate( { top: -80 }, { queue: false, duration: 500, complete: function() { animating = false; } });
}
else { // Scroll Up
$('header').animate( { top: 0 }, { queue: false, duration: 500, complete: function() { animating = false } });
}
lastScroll = st;
}
</script>
<style type="text/css">
body {
height: 2000px;
width: 100%;
background-image: url(http://static.tumblr.com/cc2l8yc/qa8nbkd68/2.jpg);
background-repeat: repeat;
}
header {
height: 80px;
width: 100%;
background-color: red;
position: fixed;
top: 0;
left: 0;
}
</style>
</head>
<body>
<header></header>
</body>
</html>