Skip to content

Instantly share code, notes, and snippets.

@djave-co
Last active October 11, 2021 15:57
Show Gist options
  • Save djave-co/00f2701fe0a18bf956fc4d908eb8758d to your computer and use it in GitHub Desktop.
Save djave-co/00f2701fe0a18bf956fc4d908eb8758d to your computer and use it in GitHub Desktop.
Automate scroll
// https://matthewlein.com/tools/ceaser
class Scroll {
constructor() {
document.documentElement.style.scrollBehavior = 'auto';
document.body.style.scrollBehavior = "auto";
window.addEventListener("scroll", this.outputScroll);
this.speed = 0.001;
this.timing = "easeInOut";
this.promise = {
res: null,
rej: null
};
return console.log("Scroller ready for commands!");
}
outputScroll(){
let top = document.documentElement.scrollTop;
console.log(`scroll.to(${top})`);
}
getNumber(str){
return parseFloat(str.match(/\d+/));
}
getMilliseconds(str){
if(str.substring(str.length - 2) == "ms"){
return this.getNumber(str);
}
return this.getNumber(str) * 1000;
}
setDuration(time) {
let t = 1000 / this.getMilliseconds(time) / 60;
return this.setSpeed(t);
}
setSpeed(speed) {
this.speed = speed;
}
setTiming(timing) {
this.timing = timing;
}
lerp(v0, v1, t) {
(1 - t) * v0 + t * v1;
}
underOver = (t) => {
return this.calcBezier([0.775, -0.415, 0.43, 1.325], t);
};
longOut = (t) => {
return this.calcBezier([0.445, 0.005, 0.045, 0.995], t);
};
smoothStraight = (t) => {
return this.calcBezier([0.315, 0.01, 0.79, 1.0], t);
};
straightish = (t) => {
return this.calcBezier([0.12, 0.005, 0.88, 0.99], t);
};
easeIn = (t) => {
return this.calcBezier([1.000, 0.010, 1.000, 0.490], t);
};
easeInOut = (t) => {
return this.calcBezier([0.575, 0.000, 0.300, 1.000], t);
};
straight = (t) => t;
calcBezier = (bezier, t) => {
let [bx, by, cx, cy] = bezier;
return {
x: 3*(1-t) ** 2 * t * bx + 3*(1-t) * t ** 2 * cx + t ** 3,
y: 3 * t * (1 - t) ** 2 * by + 3 * t ** 2 * (1 - t) * cy + t ** 3
};
};
to(target) {
this.t = 0;
this.y = document.documentElement.scrollTop;
this.startY = this.y;
if (typeof target == "string" && target.substring(0, 1) == "+") {
if (new RegExp(/\+\d+vh/).test(target)) {
this.target = parseInt(target.match(/\d+/)) * window.innerHeight * 0.01;
} else {
this.target = parseFloat(target.match(/\d+/));
}
} else if (typeof target == "string" && new RegExp(/^(\d+)(px|vh)$/gm).test(target)) {
if (new RegExp(/\d+vh/).test(target)) {
this.target = this.getNumber(target) * window.innerHeight * 0.01 - document.documentElement.scrollTop;
} else {
this.target = this.getNumber(target) - document.documentElement.scrollTop;
}
} else if (typeof target == "string") {
this.targetEl = document.querySelector(target);
this.target = this.targetEl.getBoundingClientRect().top - document.documentElement.scrollTop;
} else if (typeof target == "number") {
this.target = target - document.documentElement.scrollTop;
} else {
this.targetEl = target;
this.target = this.targetEl.getBoundingClientRect().top - document.documentElement.scrollTop;
}
}
jumpTo(to = 0){
document.documentElement.scrollTop = to;
}
toEnd() {
this.to(
"+" +
(document.body.getBoundingClientRect().height - window.innerHeight - document.documentElement.scrollTop) +
"px"
);
}
async wait(amount){
let t = this.getMilliseconds(amount);
return new Promise((res, rej) => {
setTimeout(() => {
res();
}, t)
})
}
async start() {
window.removeEventListener("scroll", this.outputScroll);
this.animate();
return new Promise((resolve, reject) =>{
this.promise.res = resolve;
this.promise.rej = reject;
});
}
animate() {
this.t += this.speed;
const { x, y } = this[this.timing](this.t);
this.y = y * this.target;
document.documentElement.scrollTop = this.startY + this.y;
if (x < 1) {
requestAnimationFrame(this.animate.bind(this));
} else {
document.documentElement.scrollTop = this.startY + this.target
this.promise.res();
window.addEventListener("scroll", this.outputScroll);
}
}
}
let scroll = new Scroll();
// jumpTo moves where the screen is instantly.
scroll.jumpTo(0);
// How long the next scroll should last.
scroll.setDuration("4s");
// vh means viewport height unit. 100vh = one screen height.
// The below means go 3 screen heights down
scroll.to("300vh");
// Start scrolling, and wait to finish!
await scroll.start();
// Pause for this many seconds (also does decimals and milliseconds — "4.3s" or "400ms")
await scroll.wait("4s");
// plus means go further than present scroll position
scroll.to("+200vh");
await scroll.start();
// Scroll the bottom of the screen
scroll.toEnd();
await scroll.start();
// A number defaults to pixels
scroll.to(0);
await scroll.start();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment