move.js 运动插件是一款针对元素动画效果的插件。可以运用此插件制作出各类元素效果。
插件GitHub地址:https://github.com/visionmedia/move.js
下面整理学习心得:
一、move.js原码:
;(function(){ /**
* Require the module at `name`.
*
* @param {String} name
* @return {Object} exports
* @api public
*/ function require(name) {
var module = require.modules[name];
if (!module) throw new Error('failed to require "' + name + '"'); if (!('exports' in module) && typeof module.definition === 'function') {
module.client = module.component = true;
module.definition.call(this, module.exports = {}, module);
delete module.definition;
} return module.exports;
} /**
* Meta info, accessible in the global scope unless you use AMD option.
*/ require.loader = 'component'; /**
* Internal helper object, contains a sorting function for semantiv versioning
*/
require.helper = {};
require.helper.semVerSort = function(a, b) {
var aArray = a.version.split('.');
var bArray = b.version.split('.');
for (var i=0; i<aArray.length; ++i) {
var aInt = parseInt(aArray[i], 10);
var bInt = parseInt(bArray[i], 10);
if (aInt === bInt) {
var aLex = aArray[i].substr((""+aInt).length);
var bLex = bArray[i].substr((""+bInt).length);
if (aLex === '' && bLex !== '') return 1;
if (aLex !== '' && bLex === '') return -1;
if (aLex !== '' && bLex !== '') return aLex > bLex ? 1 : -1;
continue;
} else if (aInt > bInt) {
return 1;
} else {
return -1;
}
}
return 0;
} /**
* Find and require a module which name starts with the provided name.
* If multiple modules exists, the highest semver is used.
* This function can only be used for remote dependencies. * @param {String} name - module name: `user~repo`
* @param {Boolean} returnPath - returns the canonical require path if true,
* otherwise it returns the epxorted module
*/
require.latest = function (name, returnPath) {
function showError(name) {
throw new Error('failed to find latest module of "' + name + '"');
}
// only remotes with semvers, ignore local files conataining a '/'
var versionRegexp = /(.*)~(.*)@v?(\d+\.\d+\.\d+[^\/]*)$/;
var remoteRegexp = /(.*)~(.*)/;
if (!remoteRegexp.test(name)) showError(name);
var moduleNames = Object.keys(require.modules);
var semVerCandidates = [];
var otherCandidates = []; // for instance: name of the git branch
for (var i=0; i<moduleNames.length; i++) {
var moduleName = moduleNames[i];
if (new RegExp(name + '@').test(moduleName)) {
var version = moduleName.substr(name.length+1);
var semVerMatch = versionRegexp.exec(moduleName);
if (semVerMatch != null) {
semVerCandidates.push({version: version, name: moduleName});
} else {
otherCandidates.push({version: version, name: moduleName});
}
}
}
if (semVerCandidates.concat(otherCandidates).length === 0) {
showError(name);
}
if (semVerCandidates.length > 0) {
var module = semVerCandidates.sort(require.helper.semVerSort).pop().name;
if (returnPath === true) {
return module;
}
return require(module);
}
// if the build contains more than one branch of the same module
// you should not use this funciton
var module = otherCandidates.sort(function(a, b) {return a.name > b.name})[0].name;
if (returnPath === true) {
return module;
}
return require(module);
} /**
* Registered modules.
*/ require.modules = {}; /**
* Register module at `name` with callback `definition`.
*
* @param {String} name
* @param {Function} definition
* @api private
*/ require.register = function (name, definition) {
require.modules[name] = {
definition: definition
};
}; /**
* Define a module's exports immediately with `exports`.
*
* @param {String} name
* @param {Generic} exports
* @api private
*/ require.define = function (name, exports) {
require.modules[name] = {
exports: exports
};
};
require.register("component~transform-property@0.0.1", function (exports, module) { var styles = [
'webkitTransform',
'MozTransform',
'msTransform',
'OTransform',
'transform'
]; var el = document.createElement('p');
var style; for (var i = 0; i < styles.length; i++) {
style = styles[i];
if (null != el.style[style]) {
module.exports = style;
break;
}
} }); require.register("component~has-translate3d@0.0.3", function (exports, module) { var prop = require('component~transform-property@0.0.1'); // IE <=8 doesn't have `getComputedStyle`
if (!prop || !window.getComputedStyle) {
module.exports = false; } else {
var map = {
webkitTransform: '-webkit-transform',
OTransform: '-o-transform',
msTransform: '-ms-transform',
MozTransform: '-moz-transform',
transform: 'transform'
}; // from: https://gist.github.com/lorenzopolidori/3794226
var el = document.createElement('div');
el.style[prop] = 'translate3d(1px,1px,1px)';
document.body.insertBefore(el, null);
var val = getComputedStyle(el).getPropertyValue(map[prop]);
document.body.removeChild(el);
module.exports = null != val && val.length && 'none' != val;
} }); require.register("yields~has-transitions@1.0.0", function (exports, module) {
/**
* Check if `el` or browser supports transitions.
*
* @param {Element} el
* @return {Boolean}
* @api public
*/ exports = module.exports = function(el){
switch (arguments.length) {
case 0: return bool;
case 1: return bool
? transitions(el)
: bool;
}
}; /**
* Check if the given `el` has transitions.
*
* @param {Element} el
* @return {Boolean}
* @api private
*/ function transitions(el, styl){
if (el.transition) return true;
styl = window.getComputedStyle(el);
return !! parseFloat(styl.transitionDuration, 10);
} /**
* Style.
*/ var styl = document.body.style; /**
* Export support.
*/ var bool = 'transition' in styl
|| 'webkitTransition' in styl
|| 'MozTransition' in styl
|| 'msTransition' in styl; }); require.register("component~event@0.1.4", function (exports, module) {
var bind = window.addEventListener ? 'addEventListener' : 'attachEvent',
unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
prefix = bind !== 'addEventListener' ? 'on' : ''; /**
* Bind `el` event `type` to `fn`.
*
* @param {Element} el
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @return {Function}
* @api public
*/ exports.bind = function(el, type, fn, capture){
el[bind](prefix + type, fn, capture || false);
return fn;
}; /**
* Unbind `el` event `type`'s callback `fn`.
*
* @param {Element} el
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @return {Function}
* @api public
*/ exports.unbind = function(el, type, fn, capture){
el[unbind](prefix + type, fn, capture || false);
return fn;
};
}); require.register("ecarter~css-emitter@0.0.1", function (exports, module) {
/**
* Module Dependencies
*/ var events = require('component~event@0.1.4'); // CSS events var watch = [
'transitionend'
, 'webkitTransitionEnd'
, 'oTransitionEnd'
, 'MSTransitionEnd'
, 'animationend'
, 'webkitAnimationEnd'
, 'oAnimationEnd'
, 'MSAnimationEnd'
]; /**
* Expose `CSSnext`
*/ module.exports = CssEmitter; /**
* Initialize a new `CssEmitter`
*
*/ function CssEmitter(element){
if (!(this instanceof CssEmitter)) return new CssEmitter(element);
this.el = element;
} /**
* Bind CSS events.
*
* @api public
*/ CssEmitter.prototype.bind = function(fn){
for (var i=0; i < watch.length; i++) {
events.bind(this.el, watch[i], fn);
}
return this;
}; /**
* Unbind CSS events
*
* @api public
*/ CssEmitter.prototype.unbind = function(fn){
for (var i=0; i < watch.length; i++) {
events.unbind(this.el, watch[i], fn);
}
return this;
}; /**
* Fire callback only once
*
* @api public
*/ CssEmitter.prototype.once = function(fn){
var self = this;
function on(){
self.unbind(on);
fn.apply(self.el, arguments);
}
self.bind(on);
return this;
}; }); require.register("component~once@0.0.1", function (exports, module) { /**
* Identifier.
*/ var n = 0; /**
* Global.
*/ var global = (function(){ return this })(); /**
* Make `fn` callable only once.
*
* @param {Function} fn
* @return {Function}
* @api public
*/ module.exports = function(fn) {
var id = n++; function once(){
// no receiver
if (this == global) {
if (once.called) return;
once.called = true;
return fn.apply(this, arguments);
} // receiver
var key = '__called_' + id + '__';
if (this[key]) return;
this[key] = true;
return fn.apply(this, arguments);
} return once;
}; }); require.register("yields~after-transition@0.0.1", function (exports, module) { /**
* dependencies
*/ var has = require('yields~has-transitions@1.0.0')
, emitter = require('ecarter~css-emitter@0.0.1')
, once = require('component~once@0.0.1'); /**
* Transition support.
*/ var supported = has(); /**
* Export `after`
*/ module.exports = after; /**
* Invoke the given `fn` after transitions
*
* It will be invoked only if the browser
* supports transitions __and__
* the element has transitions
* set in `.style` or css.
*
* @param {Element} el
* @param {Function} fn
* @return {Function} fn
* @api public
*/ function after(el, fn){
if (!supported || !has(el)) return fn();
emitter(el).bind(fn);
return fn;
}; /**
* Same as `after()` only the function is invoked once.
*
* @param {Element} el
* @param {Function} fn
* @return {Function}
* @api public
*/ after.once = function(el, fn){
var callback = once(fn);
after(el, fn = function(){
emitter(el).unbind(fn);
callback();
});
}; }); require.register("component~emitter@1.2.0", function (exports, module) { /**
* Expose `Emitter`.
*/ module.exports = Emitter; /**
* Initialize a new `Emitter`.
*
* @api public
*/ function Emitter(obj) {
if (obj) return mixin(obj);
}; /**
* Mixin the emitter properties.
*
* @param {Object} obj
* @return {Object}
* @api private
*/ function mixin(obj) {
for (var key in Emitter.prototype) {
obj[key] = Emitter.prototype[key];
}
return obj;
} /**
* Listen on the given `event` with `fn`.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/ Emitter.prototype.on =
Emitter.prototype.addEventListener = function(event, fn){
this._callbacks = this._callbacks || {};
(this._callbacks['$' + event] = this._callbacks['$' + event] || [])
.push(fn);
return this;
}; /**
* Adds an `event` listener that will be invoked a single
* time then automatically removed.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/ Emitter.prototype.once = function(event, fn){
function on() {
this.off(event, on);
fn.apply(this, arguments);
} on.fn = fn;
this.on(event, on);
return this;
}; /**
* Remove the given callback for `event` or all
* registered callbacks.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/ Emitter.prototype.off =
Emitter.prototype.removeListener =
Emitter.prototype.removeAllListeners =
Emitter.prototype.removeEventListener = function(event, fn){
this._callbacks = this._callbacks || {}; // all
if (0 == arguments.length) {
this._callbacks = {};
return this;
} // specific event
var callbacks = this._callbacks['$' + event];
if (!callbacks) return this; // remove all handlers
if (1 == arguments.length) {
delete this._callbacks['$' + event];
return this;
} // remove specific handler
var cb;
for (var i = 0; i < callbacks.length; i++) {
cb = callbacks[i];
if (cb === fn || cb.fn === fn) {
callbacks.splice(i, 1);
break;
}
}
return this;
}; /**
* Emit `event` with the given args.
*
* @param {String} event
* @param {Mixed} ...
* @return {Emitter}
*/ Emitter.prototype.emit = function(event){
this._callbacks = this._callbacks || {};
var args = [].slice.call(arguments, 1)
, callbacks = this._callbacks['$' + event]; if (callbacks) {
callbacks = callbacks.slice(0);
for (var i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
}
} return this;
}; /**
* Return array of callbacks for `event`.
*
* @param {String} event
* @return {Array}
* @api public
*/ Emitter.prototype.listeners = function(event){
this._callbacks = this._callbacks || {};
return this._callbacks['$' + event] || [];
}; /**
* Check if this emitter has `event` handlers.
*
* @param {String} event
* @return {Boolean}
* @api public
*/ Emitter.prototype.hasListeners = function(event){
return !! this.listeners(event).length;
}; }); require.register("yields~css-ease@0.0.1", function (exports, module) { /**
* CSS Easing functions
*/ module.exports = {
'in': 'ease-in'
, 'out': 'ease-out'
, 'in-out': 'ease-in-out'
, 'snap': 'cubic-bezier(0,1,.5,1)'
, 'linear': 'cubic-bezier(0.250, 0.250, 0.750, 0.750)'
, 'ease-in-quad': 'cubic-bezier(0.550, 0.085, 0.680, 0.530)'
, 'ease-in-cubic': 'cubic-bezier(0.550, 0.055, 0.675, 0.190)'
, 'ease-in-quart': 'cubic-bezier(0.895, 0.030, 0.685, 0.220)'
, 'ease-in-quint': 'cubic-bezier(0.755, 0.050, 0.855, 0.060)'
, 'ease-in-sine': 'cubic-bezier(0.470, 0.000, 0.745, 0.715)'
, 'ease-in-expo': 'cubic-bezier(0.950, 0.050, 0.795, 0.035)'
, 'ease-in-circ': 'cubic-bezier(0.600, 0.040, 0.980, 0.335)'
, 'ease-in-back': 'cubic-bezier(0.600, -0.280, 0.735, 0.045)'
, 'ease-out-quad': 'cubic-bezier(0.250, 0.460, 0.450, 0.940)'
, 'ease-out-cubic': 'cubic-bezier(0.215, 0.610, 0.355, 1.000)'
, 'ease-out-quart': 'cubic-bezier(0.165, 0.840, 0.440, 1.000)'
, 'ease-out-quint': 'cubic-bezier(0.230, 1.000, 0.320, 1.000)'
, 'ease-out-sine': 'cubic-bezier(0.390, 0.575, 0.565, 1.000)'
, 'ease-out-expo': 'cubic-bezier(0.190, 1.000, 0.220, 1.000)'
, 'ease-out-circ': 'cubic-bezier(0.075, 0.820, 0.165, 1.000)'
, 'ease-out-back': 'cubic-bezier(0.175, 0.885, 0.320, 1.275)'
, 'ease-out-quad': 'cubic-bezier(0.455, 0.030, 0.515, 0.955)'
, 'ease-out-cubic': 'cubic-bezier(0.645, 0.045, 0.355, 1.000)'
, 'ease-in-out-quart': 'cubic-bezier(0.770, 0.000, 0.175, 1.000)'
, 'ease-in-out-quint': 'cubic-bezier(0.860, 0.000, 0.070, 1.000)'
, 'ease-in-out-sine': 'cubic-bezier(0.445, 0.050, 0.550, 0.950)'
, 'ease-in-out-expo': 'cubic-bezier(1.000, 0.000, 0.000, 1.000)'
, 'ease-in-out-circ': 'cubic-bezier(0.785, 0.135, 0.150, 0.860)'
, 'ease-in-out-back': 'cubic-bezier(0.680, -0.550, 0.265, 1.550)'
}; }); require.register("component~query@0.0.3", function (exports, module) {
function one(selector, el) {
return el.querySelector(selector);
} exports = module.exports = function(selector, el){
el = el || document;
return one(selector, el);
}; exports.all = function(selector, el){
el = el || document;
return el.querySelectorAll(selector);
}; exports.engine = function(obj){
if (!obj.one) throw new Error('.one callback required');
if (!obj.all) throw new Error('.all callback required');
one = obj.one;
exports.all = obj.all;
return exports;
}; }); require.register("move", function (exports, module) {
/**
* Module Dependencies.
*/ var Emitter = require('component~emitter@1.2.0');
var query = require('component~query@0.0.3');
var after = require('yields~after-transition@0.0.1');
var has3d = require('component~has-translate3d@0.0.3');
var ease = require('yields~css-ease@0.0.1'); /**
* CSS Translate
*/ var translate = has3d
? ['translate3d(', ', 0)']
: ['translate(', ')']; /**
* Export `Move`
*/ module.exports = Move; /**
* Get computed style.
*/ var style = window.getComputedStyle
|| window.currentStyle; /**
* Library version.
*/ Move.version = '0.5.0'; /**
* Export `ease`
*/ Move.ease = ease; /**
* Defaults.
*
* `duration` - default duration of 500ms
*
*/ Move.defaults = {
duration: 500
}; /**
* Default element selection utilized by `move(selector)`.
*
* Override to implement your own selection, for example
* with jQuery one might write:
*
* move.select = function(selector) {
* return jQuery(selector).get(0);
* };
*
* @param {Object|String} selector
* @return {Element}
* @api public
*/ Move.select = function(selector){
if ('string' != typeof selector) return selector;
return query(selector);
}; /**
* Initialize a new `Move` with the given `el`.
*
* @param {Element} el
* @api public
*/ function Move(el) {
if (!(this instanceof Move)) return new Move(el);
if ('string' == typeof el) el = query(el);
if (!el) throw new TypeError('Move must be initialized with element or selector');
this.el = el;
this._props = {};
this._rotate = 0;
this._transitionProps = [];
this._transforms = [];
this.duration(Move.defaults.duration)
}; /**
* Inherit from `EventEmitter.prototype`.
*/ Emitter(Move.prototype); /**
* Buffer `transform`.
*
* @param {String} transform
* @return {Move} for chaining
* @api private
*/ Move.prototype.transform = function(transform){
this._transforms.push(transform);
return this;
}; /**
* Skew `x` and `y`.
*
* @param {Number} x
* @param {Number} y
* @return {Move} for chaining
* @api public
*/ Move.prototype.skew = function(x, y){
return this.transform('skew('
+ x + 'deg, '
+ (y || 0)
+ 'deg)');
}; /**
* Skew x by `n`.
*
* @param {Number} n
* @return {Move} for chaining
* @api public
*/ Move.prototype.skewX = function(n){
return this.transform('skewX(' + n + 'deg)');
}; /**
* Skew y by `n`.
*
* @param {Number} n
* @return {Move} for chaining
* @api public
*/ Move.prototype.skewY = function(n){
return this.transform('skewY(' + n + 'deg)');
}; /**
* Translate `x` and `y` axis.
*
* @param {Number} x
* @param {Number} y
* @return {Move} for chaining
* @api public
*/ Move.prototype.translate =
Move.prototype.to = function(x, y){
return this.transform(translate.join(''
+ x +'px, '
+ (y || 0)
+ 'px'));
}; /**
* Translate on the x axis to `n`.
*
* @param {Number} n
* @return {Move} for chaining
* @api public
*/ Move.prototype.translateX =
Move.prototype.x = function(n){
return this.transform('translateX(' + n + 'px)');
}; /**
* Translate on the y axis to `n`.
*
* @param {Number} n
* @return {Move} for chaining
* @api public
*/ Move.prototype.translateY =
Move.prototype.y = function(n){
return this.transform('translateY(' + n + 'px)');
}; /**
* Scale the x and y axis by `x`, or
* individually scale `x` and `y`.
*
* @param {Number} x
* @param {Number} y
* @return {Move} for chaining
* @api public
*/ Move.prototype.scale = function(x, y){
return this.transform('scale('
+ x + ', '
+ (y || x)
+ ')');
}; /**
* Scale x axis by `n`.
*
* @param {Number} n
* @return {Move} for chaining
* @api public
*/ Move.prototype.scaleX = function(n){
return this.transform('scaleX(' + n + ')')
}; /**
* Apply a matrix transformation
*
* @param {Number} m11 A matrix coefficient
* @param {Number} m12 A matrix coefficient
* @param {Number} m21 A matrix coefficient
* @param {Number} m22 A matrix coefficient
* @param {Number} m31 A matrix coefficient
* @param {Number} m32 A matrix coefficient
* @return {Move} for chaining
* @api public
*/ Move.prototype.matrix = function(m11, m12, m21, m22, m31, m32){
return this.transform('matrix(' + [m11,m12,m21,m22,m31,m32].join(',') + ')');
}; /**
* Scale y axis by `n`.
*
* @param {Number} n
* @return {Move} for chaining
* @api public
*/ Move.prototype.scaleY = function(n){
return this.transform('scaleY(' + n + ')')
}; /**
* Rotate `n` degrees.
*
* @param {Number} n
* @return {Move} for chaining
* @api public
*/ Move.prototype.rotate = function(n){
return this.transform('rotate(' + n + 'deg)');
}; /**
* Set transition easing function to to `fn` string.
*
* When:
*
* - null "ease" is used
* - "in" "ease-in" is used
* - "out" "ease-out" is used
* - "in-out" "ease-in-out" is used
*
* @param {String} fn
* @return {Move} for chaining
* @api public
*/ Move.prototype.ease = function(fn){
fn = ease[fn] || fn || 'ease';
return this.setVendorProperty('transition-timing-function', fn);
}; /**
* Set animation properties
*
* @param {String} name
* @param {Object} props
* @return {Move} for chaining
* @api public
*/ Move.prototype.animate = function(name, props){
for (var i in props){
if (props.hasOwnProperty(i)){
this.setVendorProperty('animation-' + i, props[i])
}
}
return this.setVendorProperty('animation-name', name);
} /**
* Set duration to `n`.
*
* @param {Number|String} n
* @return {Move} for chaining
* @api public
*/ Move.prototype.duration = function(n){
n = this._duration = 'string' == typeof n
? parseFloat(n) * 1000
: n;
return this.setVendorProperty('transition-duration', n + 'ms');
}; /**
* Delay the animation by `n`.
*
* @param {Number|String} n
* @return {Move} for chaining
* @api public
*/ Move.prototype.delay = function(n){
n = 'string' == typeof n
? parseFloat(n) * 1000
: n;
return this.setVendorProperty('transition-delay', n + 'ms');
}; /**
* Set `prop` to `val`, deferred until `.end()` is invoked.
*
* @param {String} prop
* @param {String} val
* @return {Move} for chaining
* @api public
*/ Move.prototype.setProperty = function(prop, val){
this._props[prop] = val;
return this;
}; /**
* Set a vendor prefixed `prop` with the given `val`.
*
* @param {String} prop
* @param {String} val
* @return {Move} for chaining
* @api public
*/ Move.prototype.setVendorProperty = function(prop, val){
this.setProperty('-webkit-' + prop, val);
this.setProperty('-moz-' + prop, val);
this.setProperty('-ms-' + prop, val);
this.setProperty('-o-' + prop, val);
return this;
}; /**
* Set `prop` to `value`, deferred until `.end()` is invoked
* and adds the property to the list of transition props.
*
* @param {String} prop
* @param {String} val
* @return {Move} for chaining
* @api public
*/ Move.prototype.set = function(prop, val){
if (typeof prop == "object") {
for (var key in prop) {
if (prop.hasOwnProperty(key)) {
this.transition(key);
this._props[key] = prop[key];
}
}
} else {
this.transition(prop);
this._props[prop] = val;
}
return this;
}; /**
* Increment `prop` by `val`, deferred until `.end()` is invoked
* and adds the property to the list of transition props.
*
* @param {String} prop
* @param {Number} val
* @return {Move} for chaining
* @api public
*/ Move.prototype.add = function(prop, val){
if (!style) return;
var self = this;
return this.on('start', function(){
var curr = parseInt(self.current(prop), 10);
self.set(prop, curr + val + 'px');
});
}; /**
* Decrement `prop` by `val`, deferred until `.end()` is invoked
* and adds the property to the list of transition props.
*
* @param {String} prop
* @param {Number} val
* @return {Move} for chaining
* @api public
*/ Move.prototype.sub = function(prop, val){
if (!style) return;
var self = this;
return this.on('start', function(){
var curr = parseInt(self.current(prop), 10);
self.set(prop, curr - val + 'px');
});
}; /**
* Get computed or "current" value of `prop`.
*
* @param {String} prop
* @return {String}
* @api public
*/ Move.prototype.current = function(prop){
return style(this.el).getPropertyValue(prop);
}; /**
* Add `prop` to the list of internal transition properties.
*
* @param {String} prop
* @return {Move} for chaining
* @api private
*/ Move.prototype.transition = function(prop){
if (!this._transitionProps.indexOf(prop)) return this;
this._transitionProps.push(prop);
return this;
}; /**
* Commit style properties, aka apply them to `el.style`.
*
* @return {Move} for chaining
* @see Move#end()
* @api private
*/ Move.prototype.applyProperties = function(){
for (var prop in this._props) {
this.el.style.setProperty(prop, this._props[prop], '');
}
return this;
}; /**
* Re-select element via `selector`, replacing
* the current element.
*
* @param {String} selector
* @return {Move} for chaining
* @api public
*/ Move.prototype.move =
Move.prototype.select = function(selector){
this.el = Move.select(selector);
return this;
}; /**
* Defer the given `fn` until the animation
* is complete. `fn` may be one of the following:
*
* - a function to invoke
* - an instanceof `Move` to call `.end()`
* - nothing, to return a clone of this `Move` instance for chaining
*
* @param {Function|Move} fn
* @return {Move} for chaining
* @api public
*/ Move.prototype.then = function(fn){
// invoke .end()
if (fn instanceof Move) {
this.on('end', function(){
fn.end();
});
// callback
} else if ('function' == typeof fn) {
this.on('end', fn);
// chain
} else {
var clone = new Move(this.el);
clone._transforms = this._transforms.slice(0);
this.then(clone);
clone.parent = this;
return clone;
} return this;
}; /**
* Pop the move context.
*
* @return {Move} parent Move
* @api public
*/ Move.prototype.pop = function(){
return this.parent;
}; /**
* Reset duration.
*
* @return {Move}
* @api public
*/ Move.prototype.reset = function(){
this.el.style.webkitTransitionDuration =
this.el.style.mozTransitionDuration =
this.el.style.msTransitionDuration =
this.el.style.oTransitionDuration = '';
return this;
}; /**
* Start animation, optionally calling `fn` when complete.
*
* @param {Function} fn
* @return {Move} for chaining
* @api public
*/ Move.prototype.end = function(fn){
var self = this; // emit "start" event
this.emit('start'); // transforms
if (this._transforms.length) {
this.setVendorProperty('transform', this._transforms.join(' '));
} // transition properties
this.setVendorProperty('transition-properties', this._transitionProps.join(', '));
this.applyProperties(); // callback given
if (fn) this.then(fn); // emit "end" when complete
after.once(this.el, function(){
self.reset();
self.emit('end');
}); return this;
}; }); if (typeof exports == "object") {
module.exports = require("move");
} else if (typeof define == "function" && define.amd) {
define("move", [], function(){ return require("move"); });
} else {
(this || window)["move"] = require("move");
}
})()
二、基础调用方式:
<script>
move( $('#moveId') ) // $('#moveId') 要执行动画的元素对象
.set('margin-left', '200px') // 要将元素左偏移到200像素
.end( function(){ // end 是执行完成之后的回调函数,可选
console.log('动画执行完成');
});
</script>
1) move( $obj ) 返回动画的move实例。
2) .set... 定义动画效果行为
3) .end... 执行动画。如果没有此语句,动画不会被执行,比如下例:
// 定义动画对象
var $Obj = move( $('#role') )
.set('margin-left', '200px'); // 没有下面一句,动画不会被执行
$Obj.end();
三、move.js 函数方法说明:
1) .set方法用于设置动画元素的CSS样式,示例:
$Obj.set('margin-left', '200px'); // 正确
$Obj.set('margin-left', 200); // 错误,请转换成 200PX,才能出现动画效果
在上例中,将动画元素左偏移到200像素的位置。
2) .add方法将元素的某一属性值递增,示例:
$Obj.add('margin-left', 10); // 参数2必需是数值!
在上例中,每执行一次动画元素会在当前位置基础上向左偏移10像素。
3).sub方法和add类似,不过他是递增属性值,示例:
$Obj.sub('margin-left', 10); // 参数2必需是数值!
在上例中,每执行一次动画元素会在当前位置基础上向右偏移10像素。
4) .rotate(数值),将元素旋转指定的角度,示例:
$Obj.rotate(30);
在上例中,将动画元素旋转30度。
5).duration(数值或字符),设置动画过程所消耗的时间,比如: 2000 或 2s,示例:
$Obj.duration(2000); // 或者 $Obj.duration('2s');
在上例中,将动画开始执行到结束所耗时间为2秒钟
6) .to(x[,y]) 或.translate(x[,y]) 这二个函数功能相同,都是将动画元素移动到指定的坐标处。(当前动画元素左上角为坐标原点),示例:
$Obj.translate(500, 200); // 等同于$Obj.to(500, 200);
$Obj.translate(500); // 等同于$Obj.to(500); Y坐标可以省略,表不Y坐标不变
在上例中,将动画元素移动到坐标(500,200)处。
7) translateX(值)、translateY(值)、x(值)、y(值),这四个函数功能相似,都是将动画元素移动到指定的坐标处。示例:
$Obj.translateX(500);
$Obj.x(500);
$Obj.translateY(200);
$Obj.y(200);
8) .skew(x[, y])、.skewX(值) 、.skewY(值) 将动画元素斜切,具体设置同translate类似。
9) .scale(x[, y])、.scaleX(值)、.scaleY(值)将动画元素放大或缩小指定的倍数,具体设置同translate类似。
10) .ease( in|out|in-out|snap|cubic-bezeir ) 定义动画过渡行为,可选值:
in 以慢速开始
out 以慢速结束
in-out 以慢速开始,以慢速结束
snap
cubic-bezeir(n,n,n,n) 贝塞尔曲线,n值在0-1之间
11) .delay(数字或字符) 动画延迟执行设置,设置同 duration
12) .then( $moveObj ) 这个函数用于分割动画,并按指定顺序执行。 then如果带了参数,表示该动画执行完,就执行 $moveObj的动画效果。
13) .pop() 用于每段动画阶段中,如果不加入该函数,会直接跳到最终动画效果。省略中间的动画效果,直接到结尾动画
文字解释难以表述清楚,就以官网示例,结合心德做一个诠释:
<!DOCTYPE html>
<html>
<head>
<title>Move.js - CSS3 animation framework for JavaScript</title>
<style>
body {
padding: 50px;
font: 14px/1.5 "helvetica neue", helvetica, arial, sans-serif;
color: #8b8b8b;
}
h1, h2, h3 {
font-size: 33px;
font-weight: normal;
color: #333;
-webkit-font-smoothing: antialiased;
}
h2 {
display: none;
font-size: 33px;
}
h3 {
padding: 5px 0;
font-size: 18px;
border-bottom: 3px solid #eee;
}
.box {
margin: 5px;
border: 1px solid #888;
font-size: 11px;
text-align: center;
line-height: 50px;
}
.small {
width: 50px;
height: 50px;
}
a {
color: #00B5E2;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
.sandbox {
margin: 10px 0;
padding: 5px;
border: 1px solid #eee;
}
.source {
font-family: monaco, monospace;
font-size: 12px;
color: #999;
}
.example p {
color: #333;
}
.example p code {
color: #999;
padding: 2px 5px;
border: 1px solid #eee;
-webkit-border-radius: 3px;
}
#example-1 .box,
#example-2 .box,
#example-3 .box {
margin-left: 0px;
}
@-moz-keyframes bgchange {
from {
background: green;
} to {
background: black;
}
}
@-webkit-keyframes bgchange {
from {
background: green;
} to {
background: black;
}
}
</style>
</head>
<body>
<h1>Move.js</h1>
<p>此文档非商用仅作学习使用,原文档略有修改!</p> <h2>Examples</h2> <div id="examples">
<div id="example-1" class="example">
<h3>.set(prop, val)</h3>
<p>设置动画元素样式,点击下方Play会使元素向右偏移200像素!</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
</div>
<pre class="source">
<code>
move('#example-1 .box')
.set('margin-left', '200px')
.end();
</code>
</pre>
</div> <div id="example-2" class="example">
<h3>.add(prop, val)</h3>
<p>将元素的某一属性值递增,参数val必须是数值类型!每点击下方Play,小方框会在当前位置处向右移200像素</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
</div>
<pre class="source">
<code>
move('#example-2 .box')
.add('margin-left', 200)
.end();
</code>
</pre>
</div> <div id="example-3" class="example">
<h3>.sub(prop, val)</h3>
<p>和add相反, 将元素的某一属性值递减,参数val必须是数值类型!每点击下方Play,小方框会在当前位置处向左移10像素</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
</div>
<pre class="source">
<code>
move('#example-3 .box')
.sub('margin-left', 10)
.end();
</code>
</pre>
</div> <div id="example-4" class="example">
<h3>.rotate(deg)</h3>
<p>旋转指定的角度</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
</div>
<pre class="source">
<code>
move('#example-4 .box')
.rotate(140)
.end();
</code>
</pre>
</div> <div id="example-5" class="example">
<h3>.duration(n)</h3>
<p>设置动画过程所消耗的时间,比如:2000或2s。</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
</div>
<pre class="source">
<code>
move('#example-5 .box')
.set('background-color', 'blue')
.duration('2s')
.end();
</code>
</pre>
</div> <div id="example-6" class="example">
<h3>.translate(x[, y]) 或者 .to(x[, y])</h3>
<p>将动画元素移动到指定的坐标处。(当前动画元素左上角为坐标原点)</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
</div>
<pre class="source">
<code>
move('#example-6 .box')
.translate(300, 80)
.end();
</code>
</pre>
</div> <div id="example-7" class="example">
<h3>.x(n) / .y(n) 或者 translateX(n) / translateY(n) </h3>
<p>将动画元素移动到指定的坐标处</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
</div>
<pre class="source">
<code>
move('#example-7 .box')
.x(300)
.y(20)
.end();
</code>
</pre>
</div> <div id="example-8" class="example">
<h3>.skew(x[, y]) / .skewX(n) / .skewY(n)</h3>
<p>将动画元素按X或Y轴斜切指定的角度</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
</div>
<pre class="source">
<code>
move('#example-8 .box')
.x(300)
.skew(50)
.set('height', 20)
.end();
</code>
</pre>
</div> <div id="example-9" class="example">
<h3>.scale(x[, y]) / .scaleX(n) / .scaleY(n)</h3>
<p>将动画元素指定轴放大或缩小指定的倍数</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
</div>
<pre class="source">
<code>
move('#example-9 .box')
.scale(3)
.end();
</code>
</pre>
</div> <div id="example-10" class="example">
<h3>.ease(fn)</h3>
<p>定义动画过渡行为</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box box1 small">default</div>
<div class="box box2 small" title="以慢速开始">in</div>
<div class="box box3 small" title="以慢速结束">out</div>
<div class="box box4 small" title="以慢速开始,以慢速结束">in-out</div>
<div class="box box5 small">snap</div>
<div class="box box6 small" title="贝塞尔曲线,n值在0-1之间">(0,1,1,0)</div>
</div>
<pre class="source">
<code>
move('#example-10 .box1').x(400).end();
move('#example-10 .box2').ease('in').x(400).end();
move('#example-10 .box3').ease('out').x(400).end();
move('#example-10 .box4').ease('in-out').x(400).end();
move('#example-10 .box5').ease('snap').x(400).end();
move('#example-10 .box6').ease('cubic-bezier(0,1,1,0)').x(400).end(); setTimeout(function(){
move('#example-10 .box1').x(0).end();
move('#example-10 .box2').x(0).end();
move('#example-10 .box3').x(0).end();
move('#example-10 .box4').x(0).end();
move('#example-10 .box5').x(0).end();
move('#example-10 .box6').x(0).end();
}, 1200);
</code>
</pre>
</div> <div id="example-11" class="example">
<h3>.end([fn])</h3>
<p>触发动画播放,可选择在完成时调用回调fn。</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
</div>
<pre class="source">
<code>
move('#example-11 .box')
.set('background-color', 'red')
.duration(1000)
.end(function(){
move('#example-11 .box')
.set('background-color', 'white')
.end();
});
</code>
</pre> </div> <div id="example-12" class="example">
<h3>.delay(n)</h3>
<p>设置动画延迟执行,比如 2000 或 2s</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
</div>
<pre class="source">
<code>
move('#example-12 .box')
.set('background-color', 'blue')
.delay('2s')
.end();
</code>
</pre>
</div> <div id="example-13" class="example">
<h3>.then([fn])</h3>
<p>分割动画为两个集合,并按顺序执行。</p>
<a href="#" class="play">Play</a>
<div class="sandbox">
<div class="box small"></div>
<div class="box box2 small"></div>
</div>
<pre class="source">
<code>
var moveBack = move('#example-13 .box')
.set('background-color', 'white')
.x(0); move('#example-13 .box')
.set('background-color', 'red')
.x(500)
.then(moveBack)
.end(); move('#example-13 .box2')
.set('background-color', 'red')
.x(500)
.scale(.5)
.rotate(60)
.then()
.rotate(30)
.scale(1.5)
.set('border-radius', 5)
.set('background-color', 'white')
.then()
.set('opacity', 0)
.pop()
.pop()
.end();
</code>
</pre>
</div> <div id="example-16" class="example">
<h3 style="font-weight:bold;">扩展</h3>
<p style="font-weight:bold;color:red;">.animate('CSS动画名', json) 调用一个CSS动画</p>
<a href="#" class="play">play</a>
<div class="sandbox">
<div class="box small">1</div>
</div>
<pre class="source">
<code>
// 下面是CSS样式中定义的动画,动画名称为: bgchange
@-moz-keyframes bgchange {
from {
background: green;
} to {
background: black;
}
}
@-webkit-keyframes bgchange {
from {
background: green;
} to {
background: black;
}
} // 下面是调用代码
move('#example-16 .box').animate('bgchange', {
duration: '4s',
'iteration-count': 'infinite'
}).end();
</code>
</pre>
</div> <div id="example-17" class="example">
<p style="font-weight:bold;color:red;">如何定义无限循环的动画效果</p>
<a href="#">1、使用 .animate 函数(上例中已说明)</a><br/>
<a href="#" class="play">2、利用 end( fn ) 中的fn不停的循环某一动画效果,点击播放示例:(代码理论可行,实际运行会卡死浏览器)</a>
<div class="sandbox">
<div class="box small">1</div>
</div>
<pre>
var $m1 = move('#example-17 .box')
.set('background', '#ccc')
.duration('3s'); $m2 = move('#example-17 .box')
.set('background', '#F60')
.duration('3s')
.end( function(){
$m1.end( $m2 );
});
</pre>
</div> <div id="example-14" class="example">
<h3>BUG-1:</h3>
<p style="font-weight:bold;color:red;">当定义多个动画时,某一动画过程不显示,怎么处理? </p>
<a href="#" class="play">点击观看BUG现象:(当第二个动画时,直接跳到结束状态)</a>
<div class="sandbox">
<div class="box small">1</div>
</div>
<pre class="source">
<code>
move('#example-14 .box')
.set('background-color', 'red')
.x(500)
.then()
.set('background-color', 'white')
.x(0)
.pop()
.end();
</code>
</pre>
</div> <div id="example-15" class="example">
<p style="font-weight:bold;color:red;">解决方案:使用.delay方法解决动画不显示问题! </p>
<a href="#" class="play">点击查看效果</a>
<div class="sandbox">
<div class="box small">2</div>
</div>
<pre class="source">
<code>
move('#example-15 .box2')
.set('background-color', 'red')
.x(500)
.then()
.delay(1)
.set('background-color', 'white')
.x(0)
.pop()
.end();
</code>
</pre>
</div> <script src="../move.js"></script>
<script> function $(selector) {
return document.querySelectorAll(selector)[0];
} function play(example, fn) {
$('#example-' + example + ' .play').addEventListener('click', function(e){
e.preventDefault();
fn();
}, false);
} // example 1
play(1, function(){
move('#example-1 .box')
.set('margin-left', '200px')
.end();
}); // example 2
play(2, function(){
move('#example-2 .box')
.add('margin-left', 200)
.end();
}); // example 3
play(3, function(){
move('#example-3 .box')
.sub('margin-left', 10)
.end();
}); // example 4
play(4, function(){
move('#example-4 .box').rotate(140).end();
}); // example 5
play(5, function(){
move('#example-5 .box')
.set('background-color', 'blue')
.duration(2000)
.end();
}); // example 6
play(6, function(){
move('#example-6 .box')
.translate(300, 80)
.end();
}); // example 7
play(7, function(){
move('#example-7 .box')
.x(300)
.y(20)
.end();
}); // example 8
play(8, function(){
move('#example-8 .box')
.x(300)
.skew(50)
.set('height', 20)
.end();
}); // example 9
play(9, function(){
move('#example-9 .box')
.scale(3)
.end();
}); // example 10
play(10, function(){
move('#example-10 .box1').x(400).end();
move('#example-10 .box2').ease('in').x(400).end();
move('#example-10 .box3').ease('out').x(400).end();
move('#example-10 .box4').ease('in-out').x(400).end();
move('#example-10 .box5').ease('snap').x(400).end();
move('#example-10 .box6').ease('cubic-bezier(0,1,1,0)').x(400).end(); setTimeout(function(){
move('#example-10 .box1').x(0).end();
move('#example-10 .box2').x(0).end();
move('#example-10 .box3').x(0).end();
move('#example-10 .box4').x(0).end();
move('#example-10 .box5').x(0).end();
move('#example-10 .box6').x(0).end();
}, 1200);
}); play(11, function(){
move('#example-11 .box')
.set('background-color', 'red')
.duration(1000)
.end(function(){
move('#example-11 .box')
.set('background-color', 'white')
.end();
});
}); // example 12
play(12, function(){
move('#example-12 .box')
.set('background-color', 'blue')
.delay('2s')
.end();
}); // example 13
play(13, function(){
var moveBack = move('#example-13 .box')
.set('background-color', 'white')
.x(0); move('#example-13 .box')
.set('background-color', 'red')
.x(500)
.then(moveBack)
.end(); move('#example-13 .box2')
.set('background-color', 'red')
.x(500)
.scale(.5)
.rotate(60)
.then()
.rotate(30)
.scale(1.5)
.set('border-radius', 5)
.set('background-color', 'white')
.then()
.set('opacity', 0)
.pop()
.pop()
.end();
}); play(14, function(){
move('#example-14 .box')
.set('background-color', 'red')
.x(500)
.then()
.set('background-color', 'white')
.x(300)
.pop()
.end();
}); play(15, function(){
move('#example-15 .box')
.set('background-color', 'red')
.x(500)
.then()
.delay(1) // 设置动画延迟1ms执行
.set('background-color', 'white')
.x(300)
.pop()
.end();
}); play(16, function(){
move('#example-16 .box').animate('bgchange', {
delay : '5s', // 表示动画延迟设置5s后执行
duration: '4s', // 表示动画执行时间
'iteration-count': 'infinite' // n | infinite n表示播放次数 infinite表示无限循环
}).end();
}); play(17, function(){
var $m1 = move('#example-17 .box')
.set('background', '#ccc')
.duration('3s'); $m2 = move('#example-17 .box')
.delay(1)
.set('background', '#F60')
.duration('3s')
.end( function(){
$m1.delay(1).end( $m2 );
}); });
</script>
</div>
</body>
</html>
move.js运动插件的更多相关文章
-
解析JS运动
解析JS运动 物体运动原理:通过改变物体的位置,而发生移动变化. 任何运动都是相对的,就像物理中的运动公式:s(要达到的)=s0(当前的样式值)+vt. 方法: 1.运动的物体使用绝对定位 ...
-
【干货】教你如何利用fullPage.js以及move.js插件打造高端大气的网站效果!
前言: 如今我们经常能见到全屏网站,尤其是国外网站.这些网站用几幅很大的图片或色块做背景,再添加一些简单的内容,显得格外的高端大气上档次. 在学习过jQuery插件之后,才发现之前的很多网站特效完全可 ...
-
带无缝滚动的轮播图(含JS运动框架)
今天学习了一下轮播图的写作,想到前一阵学过的无缝滚动得思想,所以就把轮播与滚动结合了一下.不过我的代码的神逻辑我自己都不敢恭维,在没网没参照的情况下,只能硬着头皮往下写,希望跟大家共勉吧. js运动框 ...
-
js运动框架之一条乱跑的虫子
克隆与运动框架的联合应用 效果:点击元素块后,元素块开始随机的向任何方向移动,并附带一堆颜色随机的"尾巴".每个方向运动3秒后改变方向,同时笑脸变哭脸. 如图所示: 朝某个方向运动 ...
-
js运动 运动效果留言本
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content ...
-
JavaScript学习总结【11】、JS 运动
动画效果在网站中是一种非常常见的交互式体验效果,比如侧边栏分享.图片淡入淡出,我们把这种动画效果就叫做运动,也就是让物体动起来.如果想让一个物体动起来,无非就是改变它的速度,也就是改变属性值,比如 l ...
-
js运动动画
原文:js运动动画 今天简单的学了一下js运动动画,再此感谢慕课网的这位老师http://www.imooc.com/view/167,讲的很不错. 下面是我整理出来的结果. 知识点一:速度动画. 1 ...
-
move.js 源码 学习笔记
源码笔记: /* move.js * @author:flfwzgl https://github.com/flfwzgl * @copyright: MIT license * Sorrow.X - ...
-
js 运动框架及实例
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
随机推荐
-
SharePoint中新创建的Web Application在浏览器中报404错误
问题描述:在安装完成SharePoint 2010后,进入Central Administration,创建一个新的Web Application,可以正常创建,但访问时却返回404. 平台环境:Wi ...
-
方便的Chrome取色插件ColorPick Eyedropper [设计, FE必备]
最近在和Design合作开发, 她发过来的原型图有各种各样色配色, 不想让她一个一个地标记颜色, 嫌效率低. 于是自己找到一款方便的Chrome取色插件, 叫做ColorPick Eyedropper ...
-
Android中AlertDialog对话框禁止按[返回键]或[搜索键]
alertDialog.setOnKeyListener(new DialogInterface.OnKeyListener() { @Override public boolean onKey(Di ...
-
JS对象、原型链
忘记在哪里看到过,有人说鉴别一个人是否 js 入门的标准就是看他有没有理解 js 原型,所以第一篇总结就从这里出发. 对象 JavaScript 是一种基于对象的编程语言,但它与一般面向对象的编程语言 ...
-
MySQL基础、主从复制、优化
MySQL apache公司 开源共享 免费 mysql [-hlocalhost] -uroot -p 以超级管理员的身份登录 use demo; 查看 DCL(数据库控制语言): DDL(数据库定 ...
-
Mysql对用户的操作
1.创建用户语法:CREATE USER 用户名@地址 IDENTIFIED BY '密码'; 2.给用户授权语法:GRANT 权限1, … , 权限n ON 数据库.* TO 用户名 3.撤销授权语 ...
-
ICE简单介绍及使用示例
转自:http://blog.csdn.net/zhu2695/article/details/51494664 1.ICE是什么? ICE是ZEROC的开源通信协议产品,它的全称是:The Inte ...
-
Presto 学习参考资料
Presto 文档资料: 0.1版:Presto 0.100 Documentation 0.213版:Presto 0.213 Documentation 阿里云 presto 学习资料:https ...
-
php 当前时间 当前时间戳和数据库里取出的时间datetime格式进行比较大小
php 当前时间 当前时间戳和数据库里取出的时间datetime格式进行比较大小 UNIX时间戳转换为日期用函数: date() ,date('Y-m-d H:i:s', 1500219870); 日 ...
-
ThinkPHP 3.2 调用自定义函数库
ThinkPHP3.2 和3.1 区别还是有点大的 引入了命名空间,强化了驱动化和行为,增强了模块化的概念和对云平台的支持,并改进了诸多的细节.主要改进包括:模块化架构的全新设计全新命名空间和自动导入 ...