检测滚动事件是否由用户创建
Detect whether scroll event was created by user
是否有可能判断滚动事件是由浏览器还是由用户完成的?具体来说,当使用后退按钮时,浏览器可能会跳转到最后一个已知的滚动位置。如果我绑定到滚动事件,我怎么知道这是由用户还是浏览器引起的?
$(document).scroll( function(){
//who did this?!
});
我看到了三种导致浏览器滚动的情况。
- 用户执行操作。例如,使用鼠标滚轮、方向键、上下翻页键、home/end键,点击滚动条或拖动拇指。
- 浏览器自动滚动。例如,当你在浏览器中使用后退按钮时,它会自动跳转到最后一个已知的滚动位置。
- Javascript卷轴。例如:
element.scrollTo(x,y)
.
不幸的是,没有直接的方法可以告诉你。
我想说,如果你可以重新设计你的应用程序,使它不依赖于这种类型的流程,那就去做吧。
如果没有,我能想到的一个解决方法是跟踪用户发起的滚动,并检查滚动是由浏览器还是由用户触发的。
这里有一个我放在一起的例子,它做得很好(除了那些jQuery历史有问题的浏览器)。
你需要在本地运行它,以便能够完全测试它(jsFiddle/jsbin不适合,因为它们iFrame内容)。
以下是我验证过的测试用例:- 页面加载-
userScroll
是false
- 使用鼠标/键盘滚动-
userScroll
变为true
- 点击链接跳转到页面底部-
userScroll
变为false
- 点击后退/前进-
userScroll
变为false
;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script type="text/javascript" src="https://raw.github.com/tkyk/jquery-history-plugin/master/jquery.history.js"></script>
</head>
<body>
<span> hello there </span><br/>
<a href="#bottom"> click here to go down </a>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>
<a name="bottom"> just sitting </a>
</body>
<script type="text/javascript">
var userScroll = false;
function mouseEvent(e) {
userScroll = true;
}
$(function() {
// reset flag on back/forward
$.history.init(function(hash){
userScroll = false;
});
$(document).keydown(function(e) {
if(e.which == 33 // page up
|| e.which == 34 // page dn
|| e.which == 32 // spacebar
|| e.which == 38 // up
|| e.which == 40 // down
|| (e.ctrlKey && e.which == 36) // ctrl + home
|| (e.ctrlKey && e.which == 35) // ctrl + end
) {
userScroll = true;
}
});
// detect user scroll through mouse
// Mozilla/Webkit
if(window.addEventListener) {
document.addEventListener('DOMMouseScroll', mouseEvent, false);
}
//for IE/OPERA etc
document.onmousewheel = mouseEvent;
// to reset flag when named anchors are clicked
$('a[href*=#]').click(function() {
userScroll = false;
});
// detect browser/user scroll
$(document).scroll( function(){
console.log('Scroll initiated by ' + (userScroll == true ? "user" : "browser"));
});
});
</script>
</html>
指出:
- 当用户用鼠标拖动滚动条时,不跟踪滚动。这可以添加一些更多的代码,我留下作为练习给你。
-
event.keyCodes
可能因操作系统而异,因此您可能必须适当更改。
希望这对你有帮助!
与其试图捕捉所有用户事件,还不如相反,只处理编程事件并忽略它们。
例如,这样的代码可以工作:
// Element that needs to be scrolled
var myElement = document.getElementById('my-container');
// Flag to tell if the change was programmatic or by the user
var ignoreNextScrollEvent = false;
function setScrollTop(scrollTop) {
ignoreNextScrollEvent = true;
myElement.scrollTop = scrollTop
}
myElement.addEventListener('scroll', function() {
if (ignoreNextScrollEvent) {
// Ignore this event because it was done programmatically
ignoreNextScrollEvent = false;
return;
}
// Process user-initiated event here
});
当调用setScrollTop()
时,滚动事件将被忽略,而如果用户使用鼠标、键盘或任何其他方式滚动,则该事件将被处理。
据我所知,不可能(没有任何工作)告诉滚动事件是何时由"user"或其他方式发出的。
你可以尝试(正如其他人提到的)捕捉鼠标滚轮事件,然后可能尝试捕捉keydown事件上的任何键,可以触发滚动(箭头,空格等),同时检查什么元素是当前聚焦的,因为你不能使用箭头键滚动,而在输入字段中输入。一般来说,这将是一个复杂而混乱的脚本。
根据你正在处理的情况,我猜你可以"恢复逻辑",而不是检测用户发出的滚动事件,只是挂钩到任何以编程方式制作的滚动,并处理任何滚动事件而不是由你的代码作为由用户制作。就像我说的,这取决于具体情况,以及你想要达到的目标。
是的,100%可能。我目前在一个应用程序中使用这个,IE不是一个要求-客户端只面对。当我的Backbone应用程序启动一个动画,其中滚动被改变-滚动发生,但不触发这些事件捕获。这是在FF, Safari &;Chrome最新。
$('html, body').bind('scroll mousedown wheel DOMMouseScroll mousewheel keyup', function(evt) {
// detect only user initiated, not by an .animate though
if (evt.type === 'DOMMouseScroll' || evt.type === 'keyup' || evt.type === 'mousewheel') {
// up
if (evt.originalEvent.detail < 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta > 0)) {
// down.
} else if (evt.originalEvent.detail > 0 || (evt.originalEvent.wheelDelta && evt.originalEvent.wheelDelta < 0)) {
}
}
});
尝试使用Mousewheel和dommousescroroll事件代替。参见http://www.quirksmode.org/dom/events/scroll.html
您可以在ready上检查滚动位置。当触发on scroll事件检查以确保滚动位置与页面加载时不同时。最后,确保在页面滚动后清除存储的值。
$(function () {
var loadScrollTop = ($(document).scrollTop() > 0 ? $(document).scrollTop() : null);
$(document).scroll(function (e) {
if ( $(document).scrollTop() !== loadScrollTop) {
// scroll code here!
}
loadScrollTop = null;
});
});
关于:
具体来说,当使用后退按钮时,浏览器可能会跳转到最后一个已知的滚动位置。
在页面呈现后很快触发。您可以将侦听滚动事件的时间延迟1秒左右。
还有一种方法可以分离用户创建的滚动:您可以使用替代事件处理程序,例如'mousewheel', 'touchmove', 'keydown',代码38和40用于箭头滚动,用于滚动条-如果'scroll'事件与'mousedown'同时触发,直到'mouseup'事件。
发现这个非常有用。这里有一个coffeescript版本给那些有兴趣的人。
$ ->
S.userScroll = false
# reset flag on back/forward
if $.history?
$.history.init (hash) ->
S.userScroll = false
mouseEvent = (e)->
S.userScroll = true
$(document).keydown (e) ->
importantKey = (e.which == 33 or # page up
e.which == 34 or # page dn
e.which == 32 or # spacebar
e.which == 38 or # up
e.which == 40 or # down
(e.ctrlKey and e.which == 36) or # ctrl + home
(e.ctrlKey and e.which == 35) # ctrl + end
)
if importantKey
S.userScroll = true;
# Detect user scroll through mouse
# Mozilla/Webkit
if window.addEventListener
document.addEventListener('DOMMouseScroll', mouseEvent, false);
# for IE/OPERA etc
document.onmousewheel = mouseEvent;
如果您正在使用JQuery,那么显然有一个更好的答案-我只是自己尝试一下。
参见:检测jquery事件触发用户或代码调用
这可能对您的应用程序没有帮助,但我需要在用户滚动上触发一个事件,而不是程序性滚动和张贴,以防它帮助其他人。
监听wheel
事件而不是scroll
,
当用户使用鼠标滚轮或跟踪板时(我觉得大多数人都是这样滚动的),它就会被触发,当你编程滚动时,它不会被触发。我用它来区分用户滚动操作和滚动功能。
https://developer.mozilla.org/en-US/docs/Web/API/Element/wheel_event
element.addEventListener('wheel', (event) => {
//do user scroll stuff here
})
需要注意的是,wheel
在移动设备上滚动时不会触发,所以我检查了设备是否为移动设备并使用了类似的功能
if(this.mobile){
element.addEventListener('scroll', (event) => {
//do mobile scroll stuff here
})
}
- 如何在节点中为用户创建某种警报
- 如何为在客户端检查其密码的用户创建登录页面
- 如何防止用户创建重复ID
- 如何在完整日历中筛选出用户创建的事件
- 使用java和html基于当前用户创建重定向链接
- 在jquery或jquery移动中,如何将用户创建的链接传递到用户创建的按钮?我所说的用户是指最终用户,而不是我
- 用户创建的应用程序的安全性
- 为多个用户创建自动低分辨率和高分辨率pdf,png与inDesign
- 如何为用户创建唯一的网址
- 如何在我的网页上为iPhone用户创建一个注释,说明有一个应用程序
- 当用户创建新帖子时,张贴到墙上时出错
- 为不同的用户创建一个常规页面
- 如何为不同的用户创建Opencart模块
- Express js会话——仅为登录用户创建
- 根据用户创建文本字段's在JavaScript函数中的输入
- 从用户创建的选择字段中获取所有选定项目的值
- 在数据库中保存用户创建的javascript是否安全
- 如何为用户创建带有构建选项的流星JS包
- 如何在Meteor中验证服务器上的用户创建
- 如何获取用户文本输入用户创建输入的值,jQuery