Функция по скролу плавному страницы до определенных точек
Есть функция которую писали под первые требования
function automatic_scroll( arrayHights = [{points: 150, delay: 0, animation: 2500}, {points: 2028, delay: 1800, animation: 2800}, {points: 3035, delay: 2200, animation: 3800},{points: 4435, delay: 4000, animation: 800},{points: 4535, delay: 7000, animation: 2000}], delayScript = 2000, debug = false) {
if(debug) {
$('body').click(function(e){
var coord = e.pageY;
console.log("Координата: " + coord);
});
}
else {
function scripts_start() {
function delay(time) {
console.log('fdelay(time) ' + time);
return new Promise(resolve => setTimeout(resolve, time)); // айминк верный передаем в тайм время плюс задержку
}
async function delayedLog(item,time,animation) {
await delay(time);
console.log('item: '+item);
console.log('time: '+time);
console.log('____________');
smoothScrollTo(item,animation,0,timereturn = true);
}
async function processArray(array) {
for (var i = 1; i <= array.length; i++) {
var c = i - 1;
if (c == 0) {
await delayedLog(array[c]['points'],delayScript,array[c]['animation']);
}
else {
await delayedLog(array[c]['points'],array[c]['delay'],array[c]['animation']);
}
}
console.log('Done!');
}
processArray(arrayHights);
}
setTimeout(scripts_start, delayScript);
window.smoothScrollTo = (function () {
var timer, start, factor;
return function (target, duration, startPlus = 0 , timereturn = false) {
var offset = window.pageYOffset,
delta = target - window.pageYOffset; // Y-offset difference
duration = duration || 1500; // default 1 sec animation
start = Date.now() + startPlus; // get start time
factor = 0;
if( timer ) {
clearInterval(timer); // stop any running animations
}
function step() {
var y;
factor = (Date.now() - start) / duration; // get interpolation factor
if( factor >= 1 ) {
clearInterval(timer); // stop animation
factor = 1; // clip to max 1.0
}
y = factor * delta + offset;
window.scrollBy(0, y - window.pageYOffset,'smooth');
}
timer = setInterval(step, 10);
return timer;
};
}());
}}
пример запуска
automatic_scroll([{points: 700, delay: 0, animation: 1500}, {points: 2528, delay: 10000, animation: 4800}, {points: 3835, delay: 9000, animation: 2800},{points: 5035, delay: 10000, animation: 2800}], 4000, false);
функция прокручивает до точек определенных со своей задержкой (задержка работает не точно из за того что не допилил расчет времени прокрутки + остановка на точке) а так же у каждой точки своя скорость прокрутки.
Но нужно теперь переписать или заново написать под задачи :
— Нужно сделать прокрутку плавнее, вроде ease-in-out — чтобы ускорялся и тормозил красиво. Без этой штуки скрипт не несёт пользы, потому что прокрутка некрасивая.
— Код нужно упростить.
- Маленький код должен быть такой:
automatic_scroll(points= [0, 659, 1274, 1807, 2330, 2993 ,3856, 4525, 4743], delays = [500, 600, 700, 700, 700, 700, 700, 700, 700], speed = 600); — никаких false или непонятных чисел в конце.
Скорость давай указывать одну и высчитывать её так: берём расстояние до следующей точки, пусть это 600 пикселей, тогда при скорости 600 пк/сек прокрутка произойдёт за 1 секунду. Если бы до следующей точки было 1200 точек, то заняла бы 2 секунды. Если указать скорсть 1200 пк/сек и до точки 1200 пикселей, то снова 1 секунда.
Подскажите как переписать ее по человечески , что использовать лучше (не шарю сильно в промисах и в async но готов разобраться) , каким образом. Достаточно будет базового наброска типо алгоритма программы и в идеале какую технологию применить. Но нужно на js что бы через консоль в браузере работал скрипт.Заранее спасибо за ответ!
Ответы (1 шт):
https://easings.net/ru#easeInOutCubic на этом сайте есть математические функции для разных типов плавностей. Вот пример реализации:
//Function that calculate animation easing
function delta(x) {
return x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
}
//async delay
async function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function automatic_scroll(points, delays, speed) {
for (let i = 0; i < points.length; i++) {
await scrollPoint(points[i], delays[i], speed);
}
}
async function scrollPoint(p, delayms, speed) {
//Save constants
const begin = +new Date();
const start = pageYOffset;
const time = (p - start) / speed;
//move
await animateTo();
//wait
await delay(delayms);
async function animateTo() {
const t = (+new Date() - begin) / 1000;
const progress = t / time;
let delt = delta(progress);
if (t > time) {
//time is over
scrollTo(0, p);
return;
} else scrollTo(0, start + delt * (p - start));
//Promisification of recursion
return new Promise((resolve, rej) => {
setTimeout(async () => {
await animateTo();
resolve();
}, 0);
});
}
}
window.onload = () => {
document.body.onclick = () => {
automatic_scroll([400, 900, 3500], [500, 200, 400], 600);
};
};
body {
height: 5000px;
}
body > div {
position: absolute;
}
#p1 {
top: 0px;
}
#p2 {
top: 400px;
}
#p3 {
top: 900px;
}
#p4 {
top: 3500px;
}
<div id="p1">Point at 0</div>
<div id="p2">Point at 400</div>
<div id="p3">Point at 900</div>
<div id="p4">Point at 3500</div>