move.js运动插件
move.js 运动插件是一款针对元素动画效果的插件。可以运用此插件制作出各类元素效果。
插件GitHub地址:https://github.com/visionmedia/move.js
下面整理学习心得:
一、move.js原码:
1 ;(function(){ 2 3 /** 4 * Require the module at `name`. 5 * 6 * @param {String} name 7 * @return {Object} exports 8 * @api public 9 */ 10 11 function require(name) { 12 var module = require.modules[name]; 13 if (!module) throw new Error('failed to require "' + name + '"'); 14 15 if (!('exports' in module) && typeof module.definition === 'function') { 16 module.client = module.component = true; 17 module.definition.call(this, module.exports = {}, module); 18 delete module.definition; 19 } 20 21 return module.exports; 22 } 23 24 /** 25 * Meta info, accessible in the global scope unless you use AMD option. 26 */ 27 28 require.loader = 'component'; 29 30 /** 31 * Internal helper object, contains a sorting function for semantiv versioning 32 */ 33 require.helper = {}; 34 require.helper.semVerSort = function(a, b) { 35 var aArray = a.version.split('.'); 36 var bArray = b.version.split('.'); 37 for (var i=0; i<aArray.length; ++i) { 38 var aInt = parseInt(aArray[i], 10); 39 var bInt = parseInt(bArray[i], 10); 40 if (aInt === bInt) { 41 var aLex = aArray[i].substr((""+aInt).length); 42 var bLex = bArray[i].substr((""+bInt).length); 43 if (aLex === '' && bLex !== '') return 1; 44 if (aLex !== '' && bLex === '') return -1; 45 if (aLex !== '' && bLex !== '') return aLex > bLex ? 1 : -1; 46 continue; 47 } else if (aInt > bInt) { 48 return 1; 49 } else { 50 return -1; 51 } 52 } 53 return 0; 54 } 55 56 /** 57 * Find and require a module which name starts with the provided name. 58 * If multiple modules exists, the highest semver is used. 59 * This function can only be used for remote dependencies. 60 61 * @param {String} name - module name: `user~repo` 62 * @param {Boolean} returnPath - returns the canonical require path if true, 63 * otherwise it returns the epxorted module 64 */ 65 require.latest = function (name, returnPath) { 66 function showError(name) { 67 throw new Error('failed to find latest module of "' + name + '"'); 68 } 69 // only remotes with semvers, ignore local files conataining a '/' 70 var versionRegexp = /(.*)~(.*)@v?(\d+\.\d+\.\d+[^\/]*)$/; 71 var remoteRegexp = /(.*)~(.*)/; 72 if (!remoteRegexp.test(name)) showError(name); 73 var moduleNames = Object.keys(require.modules); 74 var semVerCandidates = []; 75 var otherCandidates = []; // for instance: name of the git branch 76 for (var i=0; i<moduleNames.length; i++) { 77 var moduleName = moduleNames[i]; 78 if (new RegExp(name + '@').test(moduleName)) { 79 var version = moduleName.substr(name.length+1); 80 var semVerMatch = versionRegexp.exec(moduleName); 81 if (semVerMatch != null) { 82 semVerCandidates.push({version: version, name: moduleName}); 83 } else { 84 otherCandidates.push({version: version, name: moduleName}); 85 } 86 } 87 } 88 if (semVerCandidates.concat(otherCandidates).length === 0) { 89 showError(name); 90 } 91 if (semVerCandidates.length > 0) { 92 var module = semVerCandidates.sort(require.helper.semVerSort).pop().name; 93 if (returnPath === true) { 94 return module; 95 } 96 return require(module); 97 } 98 // if the build contains more than one branch of the same module 99 // you should not use this funciton 100 var module = otherCandidates.sort(function(a, b) {return a.name > b.name})[0].name; 101 if (returnPath === true) { 102 return module; 103 } 104 return require(module); 105 } 106 107 /** 108 * Registered modules. 109 */ 110 111 require.modules = {}; 112 113 /** 114 * Register module at `name` with callback `definition`. 115 * 116 * @param {String} name 117 * @param {Function} definition 118 * @api private 119 */ 120 121 require.register = function (name, definition) { 122 require.modules[name] = { 123 definition: definition 124 }; 125 }; 126 127 /** 128 * Define a module's exports immediately with `exports`. 129 * 130 * @param {String} name 131 * @param {Generic} exports 132 * @api private 133 */ 134 135 require.define = function (name, exports) { 136 require.modules[name] = { 137 exports: exports 138 }; 139 }; 140 require.register("component~transform-property@0.0.1", function (exports, module) { 141 142 var styles = [ 143 'webkitTransform', 144 'MozTransform', 145 'msTransform', 146 'OTransform', 147 'transform' 148 ]; 149 150 var el = document.createElement('p'); 151 var style; 152 153 for (var i = 0; i < styles.length; i++) { 154 style = styles[i]; 155 if (null != el.style[style]) { 156 module.exports = style; 157 break; 158 } 159 } 160 161 }); 162 163 require.register("component~has-translate3d@0.0.3", function (exports, module) { 164 165 var prop = require('component~transform-property@0.0.1'); 166 167 // IE <=8 doesn't have `getComputedStyle` 168 if (!prop || !window.getComputedStyle) { 169 module.exports = false; 170 171 } else { 172 var map = { 173 webkitTransform: '-webkit-transform', 174 OTransform: '-o-transform', 175 msTransform: '-ms-transform', 176 MozTransform: '-moz-transform', 177 transform: 'transform' 178 }; 179 180 // from: https://gist.github.com/lorenzopolidori/3794226 181 var el = document.createElement('div'); 182 el.style[prop] = 'translate3d(1px,1px,1px)'; 183 document.body.insertBefore(el, null); 184 var val = getComputedStyle(el).getPropertyValue(map[prop]); 185 document.body.removeChild(el); 186 module.exports = null != val && val.length && 'none' != val; 187 } 188 189 }); 190 191 require.register("yields~has-transitions@1.0.0", function (exports, module) { 192 /** 193 * Check if `el` or browser supports transitions. 194 * 195 * @param {Element} el 196 * @return {Boolean} 197 * @api public 198 */ 199 200 exports = module.exports = function(el){ 201 switch (arguments.length) { 202 case 0: return bool; 203 case 1: return bool 204 ? transitions(el) 205 : bool; 206 } 207 }; 208 209 /** 210 * Check if the given `el` has transitions. 211 * 212 * @param {Element} el 213 * @return {Boolean} 214 * @api private 215 */ 216 217 function transitions(el, styl){ 218 if (el.transition) return true; 219 styl = window.getComputedStyle(el); 220 return !! parseFloat(styl.transitionDuration, 10); 221 } 222 223 /** 224 * Style. 225 */ 226 227 var styl = document.body.style; 228 229 /** 230 * Export support. 231 */ 232 233 var bool = 'transition' in styl 234 || 'webkitTransition' in styl 235 || 'MozTransition' in styl 236 || 'msTransition' in styl; 237 238 }); 239 240 require.register("component~event@0.1.4", function (exports, module) { 241 var bind = window.addEventListener ? 'addEventListener' : 'attachEvent', 242 unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent', 243 prefix = bind !== 'addEventListener' ? 'on' : ''; 244 245 /** 246 * Bind `el` event `type` to `fn`. 247 * 248 * @param {Element} el 249 * @param {String} type 250 * @param {Function} fn 251 * @param {Boolean} capture 252 * @return {Function} 253 * @api public 254 */ 255 256 exports.bind = function(el, type, fn, capture){ 257 el[bind](prefix + type, fn, capture || false); 258 return fn; 259 }; 260 261 /** 262 * Unbind `el` event `type`'s callback `fn`. 263 * 264 * @param {Element} el 265 * @param {String} type 266 * @param {Function} fn 267 * @param {Boolean} capture 268 * @return {Function} 269 * @api public 270 */ 271 272 exports.unbind = function(el, type, fn, capture){ 273 el[unbind](prefix + type, fn, capture || false); 274 return fn; 275 }; 276 }); 277 278 require.register("ecarter~css-emitter@0.0.1", function (exports, module) { 279 /** 280 * Module Dependencies 281 */ 282 283 var events = require('component~event@0.1.4'); 284 285 // CSS events 286 287 var watch = [ 288 'transitionend' 289 , 'webkitTransitionEnd' 290 , 'oTransitionEnd' 291 , 'MSTransitionEnd' 292 , 'animationend' 293 , 'webkitAnimationEnd' 294 , 'oAnimationEnd' 295 , 'MSAnimationEnd' 296 ]; 297 298 /** 299 * Expose `CSSnext` 300 */ 301 302 module.exports = CssEmitter; 303 304 /** 305 * Initialize a new `CssEmitter` 306 * 307 */ 308 309 function CssEmitter(element){ 310 if (!(this instanceof CssEmitter)) return new CssEmitter(element); 311 this.el = element; 312 } 313 314 /** 315 * Bind CSS events. 316 * 317 * @api public 318 */ 319 320 CssEmitter.prototype.bind = function(fn){ 321 for (var i=0; i < watch.length; i++) { 322 events.bind(this.el, watch[i], fn); 323 } 324 return this; 325 }; 326 327 /** 328 * Unbind CSS events 329 * 330 * @api public 331 */ 332 333 CssEmitter.prototype.unbind = function(fn){ 334 for (var i=0; i < watch.length; i++) { 335 events.unbind(this.el, watch[i], fn); 336 } 337 return this; 338 }; 339 340 /** 341 * Fire callback only once 342 * 343 * @api public 344 */ 345 346 CssEmitter.prototype.once = function(fn){ 347 var self = this; 348 function on(){ 349 self.unbind(on); 350 fn.apply(self.el, arguments); 351 } 352 self.bind(on); 353 return this; 354 }; 355 356 357 }); 358 359 require.register("component~once@0.0.1", function (exports, module) { 360 361 /** 362 * Identifier. 363 */ 364 365 var n = 0; 366 367 /** 368 * Global. 369 */ 370 371 var global = (function(){ return this })(); 372 373 /** 374 * Make `fn` callable only once. 375 * 376 * @param {Function} fn 377 * @return {Function} 378 * @api public 379 */ 380 381 module.exports = function(fn) { 382 var id = n++; 383 384 function once(){ 385 // no receiver 386 if (this == global) { 387 if (once.called) return; 388 once.called = true; 389 return fn.apply(this, arguments); 390 } 391 392 // receiver 393 var key = '__called_' + id + '__'; 394 if (this[key]) return; 395 this[key] = true; 396 return fn.apply(this, arguments); 397 } 398 399 return once; 400 }; 401 402 }); 403 404 require.register("yields~after-transition@0.0.1", function (exports, module) { 405 406 /** 407 * dependencies 408 */ 409 410 var has = require('yields~has-transitions@1.0.0') 411 , emitter = require('ecarter~css-emitter@0.0.1') 412 , once = require('component~once@0.0.1'); 413 414 /** 415 * Transition support. 416 */ 417 418 var supported = has(); 419 420 /** 421 * Export `after` 422 */ 423 424 module.exports = after; 425 426 /** 427 * Invoke the given `fn` after transitions 428 * 429 * It will be invoked only if the browser 430 * supports transitions __and__ 431 * the element has transitions 432 * set in `.style` or css. 433 * 434 * @param {Element} el 435 * @param {Function} fn 436 * @return {Function} fn 437 * @api public 438 */ 439 440 function after(el, fn){ 441 if (!supported || !has(el)) return fn(); 442 emitter(el).bind(fn); 443 return fn; 444 }; 445 446 /** 447 * Same as `after()` only the function is invoked once. 448 * 449 * @param {Element} el 450 * @param {Function} fn 451 * @return {Function} 452 * @api public 453 */ 454 455 after.once = function(el, fn){ 456 var callback = once(fn); 457 after(el, fn = function(){ 458 emitter(el).unbind(fn); 459 callback(); 460 }); 461 }; 462 463 }); 464 465 require.register("component~emitter@1.2.0", function (exports, module) { 466 467 /** 468 * Expose `Emitter`. 469 */ 470 471 module.exports = Emitter; 472 473 /** 474 * Initialize a new `Emitter`. 475 * 476 * @api public 477 */ 478 479 function Emitter(obj) { 480 if (obj) return mixin(obj); 481 }; 482 483 /** 484 * Mixin the emitter properties. 485 * 486 * @param {Object} obj 487 * @return {Object} 488 * @api private 489 */ 490 491 function mixin(obj) { 492 for (var key in Emitter.prototype) { 493 obj[key] = Emitter.prototype[key]; 494 } 495 return obj; 496 } 497 498 /** 499 * Listen on the given `event` with `fn`. 500 * 501 * @param {String} event 502 * @param {Function} fn 503 * @return {Emitter} 504 * @api public 505 */ 506 507 Emitter.prototype.on = 508 Emitter.prototype.addEventListener = function(event, fn){ 509 this._callbacks = this._callbacks || {}; 510 (this._callbacks['$' + event] = this._callbacks['$' + event] || []) 511 .push(fn); 512 return this; 513 }; 514 515 /** 516 * Adds an `event` listener that will be invoked a single 517 * time then automatically removed. 518 * 519 * @param {String} event 520 * @param {Function} fn 521 * @return {Emitter} 522 * @api public 523 */ 524 525 Emitter.prototype.once = function(event, fn){ 526 function on() { 527 this.off(event, on); 528 fn.apply(this, arguments); 529 } 530 531 on.fn = fn; 532 this.on(event, on); 533 return this; 534 }; 535 536 /** 537 * Remove the given callback for `event` or all 538 * registered callbacks. 539 * 540 * @param {String} event 541 * @param {Function} fn 542 * @return {Emitter} 543 * @api public 544 */ 545 546 Emitter.prototype.off = 547 Emitter.prototype.removeListener = 548 Emitter.prototype.removeAllListeners = 549 Emitter.prototype.removeEventListener = function(event, fn){ 550 this._callbacks = this._callbacks || {}; 551 552 // all 553 if (0 == arguments.length) { 554 this._callbacks = {}; 555 return this; 556 } 557 558 // specific event 559 var callbacks = this._callbacks['$' + event]; 560 if (!callbacks) return this; 561 562 // remove all handlers 563 if (1 == arguments.length) { 564 delete this._callbacks['$' + event]; 565 return this; 566 } 567 568 // remove specific handler 569 var cb; 570 for (var i = 0; i < callbacks.length; i++) { 571 cb = callbacks[i]; 572 if (cb === fn || cb.fn === fn) { 573 callbacks.splice(i, 1); 574 break; 575 } 576 } 577 return this; 578 }; 579 580 /** 581 * Emit `event` with the given args. 582 * 583 * @param {String} event 584 * @param {Mixed} ... 585 * @return {Emitter} 586 */ 587 588 Emitter.prototype.emit = function(event){ 589 this._callbacks = this._callbacks || {}; 590 var args = [].slice.call(arguments, 1) 591 , callbacks = this._callbacks['$' + event]; 592 593 if (callbacks) { 594 callbacks = callbacks.slice(0); 595 for (var i = 0, len = callbacks.length; i < len; ++i) { 596 callbacks[i].apply(this, args); 597 } 598 } 599 600 return this; 601 }; 602 603 /** 604 * Return array of callbacks for `event`. 605 * 606 * @param {String} event 607 * @return {Array} 608 * @api public 609 */ 610 611 Emitter.prototype.listeners = function(event){ 612 this._callbacks = this._callbacks || {}; 613 return this._callbacks['$' + event] || []; 614 }; 615 616 /** 617 * Check if this emitter has `event` handlers. 618 * 619 * @param {String} event 620 * @return {Boolean} 621 * @api public 622 */ 623 624 Emitter.prototype.hasListeners = function(event){ 625 return !! this.listeners(event).length; 626 }; 627 628 }); 629 630 require.register("yields~css-ease@0.0.1", function (exports, module) { 631 632 /** 633 * CSS Easing functions 634 */ 635 636 module.exports = { 637 'in': 'ease-in' 638 , 'out': 'ease-out' 639 , 'in-out': 'ease-in-out' 640 , 'snap': 'cubic-bezier(0,1,.5,1)' 641 , 'linear': 'cubic-bezier(0.250, 0.250, 0.750, 0.750)' 642 , 'ease-in-quad': 'cubic-bezier(0.550, 0.085, 0.680, 0.530)' 643 , 'ease-in-cubic': 'cubic-bezier(0.550, 0.055, 0.675, 0.190)' 644 , 'ease-in-quart': 'cubic-bezier(0.895, 0.030, 0.685, 0.220)' 645 , 'ease-in-quint': 'cubic-bezier(0.755, 0.050, 0.855, 0.060)' 646 , 'ease-in-sine': 'cubic-bezier(0.470, 0.000, 0.745, 0.715)' 647 , 'ease-in-expo': 'cubic-bezier(0.950, 0.050, 0.795, 0.035)' 648 , 'ease-in-circ': 'cubic-bezier(0.600, 0.040, 0.980, 0.335)' 649 , 'ease-in-back': 'cubic-bezier(0.600, -0.280, 0.735, 0.045)' 650 , 'ease-out-quad': 'cubic-bezier(0.250, 0.460, 0.450, 0.940)' 651 , 'ease-out-cubic': 'cubic-bezier(0.215, 0.610, 0.355, 1.000)' 652 , 'ease-out-quart': 'cubic-bezier(0.165, 0.840, 0.440, 1.000)' 653 , 'ease-out-quint': 'cubic-bezier(0.230, 1.000, 0.320, 1.000)' 654 , 'ease-out-sine': 'cubic-bezier(0.390, 0.575, 0.565, 1.000)' 655 , 'ease-out-expo': 'cubic-bezier(0.190, 1.000, 0.220, 1.000)' 656 , 'ease-out-circ': 'cubic-bezier(0.075, 0.820, 0.165, 1.000)' 657 , 'ease-out-back': 'cubic-bezier(0.175, 0.885, 0.320, 1.275)' 658 , 'ease-out-quad': 'cubic-bezier(0.455, 0.030, 0.515, 0.955)' 659 , 'ease-out-cubic': 'cubic-bezier(0.645, 0.045, 0.355, 1.000)' 660 , 'ease-in-out-quart': 'cubic-bezier(0.770, 0.000, 0.175, 1.000)' 661 , 'ease-in-out-quint': 'cubic-bezier(0.860, 0.000, 0.070, 1.000)' 662 , 'ease-in-out-sine': 'cubic-bezier(0.445, 0.050, 0.550, 0.950)' 663 , 'ease-in-out-expo': 'cubic-bezier(1.000, 0.000, 0.000, 1.000)' 664 , 'ease-in-out-circ': 'cubic-bezier(0.785, 0.135, 0.150, 0.860)' 665 , 'ease-in-out-back': 'cubic-bezier(0.680, -0.550, 0.265, 1.550)' 666 }; 667 668 }); 669 670 require.register("component~query@0.0.3", function (exports, module) { 671 function one(selector, el) { 672 return el.querySelector(selector); 673 } 674 675 exports = module.exports = function(selector, el){ 676 el = el || document; 677 return one(selector, el); 678 }; 679 680 exports.all = function(selector, el){ 681 el = el || document; 682 return el.querySelectorAll(selector); 683 }; 684 685 exports.engine = function(obj){ 686 if (!obj.one) throw new Error('.one callback required'); 687 if (!obj.all) throw new Error('.all callback required'); 688 one = obj.one; 689 exports.all = obj.all; 690 return exports; 691 }; 692 693 }); 694 695 require.register("move", function (exports, module) { 696 /** 697 * Module Dependencies. 698 */ 699 700 var Emitter = require('component~emitter@1.2.0'); 701 var query = require('component~query@0.0.3'); 702 var after = require('yields~after-transition@0.0.1'); 703 var has3d = require('component~has-translate3d@0.0.3'); 704 var ease = require('yields~css-ease@0.0.1'); 705 706 /** 707 * CSS Translate 708 */ 709 710 var translate = has3d 711 ? ['translate3d(', ', 0)'] 712 : ['translate(', ')']; 713 714 /** 715 * Export `Move` 716 */ 717 718 module.exports = Move; 719 720 /** 721 * Get computed style. 722 */ 723 724 var style = window.getComputedStyle 725 || window.currentStyle; 726 727 /** 728 * Library version. 729 */ 730 731 Move.version = '0.5.0'; 732 733 /** 734 * Export `ease` 735 */ 736 737 Move.ease = ease; 738 739 /** 740 * Defaults. 741 * 742 * `duration` - default duration of 500ms 743 * 744 */ 745 746 Move.defaults = { 747 duration: 500 748 }; 749 750 /** 751 * Default element selection utilized by `move(selector)`. 752 * 753 * Override to implement your own selection, for example 754 * with jQuery one might write: 755 * 756 * move.select = function(selector) { 757 * return jQuery(selector).get(0); 758 * }; 759 * 760 * @param {Object|String} selector 761 * @return {Element} 762 * @api public 763 */ 764 765 Move.select = function(selector){ 766 if ('string' != typeof selector) return selector; 767 return query(selector); 768 }; 769 770 /** 771 * Initialize a new `Move` with the given `el`. 772 * 773 * @param {Element} el 774 * @api public 775 */ 776 777 function Move(el) { 778 if (!(this instanceof Move)) return new Move(el); 779 if ('string' == typeof el) el = query(el); 780 if (!el) throw new TypeError('Move must be initialized with element or selector'); 781 this.el = el; 782 this._props = {}; 783 this._rotate = 0; 784 this._transitionProps = []; 785 this._transforms = []; 786 this.duration(Move.defaults.duration) 787 }; 788 789 790 /** 791 * Inherit from `EventEmitter.prototype`. 792 */ 793 794 Emitter(Move.prototype); 795 796 /** 797 * Buffer `transform`. 798 * 799 * @param {String} transform 800 * @return {Move} for chaining 801 * @api private 802 */ 803 804 Move.prototype.transform = function(transform){ 805 this._transforms.push(transform); 806 return this; 807 }; 808 809 /** 810 * Skew `x` and `y`. 811 * 812 * @param {Number} x 813 * @param {Number} y 814 * @return {Move} for chaining 815 * @api public 816 */ 817 818 Move.prototype.skew = function(x, y){ 819 return this.transform('skew(' 820 + x + 'deg, ' 821 + (y || 0) 822 + 'deg)'); 823 }; 824 825 /** 826 * Skew x by `n`. 827 * 828 * @param {Number} n 829 * @return {Move} for chaining 830 * @api public 831 */ 832 833 Move.prototype.skewX = function(n){ 834 return this.transform('skewX(' + n + 'deg)'); 835 }; 836 837 /** 838 * Skew y by `n`. 839 * 840 * @param {Number} n 841 * @return {Move} for chaining 842 * @api public 843 */ 844 845 Move.prototype.skewY = function(n){ 846 return this.transform('skewY(' + n + 'deg)'); 847 }; 848 849 /** 850 * Translate `x` and `y` axis. 851 * 852 * @param {Number} x 853 * @param {Number} y 854 * @return {Move} for chaining 855 * @api public 856 */ 857 858 Move.prototype.translate = 859 Move.prototype.to = function(x, y){ 860 return this.transform(translate.join('' 861 + x +'px, ' 862 + (y || 0) 863 + 'px')); 864 }; 865 866 /** 867 * Translate on the x axis to `n`. 868 * 869 * @param {Number} n 870 * @return {Move} for chaining 871 * @api public 872 */ 873 874 Move.prototype.translateX = 875 Move.prototype.x = function(n){ 876 return this.transform('translateX(' + n + 'px)'); 877 }; 878 879 /** 880 * Translate on the y axis to `n`. 881 * 882 * @param {Number} n 883 * @return {Move} for chaining 884 * @api public 885 */ 886 887 Move.prototype.translateY = 888 Move.prototype.y = function(n){ 889 return this.transform('translateY(' + n + 'px)'); 890 }; 891 892 /** 893 * Scale the x and y axis by `x`, or 894 * individually scale `x` and `y`. 895 * 896 * @param {Number} x 897 * @param {Number} y 898 * @return {Move} for chaining 899 * @api public 900 */ 901 902 Move.prototype.scale = function(x, y){ 903 return this.transform('scale(' 904 + x + ', ' 905 + (y || x) 906 + ')'); 907 }; 908 909 /** 910 * Scale x axis by `n`. 911 * 912 * @param {Number} n 913 * @return {Move} for chaining 914 * @api public 915 */ 916 917 Move.prototype.scaleX = function(n){ 918 return this.transform('scaleX(' + n + ')') 919 }; 920 921 /** 922 * Apply a matrix transformation 923 * 924 * @param {Number} m11 A matrix coefficient 925 * @param {Number} m12 A matrix coefficient 926 * @param {Number} m21 A matrix coefficient 927 * @param {Number} m22 A matrix coefficient 928 * @param {Number} m31 A matrix coefficient 929 * @param {Number} m32 A matrix coefficient 930 * @return {Move} for chaining 931 * @api public 932 */ 933 934 Move.prototype.matrix = function(m11, m12, m21, m22, m31, m32){ 935 return this.transform('matrix(' + [m11,m12,m21,m22,m31,m32].join(',') + ')'); 936 }; 937 938 /** 939 * Scale y axis by `n`. 940 * 941 * @param {Number} n 942 * @return {Move} for chaining 943 * @api public 944 */ 945 946 Move.prototype.scaleY = function(n){ 947 return this.transform('scaleY(' + n + ')') 948 }; 949 950 /** 951 * Rotate `n` degrees. 952 * 953 * @param {Number} n 954 * @return {Move} for chaining 955 * @api public 956 */ 957 958 Move.prototype.rotate = function(n){ 959 return this.transform('rotate(' + n + 'deg)'); 960 }; 961 962 /** 963 * Set transition easing function to to `fn` string. 964 * 965 * When: 966 * 967 * - null "ease" is used 968 * - "in" "ease-in" is used 969 * - "out" "ease-out" is used 970 * - "in-out" "ease-in-out" is used 971 * 972 * @param {String} fn 973 * @return {Move} for chaining 974 * @api public 975 */ 976 977 Move.prototype.ease = function(fn){ 978 fn = ease[fn] || fn || 'ease'; 979 return this.setVendorProperty('transition-timing-function', fn); 980 }; 981 982 /** 983 * Set animation properties 984 * 985 * @param {String} name 986 * @param {Object} props 987 * @return {Move} for chaining 988 * @api public 989 */ 990 991 Move.prototype.animate = function(name, props){ 992 for (var i in props){ 993 if (props.hasOwnProperty(i)){ 994 this.setVendorProperty('animation-' + i, props[i]) 995 } 996 } 997 return this.setVendorProperty('animation-name', name); 998 } 999 1000 /** 1001 * Set duration to `n`. 1002 * 1003 * @param {Number|String} n 1004 * @return {Move} for chaining 1005 * @api public 1006 */ 1007 1008 Move.prototype.duration = function(n){ 1009 n = this._duration = 'string' == typeof n 1010 ? parseFloat(n) * 1000 1011 : n; 1012 return this.setVendorProperty('transition-duration', n + 'ms'); 1013 }; 1014 1015 /** 1016 * Delay the animation by `n`. 1017 * 1018 * @param {Number|String} n 1019 * @return {Move} for chaining 1020 * @api public 1021 */ 1022 1023 Move.prototype.delay = function(n){ 1024 n = 'string' == typeof n 1025 ? parseFloat(n) * 1000 1026 : n; 1027 return this.setVendorProperty('transition-delay', n + 'ms'); 1028 }; 1029 1030 /** 1031 * Set `prop` to `val`, deferred until `.end()` is invoked. 1032 * 1033 * @param {String} prop 1034 * @param {String} val 1035 * @return {Move} for chaining 1036 * @api public 1037 */ 1038 1039 Move.prototype.setProperty = function(prop, val){ 1040 this._props[prop] = val; 1041 return this; 1042 }; 1043 1044 /** 1045 * Set a vendor prefixed `prop` with the given `val`. 1046 * 1047 * @param {String} prop 1048 * @param {String} val 1049 * @return {Move} for chaining 1050 * @api public 1051 */ 1052 1053 Move.prototype.setVendorProperty = function(prop, val){ 1054 this.setProperty('-webkit-' + prop, val); 1055 this.setProperty('-moz-' + prop, val); 1056 this.setProperty('-ms-' + prop, val); 1057 this.setProperty('-o-' + prop, val); 1058 return this; 1059 }; 1060 1061 /** 1062 * Set `prop` to `value`, deferred until `.end()` is invoked 1063 * and adds the property to the list of transition props. 1064 * 1065 * @param {String} prop 1066 * @param {String} val 1067 * @return {Move} for chaining 1068 * @api public 1069 */ 1070 1071 Move.prototype.set = function(prop, val){ 1072 if (typeof prop == "object") { 1073 for (var key in prop) { 1074 if (prop.hasOwnProperty(key)) { 1075 this.transition(key); 1076 this._props[key] = prop[key]; 1077 } 1078 } 1079 } else { 1080 this.transition(prop); 1081 this._props[prop] = val; 1082 } 1083 return this; 1084 }; 1085 1086 /** 1087 * Increment `prop` by `val`, deferred until `.end()` is invoked 1088 * and adds the property to the list of transition props. 1089 * 1090 * @param {String} prop 1091 * @param {Number} val 1092 * @return {Move} for chaining 1093 * @api public 1094 */ 1095 1096 Move.prototype.add = function(prop, val){ 1097 if (!style) return; 1098 var self = this; 1099 return this.on('start', function(){ 1100 var curr = parseInt(self.current(prop), 10); 1101 self.set(prop, curr + val + 'px'); 1102 }); 1103 }; 1104 1105 /** 1106 * Decrement `prop` by `val`, deferred until `.end()` is invoked 1107 * and adds the property to the list of transition props. 1108 * 1109 * @param {String} prop 1110 * @param {Number} val 1111 * @return {Move} for chaining 1112 * @api public 1113 */ 1114 1115 Move.prototype.sub = function(prop, val){ 1116 if (!style) return; 1117 var self = this; 1118 return this.on('start', function(){ 1119 var curr = parseInt(self.current(prop), 10); 1120 self.set(prop, curr - val + 'px'); 1121 }); 1122 }; 1123 1124 /** 1125 * Get computed or "current" value of `prop`. 1126 * 1127 * @param {String} prop 1128 * @return {String} 1129 * @api public 1130 */ 1131 1132 Move.prototype.current = function(prop){ 1133 return style(this.el).getPropertyValue(prop); 1134 }; 1135 1136 /** 1137 * Add `prop` to the list of internal transition properties. 1138 * 1139 * @param {String} prop 1140 * @return {Move} for chaining 1141 * @api private 1142 */ 1143 1144 Move.prototype.transition = function(prop){ 1145 if (!this._transitionProps.indexOf(prop)) return this; 1146 this._transitionProps.push(prop); 1147 return this; 1148 }; 1149 1150 /** 1151 * Commit style properties, aka apply them to `el.style`. 1152 * 1153 * @return {Move} for chaining 1154 * @see Move#end() 1155 * @api private 1156 */ 1157 1158 Move.prototype.applyProperties = function(){ 1159 for (var prop in this._props) { 1160 this.el.style.setProperty(prop, this._props[prop], ''); 1161 } 1162 return this; 1163 }; 1164 1165 /** 1166 * Re-select element via `selector`, replacing 1167 * the current element. 1168 * 1169 * @param {String} selector 1170 * @return {Move} for chaining 1171 * @api public 1172 */ 1173 1174 Move.prototype.move = 1175 Move.prototype.select = function(selector){ 1176 this.el = Move.select(selector); 1177 return this; 1178 }; 1179 1180 /** 1181 * Defer the given `fn` until the animation 1182 * is complete. `fn` may be one of the following: 1183 * 1184 * - a function to invoke 1185 * - an instanceof `Move` to call `.end()` 1186 * - nothing, to return a clone of this `Move` instance for chaining 1187 * 1188 * @param {Function|Move} fn 1189 * @return {Move} for chaining 1190 * @api public 1191 */ 1192 1193 Move.prototype.then = function(fn){ 1194 // invoke .end() 1195 if (fn instanceof Move) { 1196 this.on('end', function(){ 1197 fn.end(); 1198 }); 1199 // callback 1200 } else if ('function' == typeof fn) { 1201 this.on('end', fn); 1202 // chain 1203 } else { 1204 var clone = new Move(this.el); 1205 clone._transforms = this._transforms.slice(0); 1206 this.then(clone); 1207 clone.parent = this; 1208 return clone; 1209 } 1210 1211 return this; 1212 }; 1213 1214 /** 1215 * Pop the move context. 1216 * 1217 * @return {Move} parent Move 1218 * @api public 1219 */ 1220 1221 Move.prototype.pop = function(){ 1222 return this.parent; 1223 }; 1224 1225 /** 1226 * Reset duration. 1227 * 1228 * @return {Move} 1229 * @api public 1230 */ 1231 1232 Move.prototype.reset = function(){ 1233 this.el.style.webkitTransitionDuration = 1234 this.el.style.mozTransitionDuration = 1235 this.el.style.msTransitionDuration = 1236 this.el.style.oTransitionDuration = ''; 1237 return this; 1238 }; 1239 1240 /** 1241 * Start animation, optionally calling `fn` when complete. 1242 * 1243 * @param {Function} fn 1244 * @return {Move} for chaining 1245 * @api public 1246 */ 1247 1248 Move.prototype.end = function(fn){ 1249 var self = this; 1250 1251 // emit "start" event 1252 this.emit('start'); 1253 1254 // transforms 1255 if (this._transforms.length) { 1256 this.setVendorProperty('transform', this._transforms.join(' ')); 1257 } 1258 1259 // transition properties 1260 this.setVendorProperty('transition-properties', this._transitionProps.join(', ')); 1261 this.applyProperties(); 1262 1263 // callback given 1264 if (fn) this.then(fn); 1265 1266 // emit "end" when complete 1267 after.once(this.el, function(){ 1268 self.reset(); 1269 self.emit('end'); 1270 }); 1271 1272 return this; 1273 }; 1274 1275 }); 1276 1277 if (typeof exports == "object") { 1278 module.exports = require("move"); 1279 } else if (typeof define == "function" && define.amd) { 1280 define("move", [], function(){ return require("move"); }); 1281 } else { 1282 (this || window)["move"] = require("move"); 1283 } 1284 })()
二、基础调用方式:
1 <script> 2 move( $('#moveId') ) // $('#moveId') 要执行动画的元素对象 3 .set('margin-left', '200px') // 要将元素左偏移到200像素 4 .end( function(){ // end 是执行完成之后的回调函数,可选 5 console.log('动画执行完成'); 6 }); 7 </script>
1) move( $obj ) 返回动画的move实例。
2) .set... 定义动画效果行为
3) .end... 执行动画。如果没有此语句,动画不会被执行,比如下例:
1 // 定义动画对象 2 var $Obj = move( $('#role') ) 3 .set('margin-left', '200px'); 4 5 // 没有下面一句,动画不会被执行 6 $Obj.end();
三、move.js 函数方法说明:
1) .set方法用于设置动画元素的CSS样式,示例:
1 $Obj.set('margin-left', '200px'); // 正确
2 $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() 用于每段动画阶段中,如果不加入该函数,会直接跳到最终动画效果。省略中间的动画效果,直接到结尾动画
文字解释难以表述清楚,就以官网示例,结合心德做一个诠释:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>Move.js - CSS3 animation framework for JavaScript</title> 5 <style> 6 body { 7 padding: 50px; 8 font: 14px/1.5 "helvetica neue", helvetica, arial, sans-serif; 9 color: #8b8b8b; 10 } 11 h1, h2, h3 { 12 font-size: 33px; 13 font-weight: normal; 14 color: #333; 15 -webkit-font-smoothing: antialiased; 16 } 17 h2 { 18 display: none; 19 font-size: 33px; 20 } 21 h3 { 22 padding: 5px 0; 23 font-size: 18px; 24 border-bottom: 3px solid #eee; 25 } 26 .box { 27 margin: 5px; 28 border: 1px solid #888; 29 font-size: 11px; 30 text-align: center; 31 line-height: 50px; 32 } 33 .small { 34 width: 50px; 35 height: 50px; 36 } 37 a { 38 color: #00B5E2; 39 text-decoration: none; 40 } 41 a:hover { 42 text-decoration: underline; 43 } 44 .sandbox { 45 margin: 10px 0; 46 padding: 5px; 47 border: 1px solid #eee; 48 } 49 .source { 50 font-family: monaco, monospace; 51 font-size: 12px; 52 color: #999; 53 } 54 .example p { 55 color: #333; 56 } 57 .example p code { 58 color: #999; 59 padding: 2px 5px; 60 border: 1px solid #eee; 61 -webkit-border-radius: 3px; 62 } 63 #example-1 .box, 64 #example-2 .box, 65 #example-3 .box { 66 margin-left: 0px; 67 } 68 @-moz-keyframes bgchange { 69 from { 70 background: green; 71 } 72 73 to { 74 background: black; 75 } 76 } 77 @-webkit-keyframes bgchange { 78 from { 79 background: green; 80 } 81 82 to { 83 background: black; 84 } 85 } 86 </style> 87 </head> 88 <body> 89 <h1>Move.js</h1> 90 <p>此文档非商用仅作学习使用,原文档略有修改!</p> 91 92 <h2>Examples</h2> 93 94 <div id="examples"> 95 <div id="example-1" class="example"> 96 <h3>.set(prop, val)</h3> 97 <p>设置动画元素样式,点击下方Play会使元素向右偏移200像素!</p> 98 <a href="#" class="play">Play</a> 99 <div class="sandbox"> 100 <div class="box small"></div> 101 </div> 102 <pre class="source"> 103 <code> 104 move('#example-1 .box') 105 .set('margin-left', '200px') 106 .end(); 107 </code> 108 </pre> 109 </div> 110 111 <div id="example-2" class="example"> 112 <h3>.add(prop, val)</h3> 113 <p>将元素的某一属性值递增,参数val必须是数值类型!每点击下方Play,小方框会在当前位置处向右移200像素</p> 114 <a href="#" class="play">Play</a> 115 <div class="sandbox"> 116 <div class="box small"></div> 117 </div> 118 <pre class="source"> 119 <code> 120 move('#example-2 .box') 121 .add('margin-left', 200) 122 .end(); 123 </code> 124 </pre> 125 </div> 126 127 <div id="example-3" class="example"> 128 <h3>.sub(prop, val)</h3> 129 <p>和add相反, 将元素的某一属性值递减,参数val必须是数值类型!每点击下方Play,小方框会在当前位置处向左移10像素</p> 130 <a href="#" class="play">Play</a> 131 <div class="sandbox"> 132 <div class="box small"></div> 133 </div> 134 <pre class="source"> 135 <code> 136 move('#example-3 .box') 137 .sub('margin-left', 10) 138 .end(); 139 </code> 140 </pre> 141 </div> 142 143 <div id="example-4" class="example"> 144 <h3>.rotate(deg)</h3> 145 <p>旋转指定的角度</p> 146 <a href="#" class="play">Play</a> 147 <div class="sandbox"> 148 <div class="box small"></div> 149 </div> 150 <pre class="source"> 151 <code> 152 move('#example-4 .box') 153 .rotate(140) 154 .end(); 155 </code> 156 </pre> 157 </div> 158 159 <div id="example-5" class="example"> 160 <h3>.duration(n)</h3> 161 <p>设置动画过程所消耗的时间,比如:2000或2s。</p> 162 <a href="#" class="play">Play</a> 163 <div class="sandbox"> 164 <div class="box small"></div> 165 </div> 166 <pre class="source"> 167 <code> 168 move('#example-5 .box') 169 .set('background-color', 'blue') 170 .duration('2s') 171 .end(); 172 </code> 173 </pre> 174 </div> 175 176 <div id="example-6" class="example"> 177 <h3>.translate(x[, y]) 或者 .to(x[, y])</h3> 178 <p>将动画元素移动到指定的坐标处。(当前动画元素左上角为坐标原点)</p> 179 <a href="#" class="play">Play</a> 180 <div class="sandbox"> 181 <div class="box small"></div> 182 </div> 183 <pre class="source"> 184 <code> 185 move('#example-6 .box') 186 .translate(300, 80) 187 .end(); 188 </code> 189 </pre> 190 </div> 191 192 <div id="example-7" class="example"> 193 <h3>.x(n) / .y(n) 或者 translateX(n) / translateY(n) </h3> 194 <p>将动画元素移动到指定的坐标处</p> 195 <a href="#" class="play">Play</a> 196 <div class="sandbox"> 197 <div class="box small"></div> 198 </div> 199 <pre class="source"> 200 <code> 201 move('#example-7 .box') 202 .x(300) 203 .y(20) 204 .end(); 205 </code> 206 </pre> 207 </div> 208 209 <div id="example-8" class="example"> 210 <h3>.skew(x[, y]) / .skewX(n) / .skewY(n)</h3> 211 <p>将动画元素按X或Y轴斜切指定的角度</p> 212 <a href="#" class="play">Play</a> 213 <div class="sandbox"> 214 <div class="box small"></div> 215 </div> 216 <pre class="source"> 217 <code> 218 move('#example-8 .box') 219 .x(300) 220 .skew(50) 221 .set('height', 20) 222 .end(); 223 </code> 224 </pre> 225 </div> 226 227 <div id="example-9" class="example"> 228 <h3>.scale(x[, y]) / .scaleX(n) / .scaleY(n)</h3> 229 <p>将动画元素指定轴放大或缩小指定的倍数</p> 230 <a href="#" class="play">Play</a> 231 <div class="sandbox"> 232 <div class="box small"></div> 233 </div> 234 <pre class="source"> 235 <code> 236 move('#example-9 .box') 237 .scale(3) 238 .end(); 239 </code> 240 </pre> 241 </div> 242 243 <div id="example-10" class="example"> 244 <h3>.ease(fn)</h3> 245 <p>定义动画过渡行为</p> 246 <a href="#" class="play">Play</a> 247 <div class="sandbox"> 248 <div class="box box1 small">default</div> 249 <div class="box box2 small" title="以慢速开始">in</div> 250 <div class="box box3 small" title="以慢速结束">out</div> 251 <div class="box box4 small" title="以慢速开始,以慢速结束">in-out</div> 252 <div class="box box5 small">snap</div> 253 <div class="box box6 small" title="贝塞尔曲线,n值在0-1之间">(0,1,1,0)</div> 254 </div> 255 <pre class="source"> 256 <code> 257 move('#example-10 .box1').x(400).end(); 258 move('#example-10 .box2').ease('in').x(400).end(); 259 move('#example-10 .box3').ease('out').x(400).end(); 260 move('#example-10 .box4').ease('in-out').x(400).end(); 261 move('#example-10 .box5').ease('snap').x(400).end(); 262 move('#example-10 .box6').ease('cubic-bezier(0,1,1,0)').x(400).end(); 263 264 setTimeout(function(){ 265 move('#example-10 .box1').x(0).end(); 266 move('#example-10 .box2').x(0).end(); 267 move('#example-10 .box3').x(0).end(); 268 move('#example-10 .box4').x(0).end(); 269 move('#example-10 .box5').x(0).end(); 270 move('#example-10 .box6').x(0).end(); 271 }, 1200); 272 </code> 273 </pre> 274 </div> 275 276 <div id="example-11" class="example"> 277 <h3>.end([fn])</h3> 278 <p>触发动画播放,可选择在完成时调用回调fn。</p> 279 <a href="#" class="play">Play</a> 280 <div class="sandbox"> 281 <div class="box small"></div> 282 </div> 283 <pre class="source"> 284 <code> 285 move('#example-11 .box') 286 .set('background-color', 'red') 287 .duration(1000) 288 .end(function(){ 289 move('#example-11 .box') 290 .set('background-color', 'white') 291 .end(); 292 }); 293 </code> 294 </pre> 295 296 </div> 297 298 <div id="example-12" class="example"> 299 <h3>.delay(n)</h3> 300 <p>设置动画延迟执行,比如 2000 或 2s</p> 301 <a href="#" class="play">Play</a> 302 <div class="sandbox"> 303 <div class="box small"></div> 304 </div> 305 <pre class="source"> 306 <code> 307 move('#example-12 .box') 308 .set('background-color', 'blue') 309 .delay('2s') 310 .end(); 311 </code> 312 </pre> 313 </div> 314 315 <div id="example-13" class="example"> 316 <h3>.then([fn])</h3> 317 <p>分割动画为两个集合,并按顺序执行。</p> 318 <a href="#" class="play">Play</a> 319 <div class="sandbox"> 320 <div class="box small"></div> 321 <div class="box box2 small"></div> 322 </div> 323 <pre class="source"> 324 <code> 325 var moveBack = move('#example-13 .box') 326 .set('background-color', 'white') 327 .x(0); 328 329 move('#example-13 .box') 330 .set('background-color', 'red') 331 .x(500) 332 .then(moveBack) 333 .end(); 334 335 move('#example-13 .box2') 336 .set('background-color', 'red') 337 .x(500) 338 .scale(.5) 339 .rotate(60) 340 .then() 341 .rotate(30) 342 .scale(1.5) 343 .set('border-radius', 5) 344 .set('background-color', 'white') 345 .then() 346 .set('opacity', 0) 347 .pop() 348 .pop() 349 .end(); 350 </code> 351 </pre> 352 </div> 353 354 355 <div id="example-16" class="example"> 356 <h3 style="font-weight:bold;">扩展</h3> 357 <p style="font-weight:bold;color:red;">.animate('CSS动画名', json) 调用一个CSS动画</p> 358 <a href="#" class="play">play</a> 359 <div class="sandbox"> 360 <div class="box small">1</div> 361 </div> 362 <pre class="source"> 363 <code> 364 // 下面是CSS样式中定义的动画,动画名称为: bgchange 365 @-moz-keyframes bgchange { 366 from { 367 background: green; 368 } 369 370 to { 371 background: black; 372 } 373 } 374 @-webkit-keyframes bgchange { 375 from { 376 background: green; 377 } 378 379 to { 380 background: black; 381 } 382 } 383 384 // 下面是调用代码 385 move('#example-16 .box').animate('bgchange', { 386 duration: '4s', 387 'iteration-count': 'infinite' 388 }).end(); 389 </code> 390 </pre> 391 </div> 392 393 394 395 <div id="example-17" class="example"> 396 <p style="font-weight:bold;color:red;">如何定义无限循环的动画效果</p> 397 <a href="#">1、使用 .animate 函数(上例中已说明)</a><br/> 398 <a href="#" class="play">2、利用 end( fn ) 中的fn不停的循环某一动画效果,点击播放示例:(代码理论可行,实际运行会卡死浏览器)</a> 399 <div class="sandbox"> 400 <div class="box small">1</div> 401 </div> 402 <pre> 403 var $m1 = move('#example-17 .box') 404 .set('background', '#ccc') 405 .duration('3s'); 406 407 $m2 = move('#example-17 .box') 408 .set('background', '#F60') 409 .duration('3s') 410 .end( function(){ 411 $m1.end( $m2 ); 412 }); 413 </pre> 414 </div> 415 416 417 <div id="example-14" class="example"> 418 <h3>BUG-1:</h3> 419 <p style="font-weight:bold;color:red;">当定义多个动画时,某一动画过程不显示,怎么处理? </p> 420 <a href="#" class="play">点击观看BUG现象:(当第二个动画时,直接跳到结束状态)</a> 421 <div class="sandbox"> 422 <div class="box small">1</div> 423 </div> 424 <pre class="source"> 425 <code> 426 move('#example-14 .box') 427 .set('background-color', 'red') 428 .x(500) 429 .then() 430 .set('background-color', 'white') 431 .x(0) 432 .pop() 433 .end(); 434 </code> 435 </pre> 436 </div> 437 438 <div id="example-15" class="example"> 439 <p style="font-weight:bold;color:red;">解决方案:使用.delay方法解决动画不显示问题! </p> 440 <a href="#" class="play">点击查看效果</a> 441 <div class="sandbox"> 442 <div class="box small">2</div> 443 </div> 444 <pre class="source"> 445 <code> 446 move('#example-15 .box2') 447 .set('background-color', 'red') 448 .x(500) 449 .then() 450 .delay(1) 451 .set('background-color', 'white') 452 .x(0) 453 .pop() 454 .end(); 455 </code> 456 </pre> 457 </div> 458 459 <script src="../move.js"></script> 460 <script> 461 462 function $(selector) { 463 return document.querySelectorAll(selector)[0]; 464 } 465 466 function play(example, fn) { 467 $('#example-' + example + ' .play').addEventListener('click', function(e){ 468 e.preventDefault(); 469 fn(); 470 }, false); 471 } 472 473 // example 1 474 play(1, function(){ 475 move('#example-1 .box') 476 .set('margin-left', '200px') 477 .end(); 478 }); 479 480 // example 2 481 play(2, function(){ 482 move('#example-2 .box') 483 .add('margin-left', 200) 484 .end(); 485 }); 486 487 // example 3 488 play(3, function(){ 489 move('#example-3 .box') 490 .sub('margin-left', 10) 491 .end(); 492 }); 493 494 // example 4 495 play(4, function(){ 496 move('#example-4 .box').rotate(140).end(); 497 }); 498 499 // example 5 500 play(5, function(){ 501 move('#example-5 .box') 502 .set('background-color', 'blue') 503 .duration(2000) 504 .end(); 505 }); 506 507 // example 6 508 play(6, function(){ 509 move('#example-6 .box') 510 .translate(300, 80) 511 .end(); 512 }); 513 514 // example 7 515 play(7, function(){ 516 move('#example-7 .box') 517 .x(300) 518 .y(20) 519 .end(); 520 }); 521 522 // example 8 523 play(8, function(){ 524 move('#example-8 .box') 525 .x(300) 526 .skew(50) 527 .set('height', 20) 528 .end(); 529 }); 530 531 // example 9 532 play(9, function(){ 533 move('#example-9 .box') 534 .scale(3) 535 .end(); 536 }); 537 538 // example 10 539 play(10, function(){ 540 move('#example-10 .box1').x(400).end(); 541 move('#example-10 .box2').ease('in').x(400).end(); 542 move('#example-10 .box3').ease('out').x(400).end(); 543 move('#example-10 .box4').ease('in-out').x(400).end(); 544 move('#example-10 .box5').ease('snap').x(400).end(); 545 move('#example-10 .box6').ease('cubic-bezier(0,1,1,0)').x(400).end(); 546 547 setTimeout(function(){ 548 move('#example-10 .box1').x(0).end(); 549 move('#example-10 .box2').x(0).end(); 550 move('#example-10 .box3').x(0).end(); 551 move('#example-10 .box4').x(0).end(); 552 move('#example-10 .box5').x(0).end(); 553 move('#example-10 .box6').x(0).end(); 554 }, 1200); 555 }); 556 557 play(11, function(){ 558 move('#example-11 .box') 559 .set('background-color', 'red') 560 .duration(1000) 561 .end(function(){ 562 move('#example-11 .box') 563 .set('background-color', 'white') 564 .end(); 565 }); 566 }); 567 568 // example 12 569 play(12, function(){ 570 move('#example-12 .box') 571 .set('background-color', 'blue') 572 .delay('2s') 573 .end(); 574 }); 575 576 // example 13 577 play(13, function(){ 578 var moveBack = move('#example-13 .box') 579 .set('background-color', 'white') 580 .x(0); 581 582 move('#example-13 .box') 583 .set('background-color', 'red') 584 .x(500) 585 .then(moveBack) 586 .end(); 587 588 move('#example-13 .box2') 589 .set('background-color', 'red') 590 .x(500) 591 .scale(.5) 592 .rotate(60) 593 .then() 594 .rotate(30) 595 .scale(1.5) 596 .set('border-radius', 5) 597 .set('background-color', 'white') 598 .then() 599 .set('opacity', 0) 600 .pop() 601 .pop() 602 .end(); 603 }); 604 605 play(14, function(){ 606 move('#example-14 .box') 607 .set('background-color', 'red') 608 .x(500) 609 .then() 610 .set('background-color', 'white') 611 .x(300) 612 .pop() 613 .end(); 614 }); 615 616 play(15, function(){ 617 move('#example-15 .box') 618 .set('background-color', 'red') 619 .x(500) 620 .then() 621 .delay(1) // 设置动画延迟1ms执行 622 .set('background-color', 'white') 623 .x(300) 624 .pop() 625 .end(); 626 }); 627 628 play(16, function(){ 629 move('#example-16 .box').animate('bgchange', { 630 delay : '5s', // 表示动画延迟设置5s后执行 631 duration: '4s', // 表示动画执行时间 632 'iteration-count': 'infinite' // n | infinite n表示播放次数 infinite表示无限循环 633 }).end(); 634 }); 635 636 637 play(17, function(){ 638 var $m1 = move('#example-17 .box') 639 .set('background', '#ccc') 640 .duration('3s'); 641 642 $m2 = move('#example-17 .box') 643 .delay(1) 644 .set('background', '#F60') 645 .duration('3s') 646 .end( function(){ 647 $m1.delay(1).end( $m2 ); 648 }); 649 650 651 }); 652 </script> 653 </div> 654 </body> 655 </html>