13

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

布局问题

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

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

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

到目前为止我已经尝试过:删除 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(); }
}

这似乎什么也没做。如何在不丢失 iScroll 的水平滚动的情况下允许在水平滚动区域中进行原生垂直滚动?我真的很难过。提前致谢。

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

4

7 回答 7

12

如果您想在不修改内核的情况下实现 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 );
    }
    },
});

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

希望有帮助

卢克斯

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

于 2012-05-18T07:52:43.163 回答
10

建议编辑@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();
        }
    },
});
于 2012-10-30T19:55:24.843 回答
4

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

于 2014-09-18T01:56:14.430 回答
1

旧答案

更新已经编写了一个特殊的插件来解决这个问题: http ://cubiq.org/swipeview

我找到了一个方法!

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

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

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

in _move 就在下面

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

添加这一行

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

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

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

谢谢。

于 2011-11-18T06:42:07.910 回答
0

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

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

于 2013-10-09T06:55:59.040 回答
0

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

http://iscrolljs.com/

于 2014-03-20T15:30:09.877 回答
0

在 iScroll5 上,只需将 eventPassthrougt 设置为 true。这解决了它。

于 2017-09-19T19:40:36.187 回答