iScroll 在一个轴上具有原生滚动功能

发布于 2024-12-10 10:49:36 字数 1147 浏览 1 评论 0原文

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

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 成为正数,无论其值如何)。

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

layout problem

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

   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.

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:

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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

<逆流佳人身旁 2024-12-17 10:49:36

如果您想在不破坏核心、不从 iScroll 更改为 swipeview 的情况下实现 Fresheyeball 所描述的效果,那么 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() 方法使浏览器滚动。这并不完全是原生的,但工作得很好。

希望对

Lukx

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

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.

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.

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.

花期渐远 2024-12-17 10:49:36

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

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

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();
        }
    },
});
拥抱没勇气 2024-12-17 10:49:36

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

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

最佳男配角 2024-12-17 10:49:36

旧答案

更新已经编写了一个特殊的插件来解决这个问题:
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 上运行。如果有人看到更好的方法,请在这里发帖。这是我(并假设其他人)需要定期使用的东西,我们应该有一个完美的坚如磐石的解决方案。

谢谢。

OLD ANSWER

UPDATE a special pluggin has been written just to address this problem:
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

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

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

the in _move just under

 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.

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.

Thanks.

全部不再 2024-12-17 10:49:36

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

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

Please test this solution from 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.

Saygoodbye 2024-12-17 10:49:36

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

http://iscrolljs.com/

iScroll 5 supports native scrolling of any axis!

http://iscrolljs.com/

初雪 2024-12-17 10:49:36

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文