Cancel scrolling after user interaction
My webpage animates scrolling when users click on links to the same page. I want to cancel this a开发者_如何学编程nimation as soon as the user tries to scroll (otherwise the user and the browser are fighting for control) – no matter whether with the mouse wheel, the keyboard or the scrollbar (or any other way – are there other ways of scrolling?). I managed to cancel the animation after the mouse wheel or keyboard are used, how do I get this working with the scrollbar?
Here is how my code looks for the keyboard:
$(document.documentElement).keydown( function (event) {
if(event.keyCode == 38 || 40) stopScroll();
});
function stopScroll() {
$("html, body").stop(true, false);
}
I also tried a more elegant way of doing this by using scroll()
, the problem is that scroll()
catches everything including the animated and automated scrolling. I could not think of any way to let it catch all scrolling except the animated scrolling.
you need animation marker, something like this
$("html, body").stop(true, false).prop('animatedMark',0.0).animate({scrollTop : top, animatedMark: '+=1.0'})
Here is the code, the code was mix of GWT and javascript so moved it to js, not fully tested, please try it
var lastAnimatedMark=0.0;
function scrollToThis(top){
// Select/ stop any previous animation / reset the mark to 0
// and finally animate the scroll and the mark
$("html, body").stop(true, false).prop('animatedMark',0.0).
animate({scrollTop : top, animatedMark: '+=1.0'}
,10000,function(){
//We finished , nothing just clear the data
lastAnimatedMark=0.0;
$("html, body").prop('animatedMark',0.0);
});
}
//Gets the animatedMark value
function animatedMark() {
var x=$("html, body").prop('animatedMark');
if (x==undefined){
$("html, body").prop('animatedMark', 0.0);
}
x=$("html, body").prop('animatedMark');
return x;
};
//Kills the animation
function stopBodyAnimation() {
lastAnimatedMark=0;
$("html, body").stop(true, false);
}
//This should be hooked to window scroll event
function scrolled(){
//get current mark
var currentAnimatedMark=animatedMark();
//mark must be more than zero (jQuery animation is on) & but
//because last=current , this is user interaction.
if (currentAnimatedMark>0 && (lastAnimatedMark==currentAnimatedMark)) {
//During Animation but the marks are the same !
stopBodyAnimation();
return;
}
lastAnimatedMark=currentAnimatedMark;
}
Here is the blog about it
http://alaamurad.com/blog/#!canceling-jquery-animation-after-user-interaction
Enjoy!
Here's a jquery function that should do the trick:
function polite_scroll_to(val, duration, callback) {
/* scrolls body to a value, without fighting the user if they
try to scroll in the middle of the animation. */
var auto_scroll = false;
function stop_scroll() {
if (!auto_scroll) {
$("html, body").stop(true, false);
}
};
$(window).on('scroll', stop_scroll);
$("html, body").animate({
scrollTop: val
}, {
duration: duration,
step: function() {
auto_scroll = true;
$(window).one('scroll', function() {
auto_scroll = false;
});
},
complete: function() {
callback && callback();
},
always: function() {
$(window).off('scroll', stop_scroll);
}
});
};
It's not very elegant, but you could use a flag of some kind to detect what type of scrolling you're dealing with (animated or 'manual') and always kill it when it's animated. Here's an untested example:
var animatedScroll = false;
// you probably have a method looking something like this:
function animatedScrollTo(top) {
// set flag to true
animatedScroll = true;
$('html').animate({
scrollTop : top
}, 'slow', function() {
// reset flag after animation is completed
animatedScroll = false;
});
}
function stopScroll() {
if (animatedScroll) {
$("html, body").stop(true, false);
}
}
精彩评论