| /*! |
| * TweenJS |
| * Visit http://createjs.com/ for documentation, updates and examples. |
| * |
| * Copyright (c) 2010 gskinner.com, inc. |
| * |
| * Permission is hereby granted, free of charge, to any person |
| * obtaining a copy of this software and associated documentation |
| * files (the "Software"), to deal in the Software without |
| * restriction, including without limitation the rights to use, |
| * copy, modify, merge, publish, distribute, sublicense, and/or sell |
| * copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following |
| * conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
| * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
| * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| * OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| |
| //############################################################################## |
| // extend.js |
| //############################################################################## |
| |
| this.createjs = this.createjs||{}; |
| |
| /** |
| * @class Utility Methods |
| */ |
| |
| /** |
| * Sets up the prototype chain and constructor property for a new class. |
| * |
| * This should be called right after creating the class constructor. |
| * |
| * function MySubClass() {} |
| * createjs.extend(MySubClass, MySuperClass); |
| * MySubClass.prototype.doSomething = function() { } |
| * |
| * var foo = new MySubClass(); |
| * console.log(foo instanceof MySuperClass); // true |
| * console.log(foo.prototype.constructor === MySubClass); // true |
| * |
| * @method extend |
| * @param {Function} subclass The subclass. |
| * @param {Function} superclass The superclass to extend. |
| * @return {Function} Returns the subclass's new prototype. |
| */ |
| createjs.extend = function(subclass, superclass) { |
| "use strict"; |
| |
| function o() { this.constructor = subclass; } |
| o.prototype = superclass.prototype; |
| return (subclass.prototype = new o()); |
| }; |
| |
| //############################################################################## |
| // promote.js |
| //############################################################################## |
| |
| this.createjs = this.createjs||{}; |
| |
| /** |
| * @class Utility Methods |
| */ |
| |
| /** |
| * Promotes any methods on the super class that were overridden, by creating an alias in the format `prefix_methodName`. |
| * It is recommended to use the super class's name as the prefix. |
| * An alias to the super class's constructor is always added in the format `prefix_constructor`. |
| * This allows the subclass to call super class methods without using `function.call`, providing better performance. |
| * |
| * For example, if `MySubClass` extends `MySuperClass`, and both define a `draw` method, then calling `promote(MySubClass, "MySuperClass")` |
| * would add a `MySuperClass_constructor` method to MySubClass and promote the `draw` method on `MySuperClass` to the |
| * prototype of `MySubClass` as `MySuperClass_draw`. |
| * |
| * This should be called after the class's prototype is fully defined. |
| * |
| * function ClassA(name) { |
| * this.name = name; |
| * } |
| * ClassA.prototype.greet = function() { |
| * return "Hello "+this.name; |
| * } |
| * |
| * function ClassB(name, punctuation) { |
| * this.ClassA_constructor(name); |
| * this.punctuation = punctuation; |
| * } |
| * createjs.extend(ClassB, ClassA); |
| * ClassB.prototype.greet = function() { |
| * return this.ClassA_greet()+this.punctuation; |
| * } |
| * createjs.promote(ClassB, "ClassA"); |
| * |
| * var foo = new ClassB("World", "!?!"); |
| * console.log(foo.greet()); // Hello World!?! |
| * |
| * @method promote |
| * @param {Function} subclass The class to promote super class methods on. |
| * @param {String} prefix The prefix to add to the promoted method names. Usually the name of the superclass. |
| * @return {Function} Returns the subclass. |
| */ |
| createjs.promote = function(subclass, prefix) { |
| "use strict"; |
| |
| var subP = subclass.prototype, supP = (Object.getPrototypeOf&&Object.getPrototypeOf(subP))||subP.__proto__; |
| if (supP) { |
| subP[(prefix+="_") + "constructor"] = supP.constructor; // constructor is not always innumerable |
| for (var n in supP) { |
| if (subP.hasOwnProperty(n) && (typeof supP[n] == "function")) { subP[prefix + n] = supP[n]; } |
| } |
| } |
| return subclass; |
| }; |
| |
| //############################################################################## |
| // Event.js |
| //############################################################################## |
| |
| this.createjs = this.createjs||{}; |
| |
| (function() { |
| "use strict"; |
| |
| // constructor: |
| /** |
| * Contains properties and methods shared by all events for use with |
| * {{#crossLink "EventDispatcher"}}{{/crossLink}}. |
| * |
| * Note that Event objects are often reused, so you should never |
| * rely on an event object's state outside of the call stack it was received in. |
| * @class Event |
| * @param {String} type The event type. |
| * @param {Boolean} bubbles Indicates whether the event will bubble through the display list. |
| * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled. |
| * @constructor |
| **/ |
| function Event(type, bubbles, cancelable) { |
| |
| |
| // public properties: |
| /** |
| * The type of event. |
| * @property type |
| * @type String |
| **/ |
| this.type = type; |
| |
| /** |
| * The object that generated an event. |
| * @property target |
| * @type Object |
| * @default null |
| * @readonly |
| */ |
| this.target = null; |
| |
| /** |
| * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will |
| * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event |
| * is generated from childObj, then a listener on parentObj would receive the event with |
| * target=childObj (the original target) and currentTarget=parentObj (where the listener was added). |
| * @property currentTarget |
| * @type Object |
| * @default null |
| * @readonly |
| */ |
| this.currentTarget = null; |
| |
| /** |
| * For bubbling events, this indicates the current event phase:<OL> |
| * <LI> capture phase: starting from the top parent to the target</LI> |
| * <LI> at target phase: currently being dispatched from the target</LI> |
| * <LI> bubbling phase: from the target to the top parent</LI> |
| * </OL> |
| * @property eventPhase |
| * @type Number |
| * @default 0 |
| * @readonly |
| */ |
| this.eventPhase = 0; |
| |
| /** |
| * Indicates whether the event will bubble through the display list. |
| * @property bubbles |
| * @type Boolean |
| * @default false |
| * @readonly |
| */ |
| this.bubbles = !!bubbles; |
| |
| /** |
| * Indicates whether the default behaviour of this event can be cancelled via |
| * {{#crossLink "Event/preventDefault"}}{{/crossLink}}. This is set via the Event constructor. |
| * @property cancelable |
| * @type Boolean |
| * @default false |
| * @readonly |
| */ |
| this.cancelable = !!cancelable; |
| |
| /** |
| * The epoch time at which this event was created. |
| * @property timeStamp |
| * @type Number |
| * @default 0 |
| * @readonly |
| */ |
| this.timeStamp = (new Date()).getTime(); |
| |
| /** |
| * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called |
| * on this event. |
| * @property defaultPrevented |
| * @type Boolean |
| * @default false |
| * @readonly |
| */ |
| this.defaultPrevented = false; |
| |
| /** |
| * Indicates if {{#crossLink "Event/stopPropagation"}}{{/crossLink}} or |
| * {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called on this event. |
| * @property propagationStopped |
| * @type Boolean |
| * @default false |
| * @readonly |
| */ |
| this.propagationStopped = false; |
| |
| /** |
| * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called |
| * on this event. |
| * @property immediatePropagationStopped |
| * @type Boolean |
| * @default false |
| * @readonly |
| */ |
| this.immediatePropagationStopped = false; |
| |
| /** |
| * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event. |
| * @property removed |
| * @type Boolean |
| * @default false |
| * @readonly |
| */ |
| this.removed = false; |
| } |
| var p = Event.prototype; |
| |
| /** |
| * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`. |
| * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} |
| * for details. |
| * |
| * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. |
| * |
| * @method initialize |
| * @protected |
| * @deprecated |
| */ |
| // p.initialize = function() {}; // searchable for devs wondering where it is. |
| |
| // public methods: |
| /** |
| * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true if the event is cancelable. |
| * Mirrors the DOM level 2 event standard. In general, cancelable events that have `preventDefault()` called will |
| * cancel the default behaviour associated with the event. |
| * @method preventDefault |
| **/ |
| p.preventDefault = function() { |
| this.defaultPrevented = this.cancelable&&true; |
| }; |
| |
| /** |
| * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} to true. |
| * Mirrors the DOM event standard. |
| * @method stopPropagation |
| **/ |
| p.stopPropagation = function() { |
| this.propagationStopped = true; |
| }; |
| |
| /** |
| * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} and |
| * {{#crossLink "Event/immediatePropagationStopped"}}{{/crossLink}} to true. |
| * Mirrors the DOM event standard. |
| * @method stopImmediatePropagation |
| **/ |
| p.stopImmediatePropagation = function() { |
| this.immediatePropagationStopped = this.propagationStopped = true; |
| }; |
| |
| /** |
| * Causes the active listener to be removed via removeEventListener(); |
| * |
| * myBtn.addEventListener("click", function(evt) { |
| * // do stuff... |
| * evt.remove(); // removes this listener. |
| * }); |
| * |
| * @method remove |
| **/ |
| p.remove = function() { |
| this.removed = true; |
| }; |
| |
| /** |
| * Returns a clone of the Event instance. |
| * @method clone |
| * @return {Event} a clone of the Event instance. |
| **/ |
| p.clone = function() { |
| return new Event(this.type, this.bubbles, this.cancelable); |
| }; |
| |
| /** |
| * Provides a chainable shortcut method for setting a number of properties on the instance. |
| * |
| * @method set |
| * @param {Object} props A generic object containing properties to copy to the instance. |
| * @return {Event} Returns the instance the method is called on (useful for chaining calls.) |
| * @chainable |
| */ |
| p.set = function(props) { |
| for (var n in props) { this[n] = props[n]; } |
| return this; |
| }; |
| |
| /** |
| * Returns a string representation of this object. |
| * @method toString |
| * @return {String} a string representation of the instance. |
| **/ |
| p.toString = function() { |
| return "[Event (type="+this.type+")]"; |
| }; |
| |
| createjs.Event = Event; |
| }()); |
| |
| //############################################################################## |
| // EventDispatcher.js |
| //############################################################################## |
| |
| this.createjs = this.createjs||{}; |
| |
| (function() { |
| "use strict"; |
| |
| |
| // constructor: |
| /** |
| * EventDispatcher provides methods for managing queues of event listeners and dispatching events. |
| * |
| * You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the |
| * EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method. |
| * |
| * Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the |
| * DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports |
| * bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent. |
| * |
| * EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier |
| * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The |
| * {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to |
| * {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}. |
| * |
| * Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}} |
| * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also |
| * includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener. |
| * |
| * <h4>Example</h4> |
| * Add EventDispatcher capabilities to the "MyClass" class. |
| * |
| * EventDispatcher.initialize(MyClass.prototype); |
| * |
| * Add an event (see {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}}). |
| * |
| * instance.addEventListener("eventName", handlerMethod); |
| * function handlerMethod(event) { |
| * console.log(event.target + " Was Clicked"); |
| * } |
| * |
| * <b>Maintaining proper scope</b><br /> |
| * Scope (ie. "this") can be be a challenge with events. Using the {{#crossLink "EventDispatcher/on"}}{{/crossLink}} |
| * method to subscribe to events simplifies this. |
| * |
| * instance.addEventListener("click", function(event) { |
| * console.log(instance == this); // false, scope is ambiguous. |
| * }); |
| * |
| * instance.on("click", function(event) { |
| * console.log(instance == this); // true, "on" uses dispatcher scope by default. |
| * }); |
| * |
| * If you want to use addEventListener instead, you may want to use function.bind() or a similar proxy to manage |
| * scope. |
| * |
| * <b>Browser support</b> |
| * The event model in CreateJS can be used separately from the suite in any project, however the inheritance model |
| * requires modern browsers (IE9+). |
| * |
| * |
| * @class EventDispatcher |
| * @constructor |
| **/ |
| function EventDispatcher() { |
| |
| |
| // private properties: |
| /** |
| * @protected |
| * @property _listeners |
| * @type Object |
| **/ |
| this._listeners = null; |
| |
| /** |
| * @protected |
| * @property _captureListeners |
| * @type Object |
| **/ |
| this._captureListeners = null; |
| } |
| var p = EventDispatcher.prototype; |
| |
| /** |
| * <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`. |
| * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} |
| * for details. |
| * |
| * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. |
| * |
| * @method initialize |
| * @protected |
| * @deprecated |
| */ |
| // p.initialize = function() {}; // searchable for devs wondering where it is. |
| |
| |
| // static public methods: |
| /** |
| * Static initializer to mix EventDispatcher methods into a target object or prototype. |
| * |
| * EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class |
| * EventDispatcher.initialize(myObject); // add to a specific instance |
| * |
| * @method initialize |
| * @static |
| * @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a |
| * prototype. |
| **/ |
| EventDispatcher.initialize = function(target) { |
| target.addEventListener = p.addEventListener; |
| target.on = p.on; |
| target.removeEventListener = target.off = p.removeEventListener; |
| target.removeAllEventListeners = p.removeAllEventListeners; |
| target.hasEventListener = p.hasEventListener; |
| target.dispatchEvent = p.dispatchEvent; |
| target._dispatchEvent = p._dispatchEvent; |
| target.willTrigger = p.willTrigger; |
| }; |
| |
| |
| // public methods: |
| /** |
| * Adds the specified event listener. Note that adding multiple listeners to the same function will result in |
| * multiple callbacks getting fired. |
| * |
| * <h4>Example</h4> |
| * |
| * displayObject.addEventListener("click", handleClick); |
| * function handleClick(event) { |
| * // Click happened. |
| * } |
| * |
| * @method addEventListener |
| * @param {String} type The string type of the event. |
| * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when |
| * the event is dispatched. |
| * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. |
| * @return {Function | Object} Returns the listener for chaining or assignment. |
| **/ |
| p.addEventListener = function(type, listener, useCapture) { |
| var listeners; |
| if (useCapture) { |
| listeners = this._captureListeners = this._captureListeners||{}; |
| } else { |
| listeners = this._listeners = this._listeners||{}; |
| } |
| var arr = listeners[type]; |
| if (arr) { this.removeEventListener(type, listener, useCapture); } |
| arr = listeners[type]; // remove may have deleted the array |
| if (!arr) { listeners[type] = [listener]; } |
| else { arr.push(listener); } |
| return listener; |
| }; |
| |
| /** |
| * A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener |
| * only run once, associate arbitrary data with the listener, and remove the listener. |
| * |
| * This method works by creating an anonymous wrapper function and subscribing it with addEventListener. |
| * The wrapper function is returned for use with `removeEventListener` (or `off`). |
| * |
| * <b>IMPORTANT:</b> To remove a listener added with `on`, you must pass in the returned wrapper function as the listener, or use |
| * {{#crossLink "Event/remove"}}{{/crossLink}}. Likewise, each time you call `on` a NEW wrapper function is subscribed, so multiple calls |
| * to `on` with the same params will create multiple listeners. |
| * |
| * <h4>Example</h4> |
| * |
| * var listener = myBtn.on("click", handleClick, null, false, {count:3}); |
| * function handleClick(evt, data) { |
| * data.count -= 1; |
| * console.log(this == myBtn); // true - scope defaults to the dispatcher |
| * if (data.count == 0) { |
| * alert("clicked 3 times!"); |
| * myBtn.off("click", listener); |
| * // alternately: evt.remove(); |
| * } |
| * } |
| * |
| * @method on |
| * @param {String} type The string type of the event. |
| * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when |
| * the event is dispatched. |
| * @param {Object} [scope] The scope to execute the listener in. Defaults to the dispatcher/currentTarget for function listeners, and to the listener itself for object listeners (ie. using handleEvent). |
| * @param {Boolean} [once=false] If true, the listener will remove itself after the first time it is triggered. |
| * @param {*} [data] Arbitrary data that will be included as the second parameter when the listener is called. |
| * @param {Boolean} [useCapture=false] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. |
| * @return {Function} Returns the anonymous function that was created and assigned as the listener. This is needed to remove the listener later using .removeEventListener. |
| **/ |
| p.on = function(type, listener, scope, once, data, useCapture) { |
| if (listener.handleEvent) { |
| scope = scope||listener; |
| listener = listener.handleEvent; |
| } |
| scope = scope||this; |
| return this.addEventListener(type, function(evt) { |
| listener.call(scope, evt, data); |
| once&&evt.remove(); |
| }, useCapture); |
| }; |
| |
| /** |
| * Removes the specified event listener. |
| * |
| * <b>Important Note:</b> that you must pass the exact function reference used when the event was added. If a proxy |
| * function, or function closure is used as the callback, the proxy/closure reference must be used - a new proxy or |
| * closure will not work. |
| * |
| * <h4>Example</h4> |
| * |
| * displayObject.removeEventListener("click", handleClick); |
| * |
| * @method removeEventListener |
| * @param {String} type The string type of the event. |
| * @param {Function | Object} listener The listener function or object. |
| * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. |
| **/ |
| p.removeEventListener = function(type, listener, useCapture) { |
| var listeners = useCapture ? this._captureListeners : this._listeners; |
| if (!listeners) { return; } |
| var arr = listeners[type]; |
| if (!arr) { return; } |
| for (var i=0,l=arr.length; i<l; i++) { |
| if (arr[i] == listener) { |
| if (l==1) { delete(listeners[type]); } // allows for faster checks. |
| else { arr.splice(i,1); } |
| break; |
| } |
| } |
| }; |
| |
| /** |
| * A shortcut to the removeEventListener method, with the same parameters and return value. This is a companion to the |
| * .on method. |
| * |
| * <b>IMPORTANT:</b> To remove a listener added with `on`, you must pass in the returned wrapper function as the listener. See |
| * {{#crossLink "EventDispatcher/on"}}{{/crossLink}} for an example. |
| * |
| * @method off |
| * @param {String} type The string type of the event. |
| * @param {Function | Object} listener The listener function or object. |
| * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. |
| **/ |
| p.off = p.removeEventListener; |
| |
| /** |
| * Removes all listeners for the specified type, or all listeners of all types. |
| * |
| * <h4>Example</h4> |
| * |
| * // Remove all listeners |
| * displayObject.removeAllEventListeners(); |
| * |
| * // Remove all click listeners |
| * displayObject.removeAllEventListeners("click"); |
| * |
| * @method removeAllEventListeners |
| * @param {String} [type] The string type of the event. If omitted, all listeners for all types will be removed. |
| **/ |
| p.removeAllEventListeners = function(type) { |
| if (!type) { this._listeners = this._captureListeners = null; } |
| else { |
| if (this._listeners) { delete(this._listeners[type]); } |
| if (this._captureListeners) { delete(this._captureListeners[type]); } |
| } |
| }; |
| |
| /** |
| * Dispatches the specified event to all listeners. |
| * |
| * <h4>Example</h4> |
| * |
| * // Use a string event |
| * this.dispatchEvent("complete"); |
| * |
| * // Use an Event instance |
| * var event = new createjs.Event("progress"); |
| * this.dispatchEvent(event); |
| * |
| * @method dispatchEvent |
| * @param {Object | String | Event} eventObj An object with a "type" property, or a string type. |
| * While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used, |
| * dispatchEvent will construct an Event instance if necessary with the specified type. This latter approach can |
| * be used to avoid event object instantiation for non-bubbling events that may not have any listeners. |
| * @param {Boolean} [bubbles] Specifies the `bubbles` value when a string was passed to eventObj. |
| * @param {Boolean} [cancelable] Specifies the `cancelable` value when a string was passed to eventObj. |
| * @return {Boolean} Returns false if `preventDefault()` was called on a cancelable event, true otherwise. |
| **/ |
| p.dispatchEvent = function(eventObj, bubbles, cancelable) { |
| if (typeof eventObj == "string") { |
| // skip everything if there's no listeners and it doesn't bubble: |
| var listeners = this._listeners; |
| if (!bubbles && (!listeners || !listeners[eventObj])) { return true; } |
| eventObj = new createjs.Event(eventObj, bubbles, cancelable); |
| } else if (eventObj.target && eventObj.clone) { |
| // redispatching an active event object, so clone it: |
| eventObj = eventObj.clone(); |
| } |
| |
| // TODO: it would be nice to eliminate this. Maybe in favour of evtObj instanceof Event? Or !!evtObj.createEvent |
| try { eventObj.target = this; } catch (e) {} // try/catch allows redispatching of native events |
| |
| if (!eventObj.bubbles || !this.parent) { |
| this._dispatchEvent(eventObj, 2); |
| } else { |
| var top=this, list=[top]; |
| while (top.parent) { list.push(top = top.parent); } |
| var i, l=list.length; |
| |
| // capture & atTarget |
| for (i=l-1; i>=0 && !eventObj.propagationStopped; i--) { |
| list[i]._dispatchEvent(eventObj, 1+(i==0)); |
| } |
| // bubbling |
| for (i=1; i<l && !eventObj.propagationStopped; i++) { |
| list[i]._dispatchEvent(eventObj, 3); |
| } |
| } |
| return !eventObj.defaultPrevented; |
| }; |
| |
| /** |
| * Indicates whether there is at least one listener for the specified event type. |
| * @method hasEventListener |
| * @param {String} type The string type of the event. |
| * @return {Boolean} Returns true if there is at least one listener for the specified event. |
| **/ |
| p.hasEventListener = function(type) { |
| var listeners = this._listeners, captureListeners = this._captureListeners; |
| return !!((listeners && listeners[type]) || (captureListeners && captureListeners[type])); |
| }; |
| |
| /** |
| * Indicates whether there is at least one listener for the specified event type on this object or any of its |
| * ancestors (parent, parent's parent, etc). A return value of true indicates that if a bubbling event of the |
| * specified type is dispatched from this object, it will trigger at least one listener. |
| * |
| * This is similar to {{#crossLink "EventDispatcher/hasEventListener"}}{{/crossLink}}, but it searches the entire |
| * event flow for a listener, not just this object. |
| * @method willTrigger |
| * @param {String} type The string type of the event. |
| * @return {Boolean} Returns `true` if there is at least one listener for the specified event. |
| **/ |
| p.willTrigger = function(type) { |
| var o = this; |
| while (o) { |
| if (o.hasEventListener(type)) { return true; } |
| o = o.parent; |
| } |
| return false; |
| }; |
| |
| /** |
| * @method toString |
| * @return {String} a string representation of the instance. |
| **/ |
| p.toString = function() { |
| return "[EventDispatcher]"; |
| }; |
| |
| |
| // private methods: |
| /** |
| * @method _dispatchEvent |
| * @param {Object | String | Event} eventObj |
| * @param {Object} eventPhase |
| * @protected |
| **/ |
| p._dispatchEvent = function(eventObj, eventPhase) { |
| var l, listeners = (eventPhase==1) ? this._captureListeners : this._listeners; |
| if (eventObj && listeners) { |
| var arr = listeners[eventObj.type]; |
| if (!arr||!(l=arr.length)) { return; } |
| try { eventObj.currentTarget = this; } catch (e) {} |
| try { eventObj.eventPhase = eventPhase; } catch (e) {} |
| eventObj.removed = false; |
| |
| arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch |
| for (var i=0; i<l && !eventObj.immediatePropagationStopped; i++) { |
| var o = arr[i]; |
| if (o.handleEvent) { o.handleEvent(eventObj); } |
| else { o(eventObj); } |
| if (eventObj.removed) { |
| this.off(eventObj.type, o, eventPhase==1); |
| eventObj.removed = false; |
| } |
| } |
| } |
| }; |
| |
| |
| createjs.EventDispatcher = EventDispatcher; |
| }()); |
| |
| //############################################################################## |
| // Ticker.js |
| //############################################################################## |
| |
| this.createjs = this.createjs||{}; |
| |
| (function() { |
| "use strict"; |
| |
| |
| // constructor: |
| /** |
| * The Ticker provides a centralized tick or heartbeat broadcast at a set interval. Listeners can subscribe to the tick |
| * event to be notified when a set time interval has elapsed. |
| * |
| * Note that the interval that the tick event is called is a target interval, and may be broadcast at a slower interval |
| * when under high CPU load. The Ticker class uses a static interface (ex. `Ticker.framerate = 30;`) and |
| * can not be instantiated. |
| * |
| * <h4>Example</h4> |
| * |
| * createjs.Ticker.addEventListener("tick", handleTick); |
| * function handleTick(event) { |
| * // Actions carried out each tick (aka frame) |
| * if (!event.paused) { |
| * // Actions carried out when the Ticker is not paused. |
| * } |
| * } |
| * |
| * @class Ticker |
| * @uses EventDispatcher |
| * @static |
| **/ |
| function Ticker() { |
| throw "Ticker cannot be instantiated."; |
| } |
| |
| |
| // constants: |
| /** |
| * In this mode, Ticker uses the requestAnimationFrame API, but attempts to synch the ticks to target framerate. It |
| * uses a simple heuristic that compares the time of the RAF return to the target time for the current frame and |
| * dispatches the tick when the time is within a certain threshold. |
| * |
| * This mode has a higher variance for time between frames than {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}}, |
| * but does not require that content be time based as with {{#crossLink "Ticker/RAF:property"}}{{/crossLink}} while |
| * gaining the benefits of that API (screen synch, background throttling). |
| * |
| * Variance is usually lowest for framerates that are a divisor of the RAF frequency. This is usually 60, so |
| * framerates of 10, 12, 15, 20, and 30 work well. |
| * |
| * Falls back to {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}} if the requestAnimationFrame API is not |
| * supported. |
| * @property RAF_SYNCHED |
| * @static |
| * @type {String} |
| * @default "synched" |
| * @readonly |
| **/ |
| Ticker.RAF_SYNCHED = "synched"; |
| |
| /** |
| * In this mode, Ticker passes through the requestAnimationFrame heartbeat, ignoring the target framerate completely. |
| * Because requestAnimationFrame frequency is not deterministic, any content using this mode should be time based. |
| * You can leverage {{#crossLink "Ticker/getTime"}}{{/crossLink}} and the {{#crossLink "Ticker/tick:event"}}{{/crossLink}} |
| * event object's "delta" properties to make this easier. |
| * |
| * Falls back on {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}} if the requestAnimationFrame API is not |
| * supported. |
| * @property RAF |
| * @static |
| * @type {String} |
| * @default "raf" |
| * @readonly |
| **/ |
| Ticker.RAF = "raf"; |
| |
| /** |
| * In this mode, Ticker uses the setTimeout API. This provides predictable, adaptive frame timing, but does not |
| * provide the benefits of requestAnimationFrame (screen synch, background throttling). |
| * @property TIMEOUT |
| * @static |
| * @type {String} |
| * @default "timeout" |
| * @readonly |
| **/ |
| Ticker.TIMEOUT = "timeout"; |
| |
| |
| // static events: |
| /** |
| * Dispatched each tick. The event will be dispatched to each listener even when the Ticker has been paused using |
| * {{#crossLink "Ticker/setPaused"}}{{/crossLink}}. |
| * |
| * <h4>Example</h4> |
| * |
| * createjs.Ticker.addEventListener("tick", handleTick); |
| * function handleTick(event) { |
| * console.log("Paused:", event.paused, event.delta); |
| * } |
| * |
| * @event tick |
| * @param {Object} target The object that dispatched the event. |
| * @param {String} type The event type. |
| * @param {Boolean} paused Indicates whether the ticker is currently paused. |
| * @param {Number} delta The time elapsed in ms since the last tick. |
| * @param {Number} time The total time in ms since Ticker was initialized. |
| * @param {Number} runTime The total time in ms that Ticker was not paused since it was initialized. For example, |
| * you could determine the amount of time that the Ticker has been paused since initialization with `time-runTime`. |
| * @since 0.6.0 |
| */ |
| |
| |
| // public static properties: |
| /** |
| * Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}, and will be removed in a future version. If true, timingMode will |
| * use {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} by default. |
| * @deprecated Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}. |
| * @property useRAF |
| * @static |
| * @type {Boolean} |
| * @default false |
| **/ |
| Ticker.useRAF = false; |
| |
| /** |
| * Specifies the timing api (setTimeout or requestAnimationFrame) and mode to use. See |
| * {{#crossLink "Ticker/TIMEOUT"}}{{/crossLink}}, {{#crossLink "Ticker/RAF"}}{{/crossLink}}, and |
| * {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} for mode details. |
| * @property timingMode |
| * @static |
| * @type {String} |
| * @default Ticker.TIMEOUT |
| **/ |
| Ticker.timingMode = null; |
| |
| /** |
| * Specifies a maximum value for the delta property in the tick event object. This is useful when building time |
| * based animations and systems to prevent issues caused by large time gaps caused by background tabs, system sleep, |
| * alert dialogs, or other blocking routines. Double the expected frame duration is often an effective value |
| * (ex. maxDelta=50 when running at 40fps). |
| * |
| * This does not impact any other values (ex. time, runTime, etc), so you may experience issues if you enable maxDelta |
| * when using both delta and other values. |
| * |
| * If 0, there is no maximum. |
| * @property maxDelta |
| * @static |
| * @type {number} |
| * @default 0 |
| */ |
| Ticker.maxDelta = 0; |
| |
| /** |
| * When the ticker is paused, all listeners will still receive a tick event, but the <code>paused</code> property |
| * of the event will be `true`. Also, while paused the `runTime` will not increase. See {{#crossLink "Ticker/tick:event"}}{{/crossLink}}, |
| * {{#crossLink "Ticker/getTime"}}{{/crossLink}}, and {{#crossLink "Ticker/getEventTime"}}{{/crossLink}} for more |
| * info. |
| * |
| * <h4>Example</h4> |
| * |
| * createjs.Ticker.addEventListener("tick", handleTick); |
| * createjs.Ticker.paused = true; |
| * function handleTick(event) { |
| * console.log(event.paused, |
| * createjs.Ticker.getTime(false), |
| * createjs.Ticker.getTime(true)); |
| * } |
| * |
| * @property paused |
| * @static |
| * @type {Boolean} |
| * @default false |
| **/ |
| Ticker.paused = false; |
| |
| |
| // mix-ins: |
| // EventDispatcher methods: |
| Ticker.removeEventListener = null; |
| Ticker.removeAllEventListeners = null; |
| Ticker.dispatchEvent = null; |
| Ticker.hasEventListener = null; |
| Ticker._listeners = null; |
| createjs.EventDispatcher.initialize(Ticker); // inject EventDispatcher methods. |
| Ticker._addEventListener = Ticker.addEventListener; |
| Ticker.addEventListener = function() { |
| !Ticker._inited&&Ticker.init(); |
| return Ticker._addEventListener.apply(Ticker, arguments); |
| }; |
| |
| |
| // private static properties: |
| /** |
| * @property _inited |
| * @static |
| * @type {Boolean} |
| * @protected |
| **/ |
| Ticker._inited = false; |
| |
| /** |
| * @property _startTime |
| * @static |
| * @type {Number} |
| * @protected |
| **/ |
| Ticker._startTime = 0; |
| |
| /** |
| * @property _pausedTime |
| * @static |
| * @type {Number} |
| * @protected |
| **/ |
| Ticker._pausedTime=0; |
| |
| /** |
| * The number of ticks that have passed |
| * @property _ticks |
| * @static |
| * @type {Number} |
| * @protected |
| **/ |
| Ticker._ticks = 0; |
| |
| /** |
| * The number of ticks that have passed while Ticker has been paused |
| * @property _pausedTicks |
| * @static |
| * @type {Number} |
| * @protected |
| **/ |
| Ticker._pausedTicks = 0; |
| |
| /** |
| * @property _interval |
| * @static |
| * @type {Number} |
| * @protected |
| **/ |
| Ticker._interval = 50; |
| |
| /** |
| * @property _lastTime |
| * @static |
| * @type {Number} |
| * @protected |
| **/ |
| Ticker._lastTime = 0; |
| |
| /** |
| * @property _times |
| * @static |
| * @type {Array} |
| * @protected |
| **/ |
| Ticker._times = null; |
| |
| /** |
| * @property _tickTimes |
| * @static |
| * @type {Array} |
| * @protected |
| **/ |
| Ticker._tickTimes = null; |
| |
| /** |
| * Stores the timeout or requestAnimationFrame id. |
| * @property _timerId |
| * @static |
| * @type {Number} |
| * @protected |
| **/ |
| Ticker._timerId = null; |
| |
| /** |
| * True if currently using requestAnimationFrame, false if using setTimeout. This may be different than timingMode |
| * if that property changed and a tick hasn't fired. |
| * @property _raf |
| * @static |
| * @type {Boolean} |
| * @protected |
| **/ |
| Ticker._raf = true; |
| |
| |
| // static getter / setters: |
| /** |
| * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead. |
| * @method setInterval |
| * @static |
| * @param {Number} interval |
| * @deprecated |
| **/ |
| Ticker.setInterval = function(interval) { |
| Ticker._interval = interval; |
| if (!Ticker._inited) { return; } |
| Ticker._setupTick(); |
| }; |
| |
| /** |
| * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead. |
| * @method getInterval |
| * @static |
| * @return {Number} |
| * @deprecated |
| **/ |
| Ticker.getInterval = function() { |
| return Ticker._interval; |
| }; |
| |
| /** |
| * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead. |
| * @method setFPS |
| * @static |
| * @param {Number} value |
| * @deprecated |
| **/ |
| Ticker.setFPS = function(value) { |
| Ticker.setInterval(1000/value); |
| }; |
| |
| /** |
| * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead. |
| * @method getFPS |
| * @static |
| * @return {Number} |
| * @deprecated |
| **/ |
| Ticker.getFPS = function() { |
| return 1000/Ticker._interval; |
| }; |
| |
| /** |
| * Indicates the target time (in milliseconds) between ticks. Default is 50 (20 FPS). |
| * Note that actual time between ticks may be more than specified depending on CPU load. |
| * This property is ignored if the ticker is using the `RAF` timing mode. |
| * @property interval |
| * @static |
| * @type {Number} |
| **/ |
| |
| /** |
| * Indicates the target frame rate in frames per second (FPS). Effectively just a shortcut to `interval`, where |
| * `framerate == 1000/interval`. |
| * @property framerate |
| * @static |
| * @type {Number} |
| **/ |
| try { |
| Object.defineProperties(Ticker, { |
| interval: { get: Ticker.getInterval, set: Ticker.setInterval }, |
| framerate: { get: Ticker.getFPS, set: Ticker.setFPS } |
| }); |
| } catch (e) { console.log(e); } |
| |
| |
| // public static methods: |
| /** |
| * Starts the tick. This is called automatically when the first listener is added. |
| * @method init |
| * @static |
| **/ |
| Ticker.init = function() { |
| if (Ticker._inited) { return; } |
| Ticker._inited = true; |
| Ticker._times = []; |
| Ticker._tickTimes = []; |
| Ticker._startTime = Ticker._getTime(); |
| Ticker._times.push(Ticker._lastTime = 0); |
| Ticker.interval = Ticker._interval; |
| }; |
| |
| /** |
| * Stops the Ticker and removes all listeners. Use init() to restart the Ticker. |
| * @method reset |
| * @static |
| **/ |
| Ticker.reset = function() { |
| if (Ticker._raf) { |
| var f = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame; |
| f&&f(Ticker._timerId); |
| } else { |
| clearTimeout(Ticker._timerId); |
| } |
| Ticker.removeAllEventListeners("tick"); |
| Ticker._timerId = Ticker._times = Ticker._tickTimes = null; |
| Ticker._startTime = Ticker._lastTime = Ticker._ticks = 0; |
| Ticker._inited = false; |
| }; |
| |
| /** |
| * Returns the average time spent within a tick. This can vary significantly from the value provided by getMeasuredFPS |
| * because it only measures the time spent within the tick execution stack. |
| * |
| * Example 1: With a target FPS of 20, getMeasuredFPS() returns 20fps, which indicates an average of 50ms between |
| * the end of one tick and the end of the next. However, getMeasuredTickTime() returns 15ms. This indicates that |
| * there may be up to 35ms of "idle" time between the end of one tick and the start of the next. |
| * |
| * Example 2: With a target FPS of 30, getFPS() returns 10fps, which indicates an average of 100ms between the end of |
| * one tick and the end of the next. However, getMeasuredTickTime() returns 20ms. This would indicate that something |
| * other than the tick is using ~80ms (another script, DOM rendering, etc). |
| * @method getMeasuredTickTime |
| * @static |
| * @param {Number} [ticks] The number of previous ticks over which to measure the average time spent in a tick. |
| * Defaults to the number of ticks per second. To get only the last tick's time, pass in 1. |
| * @return {Number} The average time spent in a tick in milliseconds. |
| **/ |
| Ticker.getMeasuredTickTime = function(ticks) { |
| var ttl=0, times=Ticker._tickTimes; |
| if (!times || times.length < 1) { return -1; } |
| |
| // by default, calculate average for the past ~1 second: |
| ticks = Math.min(times.length, ticks||(Ticker.getFPS()|0)); |
| for (var i=0; i<ticks; i++) { ttl += times[i]; } |
| return ttl/ticks; |
| }; |
| |
| /** |
| * Returns the actual frames / ticks per second. |
| * @method getMeasuredFPS |
| * @static |
| * @param {Number} [ticks] The number of previous ticks over which to measure the actual frames / ticks per second. |
| * Defaults to the number of ticks per second. |
| * @return {Number} The actual frames / ticks per second. Depending on performance, this may differ |
| * from the target frames per second. |
| **/ |
| Ticker.getMeasuredFPS = function(ticks) { |
| var times = Ticker._times; |
| if (!times || times.length < 2) { return -1; } |
| |
| // by default, calculate fps for the past ~1 second: |
| ticks = Math.min(times.length-1, ticks||(Ticker.getFPS()|0)); |
| return 1000/((times[0]-times[ticks])/ticks); |
| }; |
| |
| /** |
| * Use the {{#crossLink "Ticker/paused:property"}}{{/crossLink}} property instead. |
| * @method setPaused |
| * @static |
| * @param {Boolean} value |
| * @deprecated |
| **/ |
| Ticker.setPaused = function(value) { |
| // TODO: deprecated. |
| Ticker.paused = value; |
| }; |
| |
| /** |
| * Use the {{#crossLink "Ticker/paused:property"}}{{/crossLink}} property instead. |
| * @method getPaused |
| * @static |
| * @return {Boolean} |
| * @deprecated |
| **/ |
| Ticker.getPaused = function() { |
| // TODO: deprecated. |
| return Ticker.paused; |
| }; |
| |
| /** |
| * Returns the number of milliseconds that have elapsed since Ticker was initialized via {{#crossLink "Ticker/init"}}. |
| * Returns -1 if Ticker has not been initialized. For example, you could use |
| * this in a time synchronized animation to determine the exact amount of time that has elapsed. |
| * @method getTime |
| * @static |
| * @param {Boolean} [runTime=false] If true only time elapsed while Ticker was not paused will be returned. |
| * If false, the value returned will be total time elapsed since the first tick event listener was added. |
| * @return {Number} Number of milliseconds that have elapsed since Ticker was initialized or -1. |
| **/ |
| Ticker.getTime = function(runTime) { |
| return Ticker._startTime ? Ticker._getTime() - (runTime ? Ticker._pausedTime : 0) : -1; |
| }; |
| |
| /** |
| * Similar to the {{#crossLink "Ticker/getTime"}}{{/crossLink}} method, but returns the time on the most recent {{#crossLink "Ticker/tick:event"}}{{/crossLink}} |
| * event object. |
| * @method getEventTime |
| * @static |
| * @param runTime {Boolean} [runTime=false] If true, the runTime property will be returned instead of time. |
| * @returns {number} The time or runTime property from the most recent tick event or -1. |
| */ |
| Ticker.getEventTime = function(runTime) { |
| return Ticker._startTime ? (Ticker._lastTime || Ticker._startTime) - (runTime ? Ticker._pausedTime : 0) : -1; |
| }; |
| |
| /** |
| * Returns the number of ticks that have been broadcast by Ticker. |
| * @method getTicks |
| * @static |
| * @param {Boolean} pauseable Indicates whether to include ticks that would have been broadcast |
| * while Ticker was paused. If true only tick events broadcast while Ticker is not paused will be returned. |
| * If false, tick events that would have been broadcast while Ticker was paused will be included in the return |
| * value. The default value is false. |
| * @return {Number} of ticks that have been broadcast. |
| **/ |
| Ticker.getTicks = function(pauseable) { |
| return Ticker._ticks - (pauseable ? Ticker._pausedTicks : 0); |
| }; |
| |
| |
| // private static methods: |
| /** |
| * @method _handleSynch |
| * @static |
| * @protected |
| **/ |
| Ticker._handleSynch = function() { |
| Ticker._timerId = null; |
| Ticker._setupTick(); |
| |
| // run if enough time has elapsed, with a little bit of flexibility to be early: |
| if (Ticker._getTime() - Ticker._lastTime >= (Ticker._interval-1)*0.97) { |
| Ticker._tick(); |
| } |
| }; |
| |
| /** |
| * @method _handleRAF |
| * @static |
| * @protected |
| **/ |
| Ticker._handleRAF = function() { |
| Ticker._timerId = null; |
| Ticker._setupTick(); |
| Ticker._tick(); |
| }; |
| |
| /** |
| * @method _handleTimeout |
| * @static |
| * @protected |
| **/ |
| Ticker._handleTimeout = function() { |
| Ticker._timerId = null; |
| Ticker._setupTick(); |
| Ticker._tick(); |
| }; |
| |
| /** |
| * @method _setupTick |
| * @static |
| * @protected |
| **/ |
| Ticker._setupTick = function() { |
| if (Ticker._timerId != null) { return; } // avoid duplicates |
| |
| var mode = Ticker.timingMode||(Ticker.useRAF&&Ticker.RAF_SYNCHED); |
| if (mode == Ticker.RAF_SYNCHED || mode == Ticker.RAF) { |
| var f = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame; |
| if (f) { |
| Ticker._timerId = f(mode == Ticker.RAF ? Ticker._handleRAF : Ticker._handleSynch); |
| Ticker._raf = true; |
| return; |
| } |
| } |
| Ticker._raf = false; |
| Ticker._timerId = setTimeout(Ticker._handleTimeout, Ticker._interval); |
| }; |
| |
| /** |
| * @method _tick |
| * @static |
| * @protected |
| **/ |
| Ticker._tick = function() { |
| var paused = Ticker.paused; |
| var time = Ticker._getTime(); |
| var elapsedTime = time-Ticker._lastTime; |
| Ticker._lastTime = time; |
| Ticker._ticks++; |
| |
| if (paused) { |
| Ticker._pausedTicks++; |
| Ticker._pausedTime += elapsedTime; |
| } |
| |
| if (Ticker.hasEventListener("tick")) { |
| var event = new createjs.Event("tick"); |
| var maxDelta = Ticker.maxDelta; |
| event.delta = (maxDelta && elapsedTime > maxDelta) ? maxDelta : elapsedTime; |
| event.paused = paused; |
| event.time = time; |
| event.runTime = time-Ticker._pausedTime; |
| Ticker.dispatchEvent(event); |
| } |
| |
| Ticker._tickTimes.unshift(Ticker._getTime()-time); |
| while (Ticker._tickTimes.length > 100) { Ticker._tickTimes.pop(); } |
| |
| Ticker._times.unshift(time); |
| while (Ticker._times.length > 100) { Ticker._times.pop(); } |
| }; |
| |
| /** |
| * @method _getTime |
| * @static |
| * @protected |
| **/ |
| var now = window.performance && (performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow); |
| Ticker._getTime = function() { |
| return ((now&&now.call(performance))||(new Date().getTime())) - Ticker._startTime; |
| }; |
| |
| |
| createjs.Ticker = Ticker; |
| }()); |
| |
| //############################################################################## |
| // Tween.js |
| //############################################################################## |
| |
| // TODO: possibly add a END actionsMode (only runs actions that == position)? |
| // TODO: evaluate a way to decouple paused from tick registration. |
| |
| |
| this.createjs = this.createjs||{}; |
| |
| (function() { |
| "use strict"; |
| |
| |
| // constructor |
| /** |
| * A Tween instance tweens properties for a single target. Instance methods can be chained for easy construction and sequencing: |
| * |
| * <h4>Example</h4> |
| * |
| * target.alpha = 1; |
| * createjs.Tween.get(target) |
| * .wait(500) |
| * .to({alpha:0, visible:false}, 1000) |
| * .call(handleComplete); |
| * function handleComplete() { |
| * //Tween complete |
| * } |
| * |
| * Multiple tweens can point to the same instance, however if they affect the same properties there could be unexpected |
| * behaviour. To stop all tweens on an object, use {{#crossLink "Tween/removeTweens"}}{{/crossLink}} or pass `override:true` |
| * in the props argument. |
| * |
| * createjs.Tween.get(target, {override:true}).to({x:100}); |
| * |
| * Subscribe to the {{#crossLink "Tween/change:event"}}{{/crossLink}} event to get notified when a property of the |
| * target is changed. |
| * |
| * createjs.Tween.get(target, {override:true}).to({x:100}).addEventListener("change", handleChange); |
| * function handleChange(event) { |
| * // The tween changed. |
| * } |
| * |
| * See the Tween {{#crossLink "Tween/get"}}{{/crossLink}} method for additional param documentation. |
| * @class Tween |
| * @param {Object} target The target object that will have its properties tweened. |
| * @param {Object} [props] The configuration properties to apply to this tween instance (ex. `{loop:true, paused:true}`. |
| * All properties default to false. Supported props are:<UL> |
| * <LI> loop: sets the loop property on this tween.</LI> |
| * <LI> useTicks: uses ticks for all durations instead of milliseconds.</LI> |
| * <LI> ignoreGlobalPause: sets the {{#crossLink "Tween/ignoreGlobalPause:property"}}{{/crossLink}} property on this tween.</LI> |
| * <LI> override: if true, `Tween.removeTweens(target)` will be called to remove any other tweens with the same target. |
| * <LI> paused: indicates whether to start the tween paused.</LI> |
| * <LI> position: indicates the initial position for this tween.</LI> |
| * <LI> onChange: specifies a listener for the "change" event.</LI> |
| * </UL> |
| * @param {Object} [pluginData] An object containing data for use by installed plugins. See individual |
| * plugins' documentation for details. |
| * @extends EventDispatcher |
| * @constructor |
| */ |
| function Tween(target, props, pluginData) { |
| |
| // public properties: |
| /** |
| * Causes this tween to continue playing when a global pause is active. For example, if TweenJS is using {{#crossLink "Ticker"}}{{/crossLink}}, |
| * then setting this to true (the default) will cause this tween to be paused when <code>Ticker.setPaused(true)</code> |
| * is called. See the Tween {{#crossLink "Tween/tick"}}{{/crossLink}} method for more info. Can be set via the props |
| * parameter. |
| * @property ignoreGlobalPause |
| * @type Boolean |
| * @default false |
| */ |
| this.ignoreGlobalPause = false; |
| |
| /** |
| * If true, the tween will loop when it reaches the end. Can be set via the props param. |
| * @property loop |
| * @type {Boolean} |
| * @default false |
| */ |
| this.loop = false; |
| |
| /** |
| * Specifies the total duration of this tween in milliseconds (or ticks if useTicks is true). |
| * This value is automatically updated as you modify the tween. Changing it directly could result in unexpected |
| * behaviour. |
| * @property duration |
| * @type {Number} |
| * @default 0 |
| * @readonly |
| */ |
| this.duration = 0; |
| |
| /** |
| * Allows you to specify data that will be used by installed plugins. Each plugin uses this differently, but in general |
| * you specify data by setting it to a property of pluginData with the same name as the plugin class. |
| * @example |
| * myTween.pluginData.PluginClassName = data; |
| * <br/> |
| * Also, most plugins support a property to enable or disable them. This is typically the plugin class name followed by "_enabled".<br/> |
| * @example |
| * myTween.pluginData.PluginClassName_enabled = false;<br/> |
| * <br/> |
| * Some plugins also store instance data in this object, usually in a property named _PluginClassName. |
| * See the documentation for individual plugins for more details. |
| * @property pluginData |
| * @type {Object} |
| */ |
| this.pluginData = pluginData || {}; |
| |
| /** |
| * The target of this tween. This is the object on which the tweened properties will be changed. Changing |
| * this property after the tween is created will not have any effect. |
| * @property target |
| * @type {Object} |
| * @readonly |
| */ |
| this.target = target; |
| |
| /** |
| * The current normalized position of the tween. This will always be a value between 0 and duration. |
| * Changing this property directly will have no effect. |
| * @property position |
| * @type {Object} |
| * @readonly |
| */ |
| this.position = null; |
| |
| /** |
| * Indicates the tween's current position is within a passive wait. |
| * @property passive |
| * @type {Boolean} |
| * @default false |
| * @readonly |
| **/ |
| this.passive = false; |
| |
| // private properties: |
| /** |
| * @property _paused |
| * @type {Boolean} |
| * @default false |
| * @protected |
| */ |
| this._paused = false; |
| |
| /** |
| * @property _curQueueProps |
| * @type {Object} |
| * @protected |
| */ |
| this._curQueueProps = {}; |
| |
| /** |
| * @property _initQueueProps |
| * @type {Object} |
| * @protected |
| */ |
| this._initQueueProps = {}; |
| |
| /** |
| * @property _steps |
| * @type {Array} |
| * @protected |
| */ |
| this._steps = []; |
| |
| /** |
| * @property _actions |
| * @type {Array} |
| * @protected |
| */ |
| this._actions = []; |
| |
| /** |
| * Raw position. |
| * @property _prevPosition |
| * @type {Number} |
| * @default 0 |
| * @protected |
| */ |
| this._prevPosition = 0; |
| |
| /** |
| * The position within the current step. |
| * @property _stepPosition |
| * @type {Number} |
| * @default 0 |
| * @protected |
| */ |
| this._stepPosition = 0; // this is needed by MovieClip. |
| |
| /** |
| * Normalized position. |
| * @property _prevPos |
| * @type {Number} |
| * @default -1 |
| * @protected |
| */ |
| this._prevPos = -1; |
| |
| /** |
| * @property _target |
| * @type {Object} |
| * @protected |
| */ |
| this._target = target; |
| |
| /** |
| * @property _useTicks |
| * @type {Boolean} |
| * @default false |
| * @protected |
| */ |
| this._useTicks = false; |
| |
| /** |
| * @property _inited |
| * @type {boolean} |
| * @default false |
| * @protected |
| */ |
| this._inited = false; |
| |
| /** |
| * Indicates whether the tween is currently registered with Tween. |
| * @property _registered |
| * @type {boolean} |
| * @default false |
| * @protected |
| */ |
| this._registered = false; |
| |
| |
| if (props) { |
| this._useTicks = props.useTicks; |
| this.ignoreGlobalPause = props.ignoreGlobalPause; |
| this.loop = props.loop; |
| props.onChange && this.addEventListener("change", props.onChange); |
| if (props.override) { Tween.removeTweens(target); } |
| } |
| if (props&&props.paused) { this._paused=true; } |
| else { createjs.Tween._register(this,true); } |
| if (props&&props.position!=null) { this.setPosition(props.position, Tween.NONE); } |
| |
| }; |
| |
| var p = createjs.extend(Tween, createjs.EventDispatcher); |
| |
| // TODO: deprecated |
| // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. |
| |
| |
| // static properties |
| /** |
| * Constant defining the none actionsMode for use with setPosition. |
| * @property NONE |
| * @type Number |
| * @default 0 |
| * @static |
| */ |
| Tween.NONE = 0; |
| |
| /** |
| * Constant defining the loop actionsMode for use with setPosition. |
| * @property LOOP |
| * @type Number |
| * @default 1 |
| * @static |
| */ |
| Tween.LOOP = 1; |
| |
| /** |
| * Constant defining the reverse actionsMode for use with setPosition. |
| * @property REVERSE |
| * @type Number |
| * @default 2 |
| * @static |
| */ |
| Tween.REVERSE = 2; |
| |
| /** |
| * Constant returned by plugins to tell the tween not to use default assignment. |
| * @property IGNORE |
| * @type Object |
| * @static |
| */ |
| Tween.IGNORE = {}; |
| |
| /** |
| * @property _listeners |
| * @type Array[Tween] |
| * @static |
| * @protected |
| */ |
| Tween._tweens = []; |
| |
| /** |
| * @property _plugins |
| * @type Object |
| * @static |
| * @protected |
| */ |
| Tween._plugins = {}; |
| |
| |
| // static methods |
| /** |
| * Returns a new tween instance. This is functionally identical to using "new Tween(...)", but looks cleaner |
| * with the chained syntax of TweenJS. |
| * <h4>Example</h4> |
| * |
| * var tween = createjs.Tween.get(target); |
| * |
| * @method get |
| * @param {Object} target The target object that will have its properties tweened. |
| * @param {Object} [props] The configuration properties to apply to this tween instance (ex. `{loop:true, paused:true}`). |
| * All properties default to `false`. Supported props are: |
| * <UL> |
| * <LI> loop: sets the loop property on this tween.</LI> |
| * <LI> useTicks: uses ticks for all durations instead of milliseconds.</LI> |
| * <LI> ignoreGlobalPause: sets the {{#crossLink "Tween/ignoreGlobalPause:property"}}{{/crossLink}} property on |
| * this tween.</LI> |
| * <LI> override: if true, `createjs.Tween.removeTweens(target)` will be called to remove any other tweens with |
| * the same target. |
| * <LI> paused: indicates whether to start the tween paused.</LI> |
| * <LI> position: indicates the initial position for this tween.</LI> |
| * <LI> onChange: specifies a listener for the {{#crossLink "Tween/change:event"}}{{/crossLink}} event.</LI> |
| * </UL> |
| * @param {Object} [pluginData] An object containing data for use by installed plugins. See individual plugins' |
| * documentation for details. |
| * @param {Boolean} [override=false] If true, any previous tweens on the same target will be removed. This is the |
| * same as calling `Tween.removeTweens(target)`. |
| * @return {Tween} A reference to the created tween. Additional chained tweens, method calls, or callbacks can be |
| * applied to the returned tween instance. |
| * @static |
| */ |
| Tween.get = function(target, props, pluginData, override) { |
| if (override) { Tween.removeTweens(target); } |
| return new Tween(target, props, pluginData); |
| }; |
| |
| /** |
| * Advances all tweens. This typically uses the {{#crossLink "Ticker"}}{{/crossLink}} class, but you can call it |
| * manually if you prefer to use your own "heartbeat" implementation. |
| * @method tick |
| * @param {Number} delta The change in time in milliseconds since the last tick. Required unless all tweens have |
| * `useTicks` set to true. |
| * @param {Boolean} paused Indicates whether a global pause is in effect. Tweens with {{#crossLink "Tween/ignoreGlobalPause:property"}}{{/crossLink}} |
| * will ignore this, but all others will pause if this is `true`. |
| * @static |
| */ |
| Tween.tick = function(delta, paused) { |
| var tweens = Tween._tweens.slice(); // to avoid race conditions. |
| for (var i=tweens.length-1; i>=0; i--) { |
| var tween = tweens[i]; |
| if ((paused && !tween.ignoreGlobalPause) || tween._paused) { continue; } |
| tween.tick(tween._useTicks?1:delta); |
| } |
| }; |
| |
| /** |
| * Handle events that result from Tween being used as an event handler. This is included to allow Tween to handle |
| * {{#crossLink "Ticker/tick:event"}}{{/crossLink}} events from the createjs {{#crossLink "Ticker"}}{{/crossLink}}. |
| * No other events are handled in Tween. |
| * @method handleEvent |
| * @param {Object} event An event object passed in by the {{#crossLink "EventDispatcher"}}{{/crossLink}}. Will |
| * usually be of type "tick". |
| * @private |
| * @static |
| * @since 0.4.2 |
| */ |
| Tween.handleEvent = function(event) { |
| if (event.type == "tick") { |
| this.tick(event.delta, event.paused); |
| } |
| }; |
| |
| /** |
| * Removes all existing tweens for a target. This is called automatically by new tweens if the `override` |
| * property is `true`. |
| * @method removeTweens |
| * @param {Object} target The target object to remove existing tweens from. |
| * @static |
| */ |
| Tween.removeTweens = function(target) { |
| if (!target.tweenjs_count) { return; } |
| var tweens = Tween._tweens; |
| for (var i=tweens.length-1; i>=0; i--) { |
| var tween = tweens[i]; |
| if (tween._target == target) { |
| tween._paused = true; |
| tweens.splice(i, 1); |
| } |
| } |
| target.tweenjs_count = 0; |
| }; |
| |
| /** |
| * Stop and remove all existing tweens. |
| * @method removeAllTweens |
| * @static |
| * @since 0.4.1 |
| */ |
| Tween.removeAllTweens = function() { |
| var tweens = Tween._tweens; |
| for (var i= 0, l=tweens.length; i<l; i++) { |
| var tween = tweens[i]; |
| tween._paused = true; |
| tween.target&&(tween.target.tweenjs_count = 0); |
| } |
| tweens.length = 0; |
| }; |
| |
| /** |
| * Indicates whether there are any active tweens (and how many) on the target object (if specified) or in general. |
| * @method hasActiveTweens |
| * @param {Object} [target] The target to check for active tweens. If not specified, the return value will indicate |
| * if there are any active tweens on any target. |
| * @return {Boolean} If there are active tweens. |
| * @static |
| */ |
| Tween.hasActiveTweens = function(target) { |
| if (target) { return target.tweenjs_count != null && !!target.tweenjs_count; } |
| return Tween._tweens && !!Tween._tweens.length; |
| }; |
| |
| /** |
| * Installs a plugin, which can modify how certain properties are handled when tweened. See the {{#crossLink "CSSPlugin"}}{{/crossLink}} |
| * for an example of how to write TweenJS plugins. |
| * @method installPlugin |
| * @static |
| * @param {Object} plugin The plugin class to install |
| * @param {Array} properties An array of properties that the plugin will handle. |
| */ |
| Tween.installPlugin = function(plugin, properties) { |
| var priority = plugin.priority; |
| if (priority == null) { plugin.priority = priority = 0; } |
| for (var i=0,l=properties.length,p=Tween._plugins;i<l;i++) { |
| var n = properties[i]; |
| if (!p[n]) { p[n] = [plugin]; } |
| else { |
| var arr = p[n]; |
| for (var j=0,jl=arr.length;j<jl;j++) { |
| if (priority < arr[j].priority) { break; } |
| } |
| p[n].splice(j,0,plugin); |
| } |
| } |
| }; |
| |
| /** |
| * Registers or unregisters a tween with the ticking system. |
| * @method _register |
| * @param {Tween} tween The tween instance to register or unregister. |
| * @param {Boolean} value If `true`, the tween is registered. If `false` the tween is unregistered. |
| * @static |
| * @protected |
| */ |
| Tween._register = function(tween, value) { |
| var target = tween._target; |
| var tweens = Tween._tweens; |
| if (value && !tween._registered) { |
| // TODO: this approach might fail if a dev is using sealed objects in ES5 |
| if (target) { target.tweenjs_count = target.tweenjs_count ? target.tweenjs_count+1 : 1; } |
| tweens.push(tween); |
| if (!Tween._inited && createjs.Ticker) { createjs.Ticker.addEventListener("tick", Tween); Tween._inited = true; } |
| } else if (!value && tween._registered) { |
| if (target) { target.tweenjs_count--; } |
| var i = tweens.length; |
| while (i--) { |
| if (tweens[i] == tween) { |
| tweens.splice(i, 1); |
| break; |
| } |
| } |
| } |
| tween._registered = value; |
| }; |
| |
| |
| // events: |
| /** |
| * Called whenever the tween's position changes. |
| * @event change |
| * @since 0.4.0 |
| **/ |
| |
| |
| // public methods: |
| /** |
| * Queues a wait (essentially an empty tween). |
| * <h4>Example</h4> |
| * |
| * //This tween will wait 1s before alpha is faded to 0. |
| * createjs.Tween.get(target).wait(1000).to({alpha:0}, 1000); |
| * |
| * @method wait |
| * @param {Number} duration The duration of the wait in milliseconds (or in ticks if `useTicks` is true). |
| * @param {Boolean} [passive] Tween properties will not be updated during a passive wait. This |
| * is mostly useful for use with {{#crossLink "Timeline"}}{{/crossLink}} instances that contain multiple tweens |
| * affecting the same target at different times. |
| * @return {Tween} This tween instance (for chaining calls). |
| **/ |
| p.wait = function(duration, passive) { |
| if (duration == null || duration <= 0) { return this; } |
| var o = this._cloneProps(this._curQueueProps); |
| return this._addStep({d:duration, p0:o, e:this._linearEase, p1:o, v:passive}); |
| }; |
| |
| /** |
| * Queues a tween from the current values to the target properties. Set duration to 0 to jump to these value. |
| * Numeric properties will be tweened from their current value in the tween to the target value. Non-numeric |
| * properties will be set at the end of the specified duration. |
| * <h4>Example</h4> |
| * |
| * createjs.Tween.get(target).to({alpha:0}, 1000); |
| * |
| * @method to |
| * @param {Object} props An object specifying property target values for this tween (Ex. `{x:300}` would tween the x |
| * property of the target to 300). |
| * @param {Number} [duration=0] The duration of the wait in milliseconds (or in ticks if `useTicks` is true). |
| * @param {Function} [ease="linear"] The easing function to use for this tween. See the {{#crossLink "Ease"}}{{/crossLink}} |
| * class for a list of built-in ease functions. |
| * @return {Tween} This tween instance (for chaining calls). |
| */ |
| p.to = function(props, duration, ease) { |
| if (isNaN(duration) || duration < 0) { duration = 0; } |
| return this._addStep({d:duration||0, p0:this._cloneProps(this._curQueueProps), e:ease, p1:this._cloneProps(this._appendQueueProps(props))}); |
| }; |
| |
| /** |
| * Queues an action to call the specified function. |
| * <h4>Example</h4> |
| * |
| * //would call myFunction() after 1 second. |
| * myTween.wait(1000).call(myFunction); |
| * |
| * @method call |
| * @param {Function} callback The function to call. |
| * @param {Array} [params]. The parameters to call the function with. If this is omitted, then the function |
| * will be called with a single param pointing to this tween. |
| * @param {Object} [scope]. The scope to call the function in. If omitted, it will be called in the target's |
| * scope. |
| * @return {Tween} This tween instance (for chaining calls). |
| */ |
| p.call = function(callback, params, scope) { |
| return this._addAction({f:callback, p:params ? params : [this], o:scope ? scope : this._target}); |
| }; |
| |
| // TODO: add clarification between this and a 0 duration .to: |
| /** |
| * Queues an action to set the specified props on the specified target. If target is null, it will use this tween's |
| * target. |
| * <h4>Example</h4> |
| * |
| * myTween.wait(1000).set({visible:false},foo); |
| * |
| * @method set |
| * @param {Object} props The properties to set (ex. `{visible:false}`). |
| * @param {Object} [target] The target to set the properties on. If omitted, they will be set on the tween's target. |
| * @return {Tween} This tween instance (for chaining calls). |
| */ |
| p.set = function(props, target) { |
| return this._addAction({f:this._set, o:this, p:[props, target ? target : this._target]}); |
| }; |
| |
| /** |
| * Queues an action to play (unpause) the specified tween. This enables you to sequence multiple tweens. |
| * <h4>Example</h4> |
| * |
| * myTween.to({x:100},500).play(otherTween); |
| * |
| * @method play |
| * @param {Tween} tween The tween to play. |
| * @return {Tween} This tween instance (for chaining calls). |
| */ |
| p.play = function(tween) { |
| if (!tween) { tween = this; } |
| return this.call(tween.setPaused, [false], tween); |
| }; |
| |
| /** |
| * Queues an action to pause the specified tween. |
| * @method pause |
| * @param {Tween} tween The tween to pause. If null, it pauses this tween. |
| * @return {Tween} This tween instance (for chaining calls) |
| */ |
| p.pause = function(tween) { |
| if (!tween) { tween = this; } |
| return this.call(tween.setPaused, [true], tween); |
| }; |
| |
| /** |
| * Advances the tween to a specified position. |
| * @method setPosition |
| * @param {Number} value The position to seek to in milliseconds (or ticks if useTicks is true). |
| * @param {Number} [actionsMode=1] Specifies how actions are handled (ie. call, set, play, pause): |
| * <ul> |
| * <li>{{#crossLink "Tween/NONE:property"}}{{/crossLink}} (0) - run no actions.</li> |
| * <li>{{#crossLink "Tween/LOOP:property"}}{{/crossLink}} (1) - if new position is less than old, then run all |
| * actions between old and duration, then all actions between 0 and new.</li> |
| * <li>{{#crossLink "Tween/REVERSE:property"}}{{/crossLink}} (2) - if new position is less than old, run all |
| * actions between them in reverse.</li> |
| * </ul> |
| * @return {Boolean} Returns `true` if the tween is complete (ie. the full tween has run & {{#crossLink "Tween/loop:property"}}{{/crossLink}} |
| * is `false`). |
| */ |
| p.setPosition = function(value, actionsMode) { |
| if (value < 0) { value = 0; } |
| if (actionsMode == null) { actionsMode = 1; } |
| |
| // normalize position: |
| var t = value; |
| var end = false; |
| if (t >= this.duration) { |
| if (this.loop) { t = t%this.duration; } |
| else { |
| t = this.duration; |
| end = true; |
| } |
| } |
| if (t == this._prevPos) { return end; } |
| |
| |
| var prevPos = this._prevPos; |
| this.position = this._prevPos = t; // set this in advance in case an action modifies position. |
| this._prevPosition = value; |
| |
| // handle tweens: |
| if (this._target) { |
| if (end) { |
| // addresses problems with an ending zero length step. |
| this._updateTargetProps(null,1); |
| } else if (this._steps.length > 0) { |
| // find our new tween index: |
| for (var i=0, l=this._steps.length; i<l; i++) { |
| if (this._steps[i].t > t) { break; } |
| } |
| var step = this._steps[i-1]; |
| this._updateTargetProps(step,(this._stepPosition = t-step.t)/step.d); |
| } |
| } |
| |
| // run actions: |
| if (actionsMode != 0 && this._actions.length > 0) { |
| if (this._useTicks) { |
| // only run the actions we landed on. |
| this._runActions(t,t); |
| } else if (actionsMode == 1 && t<prevPos) { |
| if (prevPos != this.duration) { this._runActions(prevPos, this.duration); } |
| this._runActions(0, t, true); |
| } else { |
| this._runActions(prevPos, t); |
| } |
| } |
| |
| if (end) { this.setPaused(true); } |
| |
| this.dispatchEvent("change"); |
| return end; |
| }; |
| |
| /** |
| * Advances this tween by the specified amount of time in milliseconds (or ticks if`useTicks` is `true`). |
| * This is normally called automatically by the Tween engine (via {{#crossLink "Tween/tick"}}{{/crossLink}}), but is |
| * exposed for advanced uses. |
| * @method tick |
| * @param {Number} delta The time to advance in milliseconds (or ticks if `useTicks` is `true`). |
| */ |
| p.tick = function(delta) { |
| if (this._paused) { return; } |
| this.setPosition(this._prevPosition+delta); |
| }; |
| |
| /** |
| * Pauses or plays this tween. |
| * @method setPaused |
| * @param {Boolean} [value=true] Indicates whether the tween should be paused (`true`) or played (`false`). |
| * @return {Tween} This tween instance (for chaining calls) |
| */ |
| p.setPaused = function(value) { |
| if (this._paused === !!value) { return this; } |
| this._paused = !!value; |
| Tween._register(this, !value); |
| return this; |
| }; |
| |
| // tiny api (primarily for tool output): |
| p.w = p.wait; |
| p.t = p.to; |
| p.c = p.call; |
| p.s = p.set; |
| |
| /** |
| * Returns a string representation of this object. |
| * @method toString |
| * @return {String} a string representation of the instance. |
| */ |
| p.toString = function() { |
| return "[Tween]"; |
| }; |
| |
| /** |
| * @method clone |
| * @protected |
| */ |
| p.clone = function() { |
| throw("Tween can not be cloned.") |
| }; |
| |
| // private methods: |
| /** |
| * @method _updateTargetProps |
| * @param {Object} step |
| * @param {Number} ratio |
| * @protected |
| */ |
| p._updateTargetProps = function(step, ratio) { |
| var p0,p1,v,v0,v1,arr; |
| if (!step && ratio == 1) { |
| // GDS: when does this run? Just at the very end? Shouldn't. |
| this.passive = false; |
| p0 = p1 = this._curQueueProps; |
| } else { |
| this.passive = !!step.v; |
| if (this.passive) { return; } // don't update props. |
| // apply ease to ratio. |
| if (step.e) { ratio = step.e(ratio,0,1,1); } |
| p0 = step.p0; |
| p1 = step.p1; |
| } |
| |
| for (var n in this._initQueueProps) { |
| if ((v0 = p0[n]) == null) { p0[n] = v0 = this._initQueueProps[n]; } |
| if ((v1 = p1[n]) == null) { p1[n] = v1 = v0; } |
| if (v0 == v1 || ratio == 0 || ratio == 1 || (typeof(v0) != "number")) { |
| // no interpolation - either at start, end, values don't change, or the value is non-numeric. |
| v = ratio == 1 ? v1 : v0; |
| } else { |
| v = v0+(v1-v0)*ratio; |
| } |
| |
| var ignore = false; |
| if (arr = Tween._plugins[n]) { |
| for (var i=0,l=arr.length;i<l;i++) { |
| var v2 = arr[i].tween(this, n, v, p0, p1, ratio, !!step&&p0==p1, !step); |
| if (v2 == Tween.IGNORE) { ignore = true; } |
| else { v = v2; } |
| } |
| } |
| if (!ignore) { this._target[n] = v; } |
| } |
| |
| }; |
| |
| /** |
| * @method _runActions |
| * @param {Number} startPos |
| * @param {Number} endPos |
| * @param {Boolean} includeStart |
| * @protected |
| */ |
| p._runActions = function(startPos, endPos, includeStart) { |
| var sPos = startPos; |
| var ePos = endPos; |
| var i = -1; |
| var j = this._actions.length; |
| var k = 1; |
| if (startPos > endPos) { |
| // running backwards, flip everything: |
| sPos = endPos; |
| ePos = startPos; |
| i = j; |
| j = k = -1; |
| } |
| while ((i+=k) != j) { |
| var action = this._actions[i]; |
| var pos = action.t; |
| if (pos == ePos || (pos > sPos && pos < ePos) || (includeStart && pos == startPos) ) { |
| action.f.apply(action.o, action.p); |
| } |
| } |
| }; |
| |
| /** |
| * @method _appendQueueProps |
| * @param {Object} o |
| * @protected |
| */ |
| p._appendQueueProps = function(o) { |
| var arr,oldValue,i, l, injectProps; |
| for (var n in o) { |
| if (this._initQueueProps[n] === undefined) { |
| oldValue = this._target[n]; |
| |
| // init plugins: |
| if (arr = Tween._plugins[n]) { |
| for (i=0,l=arr.length;i<l;i++) { |
| oldValue = arr[i].init(this, n, oldValue); |
| } |
| } |
| this._initQueueProps[n] = this._curQueueProps[n] = (oldValue===undefined) ? null : oldValue; |
| } else { |
| oldValue = this._curQueueProps[n]; |
| } |
| } |
| |
| for (var n in o) { |
| oldValue = this._curQueueProps[n]; |
| if (arr = Tween._plugins[n]) { |
| injectProps = injectProps||{}; |
| for (i=0, l=arr.length;i<l;i++) { |
| // TODO: remove the check for .step in the next version. It's here for backwards compatibility. |
| if (arr[i].step) { arr[i].step(this, n, oldValue, o[n], injectProps); } |
| } |
| } |
| this._curQueueProps[n] = o[n]; |
| } |
| if (injectProps) { this._appendQueueProps(injectProps); } |
| return this._curQueueProps; |
| }; |
| |
| /** |
| * @method _cloneProps |
| * @param {Object} props |
| * @protected |
| */ |
| p._cloneProps = function(props) { |
| var o = {}; |
| for (var n in props) { |
| o[n] = props[n]; |
| } |
| return o; |
| }; |
| |
| /** |
| * @method _addStep |
| * @param {Object} o |
| * @protected |
| */ |
| p._addStep = function(o) { |
| if (o.d > 0) { |
| this._steps.push(o); |
| o.t = this.duration; |
| this.duration += o.d; |
| } |
| return this; |
| }; |
| |
| /** |
| * @method _addAction |
| * @param {Object} o |
| * @protected |
| */ |
| p._addAction = function(o) { |
| o.t = this.duration; |
| this._actions.push(o); |
| return this; |
| }; |
| |
| /** |
| * @method _set |
| * @param {Object} props |
| * @param {Object} o |
| * @protected |
| */ |
| p._set = function(props, o) { |
| for (var n in props) { |
| o[n] = props[n]; |
| } |
| }; |
| |
| createjs.Tween = createjs.promote(Tween, "EventDispatcher"); |
| |
| }()); |
| |
| //############################################################################## |
| // Timeline.js |
| //############################################################################## |
| |
| this.createjs = this.createjs||{}; |
| |
| |
| (function() { |
| "use strict"; |
| |
| |
| // constructor |
| /** |
| * The Timeline class synchronizes multiple tweens and allows them to be controlled as a group. Please note that if a |
| * timeline is looping, the tweens on it may appear to loop even if the "loop" property of the tween is false. |
| * @class Timeline |
| * @param {Array} tweens An array of Tweens to add to this timeline. See {{#crossLink "Timeline/addTween"}}{{/crossLink}} |
| * for more info. |
| * @param {Object} labels An object defining labels for using {{#crossLink "Timeline/gotoAndPlay"}}{{/crossLink}}/{{#crossLink "Timeline/gotoAndStop"}}{{/crossLink}}. |
| * See {{#crossLink "Timeline/setLabels"}}{{/crossLink}} |
| * for details. |
| * @param {Object} props The configuration properties to apply to this tween instance (ex. `{loop:true}`). All properties |
| * default to false. Supported props are:<UL> |
| * <LI> loop: sets the loop property on this tween.</LI> |
| * <LI> useTicks: uses ticks for all durations instead of milliseconds.</LI> |
| * <LI> ignoreGlobalPause: sets the ignoreGlobalPause property on this tween.</LI> |
| * <LI> paused: indicates whether to start the tween paused.</LI> |
| * <LI> position: indicates the initial position for this timeline.</LI> |
| * <LI> onChange: specifies a listener to add for the {{#crossLink "Timeline/change:event"}}{{/crossLink}} event.</LI> |
| * </UL> |
| * @extends EventDispatcher |
| * @constructor |
| **/ |
| function Timeline(tweens, labels, props) { |
| this.EventDispatcher_constructor(); |
| |
| // public properties: |
| /** |
| * Causes this timeline to continue playing when a global pause is active. |
| * @property ignoreGlobalPause |
| * @type Boolean |
| **/ |
| this.ignoreGlobalPause = false; |
| |
| /** |
| * The total duration of this timeline in milliseconds (or ticks if `useTicks `is `true`). This value is usually |
| * automatically updated as you modify the timeline. See {{#crossLink "Timeline/updateDuration"}}{{/crossLink}} |
| * for more information. |
| * @property duration |
| * @type Number |
| * @default 0 |
| * @readonly |
| **/ |
| this.duration = 0; |
| |
| /** |
| * If true, the timeline will loop when it reaches the end. Can be set via the props param. |
| * @property loop |
| * @type Boolean |
| **/ |
| this.loop = false; |
| |
| /** |
| * The current normalized position of the timeline. This will always be a value between 0 and |
| * {{#crossLink "Timeline/duration:property"}}{{/crossLink}}. |
| * Changing this property directly will have no effect. |
| * @property position |
| * @type Object |
| * @readonly |
| **/ |
| this.position = null; |
| |
| // private properties: |
| /** |
| * @property _paused |
| * @type Boolean |
| * @protected |
| **/ |
| this._paused = false; |
| |
| /** |
| * @property _tweens |
| * @type Array[Tween] |
| * @protected |
| **/ |
| this._tweens = []; |
| |
| /** |
| * @property _labels |
| * @type Object |
| * @protected |
| **/ |
| this._labels = null; |
| |
| /** |
| * @property _labelList |
| * @type Array[Object] |
| * @protected |
| **/ |
| this._labelList = null; |
| |
| /** |
| * @property _prevPosition |
| * @type Number |
| * @default 0 |
| * @protected |
| **/ |
| this._prevPosition = 0; |
| |
| /** |
| * @property _prevPos |
| * @type Number |
| * @default -1 |
| * @protected |
| **/ |
| this._prevPos = -1; |
| |
| /** |
| * @property _useTicks |
| * @type Boolean |
| * @default false |
| * @protected |
| **/ |
| this._useTicks = false; |
| |
| /** |
| * Indicates whether the timeline is currently registered with Tween. |
| * @property _registered |
| * @type {boolean} |
| * @default false |
| * @protected |
| */ |
| this._registered = false; |
| |
| |
| if (props) { |
| this._useTicks = props.useTicks; |
| this.loop = props.loop; |
| this.ignoreGlobalPause = props.ignoreGlobalPause; |
| props.onChange&&this.addEventListener("change", props.onChange); |
| } |
| if (tweens) { this.addTween.apply(this, tweens); } |
| this.setLabels(labels); |
| if (props&&props.paused) { this._paused=true; } |
| else { createjs.Tween._register(this,true); } |
| if (props&&props.position!=null) { this.setPosition(props.position, createjs.Tween.NONE); } |
| |
| }; |
| |
| var p = createjs.extend(Timeline, createjs.EventDispatcher); |
| |
| // TODO: deprecated |
| // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. |
| |
| |
| // events: |
| /** |
| * Called whenever the timeline's position changes. |
| * @event change |
| * @since 0.5.0 |
| **/ |
| |
| |
| // public methods: |
| /** |
| * Adds one or more tweens (or timelines) to this timeline. The tweens will be paused (to remove them from the |
| * normal ticking system) and managed by this timeline. Adding a tween to multiple timelines will result in |
| * unexpected behaviour. |
| * @method addTween |
| * @param {Tween} ...tween The tween(s) to add. Accepts multiple arguments. |
| * @return {Tween} The first tween that was passed in. |
| **/ |
| p.addTween = function(tween) { |
| var l = arguments.length; |
| if (l > 1) { |
| for (var i=0; i<l; i++) { this.addTween(arguments[i]); } |
| return arguments[0]; |
| } else if (l == 0) { return null; } |
| this.removeTween(tween); |
| this._tweens.push(tween); |
| tween.setPaused(true); |
| tween._paused = false; |
| tween._useTicks = this._useTicks; |
| if (tween.duration > this.duration) { this.duration = tween.duration; } |
| if (this._prevPos >= 0) { tween.setPosition(this._prevPos, createjs.Tween.NONE); } |
| return tween; |
| }; |
| |
| /** |
| * Removes one or more tweens from this timeline. |
| * @method removeTween |
| * @param {Tween} ...tween The tween(s) to remove. Accepts multiple arguments. |
| * @return Boolean Returns `true` if all of the tweens were successfully removed. |
| **/ |
| p.removeTween = function(tween) { |
| var l = arguments.length; |
| if (l > 1) { |
| var good = true; |
| for (var i=0; i<l; i++) { good = good && this.removeTween(arguments[i]); } |
| return good; |
| } else if (l == 0) { return false; } |
| |
| var tweens = this._tweens; |
| var i = tweens.length; |
| while (i--) { |
| if (tweens[i] == tween) { |
| tweens.splice(i, 1); |
| if (tween.duration >= this.duration) { this.updateDuration(); } |
| return true; |
| } |
| } |
| return false; |
| }; |
| |
| /** |
| * Adds a label that can be used with {{#crossLink "Timeline/gotoAndPlay"}}{{/crossLink}}/{{#crossLink "Timeline/gotoAndStop"}}{{/crossLink}}. |
| * @method addLabel |
| * @param {String} label The label name. |
| * @param {Number} position The position this label represents. |
| **/ |
| p.addLabel = function(label, position) { |
| this._labels[label] = position; |
| var list = this._labelList; |
| if (list) { |
| for (var i= 0,l=list.length; i<l; i++) { if (position < list[i].position) { break; } } |
| list.splice(i, 0, {label:label, position:position}); |
| } |
| }; |
| |
| /** |
| * Defines labels for use with gotoAndPlay/Stop. Overwrites any previously set labels. |
| * @method setLabels |
| * @param {Object} o An object defining labels for using {{#crossLink "Timeline/gotoAndPlay"}}{{/crossLink}}/{{#crossLink "Timeline/gotoAndStop"}}{{/crossLink}} |
| * in the form `{labelName:time}` where time is in milliseconds (or ticks if `useTicks` is `true`). |
| **/ |
| p.setLabels = function(o) { |
| this._labels = o ? o : {}; |
| }; |
| |
| /** |
| * Returns a sorted list of the labels defined on this timeline. |
| * @method getLabels |
| * @return {Array[Object]} A sorted array of objects with label and position properties. |
| **/ |
| p.getLabels = function() { |
| var list = this._labelList; |
| if (!list) { |
| list = this._labelList = []; |
| var labels = this._labels; |
| for (var n in labels) { |
| list.push({label:n, position:labels[n]}); |
| } |
| list.sort(function (a,b) { return a.position- b.position; }); |
| } |
| return list; |
| }; |
| |
| /** |
| * Returns the name of the label on or immediately before the current position. For example, given a timeline with |
| * two labels, "first" on frame index 4, and "second" on frame 8, getCurrentLabel would return: |
| * <UL> |
| * <LI>null if the current position is 2.</LI> |
| * <LI>"first" if the current position is 4.</LI> |
| * <LI>"first" if the current position is 7.</LI> |
| * <LI>"second" if the current position is 15.</LI> |
| * </UL> |
| * @method getCurrentLabel |
| * @return {String} The name of the current label or null if there is no label |
| **/ |
| p.getCurrentLabel = function() { |
| var labels = this.getLabels(); |
| var pos = this.position; |
| var l = labels.length; |
| if (l) { |
| for (var i = 0; i<l; i++) { if (pos < labels[i].position) { break; } } |
| return (i==0) ? null : labels[i-1].label; |
| } |
| return null; |
| }; |
| |
| /** |
| * Unpauses this timeline and jumps to the specified position or label. |
| * @method gotoAndPlay |
| * @param {String|Number} positionOrLabel The position in milliseconds (or ticks if `useTicks` is `true`) |
| * or label to jump to. |
| **/ |
| p.gotoAndPlay = function(positionOrLabel) { |
| this.setPaused(false); |
| this._goto(positionOrLabel); |
| }; |
| |
| /** |
| * Pauses this timeline and jumps to the specified position or label. |
| * @method gotoAndStop |
| * @param {String|Number} positionOrLabel The position in milliseconds (or ticks if `useTicks` is `true`) or label |
| * to jump to. |
| **/ |
| p.gotoAndStop = function(positionOrLabel) { |
| this.setPaused(true); |
| this._goto(positionOrLabel); |
| }; |
| |
| /** |
| * Advances the timeline to the specified position. |
| * @method setPosition |
| * @param {Number} value The position to seek to in milliseconds (or ticks if `useTicks` is `true`). |
| * @param {Number} [actionsMode] parameter specifying how actions are handled. See the Tween {{#crossLink "Tween/setPosition"}}{{/crossLink}} |
| * method for more details. |
| * @return {Boolean} Returns `true` if the timeline is complete (ie. the full timeline has run & {{#crossLink "Timeline/loop:property"}}{{/crossLink}} |
| * is `false`). |
| **/ |
| p.setPosition = function(value, actionsMode) { |
| var t = this._calcPosition(value); |
| var end = !this.loop && value >= this.duration; |
| if (t == this._prevPos) { return end; } |
| this._prevPosition = value; |
| this.position = this._prevPos = t; // in case an action changes the current frame. |
| for (var i=0, l=this._tweens.length; i<l; i++) { |
| this._tweens[i].setPosition(t, actionsMode); |
| if (t != this._prevPos) { return false; } // an action changed this timeline's position. |
| } |
| if (end) { this.setPaused(true); } |
| this.dispatchEvent("change"); |
| return end; |
| }; |
| |
| /** |
| * Pauses or plays this timeline. |
| * @method setPaused |
| * @param {Boolean} value Indicates whether the tween should be paused (`true`) or played (`false`). |
| **/ |
| p.setPaused = function(value) { |
| this._paused = !!value; |
| createjs.Tween._register(this, !value); |
| }; |
| |
| /** |
| * Recalculates the duration of the timeline. The duration is automatically updated when tweens are added or removed, |
| * but this method is useful if you modify a tween after it was added to the timeline. |
| * @method updateDuration |
| **/ |
| p.updateDuration = function() { |
| this.duration = 0; |
| for (var i=0,l=this._tweens.length; i<l; i++) { |
| var tween = this._tweens[i]; |
| if (tween.duration > this.duration) { this.duration = tween.duration; } |
| } |
| }; |
| |
| /** |
| * Advances this timeline by the specified amount of time in milliseconds (or ticks if `useTicks` is `true`). |
| * This is normally called automatically by the Tween engine (via the {{#crossLink "Tween/tick:event"}}{{/crossLink}} |
| * event), but is exposed for advanced uses. |
| * @method tick |
| * @param {Number} delta The time to advance in milliseconds (or ticks if useTicks is true). |
| **/ |
| p.tick = function(delta) { |
| this.setPosition(this._prevPosition+delta); |
| }; |
| |
| /** |
| * If a numeric position is passed, it is returned unchanged. If a string is passed, the position of the |
| * corresponding frame label will be returned, or `null` if a matching label is not defined. |
| * @method resolve |
| * @param {String|Number} positionOrLabel A numeric position value or label string. |
| **/ |
| p.resolve = function(positionOrLabel) { |
| var pos = Number(positionOrLabel); |
| if (isNaN(pos)) { pos = this._labels[positionOrLabel]; } |
| return pos; |
| }; |
| |
| /** |
| * Returns a string representation of this object. |
| * @method toString |
| * @return {String} a string representation of the instance. |
| **/ |
| p.toString = function() { |
| return "[Timeline]"; |
| }; |
| |
| /** |
| * @method clone |
| * @protected |
| **/ |
| p.clone = function() { |
| throw("Timeline can not be cloned.") |
| }; |
| |
| // private methods: |
| /** |
| * @method _goto |
| * @param {String | Number} positionOrLabel |
| * @protected |
| **/ |
| p._goto = function(positionOrLabel) { |
| var pos = this.resolve(positionOrLabel); |
| if (pos != null) { this.setPosition(pos); } |
| }; |
| |
| /** |
| * @method _calcPosition |
| * @param {Number} value |
| * @return {Number} |
| * @protected |
| **/ |
| p._calcPosition = function(value) { |
| if (value < 0) { return 0; } |
| if (value < this.duration) { return value; } |
| return this.loop ? value%this.duration : this.duration; |
| }; |
| |
| createjs.Timeline = createjs.promote(Timeline, "EventDispatcher"); |
| |
| }()); |
| |
| //############################################################################## |
| // Ease.js |
| //############################################################################## |
| |
| this.createjs = this.createjs||{}; |
| |
| (function() { |
| "use strict"; |
| |
| /** |
| * The Ease class provides a collection of easing functions for use with TweenJS. It does not use the standard 4 param |
| * easing signature. Instead it uses a single param which indicates the current linear ratio (0 to 1) of the tween. |
| * |
| * Most methods on Ease can be passed directly as easing functions: |
| * |
| * Tween.get(target).to({x:100}, 500, Ease.linear); |
| * |
| * However, methods beginning with "get" will return an easing function based on parameter values: |
| * |
| * Tween.get(target).to({y:200}, 500, Ease.getPowIn(2.2)); |
| * |
| * Please see the <a href="http://www.createjs.com/Demos/TweenJS/Tween_SparkTable">spark table demo</a> for an |
| * overview of the different ease types on <a href="http://tweenjs.com">TweenJS.com</a>. |
| * |
| * <em>Equations derived from work by Robert Penner.</em> |
| * @class Ease |
| * @static |
| **/ |
| function Ease() { |
| throw "Ease cannot be instantiated."; |
| } |
| |
| |
| // static methods and properties |
| /** |
| * @method linear |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.linear = function(t) { return t; }; |
| |
| /** |
| * Identical to linear. |
| * @method none |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.none = Ease.linear; |
| |
| /** |
| * Mimics the simple -100 to 100 easing in Flash Pro. |
| * @method get |
| * @param {Number} amount A value from -1 (ease in) to 1 (ease out) indicating the strength and direction of the ease. |
| * @static |
| * @return {Function} |
| **/ |
| Ease.get = function(amount) { |
| if (amount < -1) { amount = -1; } |
| if (amount > 1) { amount = 1; } |
| return function(t) { |
| if (amount==0) { return t; } |
| if (amount<0) { return t*(t*-amount+1+amount); } |
| return t*((2-t)*amount+(1-amount)); |
| }; |
| }; |
| |
| /** |
| * Configurable exponential ease. |
| * @method getPowIn |
| * @param {Number} pow The exponent to use (ex. 3 would return a cubic ease). |
| * @static |
| * @return {Function} |
| **/ |
| Ease.getPowIn = function(pow) { |
| return function(t) { |
| return Math.pow(t,pow); |
| }; |
| }; |
| |
| /** |
| * Configurable exponential ease. |
| * @method getPowOut |
| * @param {Number} pow The exponent to use (ex. 3 would return a cubic ease). |
| * @static |
| * @return {Function} |
| **/ |
| Ease.getPowOut = function(pow) { |
| return function(t) { |
| return 1-Math.pow(1-t,pow); |
| }; |
| }; |
| |
| /** |
| * Configurable exponential ease. |
| * @method getPowInOut |
| * @param {Number} pow The exponent to use (ex. 3 would return a cubic ease). |
| * @static |
| * @return {Function} |
| **/ |
| Ease.getPowInOut = function(pow) { |
| return function(t) { |
| if ((t*=2)<1) return 0.5*Math.pow(t,pow); |
| return 1-0.5*Math.abs(Math.pow(2-t,pow)); |
| }; |
| }; |
| |
| /** |
| * @method quadIn |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.quadIn = Ease.getPowIn(2); |
| /** |
| * @method quadOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.quadOut = Ease.getPowOut(2); |
| /** |
| * @method quadInOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.quadInOut = Ease.getPowInOut(2); |
| |
| /** |
| * @method cubicIn |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.cubicIn = Ease.getPowIn(3); |
| /** |
| * @method cubicOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.cubicOut = Ease.getPowOut(3); |
| /** |
| * @method cubicInOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.cubicInOut = Ease.getPowInOut(3); |
| |
| /** |
| * @method quartIn |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.quartIn = Ease.getPowIn(4); |
| /** |
| * @method quartOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.quartOut = Ease.getPowOut(4); |
| /** |
| * @method quartInOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.quartInOut = Ease.getPowInOut(4); |
| |
| /** |
| * @method quintIn |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.quintIn = Ease.getPowIn(5); |
| /** |
| * @method quintOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.quintOut = Ease.getPowOut(5); |
| /** |
| * @method quintInOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.quintInOut = Ease.getPowInOut(5); |
| |
| /** |
| * @method sineIn |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.sineIn = function(t) { |
| return 1-Math.cos(t*Math.PI/2); |
| }; |
| |
| /** |
| * @method sineOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.sineOut = function(t) { |
| return Math.sin(t*Math.PI/2); |
| }; |
| |
| /** |
| * @method sineInOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.sineInOut = function(t) { |
| return -0.5*(Math.cos(Math.PI*t) - 1); |
| }; |
| |
| /** |
| * Configurable "back in" ease. |
| * @method getBackIn |
| * @param {Number} amount The strength of the ease. |
| * @static |
| * @return {Function} |
| **/ |
| Ease.getBackIn = function(amount) { |
| return function(t) { |
| return t*t*((amount+1)*t-amount); |
| }; |
| }; |
| /** |
| * @method backIn |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.backIn = Ease.getBackIn(1.7); |
| |
| /** |
| * Configurable "back out" ease. |
| * @method getBackOut |
| * @param {Number} amount The strength of the ease. |
| * @static |
| * @return {Function} |
| **/ |
| Ease.getBackOut = function(amount) { |
| return function(t) { |
| return (--t*t*((amount+1)*t + amount) + 1); |
| }; |
| }; |
| /** |
| * @method backOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.backOut = Ease.getBackOut(1.7); |
| |
| /** |
| * Configurable "back in out" ease. |
| * @method getBackInOut |
| * @param {Number} amount The strength of the ease. |
| * @static |
| * @return {Function} |
| **/ |
| Ease.getBackInOut = function(amount) { |
| amount*=1.525; |
| return function(t) { |
| if ((t*=2)<1) return 0.5*(t*t*((amount+1)*t-amount)); |
| return 0.5*((t-=2)*t*((amount+1)*t+amount)+2); |
| }; |
| }; |
| /** |
| * @method backInOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.backInOut = Ease.getBackInOut(1.7); |
| |
| /** |
| * @method circIn |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.circIn = function(t) { |
| return -(Math.sqrt(1-t*t)- 1); |
| }; |
| |
| /** |
| * @method circOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.circOut = function(t) { |
| return Math.sqrt(1-(--t)*t); |
| }; |
| |
| /** |
| * @method circInOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.circInOut = function(t) { |
| if ((t*=2) < 1) return -0.5*(Math.sqrt(1-t*t)-1); |
| return 0.5*(Math.sqrt(1-(t-=2)*t)+1); |
| }; |
| |
| /** |
| * @method bounceIn |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.bounceIn = function(t) { |
| return 1-Ease.bounceOut(1-t); |
| }; |
| |
| /** |
| * @method bounceOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.bounceOut = function(t) { |
| if (t < 1/2.75) { |
| return (7.5625*t*t); |
| } else if (t < 2/2.75) { |
| return (7.5625*(t-=1.5/2.75)*t+0.75); |
| } else if (t < 2.5/2.75) { |
| return (7.5625*(t-=2.25/2.75)*t+0.9375); |
| } else { |
| return (7.5625*(t-=2.625/2.75)*t +0.984375); |
| } |
| }; |
| |
| /** |
| * @method bounceInOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.bounceInOut = function(t) { |
| if (t<0.5) return Ease.bounceIn (t*2) * .5; |
| return Ease.bounceOut(t*2-1)*0.5+0.5; |
| }; |
| |
| /** |
| * Configurable elastic ease. |
| * @method getElasticIn |
| * @param {Number} amplitude |
| * @param {Number} period |
| * @static |
| * @return {Function} |
| **/ |
| Ease.getElasticIn = function(amplitude,period) { |
| var pi2 = Math.PI*2; |
| return function(t) { |
| if (t==0 || t==1) return t; |
| var s = period/pi2*Math.asin(1/amplitude); |
| return -(amplitude*Math.pow(2,10*(t-=1))*Math.sin((t-s)*pi2/period)); |
| }; |
| }; |
| /** |
| * @method elasticIn |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.elasticIn = Ease.getElasticIn(1,0.3); |
| |
| /** |
| * Configurable elastic ease. |
| * @method getElasticOut |
| * @param {Number} amplitude |
| * @param {Number} period |
| * @static |
| * @return {Function} |
| **/ |
| Ease.getElasticOut = function(amplitude,period) { |
| var pi2 = Math.PI*2; |
| return function(t) { |
| if (t==0 || t==1) return t; |
| var s = period/pi2 * Math.asin(1/amplitude); |
| return (amplitude*Math.pow(2,-10*t)*Math.sin((t-s)*pi2/period )+1); |
| }; |
| }; |
| /** |
| * @method elasticOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.elasticOut = Ease.getElasticOut(1,0.3); |
| |
| /** |
| * Configurable elastic ease. |
| * @method getElasticInOut |
| * @param {Number} amplitude |
| * @param {Number} period |
| * @static |
| * @return {Function} |
| **/ |
| Ease.getElasticInOut = function(amplitude,period) { |
| var pi2 = Math.PI*2; |
| return function(t) { |
| var s = period/pi2 * Math.asin(1/amplitude); |
| if ((t*=2)<1) return -0.5*(amplitude*Math.pow(2,10*(t-=1))*Math.sin( (t-s)*pi2/period )); |
| return amplitude*Math.pow(2,-10*(t-=1))*Math.sin((t-s)*pi2/period)*0.5+1; |
| }; |
| }; |
| /** |
| * @method elasticInOut |
| * @param {Number} t |
| * @static |
| * @return {Number} |
| **/ |
| Ease.elasticInOut = Ease.getElasticInOut(1,0.3*1.5); |
| |
| createjs.Ease = Ease; |
| |
| }()); |
| |
| //############################################################################## |
| // MotionGuidePlugin.js |
| //############################################################################## |
| |
| this.createjs = this.createjs||{}; |
| |
| (function() { |
| "use strict"; |
| |
| /** |
| * A TweenJS plugin for working with motion guides. |
| * |
| * To use, install the plugin after TweenJS has loaded. Next tween the 'guide' property with an object as detailed below. |
| * |
| * createjs.MotionGuidePlugin.install(); |
| * |
| * <h4>Example</h4> |
| * |
| * // Using a Motion Guide |
| * createjs.Tween.get(target).to({guide:{ path:[0,0, 0,200,200,200, 200,0,0,0] }},7000); |
| * // Visualizing the line |
| * graphics.moveTo(0,0).curveTo(0,200,200,200).curveTo(200,0,0,0); |
| * |
| * Each path needs pre-computation to ensure there's fast performance. Because of the pre-computation there's no |
| * built in support for path changes mid tween. These are the Guide Object's properties:<UL> |
| * <LI> path: Required, Array : The x/y points used to draw the path with a moveTo and 1 to n curveTo calls.</LI> |
| * <LI> start: Optional, 0-1 : Initial position, default 0 except for when continuing along the same path.</LI> |
| * <LI> end: Optional, 0-1 : Final position, default 1 if not specified.</LI> |
| * <LI> orient: Optional, string : "fixed"/"auto"/"cw"/"ccw"<UL> |
| * <LI>"fixed" forces the object to face down the path all movement (relative to start rotation),</LI> |
| * <LI>"auto" rotates the object along the path relative to the line.</LI> |
| * <LI>"cw"/"ccw" force clockwise or counter clockwise rotations including flash like behaviour</LI> |
| * </UL></LI> |
| * </UL> |
| * Guide objects should not be shared between tweens even if all properties are identical, the library stores |
| * information on these objects in the background and sharing them can cause unexpected behaviour. Values |
| * outside 0-1 range of tweens will be a "best guess" from the appropriate part of the defined curve. |
| * |
| * @class MotionGuidePlugin |
| * @constructor |
| **/ |
| function MotionGuidePlugin() { |
| throw("MotionGuidePlugin cannot be instantiated.") |
| }; |
| |
| |
| // static properties: |
| /** |
| * @property priority |
| * @protected |
| * @static |
| **/ |
| MotionGuidePlugin.priority = 0; // high priority, should run sooner |
| |
| /** |
| * @property temporary variable storage |
| * @private |
| * @static |
| */ |
| MotionGuidePlugin._rotOffS; |
| /** |
| * @property temporary variable storage |
| * @private |
| * @static |
| */ |
| MotionGuidePlugin._rotOffE; |
| /** |
| * @property temporary variable storage |
| * @private |
| * @static |
| */ |
| MotionGuidePlugin._rotNormS; |
| /** |
| * @property temporary variable storage |
| * @private |
| * @static |
| */ |
| MotionGuidePlugin._rotNormE; |
| |
| |
| // static methods |
| /** |
| * Installs this plugin for use with TweenJS. Call this once after TweenJS is loaded to enable this plugin. |
| * @method install |
| * @static |
| **/ |
| MotionGuidePlugin.install = function() { |
| createjs.Tween.installPlugin(MotionGuidePlugin, ["guide", "x", "y", "rotation"]); |
| return createjs.Tween.IGNORE; |
| }; |
| |
| /** |
| * @method init |
| * @protected |
| * @static |
| **/ |
| MotionGuidePlugin.init = function(tween, prop, value) { |
| var target = tween.target; |
| if(!target.hasOwnProperty("x")){ target.x = 0; } |
| if(!target.hasOwnProperty("y")){ target.y = 0; } |
| if(!target.hasOwnProperty("rotation")){ target.rotation = 0; } |
| |
| if(prop=="rotation"){ tween.__needsRot = true; } |
| return prop=="guide"?null:value; |
| }; |
| |
| /** |
| * @method step |
| * @protected |
| * @static |
| **/ |
| MotionGuidePlugin.step = function(tween, prop, startValue, endValue, injectProps) { |
| // other props |
| if(prop == "rotation"){ |
| tween.__rotGlobalS = startValue; |
| tween.__rotGlobalE = endValue; |
| MotionGuidePlugin.testRotData(tween, injectProps); |
| } |
| if(prop != "guide"){ return endValue; } |
| |
| // guide only information - Start - |
| var temp, data = endValue; |
| if(!data.hasOwnProperty("path")){ data.path = []; } |
| var path = data.path; |
| if(!data.hasOwnProperty("end")){ data.end = 1; } |
| if(!data.hasOwnProperty("start")){ |
| data.start = (startValue&&startValue.hasOwnProperty("end")&&startValue.path===path)?startValue.end:0; |
| } |
| |
| // Figure out subline information |
| if(data.hasOwnProperty("_segments") && data._length){ return endValue; } |
| var l = path.length; |
| var accuracy = 10; // Adjust to improve line following precision but sacrifice performance (# of seg) |
| if(l >= 6 && (l-2) % 4 == 0){ // Enough points && contains correct number per entry ignoring start |
| data._segments = []; |
| data._length = 0; |
| for(var i=2; i<l; i+=4){ |
| var sx = path[i-2], sy = path[i-1]; |
| var cx = path[i+0], cy = path[i+1]; |
| var ex = path[i+2], ey = path[i+3]; |
| var oldX = sx, oldY = sy; |
| var tempX, tempY, total = 0; |
| var sublines = []; |
| for(var j=1; j<=accuracy; j++){ |
| var t = j/accuracy; |
| var inv = 1 - t; |
| tempX = inv*inv * sx + 2 * inv * t * cx + t*t * ex; |
| tempY = inv*inv * sy + 2 * inv * t * cy + t*t * ey; |
| total += sublines[sublines.push(Math.sqrt((temp=tempX-oldX)*temp + (temp=tempY-oldY)*temp))-1]; |
| oldX = tempX; |
| oldY = tempY; |
| } |
| data._segments.push(total); |
| data._segments.push(sublines); |
| data._length += total; |
| } |
| } else { |
| throw("invalid 'path' data, please see documentation for valid paths"); |
| } |
| |
| // Setup x/y tweens |
| temp = data.orient; |
| data.orient = true; |
| var o = {}; |
| MotionGuidePlugin.calc(data, data.start, o); |
| tween.__rotPathS = Number(o.rotation.toFixed(5)); |
| MotionGuidePlugin.calc(data, data.end, o); |
| tween.__rotPathE = Number(o.rotation.toFixed(5)); |
| data.orient = false; //here and now we don't know if we need to |
| MotionGuidePlugin.calc(data, data.end, injectProps); |
| data.orient = temp; |
| |
| // Setup rotation properties |
| if(!data.orient){ return endValue; } |
| tween.__guideData = data; |
| MotionGuidePlugin.testRotData(tween, injectProps); |
| return endValue; |
| }; |
| |
| /** |
| * @method testRotData |
| * @protected |
| * @static |
| **/ |
| MotionGuidePlugin.testRotData = function(tween, injectProps){ |
| |
| // no rotation informat? if we need it come back, if we don't use 0 & ensure we have guide data |
| if(tween.__rotGlobalS === undefined || tween.__rotGlobalE === undefined){ |
| if(tween.__needsRot){ return; } |
| if(tween._curQueueProps.rotation !== undefined){ |
| tween.__rotGlobalS = tween.__rotGlobalE = tween._curQueueProps.rotation; |
| } else { |
| tween.__rotGlobalS = tween.__rotGlobalE = injectProps.rotation = tween.target.rotation || 0; |
| } |
| } |
| if(tween.__guideData === undefined){ return; } |
| |
| // Process rotation properties |
| var data = tween.__guideData; |
| var rotGlobalD = tween.__rotGlobalE - tween.__rotGlobalS; |
| var rotPathD = tween.__rotPathE - tween.__rotPathS; |
| var rot = rotGlobalD - rotPathD; |
| |
| if(data.orient == "auto"){ |
| if(rot > 180){ rot -= 360; } |
| else if(rot < -180){ rot += 360; } |
| |
| } else if(data.orient == "cw"){ |
| while(rot < 0){ rot += 360; } |
| if(rot == 0 && rotGlobalD > 0 && rotGlobalD != 180){ rot += 360; } |
| |
| } else if(data.orient == "ccw"){ |
| rot = rotGlobalD - ((rotPathD > 180)?(360-rotPathD):(rotPathD)); // sign flipping on path |
| while(rot > 0){ rot -= 360; } |
| if(rot == 0 && rotGlobalD < 0 && rotGlobalD != -180){ rot -= 360; } |
| } |
| |
| data.rotDelta = rot; |
| data.rotOffS = tween.__rotGlobalS - tween.__rotPathS; |
| |
| // reset |
| tween.__rotGlobalS = tween.__rotGlobalE = tween.__guideData = tween.__needsRot = undefined; |
| }; |
| |
| /** |
| * @method tween |
| * @protected |
| * @static |
| **/ |
| MotionGuidePlugin.tween = function(tween, prop, value, startValues, endValues, ratio, wait, end) { |
| var data = endValues.guide; |
| if(data == undefined || data === startValues.guide){ return value; } |
| if(data.lastRatio != ratio){ |
| // first time through so calculate what I need to |
| var t = ((data.end-data.start)*(wait?data.end:ratio)+data.start); |
| MotionGuidePlugin.calc(data, t, tween.target); |
| switch(data.orient){ |
| case "cw": // mix in the original rotation |
| case "ccw": |
| case "auto": tween.target.rotation += data.rotOffS + data.rotDelta*ratio; break; |
| case "fixed": // follow fixed behaviour to solve potential issues |
| default: tween.target.rotation += data.rotOffS; break; |
| } |
| data.lastRatio = ratio; |
| } |
| if(prop == "rotation" && ((!data.orient) || data.orient == "false")){ return value; } |
| return tween.target[prop]; |
| }; |
| |
| /** |
| * Determine the appropriate x/y/rotation information about a path for a given ratio along the path. |
| * Assumes a path object with all optional parameters specified. |
| * @param data Data object you would pass to the "guide:" property in a Tween |
| * @param ratio 0-1 Distance along path, values outside 0-1 are "best guess" |
| * @param target Object to copy the results onto, will use a new object if not supplied. |
| * @return {Object} The target object or a new object w/ the tweened properties |
| * @static |
| */ |
| MotionGuidePlugin.calc = function(data, ratio, target) { |
| if(data._segments == undefined){ throw("Missing critical pre-calculated information, please file a bug"); } |
| if(target == undefined){ target = {x:0, y:0, rotation:0}; } |
| var seg = data._segments; |
| var path = data.path; |
| |
| // find segment |
| var pos = data._length * ratio; |
| var cap = seg.length - 2; |
| var n = 0; |
| while(pos > seg[n] && n < cap){ |
| pos -= seg[n]; |
| n+=2; |
| } |
| |
| // find subline |
| var sublines = seg[n+1]; |
| var i = 0; |
| cap = sublines.length-1; |
| while(pos > sublines[i] && i < cap){ |
| pos -= sublines[i]; |
| i++; |
| } |
| var t = (i/++cap)+(pos/(cap*sublines[i])); |
| |
| // find x/y |
| n = (n*2)+2; |
| var inv = 1 - t; |
| target.x = inv*inv * path[n-2] + 2 * inv * t * path[n+0] + t*t * path[n+2]; |
| target.y = inv*inv * path[n-1] + 2 * inv * t * path[n+1] + t*t * path[n+3]; |
| |
| // orientation |
| if(data.orient){ |
| target.rotation = 57.2957795 * Math.atan2( |
| (path[n+1]-path[n-1])*inv + (path[n+3]-path[n+1])*t, |
| (path[n+0]-path[n-2])*inv + (path[n+2]-path[n+0])*t); |
| } |
| |
| return target; |
| }; |
| |
| createjs.MotionGuidePlugin = MotionGuidePlugin; |
| |
| }()); |
| |
| //############################################################################## |
| // version.js |
| //############################################################################## |
| |
| this.createjs = this.createjs || {}; |
| |
| (function() { |
| "use strict"; |
| |
| /** |
| * Static class holding library specific information such as the version and buildDate of |
| * the library. |
| * @class TweenJS |
| **/ |
| var s = createjs.TweenJS = createjs.TweenJS || {}; |
| |
| /** |
| * The version string for this release. |
| * @property version |
| * @type String |
| * @static |
| **/ |
| s.version = /*=version*/"0.6.2"; // injected by build process |
| |
| /** |
| * The build date for this release in UTC format. |
| * @property buildDate |
| * @type String |
| * @static |
| **/ |
| s.buildDate = /*=date*/"Thu, 26 Nov 2015 20:44:31 GMT"; // injected by build process |
| |
| })(); |