Скользящее проникновение (тело замка) окончательное исследование

JavaScript

Сцены

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

Как показано на рисунке, содержимое под плавающим слоем не так неизменно, как ожидалось.

решать

Сначала зашел на гитхаб поискать, и нашел, что есть пакеты с открытым исходным кодом, решающие эту проблему, и просто и грубо выбрал их напрямую.starсамый высокий (body-scroll-lock) работать! После использования обнаружил некоторые проблемы:

  • Полное зависание на Android
  • Иногда сторона ios не может быть заблокирована

Проверьте исходный код и обнаружите, что пакет находится вiOSконечное применение禁止touchmoveобрабатывается отдельно, но на другом конце просто даетbodyдобавлятьoverflow: hiddenПростое обращение. Поэтому я решил написать многотерминальный общий пакет для решения подобных проблем.

Исследование 1: переполнение: скрыто

Когда вы видите прокрутку внизу, вы должны сразу думать обо всемviewportПрокрутка, то если тело установленоoverflow: hidden, содержимое тела в это время только на один экран, и оно точно не будет прокручиваться;

body { overflow: hidden; }

Это решение отлично решает нашу проблему на стороне ПК, но все не так просто;

Попробуйте еще раз на мобильном устройстве:

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

Исследование 2: положение тела

Я думал установить тело вышеoverflow: hiddenЭто не решает нашу проблему на мобильной стороне.Это потому, что высота тела не задана?

  • Установите высоту html и тела на100%;
  • Установить абсолютное позиционирование для тела (фиксированное);

Одновременное использование этих двух операций, кажется, полностью удовлетворяет наши потребности;

Однако, как показано на рисунке, страница каждый раз будет перемещаться в верхнюю позицию, что снова выглядит несовершенным; Поскольку используется позиционирование, дайтеtop值Если нет, то мы окажемся там, где захотим (насколько я умна).

советы: настройки телаrelativeПозиционирование поднимет саму страницу и оставит пустым внизу

Многие эксперименты показали, что эта схемаandroidEnd-to-end отлично достигает желаемых результатов, но вiosТерминал не идеален, каждый раз будет возникать проблема с миганием, хорошие вещи будут приходить и уходить, а затем исследовать решение на терминале ios.

Исследование 3: Запретить touchmove

Если страница заблокированаtouchmoveВозможно ли это? Нечего сказать, просто сделайте это! Отключить элементы страницы при всплывающем окнеtouchmove

document.addEventListener('touchmove', function (event) {
    event.preventDefault()
})

Тест показал, что ожидаемого эффекта не добился, считаю такой результат неприемлемым, запрещён.documentизtouchmoveНе можете остановить прокрутку?

После дальнейших изысканий выясняется, что причина именно в этом свойстве

  • Передано третьим параметром пассивного addEventListener

Оказалось, что это была некоторая оптимизация, сделанная браузером.chrome passive-event-listeners Passive Event Listenersэто новый браузер, предложенный Chromeхарактеристика: веб-разработчик через новое свойствоpassiveчтобы сообщить браузеру, будет ли вызван прослушиватель событий, зарегистрированный на текущей страницеpreventDefaultчтобы предотвратить поведение события по умолчанию, чтобы браузер мог принимать более эффективные решения на основе этой информации для оптимизации производительности страницы. когда атрибутpassiveКогда значение равно true, это означает, что слушатель не будет вызываться внутри.preventDefaultЧтобы предотвратить поведение смахивания по умолчанию, Chrome называет этот тип слушателя пассивным слушателем.

Просто скажите, если вы знаете проблему, дайтеaddEventListenerПередайте третий параметр

document.addEventListener('touchmove', function (event) {
    event.preventDefault()
}, { passive: false })

Готово! Внезапно подумалось, если еще нужно прокрутить в плавающем слое, то это будет не ГГ! Итак, можно ли выборочно запретить прокрутку (запретить прокрутку после того, как элемент в плавающем слое прокрутится вверх или вниз). Отдельно обрабатывать элементы, которые необходимо прокручивать в плавающем слое;

targetElement.ontouchmove = function (event) {
    const clientY = event.targetTouches[0].clientY - initialClientY

    if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {
        return preventDefault(event)
    }

    if (targetElement && (targetElement.scrollHeight - 1 - targetElement.scrollTop <= targetElement.clientHeight) && clientY < 0) {
        return preventDefault(event)
    }

    event.stopPropagation()
    return true
}

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

tua-body-scroll-lock

Окончательное решение здесь!

tua-body-scroll-lockэтоios,androidиPCКаждый конец обрабатывается индивидуально, что гарантирует идеальный результат на каждом конце!

demo

Установить

$ npm i -S tua-body-scroll-lock
# OR
$ yarn add tua-body-scroll-lock

использовать

мобильный
import { lock, unlock } from 'tua-body-scroll-lock'

// 禁止滑动后还需要内部可以滚动的元素(针对移动端ios处理)
const targetElement = document.querySelector("#someElementId");

lock(targetElement)
unlock(targetElement)
Сторона ПК

Советы: Стороне ПК не нужен targetElement, ни targetElement, ни приглашения консоли не могут быть переданыnull

import { lock, unlock } from 'tua-body-scroll-lock'

lock()
unlock()