-
-
Save minwe/9132756 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Usage: $(element).scrollToTop([position]) | |
;(function($){ | |
// only allow one scroll to top operation to be in progress at a time, | |
// which is probably what you want | |
var scrollToTopInProgress = false | |
$.fn.scrollToTop = function(position){ | |
var $this = this, | |
targetY = position || 0, | |
initialY = $this.scrollTop(), | |
lastY = initialY, | |
delta = targetY - initialY, | |
// duration in ms, make it a bit shorter for short distances | |
// this is not scientific and you might want to adjust this for | |
// your preferences | |
speed = Math.min(750, Math.min(1500, Math.abs(initialY-targetY))), | |
// temp variables (t will be a position between 0 and 1, y is the calculated scrollTop) | |
start, t, y, | |
// use requestAnimationFrame or polyfill | |
frame = window.requestAnimationFrame || | |
window.webkitRequestAnimationFrame || | |
window.mozRequestAnimationFrame || | |
function(callback){ setTimeout(callback,15) }, | |
cancelScroll = function(){ abort() } | |
// abort if already in progress or nothing to scroll | |
if (scrollToTopInProgress) return | |
if (delta == 0) return | |
// quint ease-in-out smoothing, from | |
// https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js#L127-L136 | |
function smooth(pos){ | |
if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,5) | |
return 0.5 * (Math.pow((pos-2),5) + 2) | |
} | |
function abort(){ | |
$this.off('touchstart', cancelScroll) | |
scrollToTopInProgress = false | |
} | |
// when there's a touch detected while scrolling is in progress, abort | |
// the scrolling (emulates native scrolling behavior) | |
$this.on('touchstart', cancelScroll) | |
scrollToTopInProgress = true | |
// start rendering away! note the function given to frame | |
// is named "render" so we can reference it again further down | |
frame(function render(now){ | |
if (!scrollToTopInProgress) return | |
if (!start) start = now | |
// calculate t, position of animation in [0..1] | |
t = Math.min(1, Math.max((now - start)/speed, 0)) | |
// calculate the new scrollTop position (don't forget to smooth) | |
y = Math.round(initialY + delta * smooth(t)) | |
// bracket scrollTop so we're never over-scrolling | |
if (delta > 0 && y > targetY) y = targetY | |
if (delta < 0 && y < targetY) y = targetY | |
// only actually set scrollTop if there was a change fromt he last frame | |
if (lastY != y) $this.scrollTop(y) | |
lastY = y | |
// if we're not done yet, queue up an other frame to render, | |
// or clean up | |
if (y !== targetY) frame(render) | |
else abort() | |
}) | |
} | |
})(Zepto) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;(function($){ | |
var scrollToTopInProgress = false | |
$.fn.scrollToTop = function(position){ | |
var $this = this, | |
targetY = position || 0, | |
initialY = $this.scrollTop(), | |
lastY = initialY, | |
delta = targetY - initialY, | |
speed = Math.min(750, Math.min(1500, Math.abs(initialY-targetY))), | |
start, t, y, frame = window.requestAnimationFrame || | |
window.webkitRequestAnimationFrame || | |
window.mozRequestAnimationFrame || | |
function(callback){ setTimeout(callback,15) }, | |
cancelScroll = function(){ abort() } | |
if (scrollToTopInProgress) return | |
if (delta == 0) return | |
function smooth(pos){ | |
if ((pos/=0.5) < 1) return 0.5*Math.pow(pos,5) | |
return 0.5 * (Math.pow((pos-2),5) + 2) | |
} | |
function abort(){ | |
$this.off('touchstart', cancelScroll) | |
scrollToTopInProgress = false | |
} | |
$this.on('touchstart', cancelScroll) | |
scrollToTopInProgress = true | |
frame(function render(now){ | |
if (!scrollToTopInProgress) return | |
if (!start) start = now | |
t = Math.min(1, Math.max((now - start)/speed, 0)) | |
y = Math.round(initialY + delta * smooth(t)) | |
if (delta > 0 && y > targetY) y = targetY | |
if (delta < 0 && y < targetY) y = targetY | |
if (lastY != y) $this.scrollTop(y) | |
lastY = y | |
if (y !== targetY) frame(render) | |
else abort() | |
}) | |
} | |
})(Zepto) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment