javascript iScroll 在一个轴上进行本机滚动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7800261/
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-26 01:22:35  来源:igfitidea点击:

iScroll with native scrolling on one axis

javascriptandroidiosmobileiscroll4

提问by Fresheyeball

I am using the most wonderful javascript tool iScroll4 http://cubiq.org/iscroll-4on a mobile website for iOS and Android. Here is what my layout looks like:

我在iOS 和 Android 的移动网站上使用了最出色的 javascript 工具 iScroll4 http://cubiq.org/iscroll-4。这是我的布局:

layout problem

布局问题

The horizontally scroll-able area is making use of iScroll4 with the following settings:

可水平滚动的区域使用 iScroll4 进行以下设置:

   var myScroll = new iScroll('frame',  { hScrollbar: false, vScrollbar: false, vScroll: false })

The horizontal scrolling part works great. This issue is what happens when a user attempts to scroll up or down the page placing their finger on the horizontal scrolling area. So I need native vertical scrolling, and iScroll horizontal scrolling on the same area.

水平滚动部分效果很好。当用户尝试向上或向下滚动页面并将手指放在水平滚动区域时会发生此问题。所以我需要在同一区域进行原生垂直滚动和 iScroll 水平滚动。

What I have tried so far: Removing e.preventDefault() in the iScroll code (allows for native scrolling, but in BOTH axes). Removing e.preventDefault() and then disabling horizontal scrolling page wide with this:

到目前为止我已经尝试过:在 iScroll 代码中删除 e.preventDefault()(允许本机滚动,但在两个轴上)。删除 e.preventDefault() 然后禁用水平滚动页面宽度:

var touchMove;

document.ontouchstart = function(e){
    touchMove = e.touches[0];
}

document.ontouchmove = function(e){
    var theTouch = e.touches[0] || e.changedTouches[0];
    var Xer      = rs(touchMove.pageX - theTouch.pageX).toPos();
    var Yer      = rs(touchMove.pageY - theTouch.pageY).toPos();        
    touchMove    = theTouch;
    if(Yer > Xer){ e.preventDefault(); }
}

which seems to do nothing. How can I allow for native vertical scrolling in the horizontal scrolling area, without loosing the horizontal scrolling of iScroll? I am really stumped here. Thanks in advance.

这似乎什么都不做。如何在不丢失 iScroll 的水平滚动的情况下允许水平滚动区域中的本机垂直滚动?我真的被难住了。提前致谢。

(just for the record rs(foo).toPos() is a function that makes foo a positive number regardless of its value).

(仅用于记录 rs(foo).toPos() 是一个使 foo 成为正数的函数,而不管其值如何)。

采纳答案by Fresheyeball

Suggested edit to @Lukx's excellent solution. New versions of iScroll4 place the e.preventDefault()in onBeforeScrollMovewhich can be overridden. By placing the if block into this option, default is not prevented for vertical scrolling, and vertical can scroll natively.

建议编辑@Lukx 的优秀解决方案。iScroll4的新版本放置e.preventDefault()onBeforeScrollMove其中可以被覆盖。通过将 if 块放入此选项,默认不会阻止垂直滚动,并且垂直可以原生滚动。

myScroll = new iScroll('scrollpanel', {
    // other options go here...
    vScroll: false,
    onBeforeScrollStart: function ( e ) {
        if ( this.absDistX > (this.absDistY + 5 ) ) {
            // user is scrolling the x axis, so prevent the browsers' native scrolling
            e.preventDefault();
        }
    },
});

回答by Lukx

If you would like to achieve the effect described by Fresheyeball without hacking the core, and without changing from iScroll to swipeview, then iScroll 4 does offer you its event listeners to work with.

如果您想在不破坏核心的情况下实现 Fresheyeball 所描述的效果,并且不想从 iScroll 更改为 swipeview,那么 iScroll 4 确实为您提供了它的事件侦听器。

myScroll = new iScroll('scrollpanel', {
    // other options go here...
    vScroll: false,
    onBeforeScrollMove: function ( e ) {
        if ( this.absDistX > (this.absDistY + 5 ) ) {
            // user is scrolling the x axis, so prevent the browsers' native scrolling
            e.preventDefault();
        } else {
            // delegate the scrolling to window object
        window.scrollBy( 0, -this.distY );
    }
    },
});

By doing so, the onBeforeScrollMove-Handler checks whether the scroll direction seems to be horizontal, and then prevents the default handler, thus effectively locking the scroll action to the X-Axis (try commenting it out, you'll see the difference). Otherwise, if the scroll direction needs to be vertical, we make the browser scroll via the window.scrollBy()method. This is not exactly native, but does the job just fine.

通过这样做,onBeforeScrollMove-Handler 检查滚动方向是否看起来是水平的,然后阻止默认处理程序,从而有效地将滚动动作锁定到 X 轴(尝试将其注释掉,您会看到区别)。否则,如果滚动方向需要垂直,我们通过该window.scrollBy()方法使浏览器滚动。这并不完全是原生的,但可以很好地完成工作。

Hope that helps

希望有帮助

Lukx

卢克斯

[EDIT] My original solution, which didn't use window.scrollBy(),did not work on slower Samsung phones, which is why I needed to adapt the answer.

[编辑] 我没有使用的原始解决方案window.scrollBy()在较慢的三星手机上不起作用,这就是我需要调整答案的原因。

回答by Greg

With iscroll 5, you can set eventPassthrough: trueto achieve this. See http://iscrolljs.com/#configuring

使用 iscroll 5,您可以设置eventPassthrough: true来实现这一点。见http://iscrolljs.com/#configuring

回答by Fresheyeball

OLD ANSWER

旧答案

UPDATE a special pluggin has been written just to address this problem: http://cubiq.org/swipeview

更新了一个专门的插件来解决这个问题:http: //cubiq.org/swipeview

I found a way!

我找到了一个方法!

add a variable to the top of the document: if android is 15 and is iOS is 3

在文档顶部添加一个变量:if android is 15 and is iOS is 3

 var scrollTolerance = ( rs().isDevice('android') )?15:3;

disable the original e.preventDefault(); for scrolling. This is under onBeforeScrollStart:

禁用原来的 e.preventDefault(); 用于滚动。这是在 onBeforeScrollStart 下:

the in _move just under

在 _move 下

 timestamp = e.timeStamp || Date.now();

add this line

添加这一行

if( Math.sqrt(deltaX*deltaX) > scrollTolerance){e.preventDefault();}

What this does is the following: the scrollTolerance sets, you guessed it, a tolerance for finger direction. We don't want to demand a perfect vertical angle to get the up down native scroll. Also iOS does not detect properly and will never be higher than 4 for some reason so I used 3. Then we disable iScroll's standard e.preventDefault(); which prevents native vertical scrolling on our bi-scrollable area. Then we insert e.preventDefault(); only upon move and based on finger direction from tolerance.

它的作用如下:scrollTolerance 设置,你猜对了,手指方向的容差。我们不想要求一个完美的垂直角度来获得向上向下的原生滚动。此外,iOS 无法正确检测并且由于某种原因永远不会高于 4,所以我使用了 3。然后我们禁用了 iScroll 的标准 e.preventDefault(); 这可以防止我们双滚动区域的原生垂直滚动。然后我们插入 e.preventDefault(); 仅在移动时并基于公差的手指方向。

This does not work perfect. But is acceptable and works on iOS and Android. If anyone sees better ways please post here. This is something I (and assume others) need to use regularly, and we should have a perfect rock solid solution.

这并不完美。但可以接受并且适用于 iOS 和 Android。如果有人看到更好的方法,请在此处发布。这是我(并假设其他人)需要经常使用的东西,我们应该有一个完美的坚如磐石的解决方案。

Thanks.

谢谢。

回答by musdy

on iScroll5 just set eventPassthrougt to true. That fixes it.

在 iScroll5 上只需将 eventPassthrougt 设置为 true。那修复它。

回答by agaase

Please test this solution from Adam. https://gist.github.com/hotmeteor/2231984

请测试 Adam 的这个解决方案。 https://gist.github.com/hotmeteor/2231984

I think the trick is to add the check in onBeforeScrollMove. First get the initial touch position in onBeforeScrollTouchStart and then in onBeforeScrollMove check the new position and then disable the required scroll based on the difference.

我认为诀窍是在 onBeforeScrollMove 中添加检查。首先在 onBeforeScrollTouchStart 中获取初始触摸位置,然后在 onBeforeScrollMove 检查新位置,然后根据差异禁用所需的滚动。

回答by Design by Adrian

iScroll 5 supports native scrolling of any axis!

iScroll 5 支持任意轴的原生滚动!

http://iscrolljs.com/

http://iscrolljs.com/