简体   繁体   English

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

[英]iScroll with native scrolling on one axis

I am using the most wonderful javascript tool iScroll4 http://cubiq.org/iscroll-4 on a mobile website for iOS and Android. 我在iOS和Android的移动网站上使用最精彩的JavaScript工具iScroll4 http://cubiq.org/iscroll-4 Here is what my layout looks like: 这是我的布局:

布局问题

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). 到目前为止我尝试过:在iScroll代码中删除e.preventDefault()(允许本地滚动,但在BOTH轴中)。 Removing e.preventDefault() and then disabling horizontal scrolling page wide with this: 删除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? 如何在水平滚动区域中允许原生垂直滚动,而不会丢失iScroll的水平滚动? I am really stumped here. 我真的很难过。 Thanks in advance. 提前致谢。

(just for the record rs(foo).toPos() is a function that makes foo a positive number regardless of its value). (仅用于记录rs(foo).toPos()是一个使foo成为正数的函数,无论其值如何)。

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). 通过这样做, onBeforeScrollMove -Handler检查滚动方向是否是水平的,然后阻止默认处理程序,从而有效地将滚动操作锁定到X轴(尝试将其注释掉,你会看到差异)。 Otherwise, if the scroll direction needs to be vertical, we make the browser scroll via the window.scrollBy() method. 否则,如果滚动方向需要是垂直的,我们通过window.scrollBy()方法滚动浏览器。 This is not exactly native, but does the job just fine. 这不完全是原生的,但是工作做得很好。

Hope that helps 希望有所帮助

Lukx 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() ,在较慢的三星手机上不起作用,这就是我需要调整答案的原因。

Suggested edit to @Lukx's excellent solution. 建议编辑@Lukx的优秀解决方案。 New versions of iScroll4 place the e.preventDefault() in onBeforeScrollMove which can be overridden. 新版本的iScroll4将e.preventDefault()放在onBeforeScrollMove ,可以覆盖它。 By placing the if block into this option, default is not prevented for vertical scrolling, and vertical can scroll natively. 通过将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();
        }
    },
});

With iscroll 5, you can set eventPassthrough: true to achieve this. 使用iscroll 5,您可以设置eventPassthrough: true来实现此目的。 See http://iscrolljs.com/#configuring 请参阅http://iscrolljs.com/#configuring

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 在文档的顶部添加一个变量:如果android是15并且iOS是3

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

disable the original e.preventDefault(); 禁用原始的e.preventDefault(); for scrolling. 滚动。 This is under onBeforeScrollStart: 这是在onBeforeScrollStart下:

the in _move just under in _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. 这样做的原因如下:你猜对了scrollTolerance设置了手指方向的容差。 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(); iOS也没有正确检测,并且由于某种原因永远不会高于4,所以我使用3.然后我们禁用iScroll的标准e.preventDefault(); which prevents native vertical scrolling on our bi-scrollable area. 这会阻止我们的双滚动区域上的原生垂直滚动。 Then we insert e.preventDefault(); 然后我们插入e.preventDefault(); only upon move and based on finger direction from tolerance. 仅在移动时并且基于手指方向的公差。

This does not work perfect. 这不是完美的。 But is acceptable and works on iOS and Android. 但是可以接受,适用于iOS和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. 这是我(并假设其他人)需要定期使用的东西,我们应该有一个完美的坚如磐石的解决方案。

Thanks. 谢谢。

Please test this solution from Adam. 请从亚当测试这个解决方案。 https://gist.github.com/hotmeteor/2231984 https://gist.github.com/hotmeteor/2231984

I think the trick is to add the check in onBeforeScrollMove. 我认为诀窍是在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. 首先获取onBeforeScrollTouchStart中的初始触摸位置,然后在onBeforeScrollMove中检查新位置,然后根据差异禁用所需的滚动。

iScroll 5 supports native scrolling of any axis! iScroll 5支持任意轴的原生滚动!

http://iscrolljs.com/ http://iscrolljs.com/

on iScroll5 just set eventPassthrougt to true. 在iScroll5上只需将eventPassthrougt设置为true即可。 That fixes it. 这解决了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM