javascript iScroll 在一个轴上进行本机滚动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7800261/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iScroll with native scrolling on one axis
提问by Fresheyeball
I am using the most wonderful javascript tool iScroll4 http://cubiq.org/iscroll-4on a mobile website for iOS and Android. Here is what my layout looks like:
我在iOS 和 Android 的移动网站上使用了最出色的 javascript 工具 iScroll4 http://cubiq.org/iscroll-4。这是我的布局:
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). Removing e.preventDefault() and then disabling horizontal scrolling page wide with this:
到目前为止我已经尝试过:在 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(); }
}
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.
这似乎什么都不做。如何在不丢失 iScroll 的水平滚动的情况下允许水平滚动区域中的本机垂直滚动?我真的被难住了。提前致谢。
(just for the record rs(foo).toPos() is a function that makes foo a positive number regardless of its value).
(仅用于记录 rs(foo).toPos() 是一个使 foo 成为正数的函数,而不管其值如何)。
采纳答案by Fresheyeball
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.
建议编辑@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();
}
},
});
回答by Lukx
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). 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.
通过这样做,onBeforeScrollMove
-Handler 检查滚动方向是否看起来是水平的,然后阻止默认处理程序,从而有效地将滚动动作锁定到 X 轴(尝试将其注释掉,您会看到区别)。否则,如果滚动方向需要垂直,我们通过该window.scrollBy()
方法使浏览器滚动。这并不完全是原生的,但可以很好地完成工作。
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.
[编辑] 我没有使用的原始解决方案window.scrollBy()
在较慢的三星手机上不起作用,这就是我需要调整答案的原因。
回答by Greg
With iscroll 5, you can set eventPassthrough: true
to achieve this. See http://iscrolljs.com/#configuring
使用 iscroll 5,您可以设置eventPassthrough: true
来实现这一点。见http://iscrolljs.com/#configuring
回答by Fresheyeball
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
在文档顶部添加一个变量: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:
禁用原来的 e.preventDefault(); 用于滚动。这是在 onBeforeScrollStart 下:
the in _move just under
在 _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. 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.
它的作用如下:scrollTolerance 设置,你猜对了,手指方向的容差。我们不想要求一个完美的垂直角度来获得向上向下的原生滚动。此外,iOS 无法正确检测并且由于某种原因永远不会高于 4,所以我使用了 3。然后我们禁用了 iScroll 的标准 e.preventDefault(); 这可以防止我们双滚动区域的原生垂直滚动。然后我们插入 e.preventDefault(); 仅在移动时并基于公差的手指方向。
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.
这并不完美。但可以接受并且适用于 iOS 和 Android。如果有人看到更好的方法,请在此处发布。这是我(并假设其他人)需要经常使用的东西,我们应该有一个完美的坚如磐石的解决方案。
Thanks.
谢谢。
回答by musdy
on iScroll5 just set eventPassthrougt to true. That fixes it.
在 iScroll5 上只需将 eventPassthrougt 设置为 true。那修复它。
回答by agaase
Please test this solution from Adam. https://gist.github.com/hotmeteor/2231984
请测试 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.
我认为诀窍是在 onBeforeScrollMove 中添加检查。首先在 onBeforeScrollTouchStart 中获取初始触摸位置,然后在 onBeforeScrollMove 检查新位置,然后根据差异禁用所需的滚动。
回答by Design by Adrian
iScroll 5 supports native scrolling of any axis!
iScroll 5 支持任意轴的原生滚动!