原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-405471
原作者:我佛山人
//
跟CSS有关的动画的基类,这里的动画,主要是从一个开始值到结束值的变化效果
Fx.CSS = new Class({
// 继承自Fx
Extends: Fx,
// prepares the base from/to object
// 动画的开始和结束值的前期处理
prepare: function (element, property, values) {
// 数组化,因为values可能传一个单值,也可能是一个数组
values = $splat(values);
// 取数组中的第二个值,作为动画的结束值
var values1 = values[ 1 ];
// 如果只传了一个值
if ( ! $chk(values1)) {
// 将传的这个值作为动画的结束值
values[ 1 ] = values[ 0 ];
// 将当前值作为开始值
values[ 0 ] = element.getStyle(property);
}
// 将数组中的项使用parse方法解释
var parsed = values.map( this .parse);
// 返回from和to两个键值的对象
return {from: parsed[ 0 ], to: parsed[ 1 ]};
},
// parses a value into an array
parse: function (value) {
/*
使用lambad表达式,将value函数化之后再执行
这样的好处是使传的值可以是function,也可以是固定值
*/
value = $lambda(value)();
// 数组化,如果是字符串类型,使用空格分隔成数组
value = ( typeof value == ' string ' ) ? value.split( ' ' ) : $splat(value);
// 对数组逐项处理
return value.map( function (val) {
// 转为字符类型
val = String(val);
var found = false ;
Fx.CSS.Parsers.each( function (parser, key) {
// 第一项时这里为false继续执行下面,找到合适的解释器后found判断不再为false,避免重复解释
if (found) return ;
// 尝试使用解释器解释值
var parsed = parser.parse(val);
// 如果解释成功,记录解释后的值和使用的解释器(因为还要使用解释器的compute和serve方法)
if ($chk(parsed)) found = {value: parsed, parser: parser};
});
// 默认使用字符串值的解释器
found = found || {value: val, parser: Fx.CSS.Parsers.String};
return found;
});
},
// computes by a from and to prepared objects, using their parsers.
// 覆盖父类Fx的同名方法,不同的算法实现不同的效果
compute: function (from, to, delta) {
var computed = [];
// 取数项小的遍历
(Math.min(from.length, to.length)).times( function (i) {
// 返回计算过的值和使用的解释器
computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
});
// 为$type提供精准类型值
computed.$family = {name: ' fx:css:value ' };
return computed;
},
// serves the value as settable
serve: function (value, unit) {
// 如果值未经解释,需要先解释
if ($type(value) != ' fx:css:value ' ) value = this .parse(value);
var returned = [];
value.each( function (bit) {
// 得到最终的使用值
returned = returned.concat(bit.parser.serve(bit.value, unit));
});
return returned;
},
// renders the change to an element
// 因为类本身是跟CSS有类,所以最终将计算出的数组通过setStyle反映到element的相应CSS属性上
render: function (element, property, value, unit) {
element.setStyle(property, this .serve(value, unit));
},
// searches inside the page css to find the values for a selector
// 从当前页面的样式中查找指定选择符的样式设置
search: function (selector) {
// 模拟缓存,先从临时对象中找相应键值,提高效率
if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
var to = {};
// 遍历当前页面的样式表
Array.each(document.styleSheets, function (sheet, j) {
var href = sheet.href;
// 忽略跨域的外链样式表
if (href && href.contains( ' :// ' ) && ! href.contains(document.domain)) return ;
// 样式规则集
var rules = sheet.rules || sheet.cssRules;
// 遍历每条规则
Array.each(rules, function (rule, i) {
if ( ! rule.style) return ;
// 选择符(类型选择符的话会转为小写)
var selectorText = (rule.selectorText) ? rule.selectorText.replace( / ^\w+ / , function (m){
return m.toLowerCase();
}) : null ;
// 匹配指定的样式选择符
if ( ! selectorText || ! selectorText.test( ' ^ ' + selector + ' $ ' )) return ;
// 样式值分析
Element.Styles.each( function (value, style) {
// 无值
if ( ! rule.style[style] || Element.ShortStyles[style]) return ;
// 转为字符串
value = String(rule.style[style]);
// 颜色值处理
to[style] = (value.test( / ^rgb / )) ? value.rgbToHex() : value;
});
});
});
// 缓存
return Fx.CSS.Cache[selector] = to;
}
});
Fx.CSS.Cache = {};
// CSS中几种值类型的解释器,每个解释器必须实现parse/compute/serve三个接口
Fx.CSS.Parsers = new Hash({
// 对颜色的解释处理
Color: {
parse: function (value) {
// 如果是十六进制的颜色表示,处理成RGB数组
if (value.match( / ^#[0-9a-f]{3,6}$ / i)) return value.hexToRgb( true );
// 如果是RGB的颜色显示,正则匹配出RGB数组,不匹配返回flase,以便引擎调用其它解释器解释
return ((value = value.match( / (\d+),\s*(\d+),\s*(\d+) / ))) ? [value[ 1 ], value[ 2 ], value[ 3 ]] : false ;
},
compute: function (from, to, delta) {
// 对R、G和B分别计算目标值
return from.map( function (value, i) {
// 可以看到仍然使用静态的compute方法
return Math.round(Fx.compute(from[i], to[i], delta));
});
},
serve: function (value) {
// 将R、G、B都转成数值型
return value.map(Number);
}
},
// 数值类型的解释处理
Number: {
parse: function (value) {
// 转为浮点数
return parseFloat(value);
},
compute: function (from, to, delta) {
// 跟Fx中的算法一样
return Fx.compute(from, to, delta);
},
serve: function (value, unit) {
// 加上单位,比如px,pt之类
return (unit) ? value + unit : value;
}
},
// 对字符类型的解释处理
String: {
// 解释器返回false,相当于parse : function(){return false;}
parse: $lambda( false ),
// compute方法执行时返回第2个参数
compute: $arguments( 1 ),
// serve方法执行时返回第1个参数
serve: $arguments( 0 )
}
});
Fx.CSS = new Class({
// 继承自Fx
Extends: Fx,
// prepares the base from/to object
// 动画的开始和结束值的前期处理
prepare: function (element, property, values) {
// 数组化,因为values可能传一个单值,也可能是一个数组
values = $splat(values);
// 取数组中的第二个值,作为动画的结束值
var values1 = values[ 1 ];
// 如果只传了一个值
if ( ! $chk(values1)) {
// 将传的这个值作为动画的结束值
values[ 1 ] = values[ 0 ];
// 将当前值作为开始值
values[ 0 ] = element.getStyle(property);
}
// 将数组中的项使用parse方法解释
var parsed = values.map( this .parse);
// 返回from和to两个键值的对象
return {from: parsed[ 0 ], to: parsed[ 1 ]};
},
// parses a value into an array
parse: function (value) {
/*
使用lambad表达式,将value函数化之后再执行
这样的好处是使传的值可以是function,也可以是固定值
*/
value = $lambda(value)();
// 数组化,如果是字符串类型,使用空格分隔成数组
value = ( typeof value == ' string ' ) ? value.split( ' ' ) : $splat(value);
// 对数组逐项处理
return value.map( function (val) {
// 转为字符类型
val = String(val);
var found = false ;
Fx.CSS.Parsers.each( function (parser, key) {
// 第一项时这里为false继续执行下面,找到合适的解释器后found判断不再为false,避免重复解释
if (found) return ;
// 尝试使用解释器解释值
var parsed = parser.parse(val);
// 如果解释成功,记录解释后的值和使用的解释器(因为还要使用解释器的compute和serve方法)
if ($chk(parsed)) found = {value: parsed, parser: parser};
});
// 默认使用字符串值的解释器
found = found || {value: val, parser: Fx.CSS.Parsers.String};
return found;
});
},
// computes by a from and to prepared objects, using their parsers.
// 覆盖父类Fx的同名方法,不同的算法实现不同的效果
compute: function (from, to, delta) {
var computed = [];
// 取数项小的遍历
(Math.min(from.length, to.length)).times( function (i) {
// 返回计算过的值和使用的解释器
computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
});
// 为$type提供精准类型值
computed.$family = {name: ' fx:css:value ' };
return computed;
},
// serves the value as settable
serve: function (value, unit) {
// 如果值未经解释,需要先解释
if ($type(value) != ' fx:css:value ' ) value = this .parse(value);
var returned = [];
value.each( function (bit) {
// 得到最终的使用值
returned = returned.concat(bit.parser.serve(bit.value, unit));
});
return returned;
},
// renders the change to an element
// 因为类本身是跟CSS有类,所以最终将计算出的数组通过setStyle反映到element的相应CSS属性上
render: function (element, property, value, unit) {
element.setStyle(property, this .serve(value, unit));
},
// searches inside the page css to find the values for a selector
// 从当前页面的样式中查找指定选择符的样式设置
search: function (selector) {
// 模拟缓存,先从临时对象中找相应键值,提高效率
if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
var to = {};
// 遍历当前页面的样式表
Array.each(document.styleSheets, function (sheet, j) {
var href = sheet.href;
// 忽略跨域的外链样式表
if (href && href.contains( ' :// ' ) && ! href.contains(document.domain)) return ;
// 样式规则集
var rules = sheet.rules || sheet.cssRules;
// 遍历每条规则
Array.each(rules, function (rule, i) {
if ( ! rule.style) return ;
// 选择符(类型选择符的话会转为小写)
var selectorText = (rule.selectorText) ? rule.selectorText.replace( / ^\w+ / , function (m){
return m.toLowerCase();
}) : null ;
// 匹配指定的样式选择符
if ( ! selectorText || ! selectorText.test( ' ^ ' + selector + ' $ ' )) return ;
// 样式值分析
Element.Styles.each( function (value, style) {
// 无值
if ( ! rule.style[style] || Element.ShortStyles[style]) return ;
// 转为字符串
value = String(rule.style[style]);
// 颜色值处理
to[style] = (value.test( / ^rgb / )) ? value.rgbToHex() : value;
});
});
});
// 缓存
return Fx.CSS.Cache[selector] = to;
}
});
Fx.CSS.Cache = {};
// CSS中几种值类型的解释器,每个解释器必须实现parse/compute/serve三个接口
Fx.CSS.Parsers = new Hash({
// 对颜色的解释处理
Color: {
parse: function (value) {
// 如果是十六进制的颜色表示,处理成RGB数组
if (value.match( / ^#[0-9a-f]{3,6}$ / i)) return value.hexToRgb( true );
// 如果是RGB的颜色显示,正则匹配出RGB数组,不匹配返回flase,以便引擎调用其它解释器解释
return ((value = value.match( / (\d+),\s*(\d+),\s*(\d+) / ))) ? [value[ 1 ], value[ 2 ], value[ 3 ]] : false ;
},
compute: function (from, to, delta) {
// 对R、G和B分别计算目标值
return from.map( function (value, i) {
// 可以看到仍然使用静态的compute方法
return Math.round(Fx.compute(from[i], to[i], delta));
});
},
serve: function (value) {
// 将R、G、B都转成数值型
return value.map(Number);
}
},
// 数值类型的解释处理
Number: {
parse: function (value) {
// 转为浮点数
return parseFloat(value);
},
compute: function (from, to, delta) {
// 跟Fx中的算法一样
return Fx.compute(from, to, delta);
},
serve: function (value, unit) {
// 加上单位,比如px,pt之类
return (unit) ? value + unit : value;
}
},
// 对字符类型的解释处理
String: {
// 解释器返回false,相当于parse : function(){return false;}
parse: $lambda( false ),
// compute方法执行时返回第2个参数
compute: $arguments( 1 ),
// serve方法执行时返回第1个参数
serve: $arguments( 0 )
}
});