Как определить, входит ли элемент в область просмотра видимой области?

внешний интерфейс программист GitHub JavaScript
Как определить, входит ли элемент в область просмотра видимой области?

Личная подпись: Живи, как летние цветы, умирай, как зимний снег, жизнь такая, о чем сожалеть или жаловаться.

Предисловие: Часто необходимо вычислить размер элемента или положение страницы.Еще более обыденным является появление таких ключевых слов, как offsetWidth, clientWidth, scrollWidth и scrollTop.Каждый раз, когда вы сталкиваетесь с этим, вам нужно заранее поэкспериментировать . Повышение эффективности для следующего развития. Вот однократное резюме,Используется для определения того, находится ли элемент в видимой области и простой ленивой загрузки с помощью нативного js.. В конце статьи есть простая демонстрация реализации ленивой загрузки, вы можете посмотреть, если вам это нужно.

содержание

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

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

1. Смещение

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

Компенсировать концепция формула
offsetHeight Объем пространства, занимаемый элементом по вертикали, в пикселях. Включает высоту элемента, высоту (видимой) горизонтальной полосы прокрутки, высоту верхней границы и высоту нижней границы. offsetHeght = content + padding + border + scrollX
offsetWidth Объем пространства, занимаемый элементом по горизонтали, в пикселях. Укажите ширину элемента, ширину (видимой) вертикальной полосы прокрутки, ширину левой границы и ширину правой границы. offsetWidth = content + padding + border + scrollY
offsetLeft Расстояние в пикселях от внешней левой границы элемента до внутренней левой границы содержащего его элемента.
offsetTop Расстояние в пикселях от верхней внешней границы элемента до верхней внутренней границы содержащего его элемента.

Среди них свойства offsetLeft и offsetTop связаны с содержащим элементом, а ссылка на содержащий элемент хранится в свойстве offsetParent.Свойство offsetParent не обязательно равно значению parentNode.

Как показано ниже

偏移量图示

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

Это тожеВ предыдущей статье проект выделения текста (Нажмите здесь, чтобы прыгнуть)После добавления прокладки, текстовая проверка должна повторно приобретать причину.

文字跑马灯

резюме

offset: свойство только для чтения; включает полосы прокрутки и границы, но не поля.

2. Размер клиентской области

Размер клиентской области доступен только для чтения и пересчитывается при каждом доступе.

размер клиентской области концепция формула
clientWidth Свойство clientWidth представляет собой ширину области содержимого элемента плюс ширину левого и правого отступов; clientWidth = content + padding
clientHeight Высота области содержимого элемента плюс высота отступов сверху и снизу. clientHeight = content + padding

Чаще всего эти свойства используются при определении размера области просмотра браузера (в версиях до IE7). Как показано в следующем примере:

function getViewport(){
    // 检查 document.compatMode 属性,以确定浏览器是否运行在混杂模式。
    // Safari3.1 之前的版本不支持这个属性,因此就会自动执行 else 语句
    if (document.compatMode == "BackCompat"){
        return {
            width: document.body.clientWidth,
            height: document.body.clientHeight
        };
    } else {
        return {
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight
        }; 
    }
}

резюме

Размер клиентской области: свойство только для чтения; исключая полосы прокрутки и границы, исключая поля.

3. Размер прокрутки

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

scrollWidth и scrollHeight в основном используются для определения фактического размера содержимого элемента.

Свойства scrollLeft и scrollTop могут определять текущее состояние прокрутки элемента и устанавливать позицию прокрутки элемента. Когда элемент не прокручивался, значение обоих свойств равно 0. Если элемент прокручивается вертикально, значение scrollTop будет больше 0 и представляет собой высоту в пикселях невидимого содержимого над элементом. Если элемент прокручивается горизонтально, значение scrollLeft будет больше 0 и представляет собой ширину в пикселях невидимого содержимого слева от элемента. Оба эти свойства можно установить, поэтому установка для scrollLeft и scrollTop элемента значения 0 сбрасывает положение прокрутки элемента. Например:Предыдущая статьяИспользование scrollLeft в проекте выделения текста (Нажмите здесь, чтобы прыгнуть)

резюме

Свойство только для чтения, за исключением полос прокрутки и границ.

4. Определите размер элемента

getBoundingClientRect

Написание совместимости getBoundingClientRect:

Для браузеров, не поддерживающих getBoundingClientRect(), ту же информацию можно получить другими способами. В общем, разница между правым и левым равна значению offsetWidth, а разница между нижним и верхним — offsetHeight. Комбинируя вышесказанное, вы можете создать следующую кросс-браузерную функцию:


function getElementLeft(element){
    var actualLeft = element.offsetLeft;
    var current = element.offsetParent;
    while (current !== null){
        actualLeft += current.offsetLeft;
        current = current.offsetParent;
    }
    return actualLeft;
}

function getElementTop(element){
    var actualTop = element.offsetTop;
    var current = element.offsetParent;
    while (current !== null){
        actualTop += current. offsetTop;
        current = current.offsetParent;
    }
    return actualTop;
}

function getBoundingClientRect(element) {
    var scrollTop = document.documentElement.scrollTop;
    var scrollLeft = document.documentElement.scrollLeft;
    if (element.getBoundingClientRect) {
        if (typeof arguments.callee.offset != "number") {
            var temp = document.createElement("div");
            temp.style.cssText = "position:absolute;left:0;top:0;"; document.body.appendChild(temp);
            arguments.callee.offset = -temp.getBoundingClientRect().top - scrollTop; document.body.removeChild(temp);
            temp = null;
        }
        var rect = element.getBoundingClientRect();
        var offset = arguments.callee.offset;
        return {
            left: rect.left + offset,
            right: rect.right + offset,
            top: rect.top + offset,
            bottom: rect.bottom + offset
        };
    } else {
        var actualLeft = getElementLeft(element);
        var actualTop = getElementTop(element);
        return {
            left: actualLeft - scrollLeft,
            right: actualLeft + element.offsetWidth - scrollLeft,
            top: actualTop - scrollTop,
            bottom: actualTop + element.offsetHeight - scrollTop
        }
    }
}

5. Определяем, находится ли элемент в видимой области

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

5.1 Первый способ

Формула: el.offsetTop - document.documentElement.scrollTop

function isInViewPortOfOne (el) {
    // viewPortHeight 兼容所有浏览器写法
    const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight 
    const offsetTop = el.offsetTop
    const scrollTop = document.documentElement.scrollTop
    const top = offsetTop - scrollTop
    console.log('top', top)
     // 这里有个+100是为了提前加载+ 100
    return top <= viewPortHeight + 100
}

5.2 Второй способ

Формула: el.getBoundingClientReact().top

На самом деле el.offsetTop - document.documentElement.scrollTop = el.getBoundingClientRect().top, воспользовавшись этим, мы можем заменить метод 1 следующим кодом

function isInViewPortOfTwo (el) {
    const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight 
    const top = el.getBoundingClientRect() && el.getBoundingClientRect().top
    console.log('top', top)
    return top  <= viewPortHeight + 100
}

5.3 Третий способ

Формула: коэффициент пересечения > 0 && коэффициент пересечения

// 定义一个交叉观察器
const io = new IntersectionObserver(ioes => {
    ioes.forEach(ioe => {
        const el = ioe.target
        const intersectionRatio = ioe.intersectionRatio
        if (intersectionRatio > 0 && intersectionRatio <= 1) {
            loadImg(el)
            io.unobserve(el)
        }
         el.onload = el.onerror = () => io.unobserve(el)
    })
})
// 执行交叉观察器
function isInViewPortOfThree (el) {
    io.observe(el)
}

5.4 Сравнение совместимости

Что касается совместимости, мы знаем, что более примитивный метод имеет наилучшую совместимость, поэтому могут ли второй метод и третий метод заменить третий метод? Давайте взглянем.

getBoundingClientReact

IntersectionObserver

Судя по данным caniuse, адаптация getBoundingClientReact выглядит очень оптимистично.

Следовательно, если совместимость и адаптация должны быть выполнены как на мобильном терминале, так и на настольном терминале, второй способ может полностью заменить первый способ адаптации. Если это только для настольной адаптации (например, рабочего фона), мы можем попробовать новый метод IntersectionObserver, ведь в IntersectionObserver есть более богатые функции, которые ждут нас, чтобы испытать.

5.5 Примеры

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

Отложенная загрузка Предварительный просмотр DEMO(Поместите свое локальное изображение, чтобы добиться ленивой загрузки, заменив различные методы)

------------------------- Великолепная разделительная линия --------------------- - -------

обо мне

Сертифицированный программист по финансовому планированию

微信公众号二维码

Спасибо за справочную информацию, представленную ниже

Связь:кликните сюда

Содержимое: document.scrollingElement заменяет document.documentElement.scrollTop и document.body.scrollTop.

document.scrollingElement объединяет реки и озера:

На рабочем столе document.scrollingElement — это document.documentElement;

На мобильных устройствах document.scrollingElement — это document.body.

Преимущество: избегайте использования совместимости document.documentElement.scrollTop = 0 (настольный компьютер), document.body.scrollTop = 0 (мобильный);