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="width: 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="width: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>
练习案例:简单轮播图,左右焦点图,无缝滚动原理,最后制作一下完整的轮播图。