Как устроена логика прокрутки колёсиком(скролла)?
Здравствуйте. Делаю свою кастомную прокрутку и столкнулся с такой проблемой: не могу понять, как работает скролл, а точнее "что происходит при кручении колёсика дважды и более".
Сейчас у меня есть такое: 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, время: 15:45. |