标签:
JS运动中的封装的部分实用函数(框架)总结
前段时间学习JS运动时做的很实用的几个函数,应该可以称之为小的框架了,现在总结一下。为什么不当时就总结呢?我认为所谓总结不是趁着大脑中还残留着对新知识印象的时候将其写下来,而是过了一段时间之后再回头去看,将其重新拾起,这个时候一般会有对这些新东西的新看法和新的体会,我把这个过程称为“知识的发酵"。对于我来说经过 “发酵”之后的带有自己的见解和体会东西才可以称之为总结。
附上封装的getStyle()函数,可以获取元素的非行间样式,由于ie获取非行间元素的方法和其他浏览器不一样,为了避免每次都判断当前浏览器类型,所以封装成一个函数:
function getStyle(obj, attr)//参数:要获取属性的元素,要获取的属性 { if(obj.currentStyle)//ie浏览器的获取方法 { return obj.currentStyle[attr]; } else//非ie用的方法 { return getComputedStyle(obj, false)[attr]; } }
----功能:实现单个特定元素的特定属性值的设置。
----思路:在由现在的值到目标值的过程中要实现带有缓冲渐变效果变化过程应该要设置一个变量来控制每一次的变化量,命名为speed,这个变量的大小应该在定时器每次调用时重新定值,而这个值由当前值和目标值的差来决定(由于当前值在没有到达目标值之前和目标值的差始终是在变化的,所以这个值也是在变化的)。在计算出speed之后将其加到当前值上然后将“新的”当前值赋给目标元素。可以在大脑中模拟一下这个过程,就很好理解了。
对于带有长度属性的元素(比如元素高度height、宽度width、距离left、right、top、bottom等)可以在用parseInt()方法来将元素的值转为数值类型,在设置的时候加上’px’转为字符串就可以了。但是有个比较特殊但是常用的属性—透明度,他是不带有单位的,所以对透明度要特殊处理:获取的透明度的当前值为默认为小数,由于函数第三个参数为整数值,所以将其转换为0~100的整数值进行处理比较方便(取出其值后*100)。在将“新的”当前值赋给目标元素的时候以透明度的方式来做就可以了。最后,若到达了目标值,就关闭定时器。其他细节在代码注释中说:
function changeTo(obj,attr,target) { clearInterval(obj.timer);//先将以前的定时器关闭,否则每调用一次这个函数就会增加一个定时器,元素的动画效果变化越来越快 var nowValue = 0 ; var speed = 0 ; obj.timer = setInterval(function(){ //处理不透明度的方法中要四舍五入,便于后面使用 nowValue = (attr == 'opacity')?Math.round(parseFloat(getStyle(obj,'opacity'))*100):parseInt(getStyle(obj,attr)); speed = (target>nowValue)?Math.ceil((target-nowValue)/10):Math.floor((target-nowValue)/10);//speed值为负时注意向下取整 nowValue+=speed; if (attr == 'opacity') {// obj.style.filter = 'alpha(opacity:'+ nowValue +')'; obj.style.opacity = nowValue/100;//非ie设置透明度方法 }else{ obj.style[attr] = nowValue + 'px';//变量做参数用方括号括起来,点号“.”调用不生效 } if (nowValue == target) {//判断是否到目标值,若到了关闭定时器 clearInterval(obj.timer); } },30); }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
第二版:
----功能:实现多个元素的特定属性值的设置。
----思路:上面的函数每次只能实现一个元素的一个属性的设置,有些时候够用了,但是在其他很多时候的需求是要求这个元素的多个属性同时发生变化的,比如元素的位置和大小同时发生变化,大小和透明度同时发生变化等等。这个时候该怎么处理呢?总体思路是在这个函数中每一次定时器调用时改变所有属性,这就需要用到循环了,但是函数参数怎么写呢?这个时候就需要用到Json了,使用Json之后参数的问题解决了,循环的问题也解决了。
但是问题又出现了--可能有的属性值会先到达目标,有些属性值后到达目标,总不能在一个属性到达目标值后就关闭定时器吧,定时器应该在所有属性值都设置完成之后再关闭。怎么解决这个问题呢?---设置一个变量就可以了:在循环开始之前设置一个布尔类型的变量isFinished,初始值设置为true,然后在循环中判断每个属性是否到达目标值,若没有到达则将isFinished设置为false,这样一来,只要有一个属性没有到达目标值,那么isFinished就是false;如果所有属性都到达了目标值,那isFinished值就不会被更改,则依然为true。最后在循环结束时,如果isFinished为true,则关闭定时器。这个方法经常被采用,怎么理解并且记住这个方法呢?可以想象有一个队列,给队列中每个人都布置不同的任务,每个任务需要的时间不同,所以队列里的人肯定不会同时完成,那么怎么判断所有人都完成了呢?那就设置一个定时器,定时器开始工作时定义一个初始值为true的布尔型变量,之后就挨个问队列中的人是否完成了任务,完成任务的人什么也不做,而没有完成任务的人,就让他大喊一声“Oh, no!!!”然后把这个变量狠狠的置为false,等到定时器这次的工作结束之前再看看这个布尔类型的变量,如果值还是true,那么就说明没人没有完成,也就是所有人都完成了,就可以解散(关闭定时器)了。
其他细节在代码注释中说:
function changeNow(obj,json) {//参数:目标元素,Json clearInterval(obj.timer);//先将以前的定时器关闭,否则每调用一次这个函数就会增加一个定时器,元素的动画效果变化越来越快 var nowValue = 0; var speed = 0; obj.timer = setInterval(function(){ for(var i in json){ var attr = i; var target = json[i]; //处理不透明度的方法中要四舍五入,便于后面使用 nowValue = (attr == 'opacity')?Math.round(parseFloat(getStyle(obj,'opacity'))*100):parseInt(getStyle(obj,attr)); //speed值为负时注意向下取整 speed = (target - nowValue) > 0 ? Math.ceil((target - nowValue)/10) : Math.floor((target - nowValue)/10); nowValue += speed;//累加现在当前值,下面赋值给元素的属性 if (nowValue != target) {//有一个元素没有到目标就将isFinished置为false isFinished = false; } if (attr == 'opacity') { obj.style.filter = 'alpha(opacity:'+ nowValue +')'; obj.style.opacity = nowValue / 100;//非ie设置透明度为小数 } else{ obj.style[attr] = nowValue + 'px';//变量做参数用方括号括起来,点号“.”调用不生效 } } if (isFinished) {//如果所有属性值都已经设置为了目标值 clearInterval(obj.timer); } },30); }
第三版:链式调用
----功能:所谓的链式函数,就是在一个函数完成之后开始另一个函数。
----思路:在函数中调用下一个函数就可以,关键在于何时调用,就上面的第二版的函数来说应该是在所有动作完成之后再调用。只需要在第二版函数中增加一个参数,如果isFinished==true,则调用这个函数。为了增加灵活性,增加一个判断—--如果这个函数存在,则调用。说的有点多,直接上关键代码把。
function changeNow(obj,json,fn) {
……//这里的代码和第二版函数的相同
if (flag) {
clearInterval(obj.timer);
if(fn) {fn();}//增加的代码,如果这个函数存在,则调用
}
}
完整代码:
function changeNow(obj,json,fn) {//参数:目标元素,Json,接下来要执行的函数 clearInterval(obj.timer);//先将以前的定时器关闭,否则每调用一次这个函数就会增加一个定时器,元素的动画效果变化越来越快 var nowValue = 0; var speed = 0; obj.timer = setInterval(function(){ var isFinished = true;//每次循环开始前设置标记,用来判断是否已经设置完成全部属性 for(var i in json){ var attr = i; var target = json[i]; //处理不透明度的方法中要四舍五入,便于后面使用 nowValue = (attr == 'opacity')?Math.round(parseFloat(getStyle(obj,'opacity'))*100):parseInt(getStyle(obj,attr)); //speed值为负时注意向下取整 speed = (target - nowValue) > 0 ? Math.ceil((target - nowValue)/10) : Math.floor((target - nowValue)/10); nowValue += speed;//累加现在当前值,下面赋值给元素的属性 if (nowValue != target) {//有一个元素没有到目标就将isFinished置为false isFinished = false; } if (attr == 'opacity') { obj.style.filter = 'alpha(opacity:'+ nowValue +')'; obj.style.opacity = nowValue / 100;//非ie设置透明度为小数 } else{ obj.style[attr] = nowValue + 'px';//变量做参数用方括号括起来,点号“.”调用不生效 } } if (isFinished) {//如果所有属性值都设置为了目标值 clearInterval(obj.timer);
<span style="white-space:pre"> </span>/*
<span style="white-space:pre"> </span>增加的代码
<span style="white-space:pre"> </span>*/ if (fn) {fn();}//fn函数是不一定存在的,只有存在时才调用 } },30); }
以上。写出这些函数是用来做东西的,后面就有用这些函数做出的效果。
标签:
原文地址:http://blog.csdn.net/rabbitter/article/details/51179583