# 元素位置

# - offsetParent

offsetParent:是一个只读属性,获得最近的定位的祖先元素。如果祖先元素没有定位,那么值为body。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #root{
            position: relative;
        }
        #app {
            position: absolute;
        }
    </style>
</head>
<body>
    <div id="root">
        <div id="app">
            <div id="content">
                <div style="display: none" id="child"></div>
            </div>
        </div>
    </div>
</body>
<script>
    var app = document.querySelector("#app");
    var content = document.querySelector("#content");
    var child = document.querySelector("#child");
    
    console.log("app->offsetParent",app.offsetParent);// #root
    console.log("content->offsetParent",content.offsetParent);// #app
    // 注意:当元素的display为none时,offsetParent返回的是null
    console.log("child->offsetParent",child.offsetParent);// null
</script>
</html>

# - offsetLeft/offsetTop

offsetLeft/offsetTop:是只读属性。返回当前元素相对于offsetParent元素的左/上偏移量

offsetLeft

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            padding:0;
            margin:0;
        }
        body{
            padding:100px;
            background: red;
            border:10px solid yellow;
        }
        #app{
            width: 500px;
            height: 500px;
            background: skyblue;
            border:10px solid blue;
        }
        #root{
            position: absolute;
            width:800px;
            height: 800px;
            background: yellow;
            margin:100px;
            padding:100px;
            border:10px solid green;
        }
    </style>
</head>
<body>
    <div id="root">
        <div id="app"></div>
    </div>
</body>
<script>
    // 注意:如果没有找到 offsetParent,那么相对的是页面的偏移量。
    // 如果有,相对的是offsetParent偏移量
    var app = document.querySelector("#app");
    console.log(app.offsetLeft);
    console.log(app.offsetTop);
</script>
</html>

# - getBoundingClientRect

Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置

getBoundingClientRect

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            pading:0;
            margin:0;
        }
        #app {
            margin:100px;
            width:100px;
            height: 100px;
            border:10px solid red;
            background: skyblue;
        }
    </style>
</head>
<body>
    <div id="app"></div>
</body>
<script>
    var app = document.querySelector("#app");
    var obj = app.getBoundingClientRect();
    console.log("obj.top",obj.top,obj.y);// 0 元素顶部相对于浏览器视口顶部的距离。
    console.log("obj.bottom",obj.bottom);// 100 元素底部相对于浏览器视口顶部的距离。
    console.log("obj.left",obj.left,obj.x);// 0 元素左边相对于浏览器视口左边的距离。
    console.log("obj.right",obj.right);// 100 元素右边相对于浏览器视口左边的距离。
    console.log("obj.width",obj.width);//100 元素的宽度
    console.log("obj.height",obj.height);//100 元素的高度
    // x与y同left与top值相同。浏览器可能不支持x,y,但是肯定支持 left top
</script>
</html>

# - scrollLeft/scrollTop

scrollTop/scrollLeft:可以读写移出可视区域外面的宽度和高度。 scrollLeft:读写元素左侧已滚动的距离。即位于元素左边界与元素当前可见内容的最左端的距离。 scrollTop:读写元素上侧已滚动的距离。即位于元素上边界与元素当前可见内容的最上端的距离。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        button{
            position: fixed;
            right: 10px;
            bottom:10px;
        }
    </style>
</head>
<body style="height:2000px;">
    <div></div>
    <button>返回顶部</button>
</body>
<script>
    window.onscroll = function(){
        // 读取1:当页面设置<!DOCTYPE html>
        // console.log("html->scrollTop",document.documentElement.scrollTop);
        // console.log("html->scrollLeft",document.documentElement.scrollLeft);

        // 读取2:当页面未设置<!DOCTYPE html>
        // console.log("body->scrollTop",document.body.scrollTop);
        // console.log("body->scrollLeft",document.body.scrollLeft);

        // 兼容写法:
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
        console.log(scrollTop,scrollLeft);
    }
    var btn = document.querySelector("button");
    btn.onclick = function(){
        // 1
        // document.body.scrollTop =0;
        // document.body.scrollLeft = 0;

        // 2:指定left与top,且不允许为空
        // window.scrollTo(0,0)


        // 3 - 兼容写法
        // var documentElement = document.documentElement;
        // // 判断是否支持body
        // if(document.body.scrollTop) documentElement = document.body;
        // documentElement.scrollTop =0;
        // documentElement.scrollLeft =0;


        // 4- window.scroll:是一个函数,该函数接收对象
        window.scroll({
            behavior:"smooth",// 行为设置为平滑的效果
            top:0,
            left:0
        })
    }
</script>
</html>

# - 案例-图片懒加载

  • 效果

  • 代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>图片懒加载-前端猫</title>
        <style>
            *{
                padding:0;
                margin:0;
            }
            #app {
                margin: 0 auto;
                width: 880px;
                display: flex;
                flex-wrap: wrap;
            }
            #app img {
                margin: 10px;
                width: 200px;
                height: 200px;
                border: none;
                background: #eee;
                opacity: 0;
                transition: opacity 500ms;
            }
        </style>
    </head>
    <body>
        <div id="app">
    
        </div>
    </body>
    <script>
        // 懒加载:又称为按需加载,延迟加载。
        // 1- 将图片地址放置在自定义的属性。。
        var app = document.querySelector("#app")
        for(var i=0;i<72;i++){
            app.innerHTML+=`<img data-src="../img/golf${i}.jpg" />`
        }
    
        // 2- 当图片距离浏览器顶部的距离小于视口的高度,那么就要加载图片。
        // 浏览器视口的高度
        var clientHeight = document.documentElement.clientHeight;
        // 获得#app元素下所有的图片
        var imgs = document.querySelectorAll("#app img");
        loadImg();
        function loadImg(){
            imgs.forEach(function (item){
                // console.log(item.getBoundingClientRect().top);// 距离浏览器顶部的距离。
                var topClient = item.getBoundingClientRect().top;// 距离浏览器顶部的距离;
                if(topClient<clientHeight){
                    // console.log(item.dataset.src);
                    item.src = item.dataset.src;
                    item.style.opacity = 1;
                }
            })
        }
        // 当滚动条进行滚动操作时,会触发该事件。
        window.onscroll = loadImg;// 将loadImg作为事件处理函数。
    </script>
    </html>
    

# - 案例-渲染国家与地区

  • 效果
  • 代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Title</title>
        <style>
            * {
                padding: 0;
                margin: 0;
            }
    
            #search {
                position: fixed;
                top: 20px;
                right: 20px;
            }
    
            #search button {
                width: 22px;
                height: 22px;
                margin: 5px 0;
                display: block;
            }
        </style>
    </head>
    <body>
    <div id="app">
    </div>
    <div id="search">
    
    </div>
    </body>
    <script src="data/index.js"></script>
    <script>
        // 将数据通过JS渲染至页面当中的id为app的元素中。
        // 1- 将data.js引入到页面中
        // 2- 进行渲染
        var app = document.querySelector("#app");
        var search = document.querySelector("#search");
        var appStr = "";
        var searchStr = "";
        // 遍历data
        for (var key in data) {
            var str = data[key].map(function (item) {
                // 如何得到属性名:
                var propName = Object.keys(item)[0];
                return `
                    <p>${propName}--->${item[propName]}</p>
                `
            }).join("");
    
            var index = "index" + key.replace("*", "");
    
            appStr += `
                <div id="${index}">
                    <h3>${key}</h3>
                    ${str}
                    <hr/>
                </div>
            `
    
            searchStr += `
                <button data-index="${index}">${key}</button>
            `
        }
        app.innerHTML = appStr;
        search.innerHTML = searchStr;
        var btns = document.querySelectorAll("button");
        btns.forEach(function (item) {
            item.onclick = function () {
                window.scroll({
                    behavior: "smooth",
                    top: document.querySelector("#" + this.dataset.index).offsetTop
                })
            }
        })
    </script>
    </html>