-
-
Save SamJakob/c9175a4c2440e1b14b0b8cf7d99d2d24 to your computer and use it in GitHub Desktop.
const SmoothScroll = (target, speed, smooth) => { | |
if (target === document) | |
target = (document.documentElement || document.body.parentNode || document.body) // cross browser support for document scrolling | |
let moving = false; | |
let pos = target.scrollTop; | |
target.addEventListener('mousewheel', scrolled, false) | |
/* target.addEventListener('DOMMouseScroll', scrolled, false) */ | |
function scrolled(e) { | |
e.preventDefault(); // disable default scrolling | |
let delta = e.delta || e.wheelDelta; | |
if (delta === undefined) { | |
//we are on firefox | |
delta = -e.detail; | |
} | |
delta = Math.max(-1, Math.min(1, delta)) // cap the delta to [-1,1] for cross browser consistency | |
pos += -delta * speed | |
pos = Math.max(0, Math.min(pos, (target.scrollHeight - target.clientHeight) + (smooth * 2))) // limit scrolling | |
if (!moving) update() | |
} | |
function update() { | |
moving = true | |
let delta = (pos - target.scrollTop) / smooth; | |
delta -= 1; | |
if(pos - target.scrollTop === smooth * 2) | |
delta = 0; | |
target.scrollTop += delta | |
if (Math.abs(delta) > 0.5) | |
requestFrame(update) | |
else | |
moving = false | |
} | |
var requestFrame = function() { // requestAnimationFrame cross browser | |
return ( | |
window.requestAnimationFrame || | |
window.webkitRequestAnimationFrame || | |
window.mozRequestAnimationFrame || | |
window.oRequestAnimationFrame || | |
window.msRequestAnimationFrame || | |
function(func) { | |
window.setTimeout(func, 1000 / 50); | |
} | |
); | |
}() | |
} | |
export default SmoothScroll; |
<template> | |
... | |
</template> | |
<script> | |
import SmoothScroll from 'assets/js/smoothscroll'; | |
export default { | |
mounted () { | |
if(!window.smoothScroll){ | |
window.smoothScroll = SmoothScroll(document, 120, 12); | |
} | |
} | |
} | |
</script> |
What to do if you drag the scrollbar and it starts to scroll from there? Now its jumping to the last scrolled position.
Works well but I think this only works with Google Chrome
Hey Sam, I really love how the script works but I have a very niche issue where the script sort of breaks and was wondering if you could give me some insight on how to solve it.
Basically, I'm in a position where I need to call the function multiple times to change the speed of the scroll at different points of the webpage. This causes the smoothness aspect of the script to stop working. Any thoughts?
@joeljose24 Thank you :)
Have you tried moving the speed
variable outside of the function or moving it to the scope where you change the speed?
@SamJakob not exactly sure what you mean by moving the variable outside the function or to a different scope.. My exact scenario is I have a main webpage with a bunch of components. As the main webpage loads, if smoothscroll.js isn't in use, it calls the function. Beyond that, there is a component at a point on the webpage within which I call the smoothscroll.js function to slow it down.
@joeljose24
So if you see on line 1, the function is defined as const SmoothScroll = (target, speed, smooth) => {
I'd suggest taking speed out of the function arguments, so it's const SmoothScroll = (target, smooth) => {
and just defining speed
as a variable outside of the function. e.g.,
// Set the initial speed.
let speed = 120;
export function setSpeed(newScrollSpeed) {
speed = newScrollSpeed;
}
const SmoothScroll = (target, smooth) => {
// .. rest of the function from above (by not specifying speed as an argument it'll use the one defined above which
// will let us call setSpeed to change it)
}
export default SmoothScroll;
Then in the Vue example, you might call it like so:
import SmoothScroll, { setScrollSpeed } from 'assets/js/smoothscroll';
// ...
mounted () {
if(!window.smoothScroll){
window.smoothScroll = SmoothScroll(document, 12);
}
}
// ...
Then, when you want to change the scroll speed like so:
setScrollSpeed(240);
@SamJakob hey sam, I figured a workaround for this, I'm just disabling window scroll for specific points and enabling it after a time out.
Regardless, this solution still helped me solve a bug that I had because of the scroll disabling so, thank you so much for taking the time to answer my doubt! :)
For Safari compatibility, we need to force using
document.body
to work. I have this added before passing to use this script:Or this script can be modified to be more specific.