Element.scrollIntoView ваш друг здесь. Вы можете выяснить, какой элемент находится в верхней части окна в ваших тормозных точках (с использованием resize event), и вызвать element.scrollIntoView()
на этом элементе.
Вы можете определить, какой элемент находится ближе к вершине с помощью функции, как:
function closestToTop() {
const top = window.scrollY;
return [].reduce.call(
document.querySelectorAll('h1, h2, h3'),
(closest, el) => Math.abs(offsetTop(el) - top) <= Math.abs(offsetTop(closest) - top)
? el
: closest,
document.body
);
}
, где вы получите offsetTop
с:
function offsetTop(el, offset = 0) {
if (el === document.body) {
return 0;
}
return offset + el.offsetTop + offsetTop(el.offsetParent);
}
Ограничимся себя к <h1>
, <h2>
и <h3>
элементов, чтобы сделать вычисление немного легче.
Что вы хотите сделать, это выяснить, какой элемент находится наверху в начале изменения размера и прокручивать его, только если он не отображается в конце прокрутки. Таким образом, нам нужно применить какой-то из throttle:
{
let throttling = false;
function throttledResize() {
if (throttling) {
return;
}
throttling = true;
window.dispatchEvent(new CustomEvent('resizeStart'));
requestAnimationFrame(() => {
window.dispatchEvent(new CustomEvent('resizeEnd'));
throttling = false;
});
};
window.addEventListener('resize', throttledResize);
}
Теперь у нас есть 'resizeStart'
и 'resizeEnd'
события. Обратите внимание: мы помещаем это в область блока ECMAScript2015, чтобы мы не загрязняли глобальную область с помощью переменных throttling
и throttleResize
. Теперь мы можем закрыть любой элемент вверху при запуске изменения размера (опять же с использованием области блока).
{
let wasAtTop = null;
window.addEventListener('resizeEnd',() => {
if (!wasAtTop) {
return;
}
wasAtTop.scrollIntoView();
wasAtTop = null;
});
window.addEventListener('resizeStart',() => {
wasAtTop = closestToTop();
});
}
Примечание: Это очень не оптимизировано. Существуют различные улучшения, которые мы можем добавить к этому. Подобно дросселю в течение более длительного времени, чем до следующего кадра анимации, и никогда не прокручивайте, если элемент не находится за пределами вида window.scrollY < offsetTop(el) && offsetTop(el) < window.scrollY + window.height
.
Спасибо. Это то, что мне интересно. Как я могу определить, какой элемент находится в верхней части окна? – IanEdington
Я отредактировал ответ с дальнейшим попыткой добиться этого. –