Как устроена логика прокрутки колёсиком(скролла)?
Здравствуйте. Делаю свою кастомную прокрутку и столкнулся с такой проблемой: не могу понять, как работает скролл, а точнее "что происходит при кручении колёсика дважды и более".
Сейчас у меня есть такое: https://jsfiddle.net/drkrol/mtvhrdgb/7/ Загвоздка вот в этом коде: // условие при двойном кручении if (per1 == 1) { step = step + shag; } else { step = shag; } Логика такая. Есть per1. При начале кручения он принимает значение 1, в конце анимации срабатывает код onComplete: function() {per1 = 0;}. При условии, когда per1 == 1 размер расстояния увеличивается на 1 шаг. Проблема заключается в том, что если крутить колёсиком на 0.5 секунде (скорость анимации = 0.7), то через несколько таких прокруток вы улетите далеко вниз. Если совсем убрать условие IF, то прокрутка будет рывками, а мне нужна плавность. Вообще я стремлюсь вот к такому результату: http://maxlepinskih.com/prices , но я не понимаю, как это сделано у него. В его коде разобраться не смог. И ещё нюанс один. Мне, чтобы оно плавно работало, нужно было убрать overflow у body, а в примере по ссылке у него плавно и сколлбар есть... Скажите, как должно быть устроено условие IF, чтобы получилось, как у maxlepinskih? |
drkrol,
скролл по блочно |
рони, что это?
Цитата:
И ещё, чтобы избежать подёргивания и блокировки полосы прокрутки, не следует менять свойство scrollTop/ScrollLeft, прокрутка тогда очень не естественная получается. И странно получается, когда полоса прокрутки пытается вырваться из под курсора мыши. (поскольку происходит подмена scrollTop/ScrollLeft) Правильно делать так, чтобы при чтении scrollTop/ScrollLeft, менялся вид, а не сами эти свойства! drkrol, Цитата:
https://jsfiddle.net/u9xw6tjy/2/ |
Malleys,
спасибо за науку. |
плавный scroll
Malleys,
насколько правильно, сделать например, так? <!DOCTYPE html> <html> <head> <title>jQuery scroll example</title> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script> <style> body { background: #20262E; font-family: Helvetica Neue; } .wrap-box { width: 290px; height: 290px; background: #777; margin: 10px; } body, html { height: 100%; margin: 0; } .wrap { overflow: auto; border: 1px solid red; box-sizing: border-box; height: 100%; } .wrap-content { overflow: hidden; } .boxes{ transition: transform 1.8s cubic-bezier(0.47, 0, 0.745, 0.715); } </style> <script> window.onload = function() { for (var i = 0; i < 100; i++) { $(".boxes").append('<div class="wrap-box">' + (1 + i) + "</div>"); } var _top = 0; var top = 0; var scrollTop = 0; var timer; $(".wrap").scroll(function() { _top = this.scrollTop; scrollTop = _top - top; window.clearTimeout(timer); $(".boxes").css({"transform":"translateY(" + scrollTop + "px)", "transitionDuration":"0ms"}); timer = window.setTimeout(function() { $(".boxes").css({"transform":"translateY(0px)", "transitionDuration":""}); top = _top; }, 100); }); }; </script> </head> <body> <div class="wrap"> <div class="wrap-content"> <div class="boxes"></div> </div> </div> </body> </html> |
Malleys,
Спасибо за код. Обычно меня пытаются научить уму разуму, тут же вы мне сразу готовое решение предоставили. Ещё раз спасибо, но я не совсем в нём разобрался. Скажите пожалуйста, как мне регулировать время анимации (скорость) и расстояние одного шага? И чёт и туда, и сюда... Если у вас будет время и если вам не сложно, то не могли бы вы чуть подробнее разъяснить свой код? Я просто хотел вникнуть. Я понял, что всё держится на performance.now(), который возвращает время. Но как время помогает с плавностью я так и не понял... upd. Проверил ваш вариант в Microsoft Edge. В начале анимации есть небольшое подёргивание, которое не наблюдается в Chrome и Opera https://yadi.sk/i/YDtQ42kBiSpm4w - видео. Лучше скачать его (860 кб весит), иначе непонятно, где лаги |
Цитата:
var a = 1 - Math.exp(-0.005 * dt);Число 0.005 поделите на нужное кол-во секунд, или умножьте на число, во сколько раз быстрее хотите! Цитата:
Цитата:
Все держится на формуле var a = 1 - Math.exp(-0.005 / T * dt);, которая и вычисляет, как быстро приближаться к конечной позиции прокрутки. Цитата:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width"> <title>Document</title> <style> body { background: #20262E; font-family: "Helvetica Neue", system-ui; } .wrap-box { width: 290px; height: 290px; background: #777; margin: 10px; } body, html { height: 100%; margin: 0; } .wrap { overflow: auto; border: 1px solid red; box-sizing: border-box; height: 100%; } .wrap-content { overflow: hidden; } </style> </head> <body> <div class="wrap"> <div class="wrap-content"> <div class="boxes"></div> </div> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script> <script> $(function() { for (var i = 0; i < 100; i++) { $(".boxes").append(`<div class="wrap-box">${1 + i}</div>`); } var T = 0.75; // время до торможения (секунды) var A = 4; // во сколько раз уменьшить полосу прокрутки? Лучше всего [1;5] var _top = 0; var top = 0; var height; var originalHeight, wrapHeight; var scrollTop = 0; var lastTime = performance.now(); var isScrolling = false; var wrap = $(".wrap"); var wrapContent = $(".wrap-content"); var boxes = $(".boxes"); wrap.scroll(function() { _top = this.scrollTop; wrapHeight = wrap.height(); if (!isScrolling) loop(); }); $(window).resize(function() { wrapHeight = wrap.height(); originalHeight = wrapContent.css("height", "").height(); height = Math.min(originalHeight - wrapHeight, (originalHeight - wrapHeight) / A) + wrapHeight; wrapContent.css("height", (height) + "px"); wrap.scroll(); }); $(window).resize(); function loop() { isScrolling = true; var dt = -lastTime + (lastTime = performance.now()); var a = 1 - Math.exp(-0.005 / T * dt); var p = _top / (height - wrapHeight); top = (1 - a) * top + a * _top; scrollTop = _top - top; scrollTop = Math.abs(scrollTop) < 0.01 ? 0 : scrollTop; boxes.css("transform", "translateY(" + (scrollTop - p * (A - 1) / A * (originalHeight - wrapHeight)) + "px)"); if (scrollTop !== 0) requestAnimationFrame(loop); else isScrolling = false; } }); </script> </body></html> Цитата:
|
Цитата:
|
Цитата:
Цитата:
в целом плохо понимаю что происходит в фунции loop, кроме того что scrollTop стремится к нулю. |
чудеса какие-то... ничего не понял...
В firefox, кстати, шаг одного прокручивания в 2 раза меньше. Даже в 2.5... Может если за место "transform", "translateY"сделать GSAP, то подёргиваний не будет? |
Часовой пояс GMT +3, время: 18:34. |