Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 23.08.2019, 13:53
Профессор
Отправить личное сообщение для demoniqus Посмотреть профиль Найти все сообщения от demoniqus
 
Регистрация: 28.05.2008
Сообщений: 182

Необъяснимое поведение прокрутки при использовании homekey
Добрый день! Помогите разобраться в одной проблеме. Моя голова уже треснула от напруги и мозг булькает от перегрева... Букаф будетЬ мноХА((((

Возникла необходимость сделать отображение данных по мере прокрутки области просмотра (данные есть сразу все в памяти и на сервер нет смысла обращаться). Контейнер заранее неизвестен, однозначно известно лишь, что это могут быть совершенно разные контейнеры (table, div, p). Физический размер контейнера также заранее неизвестен и должен подстраиваться под своего родителя. Из-за потенциально непредсказуемого размера данные в контейнере должны находиться только те, которые отображаются пользователю. Остальные данные из него выгружаются в случае выбытия за пределы области просмотра. Размер DOM-элементов, выводящих данные, не должен иметь никаких ограничений, т.е. он может быть меньше (существенно или несущественно), равен или больше (существенно или несущественно) размера области просмотра. При этом не должно быть ситуации, что какая-то часть элемента недоступна пользователю, поскольку скроллинг вызывает загрузку другого элемента вместо прокрутки данного.

В принципе, в сети есть много плагинов с отображением только элементов, относящихся к области просмотра в данный момент. Меня они не устроили по ряду весомых причин. Не важно, почему. Вопрос не об этом.

Я реализовал иной алгоритм: в начале я загружаю столько элементов, чтобы все кроме последнего хотя бы частично были в области просмотра, а последний - за областью просмотра. Такой подход позволяет не думать о размерах отображаемых элементов - может поместится только один в области просмотра, да и то не полностью, а может 33. Далее по мере прокрутки я подгружаю с той стороны, куда прокручиваю, новые элементы так, чтобы один последний по возможности выходил за область просмотра. С обратной стороны области просмотра элементы, полностью вышедшие за пределы области просмотра я удаляю из DOM-дерева. При этом элементы с верхней стороны области просмотра я компенсирую padding'ом. Получается всё так, как мне нужно. Мышью скроллится хорошо - хоть маленькие, хоть большие элементы. Клавишами PageUp, PageDown, End - тоже всё здорово. А вот с клавишей Home возникли проблемы, которые прошу помочь разобрать и задать вектор для решения.

Что есть - я загрузил в контейнер с высотой 630px сотню элементов (пока высота всех одинакова 392px). Далее я через End пролистываю до конца. После этого я начинаю клавишей Home двигаться в начало. И в непредсказуемый момент происходит резкий возврат сразу к первому элементу. Я начал разбираться и обнаружил, что определенные изменения приводят к повторному автоматическому событию скроллинга:
1) При возникновении события скроллинга контейнер сразу получает новый scrollTop, а потом уже выполняется callback. Я загружаю новый элемент, выгружаю с другой стороны ненужный элемент. Таким образом получается, что дочерний элемент в области просмотра, на котором "зафиксировался" скроллинг, смещается, что приводит по факту к изменению scrollTop для области просмотра. Эту проблему я вроде как решил, фиксируя scrollTop до момента изменения DOM-дерева и восстанавливая его после каждого append
2) DOM-элементы имеют scrollHeight. По мере изменения DOM-дерева этот параметр меняется, также вызывая за собой событие скроллинга. При этом scrollTop может не меняться. Это я и использовал, чтобы отсечь данную проблему.

Но все равно по мере прокрутки через Home происходит резкое и непредсказуемое (т.е. каждый раз в различных точках - то сразу, то по прошествии нескольких Home) уменьшение scrollTop области просмотра в несколько этапов до нуля

Я пытался разобраться, какие именно еще события могут приводить к скроллингу, но пока понять не удалось. Я пытался найти проблему в своей "математике" - может где-то что-то не учел. Я логировал все параметры области просмотра до и после функции-обработчика, но параметры были идентичными. Единственное, если теоретически какие-то манипуляции могли привести к тому, что эти изменения возникают уже после функции-обработчика где-то в глубинах ядра JS... Я уже рисовал "покадрово" происходящее. Я пробовал при прокрутке по Home не убирать нижние элементы, чтобы не менять scrollHeight области просмотра. Это не помогло. Я не могу объяснить, как именно клавиша Home решает, на сколько нужно прокрутить область просмотра - некоторые изменения scrollTop превышают 7000px при том, что элементов при указанных размерах не более 5, т.е. не более 2000px. Я не могу понять, почему каждый раз Home ведет себя по-разному, т.е. при одинаковых начальных условиях (одинаковый scrollTop, два элемента по 392px, 630px область просмотра,) я получаю неодинаковое изменение scrollTop.

Не понимая, где в коде может быть ошибка, я решил посмотреть, как выглядит контейнер после такой резкой прокрутки - быть может натолкнет на какую-нибудь мысль. Я переписал код так, что при резком изменении scrollTop по сравнению с предыдущим состоянием ничего типа не выполнять и выйти из функции-обработчика. Каково было мое удивление, когда этот "хак" сработал и не стал менять DOM-дерево, но при этом событие скроллинга продолжило выстреливать, пока прокрутка не дошла до нуля! Т.е. DOM-дерево не менялось, не менялись свойства его элементов, а скроллинг почему-то генерировался!

Ситуация такая в хроме. Мозилла такую-же проблему показала. Что стоит также отметить - как я сказал, я занимал место выгруженных из начала очереди элементов padding'ом, т.е. контейнер реально растягивался. Однако ни разу Home не приводил при первом же нажатии к обнулению scrollTop области просмотра, хотя нередко и первое нажатие Home приводило к последовательному уменьшению этого показателя до нуля...

Фуф... вот такая ситуация. Люди, опытные в гадании без кофейной гущи, подкиньте, пожалуйста, догадок, объясняющих такое поведение скроллинга при использовании Home
Ответить с цитированием
  #2 (permalink)  
Старый 24.08.2019, 05:08
Аватар для j0hnik
Профессор
Отправить личное сообщение для j0hnik Посмотреть профиль Найти все сообщения от j0hnik
 
Регистрация: 01.12.2016
Сообщений: 3,650

Пример бы с проблемой!
Если данные загружаются сразу то какова цель таких манипуляций?
Сходу пришло в голову перехватить
end -> window.scroll({ top: 1e10, behavior: 'smooth' });
home -> window.scroll({ top: 0, behavior: 'smooth' });
если проблема только в этих кнопках
Ответить с цитированием
  #3 (permalink)  
Старый 26.08.2019, 10:05
Профессор
Отправить личное сообщение для demoniqus Посмотреть профиль Найти все сообщения от demoniqus
 
Регистрация: 28.05.2008
Сообщений: 182

Цель манипуляций - не отрисовывать сразу огромный кусок DOM дерева, который может не понадобиться пользователю, а тем не менее требует заметного времени на выполнение.
С кнопкой End как раз проблем я не заметил.

Если я Вас понял, Вы предлагаете повесить на Home дополнительный обработчик с прокруткой сразу в ноль? Я уже думал об этом, но хочется всё же понять корень проблемы, а не лечить ее симптом...

Код я выложить могу, но будет ли кто-нибудь разбираться сейчас в нескольких сотнях строк?
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Помогите убрать полосу прокрутки при анимации контента Lifemaster Элементы интерфейса 6 31.07.2015 02:59
Анимация с скрытием слайдера при прокрутки вверх+привязка к кукам mylifegod Events/DOM/Window 9 17.04.2015 10:55
Не срабатывает hover при использовании в div IE 6.0 AlexMak (X)HTML/CSS 5 14.05.2009 18:26
Возникает глюк при использовании двух плагинов dummer jQuery 5 23.12.2008 20:26
Проблема в document.write при использовании setInterval() GOll Общие вопросы Javascript 21 06.10.2008 17:38