Created
October 18, 2013 09:31
-
-
Save zmmbreeze/7039023 to your computer and use it in GitHub Desktop.
Timeline
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*************************************************************************** | |
* | |
* Copyright (c) 2013 Baidu.com, Inc. All Rights Reserved | |
* $Id$ | |
* | |
**************************************************************************/ | |
goog.provide('ad.fx.Timeline'); | |
goog.provide('ad.fx.moveTo'); | |
/** | |
* @constructor | |
* @extends {baidu.lang.Class} | |
*/ | |
ad.fx.Timeline = function(options){ | |
baidu.lang.Class.call(this); | |
this.interval = 16; | |
this.duration = 500; | |
this.dynamic = true; | |
/** | |
* @type {boolean} | |
*/ | |
this.overlapping; | |
/** | |
* @type {HTMLElement} | |
*/ | |
this.element; | |
/** | |
* 用来保存初始状态的一些信息 | |
* @type {Object} | |
*/ | |
this.original; | |
/** | |
* @private | |
* @type {string} | |
*/ | |
this.__type; | |
/** | |
* @private | |
* @type {number} | |
*/ | |
this._btime; | |
/** | |
* @private | |
* @type {number} | |
*/ | |
this._etime; | |
/** | |
* @private | |
* @type {number} | |
*/ | |
this._timer; | |
/** | |
* 目的是让Ftangram把baidu.lang.Event相关的代码合并进来. | |
* @private | |
*/ | |
this._dummy = new baidu.lang.Event('_dummy'); | |
baidu.object.extend(this, options); | |
}; | |
baidu.inherits(ad.fx.Timeline, baidu.lang.Class); | |
/** | |
* @return {ad.fx.Timeline} | |
*/ | |
ad.fx.Timeline.prototype.launch = function(){ | |
var me = this; | |
me.dispatchEvent("onbeforestart"); | |
this.initialize(); | |
this._btime = new Date().getTime(); | |
this._etime = this._btime + (me.dynamic ? me.duration : 0); | |
this.pulsed(); | |
return me; | |
} | |
ad.fx.Timeline.prototype.pulsed = function(){ | |
var me = this; | |
var now = new Date().getTime(); | |
// 当前时间线的进度百分比 | |
me.percent = (now - me._btime) / me.duration; | |
me.dispatchEvent("onbeforeupdate"); | |
// 时间线已经走到终点 | |
if (now >= me._etime){ | |
me.render(me.transition(me.percent = 1)); | |
me.finish(); | |
me.dispatchEvent("onafterfinish"); | |
me.dispose(); | |
return; | |
} | |
me.render(me.transition(me.percent)); | |
me.dispatchEvent("onafterupdate"); | |
me._timer = setTimeout(function(){me.pulsed()}, me.interval); | |
} | |
/** | |
* @param {number} percent | |
* @return {number} | |
*/ | |
ad.fx.Timeline.prototype.transition = function(percent) { | |
return percent; | |
} | |
ad.fx.Timeline.prototype.initialize = baidu.fn.blank; | |
ad.fx.Timeline.prototype.restore = baidu.fn.blank; | |
ad.fx.Timeline.prototype.finish = baidu.fn.blank; | |
ad.fx.Timeline.prototype.render = baidu.fn.blank; | |
ad.fx.Timeline.prototype.cancel = function() { | |
this._timer && clearTimeout(this._timer); | |
this._etime = this._btime; | |
this.restore(); | |
this.dispatchEvent("oncancel"); | |
this.dispose(); | |
} | |
ad.fx.Timeline.prototype.end = function() { | |
this._timer && clearTimeout(this._timer); | |
this._etime = this._btime; | |
this.pulsed(); | |
} | |
/** | |
* @param {HTMLElement} element The element attached to the ad.fx.Timeline | |
* @param {Object} options The ad.fx.Timeline configuration. | |
* @param {string=} fxName the ad.fx.Timeline name. | |
* @return {ad.fx.Timeline} | |
*/ | |
ad.fx.create = function(element, options, fxName) { | |
var timeline = new ad.fx.Timeline(options); | |
timeline.element = element; | |
timeline.__type = fxName || timeline.__type; | |
timeline.original = {}; // 20100708 | |
var catt = "baidu_current_effect"; | |
/** | |
* 将实例的guid记录到DOM元素上,以便多个效果叠加时的处理 | |
*/ | |
timeline.addEventListener("onbeforestart", function(){ | |
var me = this, guid; | |
me.attribName = "att_"+ me.__type.replace(/\W/g, "_"); | |
guid = me.element.getAttribute(catt); | |
me.element.setAttribute(catt, (guid||"") +"|"+ me.guid +"|", 0); | |
if (!me.overlapping) { | |
(guid = me.element.getAttribute(me.attribName)) | |
&& window[baidu.guid]._instances[guid].cancel(); | |
//在DOM元素上记录当前效果的guid | |
me.element.setAttribute(me.attribName, me.guid, 0); | |
} | |
}); | |
/** | |
* 打扫dom元素上的痕迹,删除元素自定义属性 | |
* @this {ad.fx.Timeline} | |
*/ | |
timeline.clean = function(e) { | |
var me = this, guid; | |
if (e = me.element) { | |
e.removeAttribute(me.attribName); | |
guid = e.getAttribute(catt); | |
guid = guid.replace("|"+ me.guid +"|", ""); | |
if (!guid) e.removeAttribute(catt); | |
else e.setAttribute(catt, guid); | |
} | |
}; | |
/** | |
* 在时间线结束时净化对DOM元素的污染 | |
*/ | |
timeline.addEventListener("oncancel", function() { | |
this.clean(); | |
this.restore(); | |
}); | |
/** | |
* 在时间线结束时净化对DOM元素的污染 | |
*/ | |
timeline.addEventListener("onafterfinish", function() { | |
this.clean(); | |
this.restoreAfterFinish && this.restore(); | |
}); | |
/** | |
* 保存原始的CSS属性值 20100708 | |
* @this {ad.fx.Timeline} | |
* @param {string} key 需要保存的值. | |
*/ | |
timeline.protect = function(key) { | |
this.original[key] = this.element.style[key]; | |
}; | |
/** | |
* @this {ad.fx.Timeline} | |
* 时间线结束,恢复那些被改过的CSS属性值 | |
*/ | |
timeline.restore = function() { | |
var o = this.original, | |
s = this.element.style, | |
v; | |
for (var i in o) { | |
v = o[i]; | |
if (typeof v == "undefined") continue; | |
s[i] = v; // 还原初始值 | |
// [TODO] 假如以下语句将来达不到要求时可以使用 cssText 操作 | |
if (!v && s.removeAttribute) s.removeAttribute(i); // IE | |
else if (!v && s.removeProperty) s.removeProperty(i); // !IE | |
} | |
}; | |
return timeline; | |
}; | |
/** | |
* @param {HTMLElement} element The element which Timeline was attached. | |
* @param {Object} options The Timeline configuration. | |
* @return {ad.fx.Timeline} | |
*/ | |
ad.fx.move = function(element, options) { | |
if (baidu.dom.getStyle(element, "position") == "static") { | |
return null; | |
} | |
options = baidu.object.extend({x: 0, y: 0}, options); | |
if (options.x == 0 && options.y == 0) return null; | |
/** | |
* @this {ad.fx.Timeline} | |
*/ | |
function initialize() { | |
this.protect("top"); | |
this.protect("left"); | |
/** @type {number} */ | |
this.x; | |
/** @type {number} */ | |
this.y; | |
this.originX = parseInt(baidu.dom.getStyle(element, "left"), 10)|| 0; | |
this.originY = parseInt(baidu.dom.getStyle(element, "top"), 10) || 0; | |
} | |
/** | |
* @param {number} schedule The timeline schedule. | |
* @this {ad.fx.Timeline} | |
*/ | |
function render(schedule) { | |
element.style.top = (this.y * schedule + this.originY) +"px"; | |
element.style.left = (this.x * schedule + this.originX) +"px"; | |
} | |
/** | |
* @param {number} percent | |
* @return {number} | |
*/ | |
function transition(percent) { | |
return (1 - Math.pow(1 - percent, 2)); | |
} | |
var fx = ad.fx.create(element, baidu.object.extend({ | |
initialize : initialize, | |
transition : transition, | |
render : render | |
}, options), "ad.fx.move"); | |
return fx.launch(); | |
}; | |
/** | |
* @param {HTMLElement} element | |
* @param {{x:number, y:number}} point | |
* @param {Object=} options. | |
*/ | |
ad.fx.moveTo = function(element, point, options) { | |
if (baidu.dom.getStyle(element, "position") == "static") { | |
return null; | |
} | |
var x = parseInt(baidu.dom.getStyle(element, "left"), 10) || 0; | |
var y = parseInt(baidu.dom.getStyle(element, "top"), 10) || 0; | |
var fx = ad.fx.move(element, | |
baidu.object.extend({x: point.x - x, y: point.y - y}, options||{})); | |
return fx; | |
}; | |
/* vim: set ts=4 sw=4 sts=4 tw=100: */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment