在擁有捲軸元素內滾動時,判斷其子元素是否出現(達到可視區域)公式

水冗水孚發表於2023-02-24

問題描述

網上的帖子大多數是:判斷一個元素是否在可視區域中

而帖子中舉的例子,也是以瀏覽器最外層body/html的捲軸為例子,進行講解,基本上都是如下的效果圖:

注意這裡的捲軸是最外層的

  • 實際上,我們頁面的捲軸,有時,並不是以最外層的body或者html進行滾動的
  • 可能是頁面中間的某一個dom元素可以滾動
  • 我們需要判斷這個dom滾動元素內的某一個小dom目標元素何時出現,何時達到可視區域
  • 這裡的可視區域是能看到,和最外層的那個捲軸沒有關係的
  • 如下效果圖

如需求:當紅色盒子在內層捲軸滾動中出現時,就更改對應dom元素背景色為粉紅色

注意這裡有兩個捲軸,我們的需求是裡面的捲軸滾動時,去做對應控制

公式提出

  • 其實也很簡單,首先我們分析一些元素層級結構。
  • 最外層的肯定是bodyhtml,這個不用管它
  • body標籤內部,有一個<div class="scrollBox"></div>,這個dom元素擁有捲軸
  • 而在.scrollBoxdom元素內,還有一個目標元素<div class="target"></div>,看看這個目標元素.target何時出現,何時達到可視區域

公式:

滾動距離出現 = .target距頂部高度 - .scrollBox距頂部高度 - .scrollBox自身高度

滾動距離出現 = .target距頂部高度 - .scrollBox距頂部高度 - .scrollBox自身高度

滾動距離出現 = .target距頂部高度 - .scrollBox距頂部高度 - .scrollBox自身高度

或:

邊界值 = 目標元素距頂部高度 - 滾動盒子容器距頂部高度 - 滾動盒子容器自身高度

邊界值 = 目標元素距頂部高度 - 滾動盒子容器距頂部高度 - 滾動盒子容器自身高度

邊界值 = 目標元素距頂部高度 - 滾動盒子容器距頂部高度 - 滾動盒子容器自身高度

即,當滾動的距離超過這個邊界值時,目標元素就會出現

這裡的邊界值,一定是初始邊界值,就是要提前算好,最好存一份,因為滾動的話,會更改相應距離位置的

複製貼上程式碼看效果更好理解:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .scrollBox {
            width: 100%;
            height: 300px;
            background-color: #ccc;
            /* 擁有捲軸 */
            overflow-y: auto;
        }

        .target {
            width: 60px;
            height: 60px;
            background-color: red;
        }
    </style>
</head>

<body>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <div class="scrollBox">
        <h1>孫悟空</h1>
        <h1>孫悟空</h1>
        <h1>孫悟空</h1>
        <h1>孫悟空</h1>
        <h1>孫悟空</h1>
        <h1>孫悟空</h1>
        <h1>孫悟空</h1>
        <h1>孫悟空</h1>
        <h1>孫悟空</h1>
        <h1>孫悟空</h1>
        <div class="target"></div>
    </div>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <script>
        let scrollBoxDom = document.querySelector('.scrollBox')
        let targetDom = document.querySelector('.target')
        // 注意!這裡的邊界值,是原始的位置的值,因為滾動的話,會更改元素的getBoundingClientRect的相關值
        let boundaryValue = targetDom.getBoundingClientRect().top - scrollBoxDom.getBoundingClientRect().top - scrollBoxDom.offsetHeight
        // 邊界值 = 目標元素距離頂部高度 - 滾動盒子容器距離頂部高度 - 滾動盒子容器自身的高度
        function callBack() {
            if (scrollBoxDom.scrollTop > boundaryValue) {
                console.log('在可視區域');
                scrollBoxDom.style.backgroundColor = 'pink'
            } else {
                console.log('不在可視區域');
                scrollBoxDom.style.backgroundColor = '#ccc'
            }
        }
        scrollBoxDom.addEventListener('scroll', callBack)
    </script>
</body>

</html>

附-以瀏覽器最外層body/html的捲軸為例子程式碼

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            background-color: #ccc;
        }

        .target {
            width: 60px;
            height: 60px;
            background-color: red;
        }
    </style>
</head>

<body>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <h1>孫悟空</h1>
    <div class="target"></div>
    <script>
        window.onload = () => {
            let targetDom = document.querySelector('.target') // 目標元素dom
            function callBack() {
                const top = targetDom.getBoundingClientRect().top; // 目標元素dom距離頂部的高度
                if (top <= window.innerHeight) { // 當top小於等於文件顯示區域的高時,就進入可視區域了
                    console.log('在可視區域');
                    document.body.style.background = 'pink'
                } else {
                    console.log('不在可視區域'); // 當top大於文件顯示區域的高時,就離開可視區域了
                    document.body.style.background = '#ccc'
                }
            }
            window.addEventListener('scroll', callBack);
        }
    </script>
</body>

</html>

相關文章