Показать сообщение отдельно
  #7 (permalink)  
Старый 23.05.2019, 17:13
Аватар для Malleys
Профессор
Отправить личное сообщение для Malleys Посмотреть профиль Найти все сообщения от Malleys
 
Регистрация: 20.12.2009
Сообщений: 1,714

Сообщение от drkrol
Скажите пожалуйста, как мне регулировать время анимации (скорость) и расстояние одного шага?
В этом примере вы можете только регулировать время анимации в той строчке, где написано...
var a = 1 - Math.exp(-0.005 * dt);
Число 0.005 поделите на нужное кол-во секунд, или умножьте на число, во сколько раз быстрее хотите!

Сообщение от drkrol
upd. Проверил ваш вариант в Microsoft Edge. В начале анимации есть небольшое подёргивание...
Да, я посмотрел ваше видео, формула, по которой вычисляется позиция, представлена гладкой кривой, поэтому при идеально правильно рендеринге не должно быть никакого подёргивания. Это ошибка/недочёт движка в Microsoft Edge. По крайней мере следующая версия Microsoft Edge будет основана на webkit и эта проблема, скорей всего, исчезнет! На самом деле, те, кто используют обычно этот браузер сейчас ничего особенного не заметят, поскольку и другие анимации слегка подёргиваются!

Сообщение от drkrol
Если у вас будет время и если вам не сложно, то не могли бы вы чуть подробнее разъяснить свой код? Я просто хотел вникнуть. Я понял, что всё держится на performance.now(), который возвращает время. Но как время помогает с плавностью я так и не понял...
На самом деле performance.now() нужен только для того, чтобы вычислять время между двумя отрисовками анимации. Время между двумя кадрами.

Все держится на формуле var a = 1 - Math.exp(-0.005 / T * dt);, которая и вычисляет, как быстро приближаться к конечной позиции прокрутки.

Сообщение от drkrol
Скажите пожалуйста, как мне регулировать время анимации (скорость) и расстояние одного шага?
Расстояние одного шага можно регулировать так: нужно уменьшить область прокрутки в A раз, тогда до конца области прокрутки мы будем добираться в A раз быстрее. Но само содержимое будет прокручиваться с такой же скоростью, как обычно. Поэтому мы его будем в A раз дальше продвигать вдоль оси прокрутки. Вот пример... вынес время анимации и во сколько раз ускорить обычную прокрутку в отдельные переменные в начале
<!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>


Сообщение от рони
насколько правильно, сделать например, так?
Всё ОК, коме того, что если крутануть колёсико мыши и не дождавшись конца анимации ещё раз крутануть, то это приведёт к сдвигу к начальной какой-то позиции, т. е. к тому моменту, с которого анимация начиналась, и уже с того места запустится новая анимация, вызванная кручением колёсика мыши. (ну или любым другим способом прокрутить, но не дождаться конца анимации)

Последний раз редактировалось Malleys, 23.05.2019 в 17:32.
Ответить с цитированием