【问题标题】:iScroll with native scrolling on one axisiScroll 在一个轴上进行原生滚动
【发布时间】:2011-12-09 15:48:59
【问题描述】:

我在 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 成为正数的函数,而不管其值如何)。

【问题讨论】:

    标签: javascript android ios mobile iscroll4


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

        http://iscrolljs.com/

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

          【解决方案5】:

          建议编辑@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();
                  }
              },
          });
          

          【讨论】:

          • 对不起,我确实不知何故忘记了您的评论。这是一个很好的答案,感谢您增强它! +1
          • preventDefault 调用实际上是在 onBeforeScrollStart 中,而 absDist 属性似乎只有在此事件触发后才更新(touchstart/mousedown),因此该条件仅适用于同一方向连续第二次滑动.不过我对此很满意——事实上,切换轴所需的额外努力使我的水平滚动条更易于使用。我已经尝试了许多(全部?)其他方法来使用 iScroll 实现此功能,最终此方法获胜。 +1!
          • 请注意,如果您已经添加了 e.preventDefault 到 touchstart 和 touchmove 事件,就像他们在 iScroll 示例中推荐的那样,以防止点击拖动链接,请注意,您需要先删除该处理程序。
          • 没错,我想你也可以让垂直滚动成为 iScroll。否则它是给定的。
          • 注意,这与 iscroll 5 不再相关 - 请参阅我的回答
          【解决方案6】:

          老答案

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

          我找到了方法!

          在文档顶部添加一个变量:如果 android 是 15 而 iOS 是 3

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

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

          在 _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。如果有人看到更好的方法,请在此处发布。这是我(和假设其他人)需要经常使用的东西,我们应该有一个完美的坚如磐石的解决方案。

          谢谢。

          【讨论】:

          • 似乎对我不起作用。现在看起来包装器完全从图像中消失了......你是如何禁用原始的e.preventDefault()
          • 我把它注释掉了。无论哪种方式,现在都有更好的方法!回到 iScoll 网站,有一个新插件可以解决这个问题!
          • 真的!??!我一直在网站上,我没有看到插件。你有链接吗?非常感谢!
          • 太棒了,谢谢...用我的 iScroll4 包装器实现 SwipeView 时遇到了一些麻烦。有什么建议吗?
          • 打开您自己的 stackoverflow 问题,并在此处链接。我会尽力提供帮助。如果你想给这个问题和(或)答案+1,那也很好。
          【解决方案7】:

          如果您想在不破解内核的情况下实现 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() ,但不适用于速度较慢的三星手机,这就是我需要调整答案的原因。

          【讨论】:

          • 我想建议和编辑。如果您使用的是最新版本的 iScroll4,您可以使用新的onBeforeScrollStart 而不是onBeforeScrollMove。这样做你可以摆脱elsescrollBy,原生滚动将起作用。
          • 好的,我已经有一段时间没有收到关于建议编辑的回复了。所以我将接受的答案转移到我自己的。
          猜你喜欢
          • 1970-01-01
          • 2013-02-21
          • 1970-01-01
          • 1970-01-01
          • 2011-12-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-14
          相关资源
          最近更新 更多