zoukankan      html  css  js  c++  java
  • js-BOM之offset家族、移动函数的封装升级(轮播图)

    Obj.style.width/obj.style.height与obj.offsetWidth/obj.offsetHeight的区别:

      <style>
            #div1{
                height: 200px;
                background-color: red;
                }
            #div2{
                width: 200px;
                height: 200px;
                background-color: green;
            }
        </style>
    </head>
    <body>
    <div style=" 200px" id="div1"></div>
    <div id="div2"></div>
    <script>
        var div1=document.getElementById("div1");
        var div2=document.getElementById("div2");
        console.log(div1.style.width); //结果:200px
        console.log(div2.style.height); //
        console.log(div1.offsetWidth);  //200
        console.log(div2.offsetHeight);  //200
    </script>

    由此得出结论:Obj.style.width/obj.style.height只能获得行内样式的宽高数据,而不能获得内嵌式宽高数据。(带单位)(可以更改宽高的值)

    obj.offsetWidth/obj.offsetHeight可以获得宽高数据(不带单位)(只能够读取不能够更改)

    Obj.style.left/obj.style.top与offsetLeft/offsetTop的区别:

    Obj.style.left/obj.style.top只能获取行内式数据

    offsetLeft/offsetTop  只能读取;Obj.style.left/obj.style.top 可读可写入

    offsetLeft/offsetTop是一个数值(不带单位)

    Obj.style.left/obj.style.top  是一个字符串(带单位)

    如果不加定位:Obj.style.left/obj.style.top的数据是无效的无意义的

    在没有父盒子的情况下

    offsetLeft/offsetTop是以body的左上角为基准的

    Obj.style.left/obj.style.top 则以margin的左上角为基准。。

     <style>
            * {
                margin: 0;
                padding: 0;
            }
            .d {
                width: 300px;
                height: 300px;
                padding: 30px;
                border: 20px solid #000;
                background-color: blue;
                margin: 50px;
                /*position: absolute;*/
            }
            #demo {
                width: 100px;
                padding: 20px;
                border: 10px solid #000;
                /*margin: 30px;*/
                background-color: red;
            }
        </style>
    </head>
    <body>
    <div class="d">
    <div id="demo" style="height: 100px"></div>
    </div>
    <script>
        var demo = document.getElementById("demo");
        console.log(demo.offsetLeft); 
    //结果是100  因为父盒子没有定位所以子盒子相对body而言,offsetWidth的值是父盒子的margin+父盒子左边border+父盒子padding
    // 定位影响到了offsetLeft,offsetLeft的值与定位的父盒子有关,如果父盒子没有定位,则默认是以浏览器或是body左边为准
        // offsetLeft 是当前盒子的外边框与定位的父盒子的内边框之间的距离 ,如果父盒子没有定位,则默认是以浏览器或是body
    
        // offset家庭是可读的,不可写
    
        // style.left
    </script>

    有父盒子的情况且父盒子设置了定位

    offsetLeft/offsetTop 的值是子盒子的内边框到父盒子内边框的距离

    <style>
            * {
                margin: 0;
                padding: 0;
            }
            .d {
                width: 300px;
                height: 300px;
                padding: 30px;
                border: 20px solid #000;
                background-color: blue;
                margin: 50px;
                position: absolute;
            }
            #demo {
                width: 100px;
                padding: 20px;
                border: 10px solid #000;
                /*margin: 30px;*/
                background-color: red;
            }
        </style>
    </head>
    <body>
    <div class="d">
    <div id="demo" style="height: 100px"></div>
    </div>
    <script>
        var demo = document.getElementById("demo");
        console.log(demo.offsetLeft);
    //结果是30 父盒子定位了所以他的值是父盒子的padding值
     // 定位影响到了offsetLeft,offsetLeft的值与定位的父盒子有关,如果父盒子没有定位,则默认是以浏览器或是body左边为准
        // offsetLeft 是当前盒子的外边框与定位的父盒子的内边框之间的距离 ,如果父盒子没有定位,则默认是以浏览器或是body
    
        // offset家庭是可读的,不可写
    
        // style.left
    </script>

    点击按钮让div向右移动

     <style>
            *{
                margin: 0;
                padding: 0;
            }
            div {
                height: 200px;
                background-color: red;
                position: absolute;/*加定位,让元素脱标,left才有意义*/
                left: 20px;
                top:20px;
            }
        </style>
    </head>
    <body>
    <button id="btn">向右移动按钮</button>
    <div id="demo" style="200px;"></div>
    <script>
        var demo = document.getElementById("demo");
        var btn = document.getElementById("btn");
      //    console.log(demo.style.left); // 只能获得行内 的,如果 是left的话,最好有定位,要不然元素设置left没有意义
    //    console.log(demo.offsetLeft);// 可以获得行内的样式,也可以获取内嵌的,但是没有单位,而且是可读的,不可写
    
        btn.onclick = function(){
            var step = 10;
    //首先先定义一个移动步长
            var leader = demo.offsetLeft;
    //获取当前demo距离body左侧的距离
            console.log(leader);
            leader = leader + step;
    //不断给leader增加步长
            demo.style.left = leader + 'px';    
    //定位的left的最终值就是累加后的leader值(注意加上单位)
    }

    只有每次点击btn按钮时,元素才能够移动,这样太麻烦了,我们可以结合定时器,让元素每隔一段时间就向右移动一段距离。

    btn.onclick=function(){
        setInterval(function(){
            var step=5;
            var leader=demo.offsetTop;
            leader=leader+step;
            demo.style.top=leader+"px";
        },50);
    }

    为了解决按钮点击之后,元素一直不停向右移动,我们需要给他设置一个条件,让他到达指定的距离之后就将定时器清除。这样与元素就不会一直向右移动了。

    btn.onclick = function(){
    //此处设置一个timerId用来存储表示定时器的名称。
       var timerId= setInterval(function(){
            var step = 10;// 每次要移动的像素
            // 先要获得原来的距离左侧的位置
            var leader = demo.offsetLeft;
            leader =    leader + step;
            // 到达200的时候停止定时器
           if(leader <=200){
    //当元素距离起始位置的值小于200时让leader继续赋值给left属性,超过或等于200px时就清除定时器。
               demo.style.left = leader + 'px';
           }else {
               clearInterval(timerId);//清除定时器
           }
        },30)
    }

    最后为了重复利用让元素移动的这个功能,我们有必要对这个代码段进行封装,以便下次直接调用,优化代码。

    function animate(obj,target){
            var timerId= setInterval(function(){
                var step = 10;// 每次要移动的像素
                // 先要获得原来的距离左侧的位置
                var leader = obj.offsetLeft;
                leader =    leader + step;
    //            console.log(123);
                if(leader <= target){
                    obj.style.left = leader + 'px';
                }else {
                    clearInterval(timerId);//清除定时器
                }
            },30)
        }

    进一步封装升级:

    function animate(obj,target){
        clearInterval(obj.timerId);//这里解决了每次执行函数时都会开启一个定时器的问题-即每次运行之前先清除定时器。
        obj.timerId= setInterval(function(){
            var step=8;
            var leader=obj.offsetLeft;  //获得当前距离浏览器左边的距离
            step=leader<target?step:-step;//三元运算符判断当前位置与目标位置的长短
            leader=leader+step;
            if(Math.abs(leader-target)>Math.abs(step)){
    // 当前位置与目标位置有相当的距离的时候,才会让当前对象的offsetLeft不断的加步长,做匀速运动
                obj.style.left=leader+"px";
            }
            else{
                clearInterval(obj.timerId);
                obj.style.left=target+"px";
            }
        },10)

    offsetParent:

    <style>
            div {
                width: 100px;
                height: 100px;
                background-color: red;
            }
            #d1 {
                /*position: absolute;*/
                position: relative;
            }
        </style>
    </head>
    <body>
        <div id="d1">
            <div id="d2">
                <div id="d3"></div>
            </div>
        </div>
        <script>
            var d1 = document.getElementById("d1");
            var d2 =document.getElementById("d2");
            var d3=document.getElementById("d3");
            console.log(d2.offsetParent); // 与父级元素的有无定位有关系,如果当前元素的父级元素有定位,则为父级元素,如果当前父级元素没有定位,则会一直往上找有定位的元素,直到body为止
            console.log(d2.parentNode);
        </script>

    练习案例:简单轮播图,左右焦点图,无缝滚动原理,最后制作一下完整的轮播图。

  • 相关阅读:
    箭头函数中的this
    剑指offer(十六) 合并两个排序的链表
    http中的referer
    剑指offer(十四,十五)链表中倒数第k个结点,反转链表
    剑指offer(十二,十三) 数值的整数次方,调整数组顺序使奇数位于偶数前面
    那些短小精悍的&奇葩的&令人感到惊讶的JavaScript代码----更新中
    对箭头函数的补充
    Promise和Async/Await用法整理
    Vue父子组件互相通信实例
    Vue实例里面的data属性为什么用函数返回
  • 原文地址:https://www.cnblogs.com/xinjianheyi/p/5766808.html
Copyright © 2011-2022 走看看