js运动-offsetWidth和offsetHeight引发的血案

来源:互联网 发布:姜夔 鹧鸪天 知乎 编辑:程序博客网 时间:2024/05/10 17:02

之前说的js运动不管是单物体运动,多物体运动,还是缓冲运动。在获取元素自身宽,高的时候用的都是offsetWidth,offsetHeight,但是这会引发一些麻烦!!因为jsoffsetWidthoffsetHeight获取的不仅仅是元素样式中定义的widthheight还包括给元素设置的borderpadding的值

看看下面的测试例子:

<style>        #div1{            width:200px;height: 100px;            background: green;            /*border: 5px solid #c00;            padding: 5px;*/        }</style>

<body><div id="div1" onclick="test();"></div><script>    function test() {        var oDiv = document.getElementById('div1');        alert("offsetWidth 获取的值是:"+oDiv.offsetWidth);        alert("offsetWidth 获取的值是:"+oDiv.offsetHeight);    }</script></body>

不加border和padding的时候,弹出的值都是200和100,加了border和padding结果就成了220和120,所以offsetWidth = width + border + padding


明白了上面的问题,接下来看看offsetWidth/Height在会带来哪些麻烦??

改一下上面的案例,当点击div的时候,让div宽度逐渐变窄

<script>    function test() {        var oDiv = document.getElementById('div1');        setInterval(function () {           oDiv.style.width = oDiv.offsetWidth-1 + 'px';        },30);    }</script>

如上图所示:当不加boder和padding的时候,点击div发现很正常div逐渐变窄



当我们给div加了边框或者padding的时候,神器的事情发生了,为了看的清楚给div了2px的黄色边框,当我们点击div的时候div的宽度并没有变窄,反而越变越宽???这是为什么那??仔细分析

当我们点击div的时候oDiv.offsetWidth获取的值是204,然后oDiv.style.width = 204-1即203加上左右2px的border就成了205,所以30毫秒后,oDiv.offsetWidth取得205,然后减1变成204,再赋给oDiv.style.width,接着在加上左右2px的border就成了206,如此循环下去,导致div的宽就越变越大了。


那如何解决这个问题那??

我们只要获取div自身的宽度width,而不要包括(border和padding的宽),这样问题就解决了,那怎么获取div自身的宽度同时又不包括border和padding的宽那??不用offsetWidth来获取。

在DOM标准的API里有这样一个方法getComputedStyle通过这个方法可以可以获取到当前对象样式规则信息getComputedStyle(obj,null).width,就能获取到对象自身宽度(不包括border和padding),但是IE不支持此方法,IE需要用currentStyle,不同于全局方法getComputedStyle,它是作为DOM元素属性存在的,如:obj.currentStyle.width,在IE中就获取到对象自身的宽度了.

在如:getComputedStyle(obj,null).paddingLeft和 obj.currentStyle.paddingLeft就能获取到对象的左内边距;
      getComputedStyle(obj,null).borderWidth和 obj.currentStyle.borderWidtht就能获取到对象上下左右边框的宽度。

关于更加详细可以获取和操作哪些属性参考:http://www.jb51.net/shouce/dhtml/objects/currentStyle.html


注意一点:如果要获取当前对象的颜色信息,currentStyle返回的是16进制的'#ffffff',而getComputedStyle返回的是rgb(255,255,255) 

<script>    function test() {        var oDiv = document.getElementById('div1');        alert("getComputedStyle获取的宽度是:" + getComputedStyle(oDiv,false).width);    }</script>

测试一下,尽管我们添加了2px的border,但是弹出的结果任然是200px


 

注意:getComputedStyle获取的结果是字符串,需要用 parseInt( )转换一下;然后将之前程序中的offsetWidth换成getComputedStyle之后,在点击div就不再变宽了,而是正常的变窄了

<script>    function test() {        var oDiv = document.getElementById('div1');        setInterval(function () {           oDiv.style.width = parseInt(getComputedStyle(oDiv,false).width)-1 + 'px';        },30);    }</script>

把之前多物体运动中通过offsetWidht获取物体的宽度,改成getComputedStyle

为了方便,且浏览器兼容,我们封装一个函数getStyle

function getStyle(obj,attr){            /*if(obj.currentStyle){                return obj.currentStyle[attr];// ie            }else{                return getComputedStyle(obj,false)[attr];            }*/            return getComputedStyle?getComputedStyle(obj,false)[attr]: obj.currentStyle[attr];        }

完整代码:

<ul>    <li></li>    <li></li>    <li></li>    <li></li></ul>

样式:

<style>        ul{list-style: none;}        ul li{            margin: 10px;            width: 200px;height: 50px;            border: 2px solid #c00;            background: lightblue;        }</style>

<script>        window.onload = function(){            var liTags = document.getElementsByTagName('li');            for(var i=0;i<liTags.length;i++){                 liTags[i].timer = null;// 给每个li都添加一个timer                 liTags[i].onmouseover = function () {                    startMove(this,400);                 }                 liTags[i].onmouseout = function () {                    startMove(this,200);                 }            }        }        function getStyle(obj,attr){            return getComputedStyle ? getComputedStyle(obj,false)[attr] : obj.currentStyle[attr];        }        function startMove(obj,iTarget) {            clearInterval(obj.timer);            obj.timer = setInterval(function () {                var objWidth = parseInt(getStyle(obj,'width'));//因为是通过[]调用属性,所以width必须加单引号               // var iSpeed = (iTarget -obj.offsetWidth)/10;               // 因为objWidth存放的就是当前对象的宽,所以直接写objWidth而不是obj.objWidth                var iSpeed = (iTarget -objWidth)/10;                    iSpeed = iSpeed>0 ?Math.ceil(iSpeed):Math.floor(iSpeed);                if(objWidth == iTarget){                    clearInterval(obj.timer);                }else{                    obj.style.width =  objWidth+iSpeed+'px';                }            },30);        }</script>


0 0
原创粉丝点击