[转帖]Mootools源码分析-30 -- Fx.Tween
原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-405756
原作者:我佛山人
Fx.Tween = new Class({
//继承自Fx.CSS
Extends: Fx.CSS,
//构造函数,会覆盖父类的构造函数
initialize: function(element, options) {
//覆盖父类的构造函数是为了添加element参数
this.element = this.subject = $(element);
/*
调用父类的同名方法,固定的用法,一般情况下也可以用this.parent
截至1543版本,已经完全可以抛弃arguments.callee直接使用this,但是由于Opera不支持caller,不够完美
*/
arguments.callee.parent(options);
},
//直接覆盖父类的同名方法,参考Fx基类
set: function(property, now) {
//如果只提供一个参数
if (arguments.length == 1) {
//将此参数作为目标值
now = property;
//此时属性另取他处
property = this.property || this.options.property;
}
//最终渲染效果
this.render(this.element, property, now, this.options.unit);
return this;
},
//覆盖父类同名方法,参考Fx基类
start: function(property, from, to) {
//检查当前特效运行状态,决定是否运行新特效
if (!this.check(property, from, to)) return this;
//将参数降维
var args = Array.flatten(arguments);
//取属性,有优先级
this.property = this.options.property || args.shift();
//调用父类Fx.CSS的prepare方法解释参数,得到from和to值
var parsed = this.prepare(this.element, this.property, args);
//调用Fx基类的同名方法,开始执行
return arguments.callee.parent(parsed.from, parsed.to);
}
});
//静态属性,用于element.set和element.get
Element.Properties.tween = {
//setter设置Fx.Tween对象参数
set: function(options) {
//先从临时对象读取,看有没缓存到Fx.Tween实例
var tween = this.retrieve('tween');
//如果存在,取消执行中的特效
if (tween) tween.cancel();
//删去旧对象,用新配置项保存为新对象
return this.eliminate('tween').store('tween:options', $extend({link: 'cancel'}, options));
},
//getter获取Fx.Tween对象
get: function(options) {
//如果提供参数或者尚未存在与当前Element关联的Fx.Tween实例
if (options || !this.retrieve('tween')) {
//如果提供参数并且未保存关联的Fx.Tween实例的参数,调用setter设置参数
if (options || !this.retrieve('tween:options')) this.set('tween', options);
//保存Fx.Tween实例
this.store('tween', new Fx.Tween(this, this.retrieve('tween:options')));
}
return this.retrieve('tween');
}
};
//对象Fx.Tween为Element添加的扩展实现
Element.implement({
//Fx.Tween的快捷方式,遗憾的这里不支持参数设置,需要手工调用elemenet.set('tween', options)设置
tween: function(property, from, to) {
/*
这是使用上面的getter取Fx.Tween实例,再start
因为start方法里使用Array.flatten处理参数
所以直接传送arguments对象过去,否则这里还要判断参数的数量
*/
this.get('tween').start(arguments);
return this;
},
//使用Fx.Tween实现的深入浅出效果
fade: function(how) {
var fade = this.get('tween'), o = 'opacity', toggle;
how = $pick(how, 'toggle');
//几种淡入淡出的方式
switch (how) {
//淡入
case 'in': fade.start(o, 1); break;
//淡入
case 'out': fade.start(o, 0); break;
//显示
case 'show': fade.set(o, 1); break;
//隐藏
case 'hide': fade.set(o, 0); break;
//开关
case 'toggle':
//获取标记变量,第二个参数用于默认值
var flag = this.retrieve('fade:flag', this.get('opacity') == 1);
//根据标记状态控制淡入还是淡出
fade.start(o, (flag) ? 0 : 1);
//将标记取反保存
this.store('fade:flag', !flag);
toggle = true;
break;
default: fade.start(o, arguments);
}
/*
如果没有使用开关方式,删除临时标记
避免在使用toggle之后又使用其它方式,导致toggle响应错误
*/
if (!toggle) this.eliminate('fade:flag');
return this;
},
//通常背景色动画实现的高亮显示效果
highlight: function(start, end) {
//end为动画结束后使用的背景色,通常是原来恢复原来的颜色
if (!end) {
//临时对象取值
end = this.retrieve('highlight:original', this.getStyle('background-color'));
//透明的话按白色处理
end = (end == 'transparent') ? '#fff' : end;
}
//获取Fx.Tween实例
var tween = this.get('tween');
//开始执行
tween.start('background-color', start || '#ffff88', end).chain(function() {
//动画结束恢复原来颜色
this.setStyle('background-color', this.retrieve('highlight:original'));
//链式执行
tween.callChain();
}.bind(this));
return this;
}
});
//继承自Fx.CSS
Extends: Fx.CSS,
//构造函数,会覆盖父类的构造函数
initialize: function(element, options) {
//覆盖父类的构造函数是为了添加element参数
this.element = this.subject = $(element);
/*
调用父类的同名方法,固定的用法,一般情况下也可以用this.parent
截至1543版本,已经完全可以抛弃arguments.callee直接使用this,但是由于Opera不支持caller,不够完美
*/
arguments.callee.parent(options);
},
//直接覆盖父类的同名方法,参考Fx基类
set: function(property, now) {
//如果只提供一个参数
if (arguments.length == 1) {
//将此参数作为目标值
now = property;
//此时属性另取他处
property = this.property || this.options.property;
}
//最终渲染效果
this.render(this.element, property, now, this.options.unit);
return this;
},
//覆盖父类同名方法,参考Fx基类
start: function(property, from, to) {
//检查当前特效运行状态,决定是否运行新特效
if (!this.check(property, from, to)) return this;
//将参数降维
var args = Array.flatten(arguments);
//取属性,有优先级
this.property = this.options.property || args.shift();
//调用父类Fx.CSS的prepare方法解释参数,得到from和to值
var parsed = this.prepare(this.element, this.property, args);
//调用Fx基类的同名方法,开始执行
return arguments.callee.parent(parsed.from, parsed.to);
}
});
//静态属性,用于element.set和element.get
Element.Properties.tween = {
//setter设置Fx.Tween对象参数
set: function(options) {
//先从临时对象读取,看有没缓存到Fx.Tween实例
var tween = this.retrieve('tween');
//如果存在,取消执行中的特效
if (tween) tween.cancel();
//删去旧对象,用新配置项保存为新对象
return this.eliminate('tween').store('tween:options', $extend({link: 'cancel'}, options));
},
//getter获取Fx.Tween对象
get: function(options) {
//如果提供参数或者尚未存在与当前Element关联的Fx.Tween实例
if (options || !this.retrieve('tween')) {
//如果提供参数并且未保存关联的Fx.Tween实例的参数,调用setter设置参数
if (options || !this.retrieve('tween:options')) this.set('tween', options);
//保存Fx.Tween实例
this.store('tween', new Fx.Tween(this, this.retrieve('tween:options')));
}
return this.retrieve('tween');
}
};
//对象Fx.Tween为Element添加的扩展实现
Element.implement({
//Fx.Tween的快捷方式,遗憾的这里不支持参数设置,需要手工调用elemenet.set('tween', options)设置
tween: function(property, from, to) {
/*
这是使用上面的getter取Fx.Tween实例,再start
因为start方法里使用Array.flatten处理参数
所以直接传送arguments对象过去,否则这里还要判断参数的数量
*/
this.get('tween').start(arguments);
return this;
},
//使用Fx.Tween实现的深入浅出效果
fade: function(how) {
var fade = this.get('tween'), o = 'opacity', toggle;
how = $pick(how, 'toggle');
//几种淡入淡出的方式
switch (how) {
//淡入
case 'in': fade.start(o, 1); break;
//淡入
case 'out': fade.start(o, 0); break;
//显示
case 'show': fade.set(o, 1); break;
//隐藏
case 'hide': fade.set(o, 0); break;
//开关
case 'toggle':
//获取标记变量,第二个参数用于默认值
var flag = this.retrieve('fade:flag', this.get('opacity') == 1);
//根据标记状态控制淡入还是淡出
fade.start(o, (flag) ? 0 : 1);
//将标记取反保存
this.store('fade:flag', !flag);
toggle = true;
break;
default: fade.start(o, arguments);
}
/*
如果没有使用开关方式,删除临时标记
避免在使用toggle之后又使用其它方式,导致toggle响应错误
*/
if (!toggle) this.eliminate('fade:flag');
return this;
},
//通常背景色动画实现的高亮显示效果
highlight: function(start, end) {
//end为动画结束后使用的背景色,通常是原来恢复原来的颜色
if (!end) {
//临时对象取值
end = this.retrieve('highlight:original', this.getStyle('background-color'));
//透明的话按白色处理
end = (end == 'transparent') ? '#fff' : end;
}
//获取Fx.Tween实例
var tween = this.get('tween');
//开始执行
tween.start('background-color', start || '#ffff88', end).chain(function() {
//动画结束恢复原来颜色
this.setStyle('background-color', this.retrieve('highlight:original'));
//链式执行
tween.callChain();
}.bind(this));
return this;
}
});