Last active
August 29, 2015 14:10
-
-
Save maolion/73f1f1a5d4142ac40b44 to your computer and use it in GitHub Desktop.
Animation
This file contains 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
/// @require ../libs/jQuery/jquery.easing.1.3.js | |
var | |
Utils = require("./Utils.js"), | |
Env = require("./Env.js"), | |
Event = require("./Event.js"), | |
own = Object.prototype.hasOwnProperty, | |
slice = Array.prototype.slice | |
; | |
var | |
PLAY_STATE_NONE = 0, | |
PLAY_STATE_RUNNING = 1, | |
PLAY_STATE_PAUSED = 2, | |
PLAY_STATE_DONE = 3 | |
; | |
var | |
transitions = { | |
linear : 'linear', | |
ease : 'ease', | |
easeIn : 'ease-in', | |
easeOut : 'ease-out', | |
easeInOut : 'ease-in-out', | |
easeInSine : 'cubic-bezier(0.47, 0, 0.745, 0.715)', | |
easeOutSine : 'cubic-bezier(0.39, 0.575, 0.565, 1)', | |
easeInOutSine : 'cubic-bezier(0.445, 0.05, 0.55, 0.95)', | |
easeInQuad : 'cubic-bezier(0.55, 0.085, 0.68, 0.53)', | |
easeOutQuad : 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', | |
easeInOutQuad : 'cubic-bezier(0.455, 0.03, 0.515, 0.955)', | |
easeInCubic : 'cubic-bezier(0.55, 0.055, 0.675, 0.19)', | |
easeOutCubic : 'cubic-bezier(0.215, 0.61, 0.355, 1)', | |
easeInOutCubic : 'cubic-bezier(0.645, 0.045, 0.355, 1)', | |
easeInQuart : 'cubic-bezier(0.895, 0.03, 0.685, 0.22)', | |
easeOutQuart : 'cubic-bezier(0.165, 0.84, 0.44, 1)', | |
easeInOutQuart : 'cubic-bezier(0.77, 0, 0.175, 1)', | |
easeInQuint : 'cubic-bezier(0.755, 0.05, 0.855, 0.06)', | |
easeOutQuint : 'cubic-bezier(0.23, 1, 0.32, 1)', | |
easeInOutQuint : 'cubic-bezier(0.86, 0, 0.07, 1)', | |
easeInExpo : 'cubic-bezier(0.95, 0.05, 0.795, 0.035)', | |
easeOutExpo : 'cubic-bezier(0.19, 1, 0.22, 1)', | |
easeInOutExpo : 'cubic-bezier(1, 0, 0, 1)', | |
easeInCirc : 'cubic-bezier(0.6, 0.04, 0.98, 0.335)', | |
easeOutCirc : 'cubic-bezier(0.075, 0.82, 0.165, 1)', | |
easeInOutCirc : 'cubic-bezier(0.785, 0.135, 0.15, 0.86)', | |
easeInBack : 'cubic-bezier(0.6, -0.28, 0.735, 0.045)', | |
easeOutBack : 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', | |
easeInOutBack : 'cubic-bezier(0.68, -0.55, 0.265, 1.55)' | |
} | |
; | |
function Animate(opt){ | |
var _this = this; | |
Event.call(this); | |
this.el = opt.element instanceof jQuery ? opt.element : jQuery(opt.element||document.body); | |
this.elStyle = this.el[0].style; | |
this.duration = opt.duration || 400; | |
this.delay = Math.max(~~opt.delay, 0); | |
this.timing = opt.timing || 'ease'; | |
this.fillMode = opt.fillMode || 'forwards'; | |
this.to = opt.to ? getCompatibilityStyle(opt.to) : {}; | |
this.from = opt.from ? getCompatibilityStyle(opt.from) : {}; | |
this.playState = PLAY_STATE_NONE; | |
this.startTime = 0; | |
this.currentTime = 0; | |
this.timer = null; | |
jQuery.each(['onStart', 'onPaused', 'onEnd'], function(index, event){ | |
if (opt[event] instanceof Function) { | |
_this[event] = opt[event]; | |
} | |
}); | |
if (Env.CSS_SUPPORT.ANIMATE) { | |
this.timing = transitions[this.timing] || this.timing || 'ease'; | |
this.property = function(){ | |
var keys = []; | |
for(var k in _this.to) { | |
if (own.call(_this.to, k)) keys.push(toNormalizationtyleProperty(k)); | |
} | |
return keys.join(","); | |
}(); | |
this.el.on("webkitTransitionEnd transitionend", function(){ | |
if (_this.playState !== PLAY_STATE_RUNNING) return; | |
_this.end(); | |
}); | |
} else { | |
this.animateDoneHandler = function(){ | |
_this.end(); | |
}; | |
this.timing = own.call(jQuery.easing, this.timing) ? this.timing : 'swing'; | |
} | |
}; | |
var api = Animate.prototype = Utils.create(Event.prototype, Animate); | |
api.onStart = | |
api.onPaused = | |
api.onEnd = jQuery.noop; | |
[ | |
function(){ | |
api.play = function(){ | |
var _this = this; | |
switch(this.playState) { | |
case PLAY_STATE_NONE: | |
case PLAY_STATE_DONE: | |
_this.timer = setTimeout(function(){ | |
_this.playState = PLAY_STATE_RUNNING; | |
_this.currentTime = 0; | |
_this.startTime = new Date().getTime(); | |
_this.el.stop() | |
.css(_this.from) | |
.animate(_this.to, _this.duration, _this.timing, _this.animateDoneHandler) | |
; | |
_this.onStart(); | |
_this.fireEvent("start"); | |
}, this.delay); | |
break; | |
case PLAY_STATE_PAUSED: | |
this.startTime = new Date().getTime(); | |
this.playState = PLAY_STATE_RUNNING; | |
this.el.stop() | |
.animate(this.to, this.duration, this.timing, this.animateDoneHandler) | |
; | |
this.onStart(); | |
this.fireEvent("start"); | |
break; | |
} | |
}; | |
api.pause = function(){ | |
clearTimeout(this.timer); | |
if (this.playState !== PLAY_STATE_RUNNING) return; | |
this.currentTime += new Date().getTime() - this.startTime; | |
this.el.stop(); | |
this.playState = PLAY_STATE_PAUSED; | |
this.onPaused(); | |
this.fireEvent("paused"); | |
}; | |
api.end = function(){ | |
if (this.playState === PLAY_STATE_DONE) return; | |
this.el.stop(); | |
if (this.fillMode === 'forwards') { | |
if (this.playState === PLAY_STATE_PAUSED || this.currentTime + (new Date() - this.startTime) < this.duration) { | |
this.el.css(this.to); | |
} | |
} else { | |
this.el.css(this.from); | |
} | |
this.playState = PLAY_STATE_DONE; | |
this.currentTime = this.duration; | |
this.onEnd(); | |
this.fireEvent("end"); | |
}; | |
}, | |
function(){ | |
api.play = function(){ | |
var _this = this; | |
switch(this.playState) { | |
case PLAY_STATE_NONE: | |
case PLAY_STATE_DONE: | |
this.elStyle[Env.CSSPROP.transitionDuration] = '0ms'; | |
this.elStyle[Env.CSSPROP.transitionTimingFunction] = this.timing; | |
this.elStyle[Env.CSSPROP.transitionProperty] = this.property; | |
_this.timer = setTimeout(function(){ | |
setStyle(_this.elStyle, _this.from); | |
_this.timer = setTimeout(function(){ | |
_this.playState = PLAY_STATE_RUNNING; | |
_this.currentTime = 0; | |
_this.startTime = new Date().getTime(); | |
_this.elStyle[Env.CSSPROP.transitionDuration] = _this.duration + 'ms'; | |
setStyle(_this.elStyle, _this.to); | |
_this.onStart(); | |
_this.fireEvent("start"); | |
}, 16); | |
}, this.delay); | |
break; | |
case PLAY_STATE_PAUSED: | |
_this.startTime = new Date().getTime(); | |
this.playState = PLAY_STATE_RUNNING; | |
this.elStyle[Env.CSSPROP.transitionDuration] = (this.duration - this.currentTime) + 'ms'; | |
setStyle(this.elStyle, this.to); | |
this.onStart(); | |
this.fireEvent("start"); | |
break; | |
} | |
}; | |
api.pause = function(){ | |
clearTimeout(this.timer); | |
if (this.playState !== PLAY_STATE_RUNNING) return; | |
this.currentTime += new Date().getTime() - this.startTime; | |
this.elStyle[Env.CSSPROP.transitionDuration] = '0ms'; | |
var cStyle = window.getComputedStyle(this.el[0], null); | |
for(var k in this.to) { | |
if (!own.call(this.to, k)) continue; | |
this.elStyle[k] = cStyle[k]; | |
} | |
this.playState = PLAY_STATE_PAUSED; | |
this.onPaused(); | |
this.fireEvent("paused"); | |
}; | |
api.end = function(){ | |
if (this.playState === PLAY_STATE_DONE) return; | |
this.elStyle[Env.CSSPROP.transition] = 'none'; | |
if (this.fillMode === 'forwards') { | |
if (this.playState === PLAY_STATE_PAUSED || this.currentTime + (new Date() - this.startTime) < this.duration) { | |
setStyle(this.elStyle, this.to); | |
} | |
} else { | |
setStyle(this.elStyle, this.from); | |
} | |
this.playState = PLAY_STATE_DONE; | |
this.currentTime = this.duration; | |
this.onEnd(); | |
this.fireEvent("end"); | |
}; | |
} | |
][+Env.CSS_SUPPORT.ANIMATE](); | |
function getCompatibilityStyle(style) { | |
var | |
r = {} | |
; | |
if (Env.CSS_SUPPORT.ANIMATE) { | |
var re = /^\*/; | |
style = style.CSS3 || style; | |
for(var k in style) { | |
if (!own.call(style, k)) continue; | |
r[toJsStyleProperty(k.replace(re, Env.CSS_VENDOR))] = style[k]; | |
} | |
} else { | |
delete style.CSS3; | |
for(var k in style) { | |
if (!own.call(style, k)) continue; | |
r[toJsStyleProperty(k)] = style[k]; | |
} | |
} | |
return r; | |
}; | |
function toJsStyleProperty(name){ | |
var | |
name = name.split('-'), | |
n = 0 | |
; | |
for(var i = 0, l = name.length; i < l; i++) { | |
var p = name[i]; | |
if (!p) continue; | |
name[n] = n === 0 ? p : p.charAt(0).toUpperCase() + p.slice(1); | |
n++; | |
} | |
name.length = n; | |
return name.join(""); | |
} | |
function toNormalizationtyleProperty(name){ | |
name = name.replace(/([A-Z])/g, function(match, $1){ | |
return '-' + $1.toLowerCase() | |
}); | |
if (/^(?:webkit|moz|ms|o)-/.test(name)) { | |
name = '-' + name; | |
} | |
return name; | |
} | |
function setStyle(style, css) { | |
for(var k in css) { | |
style[k] = css[k]; | |
} | |
} | |
//x = new Animate({ | |
// element : '#akd_logo', | |
// duration : 5000, | |
// fillMode : 'backwards', | |
// to : { | |
// left : 10, | |
// width : 100, | |
// CSS3 : { | |
// '*transform' : 'translateX(10px)', | |
// width : '100px' | |
// } | |
// }, | |
// from : { | |
// left : 50, | |
// width : 200, | |
// CSS3 : { | |
// '*transform' : 'translateX(50px)', | |
// width : '200px' | |
// } | |
// } | |
//}); | |
//x.onStart = function(){ | |
// console.log("start"); | |
//}; | |
//x.onDone = function(){ | |
// console.log("done"); | |
// x.play(); | |
//}; | |
//x.onPaused = function(){ | |
// console.log("paused"); | |
//}; | |
//x.play(); | |
function Animation(){ | |
Event.call(this); | |
var | |
_this = this, | |
animates = slice.call(arguments), | |
n = 0 | |
; | |
jQuery.each(animates, function(index, animate){ | |
if (!animate || !(animate instanceof Object)) return; | |
animate = animates[index = n++] = animate instanceof Animation ? animate : new Animate(animate); | |
animate.on("end", function(){ | |
if (index + 1 >= _this._count) { | |
_this.end(); | |
return; | |
} | |
animates[_this._currentIndex = index+1].play(); | |
}); | |
}); | |
animates.length = n; | |
this._animates = animates; | |
this._currentIndex = 0; | |
this._count = animates.length; | |
this._playState = PLAY_STATE_NONE; | |
}; | |
var api = Animation.prototype = Utils.create(Event.prototype, Animation); | |
api.onStart = | |
api.onPaused = | |
api.onEnd = jQuery.noop; | |
api.play = function() { | |
if (!this._count) return; | |
switch(this._playState) { | |
case PLAY_STATE_NONE: | |
case PLAY_STATE_DONE: | |
this._currentIndex = 0; | |
this._animates[0].play(); | |
this._playState = PLAY_STATE_RUNNING; | |
this.onStart(); | |
this.fireEvent("start"); | |
break; | |
case PLAY_STATE_PAUSED: | |
this._animates[this._currentIndex].play(); | |
this.onStart(); | |
this.fireEvent("start"); | |
break; | |
} | |
}; | |
api.pause = function(){ | |
if (!this._count) return; | |
if (this._playState === PLAY_STATE_PAUSED) return; | |
this._animates[this._currentIndex].pause(); | |
this.onPaused(); | |
this.fireEvent("paused"); | |
}; | |
api.end = function(){ | |
if (!this._count) return; | |
if (this._playState === PLAY_STATE_DONE) return; | |
for(var i = this._animates.length; --i>=0;) this._animates[i].end(); | |
this._currentIndex = this._count - 1; | |
this._playState = PLAY_STATE_DONE; | |
this.onEnd(); | |
this.fireEvent("end"); | |
}; | |
api.isRunning = function() { | |
return this._playState === PLAY_STATE_RUNNING; | |
}; | |
api.isPaused = function(){ | |
return this._playState === PLAY_STATE_PAUSED; | |
}; | |
api.isDone = function(){ | |
return this._playState === PLAY_STATE_DONE; | |
}; | |
module.exports = Animation; | |
//example | |
jQuery('#akd_logo').css('webkitAnimation', 'none'); | |
x = new Animation( | |
{ | |
element : '#akd_logo', | |
duration : 1200, | |
from : { | |
top : '50%', | |
opacity : 1, | |
CSS3 : { | |
'*transform' : 'translateY(0)', | |
opacity : 1 | |
} | |
}, | |
to : { | |
top : '20%', | |
opacity : 0, | |
CSS3 : { | |
'*transform' : 'translateY(-200px)', | |
opacity : 0 | |
} | |
}, | |
onStart : function() { | |
console.log("a"); | |
} | |
}, | |
{ | |
element : '#akd_logo', | |
duration : 2000, | |
timing : 'easeOutBack', | |
from : { | |
top : '80%', | |
opacity : 0, | |
CSS3 : { | |
'*transform' : 'translateY(200px)', | |
opacity : 0 | |
} | |
}, | |
to : { | |
top : '50%', | |
opacity : 1, | |
CSS3 : { | |
'*transform' : 'translateY(0)', | |
opacity : 1 | |
} | |
}, | |
onStart : function(){ | |
console.log("b"); | |
} | |
} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment