Обновление позиции фиксированного элемента в событии прокрутки на неотвечающей странице

75
5

У меня есть большая страница, на которой написано много javascript, в котором также содержится элемент с фиксированной позицией. Плавающий элемент обновляет свою позицию на основе текущей позиции прокрутки пользователя с помощью функции, которая срабатывает при событии прокрутки.

Проблема, с которой я сталкиваюсь, заключается в том, что из-за размера и сложности страницы происходит задержка до того, как будет выполнен код в событии прокрутки, и это заставит фиксированный элемент заметно прыгать при прокрутке быстро или с помощью колеса мыши.

См. Jsfiddle: http://jsfiddle.net/jorsgj2b/1/ (Использование setTimeout имитирует задержку при выполнении функции на реальной странице.)

<div class="header"></div>
<div class="main"></div>
<div class="float"></div>

.header {
width: 100%;
height: 200px;
background-color: #787878;
}

.main {
width: 100%;
height: 1400px;
background-color: lightblue;
}

.float {
position: fixed;
width: 100px;
height: 50px;
top: 233px;
right: 25px;
background-color: red;
z-index: 2;
}

$(function() {
$(window).scroll(function() {
setTimeout(updateFloat, 50);
});
});

var updateFloat = function() {
var mainTop = $('.main').offset().top;
var scrollPos = $(window).scrollTop();
var floatOffset = 25;
var newTop = (scrollPos > mainTop)
? floatOffset + 'px'
: mainTop + floatOffset - scrollPos + 'px';

$('.float').css('top', newTop);;
}

Я немного теряю, как решить эту проблему. Я попытался обновить поле вместо верхнего положения, а также переключиться между абсолютным и фиксированным позиционированием. Возможно, есть способ использовать css-переходы, чтобы помочь, однако мне не удалось заставить их работать здесь.

спросил(а) 2021-01-28T00:39:35+03:00 3 месяца, 1 неделя назад
1
Решение
88

Вы можете добавить position: sticky к вашему css, чтобы клейкость выполнялась браузерами, которые его поддерживают (только Firefox и Safari в соответствии с caniuse.com).

Вы всегда будете ограничены точностью событий прокрутки, поэтому вы можете всегда видеть небольшую задержку, но вы можете немного улучшить ситуацию, кэшируя значения, а не просматривая их каждый раз, когда вызывается updateFloat(). Например

var mainElement = $('.main');
var windowElement = $(window);
var floatElement = $('.float');

var updateFloat = function() {
var mainTop = mainElement.offset().top;
var scrollPos = windowElement.scrollTop();
var floatOffset = 25;
var newTop = (scrollPos > mainTop)
? floatOffset + 'px'
: mainTop + floatOffset - scrollPos + 'px';

floatElement.css('top', newTop);
}

Проблема также может быть связана с браузером, пытающимся переформатировать страницу, потому что элемент.float находится в том же уровне рендеринга, что и другие div. Вы можете исправить это, добавив стиль, который сообщает браузеру о том, чтобы поместить элемент.float в свой собственный уровень рендеринга (что привело к значительному ускорению рендеринга из-за компоновки графического процессора). Наиболее распространенный трюк заключается в том, чтобы добавить transform: translateZ(0); к вашему стилю, но там также будет предложен предлагаемый стиль , который поддерживается несколькими браузерами. Поэтому вы должны обновить свой css, как это

.float {
will-change: scroll-position;
transform: translateZ(0);
position: fixed;
width: 100px;
height: 50px;
top: 233px;
right: 25px;
background-color: red;
z-index: 2;
}

Обратите внимание, что добавление слоев слоев увеличивает использование памяти, поэтому не переходите за ее пределы. Это также иногда влияет на другие функции, такие как сглаживание текста.

ответил(а) 2021-01-28T00:39:35+03:00 3 месяца, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема