Skip to content

Instantly share code, notes, and snippets.

@zmmbreeze
Created October 18, 2013 09:31
Show Gist options
  • Save zmmbreeze/7039023 to your computer and use it in GitHub Desktop.
Save zmmbreeze/7039023 to your computer and use it in GitHub Desktop.
Timeline
/***************************************************************************
*
* 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