javascript 检查触摸设备上的 scrollTop

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17189004/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 07:25:07  来源:igfitidea点击:

Check scrollTop on touch device

javascriptjquerytouch

提问by Cameron

I have the following function that checks the scrolling position of a user so that the menu becomes fixed once they scroll past the masthead

我有以下功能可以检查用户的滚动位置,以便一旦他们滚动超过刊头,菜单就会固定

function checkScrolling() {
    if( $(window).scrollTop() > $('.masthead').height() ) { // we check against ACTUAL height
        $('.menu').addClass('fixed');
    }else {
        $('.menu').removeClass('fixed');
    }
}

and here the desktop and touch screen event listeners:

这里是桌面和触摸屏事件侦听器:

$(document).bind('touchstart touchend touchcancel touchleave touchmove', function(e){
    checkScrolling();
});

$(window).scroll(function(){
    checkScrolling();
});

However the touch events only make the menu fixed during the touchmove reliably. If I scroll really fast with a swipe up or down, there is a delay before the menu becomes fixed or unfixed.

然而,触摸事件只会在触摸移动期间可靠地固定菜单。如果我通过向上或向下滑动非常快速地滚动,则在菜单变为固定或未固定之前会有一段延迟。

Any ideas on how to fix this? See a code example here: http://dev.driz.co.uk/mobileMasthead.html(has been amended based on some answers below, but still does not work correctly on an iPad or iPhone)

有想法该怎么解决这个吗?在此处查看代码示例:http: //dev.driz.co.uk/mobileMasthead.html(已根据下面的一些答案进行了修改,但在 iPad 或 iPhone 上仍无法正常工作)

Update:And reading up on the topic reveals that JS like checking scroll position don't happen during the scroll... BUT... I've noticed that http://www.facebook.com/home/doesn't have this issuewhen testing it on my iPad. So it's definitely possible to achieve this effect without using any custom JavaScript scrollbars like iScroll or similar.

更新:阅读该主题后发现,在滚动过程中不会发生像检查滚动位置这样的 JS ......但是......我注意到http://www.facebook.com/home/没有在我的 iPad 上测试时出现此问题。因此,绝对可以在不使用任何自定义 JavaScript 滚动条(如 iScroll 或类似工具)的情况下实现此效果。

回答by Jean-Paul

Maybe I understand the question wrong, but to ensure functionality with high speed scrolling, why don't you tackle it the pure CSS way (aka faking the 'fancy' effect):

也许我理解这个问题是错误的,但是为了确保高速滚动的功能,为什么不以纯 CSS 方式解决它(也就是伪造“花哨”效果):

Old School (fast but primitive)

老派(快速但原始)

HTML

HTML

<div id="menu2"></div>
    <div class="scroll" id="scroller">
        <div id="overlay"></div>
        <div id="menu"></div>
    </div>

With the simple CSS:

使用简单的 CSS:

html, body { overflow: hidden; height: 100% }
body { margin:0; padding:0; }

 .scroll {
     -webkit-overflow-scrolling: touch;
     height:960px;
     width:640px;
 }

 #menu2 {
     width:640px;
     height:20px;
     background:red;
     position:absolute;
     z-index:-1;
 }

 #menu {
     width:100%;
     height:20px;
     background:red;
     z-index:0;
 }

You can see a working example HERE.

你可以在这里看到一个工作示例。

It may be a bit primitive: but hey! It works! :)

这可能有点原始:但是嘿!有用!:)

New School (fancy but slow)

新学校(花哨但缓慢)

Check all of the other answers supplied.

检查提供的所有其他答案。

But note that it 'is known' that the usage of JavaScript in combination with scrolling on mobile devices is causing a lot of trouble regarding speed.

但请注意,众所周知,在移动设备上结合使用 JavaScript 和滚动会导致很多速度问题。

That's why I think the simple CSS approach may be better.

这就是为什么我认为简单的 CSS 方法可能更好。

If you want to learn about JavaScript and scrolling on mobile devices (and other functions), then there are two articles which I highly recommend reading:

如果您想了解 JavaScript 和移动设备上的滚动(和其他功能),那么我强烈建议您阅读两篇文章:

回答by a better oliver

Facebook doesn't use JavaScript but pure css:

Facebook 不使用 JavaScript,而是使用纯 css:

position: -webkit-sticky;

If i remember it correctly this makes the element stick at the top of its parent container when scrolled.

如果我没记错的话,这会使元素在滚动时粘在其父容器的顶部。

回答by ihor marusyk

I once tried to implement sticky headers on mobile version of a site but had encountered whole set of problems.

我曾经尝试在网站的移动版本上实现粘性标题,但遇到了一系列问题。

First and most important is that scrollevent does not fire on mobile devices as often as it does on desktop. Usually it does fire when page stops. I don't know the exact reason for that but I can suggest it's because browsers on mobile "send" such tasks to GPU meantime CPU can not keep JS objects up to date with what happens to the canvas (but that's just my suggestion). Newer version of iOSes are making it better for us and probably scrollwill work on iPhones.

首先也是最重要的是,该scroll事件在移动设备上不会像在桌面上那样频繁地触发。通常它会在页面停止时触发。我不知道确切的原因,但我可以建议这是因为移动浏览器将此类任务“发送”到 GPU,同时 CPU 无法使 JS 对象与画布发生的情况保持同步(但这只是我的建议)。较新版本的 iOS 使其对我们更好,并且可能scroll适用于 iPhone。

You should use touchevents. This makes you write a separate version of code for devices that support touch input. So have to look for reliable ways of testing for platform.

你应该使用touch事件。这使您可以为支持触摸输入的设备编写单独的代码版本。所以必须寻找可靠的平台测试方法。

But touchevents are also tricky especially on Android. I thought that in the callback for touchmoveevent I will be able to figure out current coordinates and go further from that point.

touch事件也很棘手,尤其是在 Android 上。我认为在touchmove事件的回调中我将能够找出当前坐标并从该点走得更远。

But There this issue https://code.google.com/p/android/issues/detail?id=5491on Android, in summary touchmovefires once or twice at the very beginning of the touch action and does not fire again. Which makes it totally useless. People are suggesting preventDefault() but you no longer can scroll with that.

但是在 Android 上有这个问题https://code.google.com/p/android/issues/detail?id=5491,总而言之touchmove,在触摸动作的最开始时会触发一两次,并且不会再次触发。这使它完全没用。人们建议 preventDefault() 但你不能再滚动了。

So I ended up with idea to reimplement scrolling from scratch using CSS transforms. And here is my results so far:

所以我最终想到了使用 CSS 转换从头开始重新实现滚动的想法。这是我到目前为止的结果:

http://jsbin.com/elaker/23

http://jsbin.com/elaker/23

Open that link on your device and http://jsbin.com/elaker/23/editon your desktop: you'll be able to edit code and it will live update on you device, very convenient.

在您的设备上打开该链接并在您的桌面上打开http://jsbin.com/elaker/23/edit:您将能够编辑代码,它会在您的设备上实时更新,非常方便。

NOTE:I'd like to warn you that this CSS scrolling thing is raw and there are some known problems that are not resolved yet: like you can sometimes scroll beyond top or bottom boundaries or if you just touch (not move) it still will scroll. Also the notorious URL bar will not hide. So there is work to do.

注意:我想警告你,这个 CSS 滚动是原始的,有一些已知的问题还没有解决:比如你有时可以滚动超出顶部或底部边界,或者如果你只是触摸(不移动)它仍然会滚动。臭名昭著的网址栏也不会隐藏。所以有工作要做。

回答by Jaibuu

You just needed to attach your scroll events, not to window, document or body, but to a custom container.

您只需要将滚动事件附加到窗口、文档或正文,而是附加到自定义容器。

On iOS you can't programatically react during these hardware-accelerated window scrolling behaviour.

在 iOS 上,您无法在这些硬件加速的窗口滚动行为期间以编程方式做出反应。

Here's a fiddle: a wrapper:

这是一个小提琴:一个包装器:

<div id="content">

some not-so-relevant css:

一些不太相关的css:

html,body,#content {
    width:100%;
    height:100%;
}
#content {
    background-color: lightblue;
    overflow:scroll;
}

attaching the listeners to the container:

将侦听器附加到容器:

function checkScrolling() {
    if ($('#content').scrollTop() > mastheadHeight) {
        menu.addClass('fixed');
    } else {
        menu.removeClass('fixed');
    }
}

$('#content').scroll(function () {
    checkScrolling();
});

You can see it working here for the JS-only fallback:

您可以在此处看到它仅用于 JS 回退:

http://jsfiddle.net/jaibuu/YqPzS/

http://jsfiddle.net/jaibuu/YqPzS/

direct URL: http://fiddle.jshell.net/jaibuu/YqPzS/show/

直接网址:http: //fiddle.jshell.net/jaibuu/YqPzS/show/

回答by Jason Lydon

Do you need the touch events to fire this at all? Modern devices should return $(window).scroll()events and scrollTopvalues. On older Android and and pre-ios5 (I think), position:fixed:didn't work as expected because the of how the viewport worked. But it has been corrected in all new releases.

您是否需要触摸事件来触发它?现代设备应该返回$(window).scroll()事件和scrollTop值。在较旧的 Android 和 ios5 之前(我认为)上,position:fixed:由于视口的工作方式,没有按预期工作。但它已在所有新版本中得到纠正。

To further debug devices, I highly recommend Adobe Edge Inspect. You could console.logthe scrollTop and see if the devices you care about actually work correctly with out any trickery. You'll get everything you need with their free version.

为了进一步调试设备,我强烈推荐 Adob​​e Edge Inspect。您可以console.log使用 scrollTop 并查看您关心的设备是否真正正常工作而没有任何技巧。您将通过他们的免费版本获得所需的一切。

回答by Abdoul Sy

A great way to dealing with scroll events is not to attach your checks to the scroll event takes a lot of resources and doesn't work very well with older browsers. fortunately you can have a lot more control if you just perform a time loop to do that. codewise that looks like that: (It's used by twitter)

处理滚动事件的一个好方法是不要将检查附加到滚动事件上,这会占用大量资源,并且在旧浏览器中不能很好地工作。幸运的是,如果您只是执行一个时间循环来做到这一点,您可以获得更多的控制权。codewise 看起来像这样:(它被 twitter 使用)

var MyMenu = $('#menu'),
    didScroll = false;

$(window).scroll(function() {
    didScroll = true;
});

setInterval(function() {
    if ( didScroll ) {
        didScroll = false;
        //Do your check here
        checkScrolling();
    }
}, 180);

You should put your $('.masthead').height() outside this checkScrolling function of yours (in a higher scope) as this kind of operations takes a lot of resources and always ask jquery to "select your element" and calculate its size will eventually make your application laggy:

你应该把你的 $('.masthead').height() 放在你的这个 checkScrolling 函数之外(在更高的范围内),因为这种操作需要大量资源并且总是要求 jquery“选择你的元素”并计算它的大小最终会使您的应用程序滞后:

  var headerHeight = $('.masthead').height()
  function checkScrolling()
  .....

Last thing , you can change the value of the interval attribute (right now it's 180 (a bit more that 60hz -. refresh time of the screen) you can make this value bigger, if you want your app to be more performant but a bit less accurate)

最后一件事,您可以更改 interval 属性的值(现在是 180(比 60hz 多一点 - 屏幕刷新时间)您可以将此值设置得更大,如果您希望您的应用程序性能更高但有点不太准确)

Thanks John Resig and twitter: http://ejohn.org/blog/learning-from-twitter/

感谢 John Resig 和 twitter:http: //ejohn.org/blog/learning-from-twitter/

Hope that helped Ajios !

希望对 Ajios 有所帮助!

回答by krishna singh

setScrollTop: function(inTop) {
    var top = Math.max(0,inTop);

    if (wm.isMobile) { // should always be true for touch events 
        top = Math.min(top, this.listNode.clientHeight - this.listNodeWrapper.clientHeight);

        if (dojo.isWebKit) {
            this.listNode.style.WebkitTransform = "translate(0,-" + top + "px)";
        } else if (dojo.isMoz) {
            this.listNode.style.MozTransform = "translate(0,-" + top + "px)";
        } else if (dojo.isOpera) {
            this.listNode.style.OTransform = "translate(0,-" + top + "px)";
        } else if (dojo.isIE) {
            this.listNode.style.MsTransform = "translate(0,-" + top + "px)";
        }
        this.listNode.style.transform = "translate(0,-" + top + "px)";
        this._scrollTop = top;
        this._onScroll();
    } else {
        this.listNode.scrollTop = top + "px";
    }
},

回答by Wasim A.

I have just tested your functions for efficiency. You should try this

我刚刚测试了您的功能以提高效率。你应该试试这个

function checkScrolling() {         
    if( $(window).scrollTop() > mastheadHeight )menu.css('position','fixed');
    else menu.css('position','');
}

This will reduce function call of addClass and RemoveClass and your execution time will take effect. If you want to reduce more execution time, then better to use pure JavaScript

这将减少 addClass 和 RemoveClass 的函数调用,并且您的执行时间将生效。如果你想减少更多的执行时间,那么最好使用纯 JavaScript

回答by Ramsharan

$(document).ready(function(){
     var p = $("#stop").offset().top;

    $(window).scroll(function(){
        if(p<$(window).scrollTop()){
            console.log("div reached");
            $("#stop").css({position:"fixed",top:0});
        }
        else{
            console.log("div out");
            $("#stop").css({position:"static"});
        }

    })
});

I think this will help you.

我想这会对你有所帮助。

The total code is herein jsfiddle.net.

总的代码是这里的jsfiddle.net。

I have tested it for ipad using safari of online ipad2 simulatorin http://alexw.me/ipad2/and it has worked there. So, I think it will work on real ipad too.

我已经在http://alexw.me/ipad2/ 中使用在线 ipad2 模拟器的 safariipad 进行了测试,它在那里工作。所以,我认为它也适用于真正的 ipad。