文章标签 ‘位置’

没有评论即拷即用动画函数:透明度渐变、位置移动、尺寸变化

2010年3月31日

首先感谢一下 51js的 abeet 同学 给我们提取出这么简洁的函数
和大家分享一下吧 查看Demo
这三个函数适用于以下情况
1、在做前端页面时,只需要简单的动画效果,不想引入整个动画类,使用本函数。
2、在写js类时,需要用到简单的动画,为了降低藕合性,使用本函数。

使用方法如下:

var fade = function(element, transparency, speed, callback){……}
透明度渐变:transparency:透明度 0(全透)-100(不透);speed:速度1-100,默认为1
例<input onclick="fade('testDiv', 40)" type="button" value="透明度变化" />

var move = function(element, position, speed, callback){……}
//移动到指定位置,position:移动到指定left及top 格式{left:120, top:340}或{left:120}或{top:340};speed:速度 1-100,默认为10
例<input onclick="move('testDiv', {top:400})" type="button" value="垂直移动" />

var resize = function(element, size, speed, callback){……}
//长宽渐变:size:要改变到的尺寸 格式 {width:400, height:250}或{width:400}或{height:250};speed:速度 1-100,默认为10
例<input onclick="resize('testDiv', {height:300})" type="button" value="改变高度" />

核心代码分析
1、获取一个元素的透明度

如果是IE浏览器,则攻取最终样式的滤镜filter的值,再通过正则表达式获取到透明度滤镜alpha的值,如果不存在透明度滤镜值,则透明度为100。
如果是非IE浏览器,那么可以获取最终样式的opacity属性,

function getOpacity(elem){
var alpha;
if(navigator.userAgent.toLowerCase().indexOf('msie') != -1){
alpha=elem.currentStyle.filter.indexOf("opacity=") &gt;= 0?(parseFloat( elem.currentStyle.filter.match(/opacity=([^)]*)/)[1] )) + '':
'100';
}else{
alpha=100*elem.ownerDocument.defaultView.getComputedStyle(elem,null)['opacity'];
}
return alpha;
};

2、设置透明度
这个就简单了,不用管浏览器,通通的设置opacity及filter,
element.style.opacity = start / 100;
element.style.filter = ‘alpha(opacity=’ + start + ‘)’;
实际上这儿我偷了个懒,真正无懈可击的写法,应该是判断一下是否IE浏览器,因为在一些情况下可能使用多个滤镜,这时应该用正则替换alpha滤镜的值,而不是直接设置style.filter = ‘alpha(opacity=’ + start + ‘)’;

3、element.offsetWidth、element.offsetHeight与element.style.width、element.style.height的关系
只有在IE的border-content式盒模型情况下,这两个值才是相等的,即elementoffsetWidth==element.style.width+element.style.paddingLeft+element.style.paddingRight+element.style.borderLeftWidth+element.style.borderRightWidth
而我认为border-content式盒模型是符合修改元素尺寸时的心理预期的,对非border-content式盒模型情况下要作一个尺寸的修正。
在其它情况下应该对该值加以修正

if(!(navigator.userAgent.toLowerCase().indexOf('msie') != -1&&document.compatMode == 'BackCompat')){
//除了ie下border-content式盒模型情况外,需要对size加以修正
var CStyle=document.defaultView?document.defaultView.getComputedStyle(element,null):element.currentStyle;
if(typeof(size.width)=='number'){
size.width=size.width-CStyle.paddingLeft.replace(/D/g,'')-CStyle.paddingRight.replace(/D/g,'');
}
if(typeof(size.height)=='number'){
size.height=size.height-CStyle.paddingTop.replace(/D/g,'')-CStyle.paddingBottom.replace(/D/g,'');
}
}

有人认为以上的修正中默认了padding值的单位是px并且为整数,是不对的,
实际上经由我在ie及firefox下的测试,引用最终样式的padding值,必然是整数,并以px为单位。

4、关于把三个函数合并成一个通用动画函数
以上三个函数的主要逻辑都是一样的:
通过setInterval每隔一定时间修改元素的style属性,以达到动画效果。
所以,把三个函数合并成一个函数是可以的
只是需要在修改特定的属性时出于兼容性,必须作些处理,
因为不同的属性其值类型及单位不一样,不同浏览器下也有区别
如透明度 在非ie下为小数,在ie下是一个特别的滤镜设置
如颜色 一般是用16进制,并有#号前缀
预计这个通用的动画函数的参数会有点多,接口类下
function animator(element, interval, start, end, style, speed, tmp, callback){……}
说明
function animator(元素或元素ID, 计时器句柄,起始值,目标值,需修改的属性, 步进值(增量),值转换过滤方法(用于修改非普通递增递减形的数据,比如16进制颜色递增、前缀符号后缀单位修正), 回调函数)
function animator(‘testdiv’,'bgcolor’,'#336699′,’#aabbcc’,'backgroundColor’,2,changeColor,callback)
颜色修改方法示例(仅供参考,未测试)

changeColor=function(start,end,speed){
var _10to16 = function(color){
function tmp(index){
var tmp = color[index].toString(16);
return tmp.length == 1 ? "0" + tmp : tmp;
};
return "#" + tmp(0) + tmp(1) + tmp(2);
};
var x16to10 = function(color){
if(!/^#[0-9A-Fa-f]{3,6}$/i.test(color))retun color;
function tmp(index){
return color.charAt(index);
};
color = color.substring(1);
if(color.length == 3)
color = tmp(0) + tmp(0) + tmp(1) + tmp(1) + tmp(2) + tmp(2);
return [parseInt(tmp(0) + tmp(1), 16), parseInt(tmp(2) + tmp(3), 16), parseInt(tmp(4) + tmp(5), 16)];
};
var color = x16to10(start),
var end = x16to10(end),
var index = 3;
while(index--)
color[index] = color[index] < end[index] ? min(color[index] + speed, end[index]) : max(color[index] - speed, end[index]);
reutn color;
}

原文见:http://bbs.51js.com/viewthread.php?tid=86901