JS动画-获取样式

探讨JS动画中获取样式的缘故,是因为在添加边框之后的元素缩小其宽度时,会出现不减反增的bug。如下:

<style>
    #div1{width: 200px;height: 200px;background: red;border: 1px solid black;}
</style>

<div id="div1"></div>

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

如上代码显示,我们的需求是让原本宽度为200像素的div元素以30毫秒的速度减少1个像素的宽度,那这目标效果应该是div元素宽度不断缩小。其实不仅是增添了border会出现这样的问题,在增加其他的譬如padding值都会出现offset这个属性导致的问题。

解决办法:在行间样式中设置宽度,并将当前的宽度样式的字符串解析,返回一个宽度值。这就可以解决问题使div元素宽度不断缩小。但是这是为什么?实现的原理是什么?还不清楚,猜测可能是因为行间样式的权重更大。

<style>
    #div1{height: 200px;background: red;border: 1px solid black;}
</style>

<div id="div1" style="width:200px"></div>

<script>
	startMove();
	function startMove(){
		timer=setInterval(function(){
		var oDiv=document.getElementById("div1");
		oDiv.style.width=parseInt(oDiv.style.width)-1+"px";
		},30)
	}
</script>

显然,解决办法在行间样式中设置不太方便也不太优美。我们可以来将其封装成一个获取样式的函数。点题了吧。

<style>
    #div1{height: 200px;background: red;border: 1px solid black;}
</style>

<div id="div1" style="width:200px"></div>

<script>
	startMove();
	function startMove(){
		timer=setInterval(function(){
		var oDiv=document.getElementById("div1");
		oDiv.style.width=parseInt(getStyle(oDiv,"width"))-1+"px";
		},30)
	}
	function getStyle(obj,attr){
		if(obj.currentStyle){
			return obj.currentStyle[attr];
		}else{
			return getComputedStyle(obj,false)[attr];
		}
	}
</script>
  • currentStyle :针对IE浏览器
  • getComputedStyle :针对firefox浏览器

这个getStyle函数不仅仅可以修改宽度,其他的样式修改都可以实现的。譬如,增大字体大小。

<style>
    #div1{height: 200px;background: red;border: 1px solid black;font-size: 12px;}
</style>

<div id="div1" style="width:200px"></div>

<script>
	startMove();
	function startMove(){
		timer=setInterval(function(){
		var oDiv=document.getElementById("div1");
		oDiv.style.fontSize=parseInt(getStyle(oDiv,"fontSize"))+1+"px";
		},30)
	}
	function getStyle(obj,attr){
		if(obj.currentStyle){
			return obj.currentStyle[attr];
		}else{
			return getComputedStyle(obj,false)[attr];
		}
	}
</script>

在实现多物体缓冲运动时,增添了border属性,发现鼠标移开元素恢复的宽度比原本的要大。

 此时就用到了getStyle函数,并将原本使用的offset类的属性替换成parseInt(getStyle(obj,attr))。

<style>
  ul,li{list-style: none;}
  ul li{width: 200px;height: 100px;background: red;margin-bottom: 20px;border: 2px solid black;}
  </style>

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

<script>
    var aLi=document.getElementsByTagName("li");
    for(var i=0; i<aLi.length; i++){
        aLi[i].timer=null;
        aLi[i].onmouseover=function(){
          startMove(this,400);
        }
        aLi[i].onmouseout=function(){
          startMove(this,200);
        }
      }
function getStyle(obj,attr){
    if(obj.currentStyle){
        return obj.currentStyle[attr];
    }else{
        return getComputedStyle(obj,false)[attr];
    }
}
function startMove(obj,iTarget){
    clearInterval(obj.timer);
    obj.timer=setInterval(function(){
        var icur=parseInt(getStyle(obj,"width"));
        var speed=(iTarget-icur)/8;
        speed=speed>0?Math.ceil(speed):Math.floor(speed);
        if(icur == iTarget){
            clearInterval(obj.timer);
        }else{
            obj.style.width = icur+speed+"px";
        }
    },30)
}
</script>

之前已经说过getStyle函数可以处理border、font-szie...的变化,但也有无法直接套用处理的,那就是透明度。

对于透明度无法直接套用的原因:

 因此为了可以一并处理透明度的问题,可以在这两个关键地方做一下兼容的处理。处理如下:

就此已经实现了透明度的变化,但仍然存在小bug,查看控制台发现透明度的值不是如期的0.3——1之间的变化,它存在着小数点。

<style>
ul,li{list-style: none;}
ul li{
    width: 200px;
    height: 100px;
    background: red;
    margin-bottom: 20px;
    border: 2px solid black;
    filter: alpha(opacity=30);
    opacity: 0.3;
    }
</style>
<ul>
    <li></li>
    <li></li>
    <li></li>
</ul>

<script>
window.onload=function(){
    var aLi=document.getElementsByTagName("li");
    for(var i=0; i<aLi.length; i++){
        aLi[i].timer=null;
        aLi[i].onmouseover=function(){
            startMove(this,"opacity",100);
        }
        aLi[i].onmouseout=function(){
            startMove(this,"opacity",30);
        }
    }
}
function getStyle(obj,attr){
    if(obj.currentStyle){
        return obj.currentStyle[attr];
    }else{
        return getComputedStyle(obj,false)[attr];
    }
}

function startMove(obj,attr,iTarget){
    clearInterval(obj.timer);
    obj.timer=setInterval(function(){

        var icur=0;
        if(attr == "opacity"){
            icur=parseFloat(getStyle(obj,attr))*100;
        }else{
            icur=parseInt(getStyle(obj,attr));
        }

        var speed=(iTarget-icur)/8;
        speed=speed>0?Math.ceil(speed):Math.floor(speed);
        if(icur == iTarget){
            clearInterval(obj.timer);
        }else{

            if(attr == "opacity"){
                obj.style.filter="alpha(opacity=)"+(icur+speed)+")";
                obj.style.opacity=(icur+speed)/100;
            }else{
                obj.style[attr] = icur+speed+"px";
            }
            
        }
    },30)
}
</script>

猜你喜欢

转载自blog.csdn.net/bertZuo/article/details/84291947