JavaScript 中检测滚动方向

所以我试图使用 JavaScript on scroll 来调用一个函数。但是我想知道我是否可以不使用 jQuery 检测滚动的方向。如果没有,有什么变通办法吗?

我想只放一个“顶部”按钮,但如果可以的话,我想避免展示这个按钮。

我刚刚尝试使用如下这段代码,但它不起作用:

if document.body.scrollTop <= 0 {
alert ("scrolling down")
} else {
alert ("scrolling up")
}
292457 次浏览

你可以使用document.documentElement.scrollTop来获取滚动条的位置。然后就是简单地将它与之前的位置进行比较。

可以通过存储之前的scrollTop值并将当前scrollTop值与其进行比较来检测它。

JavaScript:

var lastScrollTop = 0;


// element should be replaced with the actual target element on which you have applied scroll, use window in case of no target element.
element.addEventListener("scroll", function(){ // or window.addEventListener("scroll"....
var st = window.pageYOffset || document.documentElement.scrollTop; // Credits: "https://github.com/qeremy/so/blob/master/so.dom.js#L426"
if (st > lastScrollTop){
// downscroll code
} else {
// upscroll code
}
lastScrollTop = st <= 0 ? 0 : st; // For Mobile or negative scrolling
}, false);

使用这个来找到滚动方向。这只是为了找到垂直滚动的方向。支持所有跨浏览器。

var scrollableElement = document.body; //document.getElementById('scrollableElement');


scrollableElement.addEventListener('wheel', checkScrollDirection);


function checkScrollDirection(event) {
if (checkScrollDirectionIsUp(event)) {
console.log('UP');
} else {
console.log('Down');
}
}


function checkScrollDirectionIsUp(event) {
if (event.wheelDelta) {
return event.wheelDelta > 0;
}
return event.deltaY < 0;
}

使用实例

这是对prateek的回答的补充。在IE的代码中似乎有一个小故障,所以我决定修改它一点也不花哨(只是另一个条件)

$('document').ready(function() {
var lastScrollTop = 0;
$(window).scroll(function(event){
var st = $(this).scrollTop();
if (st > lastScrollTop){
console.log("down")
}
else if(st == lastScrollTop)
{
//do nothing
//In IE this is an important condition because there seems to be some instances where the last scrollTop is equal to the new one
}
else {
console.log("up")
}
lastScrollTop = st;
});});

捕捉所有滚动事件(触摸和滚轮)的简单方法

window.onscroll = function(e) {
// print "false" if direction is down and "true" if up
console.log(this.oldScroll > this.scrollY);
this.oldScroll = this.scrollY;
}

你可以试试这样做。

function scrollDetect(){
var lastScroll = 0;


window.onscroll = function() {
let currentScroll = document.documentElement.scrollTop || document.body.scrollTop; // Get Current Scroll Value


if (currentScroll > 0 && lastScroll <= currentScroll){
lastScroll = currentScroll;
document.getElementById("scrollLoc").innerHTML = "Scrolling DOWN";
}else{
lastScroll = currentScroll;
document.getElementById("scrollLoc").innerHTML = "Scrolling UP";
}
};
}




scrollDetect();
html,body{
height:100%;
width:100%;
margin:0;
padding:0;
}


.cont{
height:100%;
width:100%;
}


.item{
margin:0;
padding:0;
height:100%;
width:100%;
background: #ffad33;
}


.red{
background: red;
}


p{
position:fixed;
font-size:25px;
top:5%;
left:5%;
}
<div class="cont">
<div class="item"></div>
<div class="item red"></div>
<p id="scrollLoc">0</p>
</div>

  1. 初始化一个oldValue
  2. 通过监听事件获取newValue
  3. 两者相减
  4. 从结果得出结论
  5. 用newValue更新oldValue

/ /初始化

let oldValue = 0;

//监听事件

window.addEventListener('scroll', function(e){


// Get the new Value
newValue = window.pageYOffset;


//Subtract the two and conclude
if(oldValue - newValue < 0){
console.log("Up");
} else if(oldValue - newValue > 0){
console.log("Down");
}


// Update the old value
oldValue = newValue;
});

我个人使用这个代码来检测javascript中的滚动方向… 你只需要定义一个变量来存储lastscrollvalue,然后使用这个if&else

let lastscrollvalue;


function headeronscroll() {


// document on which scroll event will occur
var a = document.querySelector('.refcontainer');


if (lastscrollvalue == undefined) {


lastscrollvalue = a.scrollTop;


// sets lastscrollvalue
} else if (a.scrollTop > lastscrollvalue) {


// downscroll rules will be here
lastscrollvalue = a.scrollTop;


} else if (a.scrollTop < lastscrollvalue) {


// upscroll rules will be here
lastscrollvalue = a.scrollTop;


}
}

这段简单的代码可以工作:检查控制台的结果。

let scroll_position = 0;
let scroll_direction;


window.addEventListener('scroll', function(e){
scroll_direction = (document.body.getBoundingClientRect()).top > scroll_position ? 'up' : 'down';
scroll_position = (document.body.getBoundingClientRect()).top;
console.log(scroll_direction);
});

虽然公认的答案是可行的,但值得注意的是,这将以很高的速率发射。对于计算成本高的操作,这可能会导致性能问题。

MDN的建议是限制这些事件。下面是他们的样例的修改,增强检测滚动方向。

修改自:https://developer.mozilla.org/en-US/docs/Web/API/Document/scroll_event

// ## function declaration
function scrollEventThrottle(fn) {
let last_known_scroll_position = 0;
let ticking = false;
window.addEventListener("scroll", function () {
let previous_known_scroll_position = last_known_scroll_position;
last_known_scroll_position = window.scrollY;
if (!ticking) {
window.requestAnimationFrame(function () {
fn(last_known_scroll_position, previous_known_scroll_position);
ticking = false;
});
ticking = true;
}
});
}


// ## function invocation
scrollEventThrottle((scrollPos, previousScrollPos) => {
if (previousScrollPos > scrollPos) {
console.log("going up");
} else {
console.log("going down");
}
});


如果有人想用React hooks实现它

  const [scrollStatus, setScrollStatus] = useState({
scrollDirection: null,
scrollPos: 0,
});


useEffect(() => {
window.addEventListener("scroll", handleScrollDocument);


return () => window.removeEventListener("scroll", handleScrollDocument);
}, []);


function handleScrollDocument() {
setScrollStatus((prev) => { // to get 'previous' value of state
return {
scrollDirection:
document.body.getBoundingClientRect().top > prev.scrollPos
? "up"
: "down",
scrollPos: document.body.getBoundingClientRect().top,
};
});
}


console.log(scrollStatus.scrollDirection)

修改Prateek的答案,如果lastScrollTop没有变化,那么它将是一个水平滚动(在x方向溢出,可以通过使用鼠标使用水平滚动条或使用滚动轮+ shift来使用。

const containerElm = document.getElementById("container");


let lastScrollTop = containerElm.scrollTop;


containerElm.addEventListener("scroll", (evt) => {
const st = containerElm.scrollTop;


if (st > lastScrollTop) {
console.log("down scroll");
} else if (st < lastScrollTop) {
console.log("up scroll");
} else {
console.log("horizontal scroll");
}


lastScrollTop = Math.max(st, 0); // For mobile or negative scrolling
});

这似乎工作得很好。

document.addEventListener('DOMContentLoaded', () => {


var scrollDirectionDown;
scrollDirectionDown = true;


window.addEventListener('scroll', () => {


if (this.oldScroll > this.scrollY) {
scrollDirectionDown = false;
} else {
scrollDirectionDown = true;
}
this.oldScroll = this.scrollY;




// test
if (scrollDirectionDown) {
console.log('scrolling down');
} else {
console.log('scrolling up');
}






});
});

有时滚动行为会出现不一致,不能正确更新元素的scrollTop属性。在决定滚动方向之前设置一些阈值会更安全。

let lastScroll = 0
let threshold = 10 // must scroll by 10 units to know the direction of scrolling




element.addEventListener("scroll", () => {
let newScroll = element.scrollTop
    

if (newScroll - lastScroll > threshold) {
// "up" code here
} else if (newScroll - lastScroll < -threshold) {
// "down" code here
}
    

lastScroll = newScroll


})