Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как устроена логика прокрутки колёсиком(скролла)? (https://javascript.ru/forum/misc/77564-kak-ustroena-logika-prokrutki-koljosikom-skrolla.html)

Malleys 24.05.2019 13:16

Цитата:

Сообщение от drkrol
В firefox, кстати, шаг одного прокручивания в 2 раза меньше. Даже в 2.5...

Это зависит от встроенного шага прокрутки, значит обычная прокрутка там в 2..2,5 раза медленней, по сравнению с тем, что вы обычно в другом месте видели... Эта скорость зависит от настроек ОП системы, в посте №7 я добавил переменную A, которая указывает во сколько раз ускорить встроенный шаг прокрутки...

Цитата:

Сообщение от drkrol
Может если за место
"transform", "translateY"
сделать GSAP, то подёргиваний не будет?

Какой смысл сюда тащить абстракцию, которая применит то же самый transform? Я проверил в Chrome, и в ПК и телефоне оно прокручивается идеально! В Firefox проверил... да, если приглядеться, то оно анимируется по пикселям, это поскольку в Firefox значения дробных пикселей округляются до целого числа. Т. е. не используется субпиксельный рендеринг, можно всё повернуть на 0,001°, чтобы использовался такой рендеринг.
<!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%;
			scroll-behavior: unset;
			position: relative;
		}

		.wrap-content {
			overflow: hidden;
			height: 100%;
			position: -webkit-sticky;
			position: sticky;
			top: 0;
		}
		
		.boxes {
			will-change: transform;
			display: inline-block;
			width: 100%;
		}
		
		.height {
			position: absolute;
			top: 0;
			width: 1px;
		}
	</style>
</head>

<body>
	<div class="wrap">
		<div class="wrap-content">
			<div class="boxes"></div>
		</div>
		<div class="height"></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.8; // время до торможения (секунды)
			var A = 5; // во сколько раз уменьшить полосу прокрутки? Лучше всего [1;5]

			var _top = 0;
			var top = 0;
			var height;
			var originalHeight, wrapHeight;
			var scrollTop = 0, _scrollTop = 0;
			var lastTime = performance.now();
			var isScrolling = false;
			
			var wrap = $(".wrap");
			var heightElement = $(".height");
			var boxes = $(".boxes");

			wrap.scroll(function(event) {
				event.preventDefault();
				_top = this.scrollTop;
				wrapHeight = wrap.height();
				if (!isScrolling) loop();
			});
			
			$(window).resize(function() {
				wrapHeight = wrap.height();
				originalHeight = boxes.height();
				height = Math.min(originalHeight - wrapHeight, (originalHeight - wrapHeight) / A) + wrapHeight;
				
				heightElement.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;
				boxes.css("transform", "translateY(" + (scrollTop + p * (A - 1) / A * (wrapHeight - originalHeight)) + "px) rotate(0.0001deg)");

				if (scrollTop !== _scrollTop) {
					requestAnimationFrame(loop);
					_scrollTop = scrollTop;
				} else
					isScrolling = false;
			}
		});
	</script>
</body></html>


Часовой пояс GMT +3, время: 05:36.