在一个轴上使用原生滚动进行iScroll

时间:2011-10-17 22:17:25

标签: javascript android ios mobile iscroll4

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

layout problem

可水平滚动的区域正在使用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成为正数而不管其值如何的函数。)

7 个答案:

答案 0 :(得分: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 - 处理程序检查滚动方向是否为水平,然后阻止默认处理程序,从而有效地将滚动操作锁定到X轴(尝试将其注释掉,你会看到差异)。否则,如果滚动方向需要是垂直的,我们通过window.scrollBy()方法滚动浏览器。这不完全是原生的,但是工作做得很好。

希望有所帮助

Lukx

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

答案 1 :(得分:10)

推荐编辑@Lukx的优秀解决方案。新版本的iScroll4将e.preventDefault()放在onBeforeScrollMove中,可以覆盖它。通过将if块放入此选项,不会阻止垂直滚动的默认值,而vertical可以本机滚动。

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();
        }
    },
});

答案 2 :(得分:4)

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

答案 3 :(得分:1)

OLD ANSWER

更新了一个特殊的插件,只是为了解决这个问题: http://cubiq.org/swipeview

我找到了办法!

在文档顶部添加一个变量:如果android为15且iOS为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。如果有人看到更好的方式,请在这里发布这是我(并假设其他人)需要定期使用的东西,我们应该有一个完美的坚如磐石的解决方案。

感谢。

答案 4 :(得分:0)

请从亚当测试此解决方案。 https://gist.github.com/hotmeteor/2231984

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

答案 5 :(得分:0)

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

http://iscrolljs.com/

答案 6 :(得分:0)

iScroll5上的

只是将eventPassthrougt设置为true。这解决了它。