I can't seem to capture the scroll event on an iPad. None of these work, what I am doing wrong?
window.onscroll=myFunction;
document.onscroll=myFunction;
window.attachEvent("scroll",myFunction,false);
document.attachEvent("scroll",myFunction,false);
They all work even on Safari 3 on Windows.
Ironically, EVERY browser on the PC supp开发者_StackOverfloworts window.onload=
if you don't mind clobbering existing events. But no go on iPad.
The iPhoneOS does capture onscroll
events, except not the way you may expect.
One-finger panning doesn’t generate any events until the user stops panning—an
onscroll
event is generated when the page stops moving and redraws—as shown in Figure 6-1.
Similarly, scroll with 2 fingers fires onscroll
only after you've stopped scrolling.
The usual way of installing the handler works e.g.
window.addEventListener('scroll', function() { alert("Scrolled"); });
// or
$(window).scroll(function() { alert("Scrolled"); });
// or
window.onscroll = function() { alert("Scrolled"); };
// etc
(See also https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)
For iOS you need to use the touchmove event as well as the scroll event like this:
document.addEventListener("touchmove", ScrollStart, false);
document.addEventListener("scroll", Scroll, false);
function ScrollStart() {
//start of scroll event for iOS
}
function Scroll() {
//end of scroll event for iOS
//and
//start/end of scroll event for other browsers
}
Sorry for adding another answer to an old post but I usually get a scroll event very well by using this code (it works at least on 6.1)
element.addEventListener('scroll', function() {
console.log(this.scrollTop);
});
// This is the magic, this gives me "live" scroll events
element.addEventListener('gesturechange', function() {});
And that works for me. Only thing it doesn't do is give a scroll event for the deceleration of the scroll (Once the deceleration is complete you get a final scroll event, do as you will with it.) but if you disable inertia with css by doing this
-webkit-overflow-scrolling: none;
You don't get inertia on your elements, for the body though you might have to do the classic
document.addEventListener('touchmove', function(e) {e.preventDefault();}, true);
I was able to get a great solution to this problem with iScroll, with the feel of momentum scrolling and everything https://github.com/cubiq/iscroll The github doc is great, and I mostly followed it. Here's the details of my implementation.
HTML: I wrapped the scrollable area of my content in some divs that iScroll can use:
<div id="wrapper">
<div id="scroller">
... my scrollable content
</div>
</div>
CSS: I used the Modernizr class for "touch" to target my style changes only to touch devices (because I only instantiated iScroll on touch).
.touch #wrapper {
position: absolute;
z-index: 1;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
}
.touch #scroller {
position: absolute;
z-index: 1;
width: 100%;
}
JS: I included iscroll-probe.js from the iScroll download, and then initialized the scroller as below, where updatePosition is my function that reacts to the new scroll position.
# coffeescript
if Modernizr.touch
myScroller = new IScroll('#wrapper', probeType: 3)
myScroller.on 'scroll', updatePosition
myScroller.on 'scrollEnd', updatePosition
You have to use myScroller to get the current position now, instead of looking at the scroll offset. Here is a function taken from http://markdalgleish.com/presentations/embracingtouch/ (a super helpful article, but a little out of date now)
function getScroll(elem, iscroll) {
var x, y;
if (Modernizr.touch && iscroll) {
x = iscroll.x * -1;
y = iscroll.y * -1;
} else {
x = elem.scrollTop;
y = elem.scrollLeft;
}
return {x: x, y: y};
}
The only other gotcha was occasionally I would lose part of my page that I was trying to scroll to, and it would refuse to scroll. I had to add in some calls to myScroller.refresh() whenever I changed the contents of the #wrapper, and that solved the problem.
EDIT: Another gotcha was that iScroll eats all the "click" events. I turned on the option to have iScroll emit a "tap" event and handled those instead of "click" events. Thankfully I didn't need much clicking in the scroll area, so this wasn't a big deal.
Since iOS 8 came out, this problem does not exist any more. The scroll event is now fired smoothly in iOS Safari as well.
So, if you register the scroll
event handler and check window.pageYOffset
inside that event handler, everything works just fine.
After some testing on the ios, I found that this is the way to go for ios and desktop, if you are not worried of that delay of 120ms on desktop. Works like a charm.
let isScrolling;
document.addEventListener("scroll", () => {
// Clear our timeout throughout the scroll
window.clearTimeout( isScrolling );
// Set a timeout to run after scrolling ends
isScrolling = setTimeout(function() {
// Run the callback
console.log( 'Scrolling has stopped.' );
}, 120);
});
精彩评论