iOS 5 上的 document.ontouchmove 和滚动

发布于 2024-12-10 10:05:14 字数 343 浏览 0 评论 0原文

iOS 5 为 JavaScript/Web 应用程序带来了许多好东西。其中之一是改进的滚动。如果添加

-webkit-overflow-scroll:touch;

到文本区域元素的样式,则用一根手指即可很好地滚动。

但有一个问题。为了防止整个屏幕滚动,建议 Web 应用程序添加以下代码行:

document.ontouchmove = function(e) {e.preventDefault()};

但是,这会禁用新的滚动。

有谁有一个好方法来允许在文本区域内进行新的滚动,但不允许整个表单滚动?

iOS 5 has brought a number of nice things to JavaScript/Web Apps. One of them is improved scrolling. If you add

-webkit-overflow-scroll:touch;

to the style of a textarea element, scrolling will work nicely with one finger.

But there's a problem. To prevent the entire screen from scrolling, it is recommended that web apps add this line of code:

document.ontouchmove = function(e) {e.preventDefault()};

This, however, disables the new scrolling.

Does anyone have a nice way to allow the new scrolling within a textarea, but not allow the whole form to scroll?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

邮友 2024-12-17 10:05:15

Brian Nickel 的答案的唯一问题是(正如 user1012566 提到的)stopPropagation 并不能阻止当你到达可滚动边界时冒泡。您可以通过以下方法来防止这种情况:

elem.addEventListener('touchstart', function(event){
    this.allowUp = (this.scrollTop > 0);
    this.allowDown = (this.scrollTop < this.scrollHeight - this.clientHeight);
    this.prevTop = null; 
    this.prevBot = null;
    this.lastY = event.pageY;
});

elem.addEventListener('touchmove', function(event){
    var up = (event.pageY > this.lastY), 
        down = !up;

    this.lastY = event.pageY;

    if ((up && this.allowUp) || (down && this.allowDown)) 
        event.stopPropagation();
    else 
        event.preventDefault();
});

The only issue with Brian Nickel's answer is that (as user1012566 mentioned) stopPropagation doesn't prevent bubbling when you hit your scrollable's boundaries. You can prevent this with the following:

elem.addEventListener('touchstart', function(event){
    this.allowUp = (this.scrollTop > 0);
    this.allowDown = (this.scrollTop < this.scrollHeight - this.clientHeight);
    this.prevTop = null; 
    this.prevBot = null;
    this.lastY = event.pageY;
});

elem.addEventListener('touchmove', function(event){
    var up = (event.pageY > this.lastY), 
        down = !up;

    this.lastY = event.pageY;

    if ((up && this.allowUp) || (down && this.allowDown)) 
        event.stopPropagation();
    else 
        event.preventDefault();
});
我们的影子 2024-12-17 10:05:15

对于尝试使用 PhoneGap 实现此目的的任何人,您可以在 cordova.plist 中禁用弹性滚动,将 UIWebViewBounce 的值设置为 NO。我希望这对那些在这方面花费了很长时间的人(就像我一样)有所帮助。

For anyone trying to acheive this with PhoneGap, you can disable the elastic scrolling in the cordova.plist, set the value for UIWebViewBounce to NO. I hope that helps anyone spending ages on this (like i was).

↘紸啶 2024-12-17 10:05:15

ScrollFix 似乎是完美的解决方案。我测试了它,它的效果就像一个魅力!

https://github.com/joelambert/ScrollFix

/**
 * ScrollFix v0.1
 * http://www.joelambert.co.uk
 *
 * Copyright 2011, Joe Lambert.
 * Free to use under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */

var ScrollFix = function(elem) {
    // Variables to track inputs
    var startY, startTopScroll;

    elem = elem || document.querySelector(elem);

    // If there is no element, then do nothing  
    if(!elem)
        return;

    // Handle the start of interactions
    elem.addEventListener('touchstart', function(event){
        startY = event.touches[0].pageY;
        startTopScroll = elem.scrollTop;

        if(startTopScroll <= 0)
            elem.scrollTop = 1;

        if(startTopScroll + elem.offsetHeight >= elem.scrollHeight)
            elem.scrollTop = elem.scrollHeight - elem.offsetHeight - 1;
    }, false);
};

ScrollFix seems to be perfect solution. I tested it and it works like a charm!

https://github.com/joelambert/ScrollFix

/**
 * ScrollFix v0.1
 * http://www.joelambert.co.uk
 *
 * Copyright 2011, Joe Lambert.
 * Free to use under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 */

var ScrollFix = function(elem) {
    // Variables to track inputs
    var startY, startTopScroll;

    elem = elem || document.querySelector(elem);

    // If there is no element, then do nothing  
    if(!elem)
        return;

    // Handle the start of interactions
    elem.addEventListener('touchstart', function(event){
        startY = event.touches[0].pageY;
        startTopScroll = elem.scrollTop;

        if(startTopScroll <= 0)
            elem.scrollTop = 1;

        if(startTopScroll + elem.offsetHeight >= elem.scrollHeight)
            elem.scrollTop = elem.scrollHeight - elem.offsetHeight - 1;
    }, false);
};
缱倦旧时光 2024-12-17 10:05:15

发现 stopPropagation 和本机 div 滚动的已知问题令人沮丧。它似乎并不能阻止onTouchMove向上冒泡,这样当滚动超出div的边界(顶部向上或底部向下)时,整个页面都会弹起。

更多讨论此处< /a> 和此处

It was frustrating to discover a known problem with stopPropagation and native div scrolling. It does not seem to prevent the onTouchMove from bubbling up, so that when scrolling beyond the bounds of the div (upwards at the top or downwards at the bottom), the entire page will bounce.

More discussion here and here.

硪扪都還晓 2024-12-17 10:05:14

更新Alvaro 的评论,从 iOS 11.3 开始,此解决方案可能不再有效。

您应该能够通过选择是否调用 PreventDefault 来允许滚动。例如,

document.ontouchmove = function(e) {
    var target = e.currentTarget;
    while(target) {
        if(checkIfElementShouldScroll(target))
            return;
        target = target.parentNode;
    }

    e.preventDefault();
};

或者,这可以通过阻止事件到达文档级别来起作用。

elementYouWantToScroll.ontouchmove = function(e) {
    e.stopPropagation();
};

编辑对于稍后阅读的任何人来说,替代答案确实有效并且更容易。

Update Per Alvaro's comment, this solution may no longer work as of iOS 11.3.

You should be able to allow scrolling by selecting whether or not preventDefault is called. E.g.,

document.ontouchmove = function(e) {
    var target = e.currentTarget;
    while(target) {
        if(checkIfElementShouldScroll(target))
            return;
        target = target.parentNode;
    }

    e.preventDefault();
};

Alternatively, this may work by preventing the event from reaching the document level.

elementYouWantToScroll.ontouchmove = function(e) {
    e.stopPropagation();
};

Edit For anyone reading later, the alternate answer does work and is way easier.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文