/*! * 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; }; //############################################################################## // deprecate.js //############################################################################## this.createjs = this.createjs||{}; /** * @class Utility Methods */ /** * Wraps deprecated methods so they still be used, but throw warnings to developers. * * obj.deprecatedMethod = createjs.deprecate("Old Method Name", obj._fallbackMethod); * * The recommended approach for deprecated properties is: * * try { * Obj ect.defineProperties(object, { * readyOnlyProp: { get: createjs.deprecate("readOnlyProp", function() { return this.alternateProp; }) }, * readWriteProp: { * get: createjs.deprecate("readOnlyProp", function() { return this.alternateProp; }), * set: createjs.deprecate("readOnlyProp", function(val) { this.alternateProp = val; }) * }); * } catch (e) {} * * @method deprecate * @param {Function} [fallbackMethod=null] A method to call when the deprecated method is used. See the example for how * @param {String} [name=null] The name of the method or property to display in the console warning. * to deprecate properties. * @return {Function} If a fallbackMethod is supplied, returns a closure that will call the fallback method after * logging the warning in the console. */ createjs.deprecate = function(fallbackMethod, name) { "use strict"; return function() { var msg = "Deprecated property or method '"+name+"'. See docs for info."; console && (console.warn ? console.warn(msg) : console.log(msg)); return fallbackMethod && fallbackMethod.apply(this, arguments); } }; //############################################################################## // 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:
    *
  1. capture phase: starting from the top parent to the target
  2. *
  3. at target phase: currently being dispatched from the target
  4. *
  5. bubbling phase: from the target to the top parent
  6. *
* @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; // 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. * *

Example

* 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"); * } * * Maintaining proper scope
* 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. * * Browser support * 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; // 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. * *

Example

* * 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`). * * IMPORTANT: 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. * *

Example

* * 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. * * Important Note: 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. * *

Example

* * 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; iIMPORTANT: 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. * *

Example

* * // 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. * *

Example

* * // 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; iExample * * 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/paused:property"}}{{/crossLink}}. * *

Example

* * 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: /** * Specifies the timing api (setTimeout or requestAnimationFrame) and mode to use. See * {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}}, {{#crossLink "Ticker/RAF:property"}}{{/crossLink}}, and * {{#crossLink "Ticker/RAF_SYNCHED:property"}}{{/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 paused 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. * *

Example

* * 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} * @private **/ Ticker._inited = false; /** * @property _startTime * @static * @type {Number} * @private **/ Ticker._startTime = 0; /** * @property _pausedTime * @static * @type {Number} * @private **/ Ticker._pausedTime=0; /** * The number of ticks that have passed * @property _ticks * @static * @type {Number} * @private **/ Ticker._ticks = 0; /** * The number of ticks that have passed while Ticker has been paused * @property _pausedTicks * @static * @type {Number} * @private **/ Ticker._pausedTicks = 0; /** * @property _interval * @static * @type {Number} * @private **/ Ticker._interval = 50; /** * @property _lastTime * @static * @type {Number} * @private **/ Ticker._lastTime = 0; /** * @property _times * @static * @type {Array} * @private **/ Ticker._times = null; /** * @property _tickTimes * @static * @type {Array} * @private **/ Ticker._tickTimes = null; /** * Stores the timeout or requestAnimationFrame id. * @property _timerId * @static * @type {Number} * @private **/ 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} * @private **/ Ticker._raf = true; // static getter / setters: /** * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead. * @method _setInterval * @private * @static * @param {Number} interval **/ Ticker._setInterval = function(interval) { Ticker._interval = interval; if (!Ticker._inited) { return; } Ticker._setupTick(); }; // Ticker.setInterval is @deprecated. Remove for 1.1+ Ticker.setInterval = createjs.deprecate(Ticker._setInterval, "Ticker.setInterval"); /** * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead. * @method _getInterval * @private * @static * @return {Number} **/ Ticker._getInterval = function() { return Ticker._interval; }; // Ticker.getInterval is @deprecated. Remove for 1.1+ Ticker.getInterval = createjs.deprecate(Ticker._getInterval, "Ticker.getInterval"); /** * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead. * @method _setFPS * @private * @static * @param {Number} value **/ Ticker._setFPS = function(value) { Ticker._setInterval(1000/value); }; // Ticker.setFPS is @deprecated. Remove for 1.1+ Ticker.setFPS = createjs.deprecate(Ticker._setFPS, "Ticker.setFPS"); /** * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead. * @method _getFPS * @static * @private * @return {Number} **/ Ticker._getFPS = function() { return 1000/Ticker._interval; }; // Ticker.getFPS is @deprecated. Remove for 1.1+ Ticker.getFPS = createjs.deprecate(Ticker._getFPS, "Ticker.getFPS"); /** * 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 = Ticker._pausedTime = 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, {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} returns 10fps, which * indicates an average of 100ms between the end of one tick and the end of the next. However, {{#crossLink "Ticker/getMeasuredTickTime"}}{{/crossLink}} * 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= (Ticker._interval-1)*0.97) { Ticker._tick(); } }; /** * @method _handleRAF * @static * @private **/ Ticker._handleRAF = function() { Ticker._timerId = null; Ticker._setupTick(); Ticker._tick(); }; /** * @method _handleTimeout * @static * @private **/ Ticker._handleTimeout = function() { Ticker._timerId = null; Ticker._setupTick(); Ticker._tick(); }; /** * @method _setupTick * @static * @private **/ Ticker._setupTick = function() { if (Ticker._timerId != null) { return; } // avoid duplicates var mode = Ticker.timingMode; 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 * @private **/ 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 * @private **/ var w=window, now=w.performance.now || w.performance.mozNow || w.performance.msNow || w.performance.oNow || w.performance.webkitNow; Ticker._getTime = function() { return ((now&&now.call(w.performance))||(new Date().getTime())) - Ticker._startTime; }; createjs.Ticker = Ticker; }()); //############################################################################## // AbstractTween.js //############################################################################## this.createjs = this.createjs||{}; (function() { "use strict"; // constructor /** * Base class that both {{#crossLink "Tween"}}{{/crossLink}} and {{#crossLink "Timeline"}}{{/crossLink}} extend. Should not be instantiated directly. * @class AbstractTween * @param {Object} [props] The configuration properties to apply to this instance (ex. `{loop:-1, paused:true}`). * Supported props are listed below. These props are set on the corresponding instance properties except where * specified. * @param {boolean} [props.useTicks=false] See the {{#crossLink "AbstractTween/useTicks:property"}}{{/crossLink}} property for more information. * @param {boolean} [props.ignoreGlobalPause=false] See the {{#crossLink "AbstractTween/ignoreGlobalPause:property"}}{{/crossLink}} for more information. * @param {number|boolean} [props.loop=0] See the {{#crossLink "AbstractTween/loop:property"}}{{/crossLink}} for more information. * @param {boolean} [props.reversed=false] See the {{#crossLink "AbstractTween/reversed:property"}}{{/crossLink}} for more information. * @param {boolean} [props.bounce=false] See the {{#crossLink "AbstractTween/bounce:property"}}{{/crossLink}} for more information. * @param {number} [props.timeScale=1] See the {{#crossLink "AbstractTween/timeScale:property"}}{{/crossLink}} for more information. * @param {Function} [props.onChange] Adds the specified function as a listener to the {{#crossLink "AbstractTween/change:event"}}{{/crossLink}} event * @param {Function} [props.onComplete] Adds the specified function as a listener to the {{#crossLink "AbstractTween/complete:event"}}{{/crossLink}} event * @extends EventDispatcher * @constructor */ function AbstractTween(props) { this.EventDispatcher_constructor(); // 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 false (the default) will cause this tween to be paused when `Ticker.paused` is set to * `true`. See the {{#crossLink "Tween/tick"}}{{/crossLink}} method for more info. Can be set via the `props` * parameter. * @property ignoreGlobalPause * @type Boolean * @default false */ this.ignoreGlobalPause = false; /** * Indicates the number of times to loop. If set to -1, the tween will loop continuously. * * Note that a tween must loop at _least_ once to see it play in both directions when `{{#crossLink "AbstractTween/bounce:property"}}{{/crossLink}}` * is set to `true`. * @property loop * @type {Number} * @default 0 */ this.loop = 0; /** * Uses ticks for all durations instead of milliseconds. This also changes the behaviour of some actions (such as `call`). * Changing this value on a running tween could have unexpected results. * @property useTicks * @type {Boolean} * @default false * @readonly */ this.useTicks = false; /** * Causes the tween to play in reverse. * @property reversed * @type {Boolean} * @default false */ this.reversed = false; /** * Causes the tween to reverse direction at the end of each loop. Each single-direction play-through of the * tween counts as a single bounce. For example, to play a tween once forward, and once back, set the * `{{#crossLink "AbstractTween/loop:property"}}{{/crossLink}}` to `1`. * @property bounce * @type {Boolean} * @default false */ this.bounce = false; /** * Changes the rate at which the tween advances. For example, a `timeScale` value of `2` will double the * playback speed, a value of `0.5` would halve it. * @property timeScale * @type {Number} * @default 1 */ this.timeScale = 1; /** * Indicates the duration of this tween in milliseconds (or ticks if `useTicks` is true), irrespective of `loops`. * 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; /** * The current normalized position of the tween. This will always be a value between 0 and `duration`. * Changing this property directly will have unexpected results, use {{#crossLink "Tween/setPosition"}}{{/crossLink}}. * @property position * @type {Object} * @default 0 * @readonly */ this.position = 0; /** * The raw tween position. This value will be between `0` and `loops * duration` while the tween is active, or -1 before it activates. * @property rawPosition * @type {Number} * @default -1 * @readonly */ this.rawPosition = -1; // private properties: /** * @property _paused * @type {Boolean} * @default false * @protected */ this._paused = true; /** * @property _next * @type {Tween} * @default null * @protected */ this._next = null; /** * @property _prev * @type {Tween} * @default null * @protected */ this._prev = null; /** * @property _parent * @type {Object} * @default null * @protected */ this._parent = null; /** * @property _labels * @type Object * @protected **/ this._labels = null; /** * @property _labelList * @type Array[Object] * @protected **/ this._labelList = null; if (props) { this.useTicks = !!props.useTicks; this.ignoreGlobalPause = !!props.ignoreGlobalPause; this.loop = props.loop === true ? -1 : (props.loop||0); this.reversed = !!props.reversed; this.bounce = !!props.bounce; this.timeScale = props.timeScale||1; props.onChange && this.addEventListener("change", props.onChange); props.onComplete && this.addEventListener("complete", props.onComplete); } // while `position` is shared, it needs to happen after ALL props are set, so it's handled in _init() }; var p = createjs.extend(AbstractTween, createjs.EventDispatcher); // events: /** * Dispatched whenever the tween's position changes. It occurs after all tweened properties are updated and actions * are executed. * @event change **/ /** * Dispatched when the tween reaches its end and has paused itself. This does not fire until all loops are complete; * tweens that loop continuously will never fire a complete event. * @event complete **/ // getter / setters: /** * Use the {{#crossLink "AbstractTween/paused:property"}}{{/crossLink}} property instead. * @method _setPaused * @param {Boolean} [value=true] Indicates whether the tween should be paused (`true`) or played (`false`). * @return {AbstractTween} This tween instance (for chaining calls) * @protected * @chainable */ p._setPaused = function(value) { createjs.Tween._register(this, value); return this; }; p.setPaused = createjs.deprecate(p._setPaused, "AbstractTween.setPaused"); /** * Use the {{#crossLink "AbstractTween/paused:property"}}{{/crossLink}} property instead. * @method _getPaused * @protected */ p._getPaused = function() { return this._paused; }; p.getPaused = createjs.deprecate(p._getPaused, "AbstactTween.getPaused"); /** * Use the {{#crossLink "AbstractTween/currentLabel:property"}}{{/crossLink}} property instead. * @method _getCurrentLabel * @protected * @return {String} The name of the current label or null if there is no label **/ p._getCurrentLabel = function(pos) { var labels = this.getLabels(); if (pos == null) { pos = this.position; } for (var i = 0, l = labels.length; i *
  • null if the current position is 2.
  • *
  • "first" if the current position is 4.
  • *
  • "first" if the current position is 7.
  • *
  • "second" if the current position is 15.
  • * * @property currentLabel * @type String * @readonly **/ try { Object.defineProperties(p, { paused: { set: p._setPaused, get: p._getPaused }, currentLabel: { get: p._getCurrentLabel } }); } catch (e) {} // public methods: /** * Advances the tween by a specified amount. * @method advance * @param {Number} delta The amount to advance in milliseconds (or ticks if useTicks is true). Negative values are supported. * @param {Number} [ignoreActions=false] If true, actions will not be executed due to this change in position. */ p.advance = function(delta, ignoreActions) { this.setPosition(this.rawPosition+delta*this.timeScale, ignoreActions); }; /** * Advances the tween to a specified position. * @method setPosition * @param {Number} rawPosition The raw position to seek to in milliseconds (or ticks if useTicks is true). * @param {Boolean} [ignoreActions=false] If true, do not run any actions that would be triggered by this operation. * @param {Boolean} [jump=false] If true, only actions at the new position will be run. If false, actions between the old and new position are run. * @param {Function} [callback] Primarily for use with MovieClip, this callback is called after properties are updated, but before actions are run. */ p.setPosition = function(rawPosition, ignoreActions, jump, callback) { var d=this.duration, loopCount=this.loop, prevRawPos = this.rawPosition; var loop=0, t=0, end=false; // normalize position: if (rawPosition < 0) { rawPosition = 0; } if (d === 0) { // deal with 0 length tweens. end = true; if (prevRawPos !== -1) { return end; } // we can avoid doing anything else if we're already at 0. } else { loop = rawPosition/d|0; t = rawPosition-loop*d; end = (loopCount !== -1 && rawPosition >= loopCount*d+d); if (end) { rawPosition = (t=d)*(loop=loopCount)+d; } if (rawPosition === prevRawPos) { return end; } // no need to update var rev = !this.reversed !== !(this.bounce && loop%2); // current loop is reversed if (rev) { t = d-t; } } // set this in advance in case an action modifies position: this.position = t; this.rawPosition = rawPosition; this._updatePosition(jump, end); if (end) { this.paused = true; } callback&&callback(this); if (!ignoreActions) { this._runActions(prevRawPos, rawPosition, jump, !jump && prevRawPos === -1); } this.dispatchEvent("change"); if (end) { this.dispatchEvent("complete"); } }; /** * Calculates a normalized position based on a raw position. For example, given a tween with a duration of 3000ms set to loop: * console.log(myTween.calculatePosition(3700); // 700 * @method calculatePosition * @param {Number} rawPosition A raw position. */ p.calculatePosition = function(rawPosition) { // largely duplicated from setPosition, but necessary to avoid having to instantiate generic objects to pass values (end, loop, position) back. var d=this.duration, loopCount=this.loop, loop=0, t=0; if (d===0) { return 0; } if (loopCount !== -1 && rawPosition >= loopCount*d+d) { t = d; loop = loopCount } // end else if (rawPosition < 0) { t = 0; } else { loop = rawPosition/d|0; t = rawPosition-loop*d; } var rev = !this.reversed !== !(this.bounce && loop%2); // current loop is reversed return rev ? d-t : t; }; /** * Returns a list of the labels defined on this tween sorted by position. * @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; }; /** * Defines labels for use with gotoAndPlay/Stop. Overwrites any previously set labels. * @method setLabels * @param {Object} labels An object defining labels for using {{#crossLink "Timeline/gotoAndPlay"}}{{/crossLink}}/{{#crossLink "Timeline/gotoAndStop"}}{{/crossLink}} * in the form `{myLabelName:time}` where time is in milliseconds (or ticks if `useTicks` is `true`). **/ p.setLabels = function(labels) { this._labels = labels; this._labelList = null; }; /** * 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) { if (!this._labels) { this._labels = {}; } this._labels[label] = position; var list = this._labelList; if (list) { for (var i= 0,l=list.length; i Tween" : "Timeline", "run", startRawPos, endRawPos, jump, includeStart); // if we don't have any actions, and we're not a Timeline, then return: // TODO: a cleaner way to handle this would be to override this method in Tween, but I'm not sure it's worth the overhead. if (!this._actionHead && !this.tweens) { return; } var d=this.duration, reversed=this.reversed, bounce=this.bounce, loopCount=this.loop; var loop0, loop1, t0, t1; if (d === 0) { // deal with 0 length tweens: loop0 = loop1 = t0 = t1 = 0; reversed = bounce = false; } else { loop0=startRawPos/d|0; loop1=endRawPos/d|0; t0=startRawPos-loop0*d; t1=endRawPos-loop1*d; } // catch positions that are past the end: if (loopCount !== -1) { if (loop1 > loopCount) { t1=d; loop1=loopCount; } if (loop0 > loopCount) { t0=d; loop0=loopCount; } } // special cases: if (jump) { return this._runActionsRange(t1, t1, jump, includeStart); } // jump. else if (loop0 === loop1 && t0 === t1 && !jump && !includeStart) { return; } // no actions if the position is identical and we aren't including the start else if (loop0 === -1) { loop0 = t0 = 0; } // correct the -1 value for first advance, important with useTicks. var dir = (startRawPos <= endRawPos), loop = loop0; do { var rev = !reversed !== !(bounce && loop % 2); var start = (loop === loop0) ? t0 : dir ? 0 : d; var end = (loop === loop1) ? t1 : dir ? d : 0; if (rev) { start = d - start; end = d - end; } if (bounce && loop !== loop0 && start === end) { /* bounced onto the same time/frame, don't re-execute end actions */ } else if (this._runActionsRange(start, end, jump, includeStart || (loop !== loop0 && !bounce))) { return true; } includeStart = false; } while ((dir && ++loop <= loop1) || (!dir && --loop >= loop1)); }; p._runActionsRange = function(startPos, endPos, jump, includeStart) { // abstract }; createjs.AbstractTween = createjs.promote(AbstractTween, "EventDispatcher"); }()); //############################################################################## // Tween.js //############################################################################## this.createjs = this.createjs||{}; (function() { "use strict"; // constructor /** * Tweens properties for a single target. Methods can be chained to create complex animation sequences: * *

    Example

    * * createjs.Tween.get(target) * .wait(500) * .to({alpha:0, visible:false}, 1000) * .call(handleComplete); * * Multiple tweens can share a target, 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 be notified when the tween position changes. * * createjs.Tween.get(target, {override:true}).to({x:100}).addEventListener("change", handleChange); * function handleChange(event) { * // The tween changed. * } * * See the {{#crossLink "Tween/get"}}{{/crossLink}} method also. * @class Tween * @param {Object} target The target object that will have its properties tweened. * @param {Object} [props] The configuration properties to apply to this instance (ex. `{loop:-1, paused:true}`). * Supported props are listed below. These props are set on the corresponding instance properties except where * specified. * @param {boolean} [props.useTicks=false] See the {{#crossLink "AbstractTween/useTicks:property"}}{{/crossLink}} property for more information. * @param {boolean} [props.ignoreGlobalPause=false] See the {{#crossLink "AbstractTween/ignoreGlobalPause:property"}}{{/crossLink}} for more information. * @param {number|boolean} [props.loop=0] See the {{#crossLink "AbstractTween/loop:property"}}{{/crossLink}} for more information. * @param {boolean} [props.reversed=false] See the {{#crossLink "AbstractTween/reversed:property"}}{{/crossLink}} for more information. * @param {boolean} [props.bounce=false] See the {{#crossLink "AbstractTween/bounce:property"}}{{/crossLink}} for more information. * @param {number} [props.timeScale=1] See the {{#crossLink "AbstractTween/timeScale:property"}}{{/crossLink}} for more information. * @param {object} [props.pluginData] See the {{#crossLink "Tween/pluginData:property"}}{{/crossLink}} for more information. * @param {boolean} [props.paused=false] See the {{#crossLink "AbstractTween/paused:property"}}{{/crossLink}} for more information. * @param {number} [props.position=0] The initial position for this tween. See {{#crossLink "AbstractTween/position:property"}}{{/crossLink}} * @param {Function} [props.onChange] Adds the specified function as a listener to the {{#crossLink "AbstractTween/change:event"}}{{/crossLink}} event * @param {Function} [props.onComplete] Adds the specified function as a listener to the {{#crossLink "AbstractTween/complete:event"}}{{/crossLink}} event * @param {boolean} [props.override=false] Removes all existing tweens for the target when set to `true`. * * @extends AbstractTween * @constructor */ function Tween(target, props) { this.AbstractTween_constructor(props); // public properties: /** * Allows you to specify data that will be used by installed plugins. Each plugin uses this differently, but in general * you specify data by assigning it to a property of `pluginData` with the same name as the plugin. * Note that in many cases, this data is used as soon as the plugin initializes itself for the tween. * As such, this data should be set before the first `to` call in most cases. * @example * myTween.pluginData.SmartRotation = data; * * Most plugins also support a property to disable them for a specific tween. This is typically the plugin name followed by "_disabled". * @example * myTween.pluginData.SmartRotation_disabled = true; * * Some plugins also store working 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 = null; /** * The target of this tween. This is the object on which the tweened properties will be changed. * @property target * @type {Object} * @readonly */ this.target = target; /** * Indicates the tween's current position is within a passive wait. * @property passive * @type {Boolean} * @default false * @readonly **/ this.passive = false; // private properties: /** * @property _stepHead * @type {TweenStep} * @protected */ this._stepHead = new TweenStep(null, 0, 0, {}, null, true); /** * @property _stepTail * @type {TweenStep} * @protected */ this._stepTail = this._stepHead; /** * The position within the current step. Used by MovieClip. * @property _stepPosition * @type {Number} * @default 0 * @protected */ this._stepPosition = 0; /** * @property _actionHead * @type {TweenAction} * @protected */ this._actionHead = null; /** * @property _actionTail * @type {TweenAction} * @protected */ this._actionTail = null; /** * Plugins added to this tween instance. * @property _plugins * @type Array[Object] * @default null * @protected */ this._plugins = null; /** * Hash for quickly looking up added plugins. Null until a plugin is added. * @property _plugins * @type Object * @default null * @protected */ this._pluginIds = null; /** * Used by plugins to inject new properties. * @property _injected * @type {Object} * @default null * @protected */ this._injected = null; if (props) { this.pluginData = props.pluginData; if (props.override) { Tween.removeTweens(target); } } if (!this.pluginData) { this.pluginData = {}; } this._init(props); }; var p = createjs.extend(Tween, createjs.AbstractTween); // static properties /** * 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 = null; /** * @property _tweenHead * @type Tween * @static * @protected */ Tween._tweenHead = null; /** * @property _tweenTail * @type Tween * @static * @protected */ Tween._tweenTail = null; // static methods /** * Returns a new tween instance. This is functionally identical to using `new Tween(...)`, but may look cleaner * with the chained syntax of TweenJS. *

    Example

    * * var tween = createjs.Tween.get(target).to({x:100}, 500); * // equivalent to: * var tween = new createjs.Tween(target).to({x:100}, 500); * * @method get * @param {Object} target The target object that will have its properties tweened. * @param {Object} [props] The configuration properties to apply to this instance (ex. `{loop:-1, paused:true}`). * Supported props are listed below. These props are set on the corresponding instance properties except where * specified. * @param {boolean} [props.useTicks=false] See the {{#crossLink "AbstractTween/useTicks:property"}}{{/crossLink}} property for more information. * @param {boolean} [props.ignoreGlobalPause=false] See the {{#crossLink "AbstractTween/ignoreGlobalPause:property"}}{{/crossLink}} for more information. * @param {number|boolean} [props.loop=0] See the {{#crossLink "AbstractTween/loop:property"}}{{/crossLink}} for more information. * @param {boolean} [props.reversed=false] See the {{#crossLink "AbstractTween/reversed:property"}}{{/crossLink}} for more information. * @param {boolean} [props.bounce=false] See the {{#crossLink "AbstractTween/bounce:property"}}{{/crossLink}} for more information. * @param {number} [props.timeScale=1] See the {{#crossLink "AbstractTween/timeScale:property"}}{{/crossLink}} for more information. * @param {object} [props.pluginData] See the {{#crossLink "Tween/pluginData:property"}}{{/crossLink}} for more information. * @param {boolean} [props.paused=false] See the {{#crossLink "AbstractTween/paused:property"}}{{/crossLink}} for more information. * @param {number} [props.position=0] The initial position for this tween. See {{#crossLink "AbstractTween/position:property"}}{{/crossLink}} * @param {Function} [props.onChange] Adds the specified function as a listener to the {{#crossLink "AbstractTween/change:event"}}{{/crossLink}} event * @param {Function} [props.onComplete] Adds the specified function as a listener to the {{#crossLink "AbstractTween/complete:event"}}{{/crossLink}} event * @param {boolean} [props.override=false] Removes all existing tweens for the target when set to `true`. * @return {Tween} A reference to the created tween. * @static */ Tween.get = function(target, props) { return new Tween(target, props); }; /** * 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 tween = Tween._tweenHead; while (tween) { var next = tween._next; // in case it completes and wipes its _next property if ((paused && !tween.ignoreGlobalPause) || tween._paused) { /* paused */ } else { tween.advance(tween.useTicks?1:delta); } tween = next; } }; /** * 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 tween = Tween._tweenHead; while (tween) { var next = tween._next; if (tween.target === target) { Tween._register(tween, true); } tween = next; } target.tweenjs_count = 0; }; /** * Stop and remove all existing tweens. * @method removeAllTweens * @static * @since 0.4.1 */ Tween.removeAllTweens = function() { var tween = Tween._tweenHead; while (tween) { var next = tween._next; tween._paused = true; tween.target&&(tween.target.tweenjs_count = 0); tween._next = tween._prev = null; tween = next; } Tween._tweenHead = Tween._tweenTail = null; }; /** * Indicates whether there are any active tweens 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} Indicates if there are active tweens. * @static */ Tween.hasActiveTweens = function(target) { if (target) { return !!target.tweenjs_count; } return !!Tween._tweenHead; }; /** * Installs a plugin, which can modify how certain properties are handled when tweened. See the {{#crossLink "SamplePlugin"}}{{/crossLink}} * for an example of how to write TweenJS plugins. Plugins should generally be installed via their own `install` method, in order to provide * the plugin with an opportunity to configure itself. * @method _installPlugin * @param {Object} plugin The plugin to install * @static * @protected */ Tween._installPlugin = function(plugin) { var priority = (plugin.priority = plugin.priority||0), arr = (Tween._plugins = Tween._plugins || []); for (var i=0,l=arr.length;iExample * * //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=false] 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). * @chainable **/ p.wait = function(duration, passive) { if (duration > 0) { this._addStep(+duration, this._stepTail.props, null, passive); } return this; }; /** * Adds a tween from the current values to the specified 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. *

    Example

    * * createjs.Tween.get(target).to({alpha:0, visible:false}, 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 tween 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). * @chainable */ p.to = function(props, duration, ease) { if (duration == null || duration < 0) { duration = 0; } var step = this._addStep(+duration, null, ease); this._appendProps(props, step); return this; }; /** * Adds a label that can be used with {{#crossLink "Tween/gotoAndPlay"}}{{/crossLink}}/{{#crossLink "Tween/gotoAndStop"}}{{/crossLink}} * at the current point in the tween. For example: * * var tween = createjs.Tween.get(foo) * .to({x:100}, 1000) * .label("myLabel") * .to({x:200}, 1000); * // ... * tween.gotoAndPlay("myLabel"); // would play from 1000ms in. * * @method addLabel * @param {String} label The label name. * @return {Tween} This tween instance (for chaining calls). * @chainable **/ p.label = function(name) { this.addLabel(name, this.duration); return this; }; /** * Adds an action to call the specified function. *

    Example

    * * //would call myFunction() after 1 second. * createjs.Tween.get().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). * @chainable */ p.call = function(callback, params, scope) { return this._addAction(scope||this.target, callback, params||[this]); }; /** * Adds an action to set the specified props on the specified target. If `target` is null, it will use this tween's * target. Note that for properties on the target object, you should consider using a zero duration {{#crossLink "Tween/to"}}{{/crossLink}} * operation instead so the values are registered as tweened props. *

    Example

    * * 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). * @chainable */ p.set = function(props, target) { return this._addAction(target||this.target, this._set, [props]); }; /** * Adds an action to play (unpause) the specified tween. This enables you to sequence multiple tweens. *

    Example

    * * myTween.to({x:100}, 500).play(otherTween); * * @method play * @param {Tween} [tween] The tween to play. Defaults to this tween. * @return {Tween} This tween instance (for chaining calls). * @chainable */ p.play = function(tween) { return this._addAction(tween||this, this._set, [{paused:false}]); }; /** * Adds an action to pause the specified tween. * * myTween.pause(otherTween).to({alpha:1}, 1000).play(otherTween); * * Note that this executes at the end of a tween update, so the tween may advance beyond the time the pause * action was inserted at. For example: * * myTween.to({foo:0}, 1000).pause().to({foo:1}, 1000); * * At 60fps the tween will advance by ~16ms per tick, if the tween above was at 999ms prior to the current tick, it * will advance to 1015ms (15ms into the second "step") and then pause. * * @method pause * @param {Tween} [tween] The tween to pause. Defaults to this tween. * @return {Tween} This tween instance (for chaining calls) * @chainable */ p.pause = function(tween) { return this._addAction(tween||this, this._set, [{paused:true}]); }; // 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: /** * Adds a plugin to this tween. * @method _addPlugin * @param {Object} plugin * @protected */ p._addPlugin = function(plugin) { var ids = this._pluginIds || (this._pluginIds = {}), id = plugin.ID; if (!id || ids[id]) { return; } // already added ids[id] = true; var plugins = this._plugins || (this._plugins = []), priority = plugin.priority || 0; for (var i=0,l=plugins.length; i= 1 ? v1 : v0; } if (plugins) { for (var i=0,l=plugins.length;i endPos; var action = rev ? this._actionTail : this._actionHead; var ePos = endPos, sPos = startPos; if (rev) { ePos=startPos; sPos=endPos; } var t = this.position; while (action) { var pos = action.t; if (pos === endPos || (pos > sPos && pos < ePos) || (includeStart && pos === startPos)) { action.funct.apply(action.scope, action.params); if (t !== this.position) { return true; } } action = rev ? action.prev : action.next; } }; /** * @method _appendProps * @param {Object} props * @protected */ p._appendProps = function(props, step, stepPlugins) { var initProps = this._stepHead.props, target = this.target, plugins = Tween._plugins; var n, i, value, initValue, inject; var oldStep = step.prev, oldProps = oldStep.props; var stepProps = step.props || (step.props = this._cloneProps(oldProps)); var cleanProps = {}; // TODO: is there some way to avoid this additional object? for (n in props) { if (!props.hasOwnProperty(n)) { continue; } cleanProps[n] = stepProps[n] = props[n]; if (initProps[n] !== undefined) { continue; } initValue = undefined; // accessing missing properties on DOMElements when using CSSPlugin is INSANELY expensive, so we let the plugin take a first swing at it. if (plugins) { for (i = plugins.length-1; i >= 0; i--) { value = plugins[i].init(this, n, initValue); if (value !== undefined) { initValue = value; } if (initValue === Tween.IGNORE) { delete(stepProps[n]); delete(cleanProps[n]); break; } } } if (initValue !== Tween.IGNORE) { if (initValue === undefined) { initValue = target[n]; } oldProps[n] = (initValue === undefined) ? null : initValue; } } for (n in cleanProps) { value = props[n]; // propagate old value to previous steps: var o, prev=oldStep; while ((o = prev) && (prev = o.prev)) { if (prev.props === o.props) { continue; } // wait step if (prev.props[n] !== undefined) { break; } // already has a value, we're done. prev.props[n] = oldProps[n]; } } if (stepPlugins !== false && (plugins = this._plugins)) { for (i = plugins.length-1; i >= 0; i--) { plugins[i].step(this, step, cleanProps); } } if (inject = this._injected) { this._injected = null; this._appendProps(inject, step, false); } }; /** * Used by plugins to inject properties onto the current step. Called from within `Plugin.step` calls. * For example, a plugin dealing with color, could read a hex color, and inject red, green, and blue props into the tween. * See the SamplePlugin for more info. * @method _injectProp * @param {String} name * @param {Object} value * @protected */ p._injectProp = function(name, value) { var o = this._injected || (this._injected = {}); o[name] = value; }; /** * @method _addStep * @param {Number} duration * @param {Object} props * @param {Function} ease * @param {Boolean} passive * @protected */ p._addStep = function(duration, props, ease, passive) { var step = new TweenStep(this._stepTail, this.duration, duration, props, ease, passive||false); this.duration += duration; return this._stepTail = (this._stepTail.next = step); }; /** * @method _addAction * @param {Object} scope * @param {Function} funct * @param {Array} params * @protected */ p._addAction = function(scope, funct, params) { var action = new TweenAction(this._actionTail, this.duration, scope, funct, params); if (this._actionTail) { this._actionTail.next = action; } else { this._actionHead = action; } this._actionTail = action; return this; }; /** * @method _set * @param {Object} props * @protected */ p._set = function(props) { for (var n in props) { this[n] = props[n]; } }; /** * @method _cloneProps * @param {Object} props * @protected */ p._cloneProps = function(props) { var o = {}; for (var n in props) { o[n] = props[n]; } return o; }; createjs.Tween = createjs.promote(Tween, "AbstractTween"); function TweenStep(prev, t, d, props, ease, passive) { this.next = null; this.prev = prev; this.t = t; this.d = d; this.props = props; this.ease = ease; this.passive = passive; this.index = prev ? prev.index+1 : 0; }; function TweenAction(prev, t, scope, funct, params) { this.next = null; this.prev = prev; this.t = t; this.d = 0; this.scope = scope; this.funct = funct; this.params = params; }; }()); //############################################################################## // 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. * * NOTE: Timeline currently also accepts a param list in the form: `tweens, labels, props`. This is for backwards * compatibility only and will be removed in the future. Include tweens and labels as properties on the props object. * @class Timeline * @param {Object} [props] The configuration properties to apply to this instance (ex. `{loop:-1, paused:true}`). * Supported props are listed below. These props are set on the corresponding instance properties except where * specified.
      *
    • `useTicks`
    • *
    • `ignoreGlobalPause`
    • *
    • `loop`
    • *
    • `reversed`
    • *
    • `bounce`
    • *
    • `timeScale`
    • *
    • `paused`
    • *
    • `position`: indicates the initial position for this tween.
    • *
    • `onChange`: adds the specified function as a listener to the `change` event
    • *
    • `onComplete`: adds the specified function as a listener to the `complete` event
    • *
    * @extends AbstractTween * @constructor **/ function Timeline(props) { var tweens, labels; // handle old params (tweens, labels, props): // TODO: deprecated. if (props instanceof Array || (props == null && arguments.length > 1)) { tweens = props; labels = arguments[1]; props = arguments[2]; } else if (props) { tweens = props.tweens; labels = props.labels; } this.AbstractTween_constructor(props); // private properties: /** * The array of tweens in the timeline. It is *strongly* recommended that you use * {{#crossLink "Tween/addTween"}}{{/crossLink}} and {{#crossLink "Tween/removeTween"}}{{/crossLink}}, * rather than accessing this directly, but it is included for advanced uses. * @property tweens * @type Array **/ this.tweens = []; if (tweens) { this.addTween.apply(this, tweens); } this.setLabels(labels); this._init(props); }; var p = createjs.extend(Timeline, createjs.AbstractTween); // events: // docced in AbstractTween. // 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) { if (tween._parent) { tween._parent.removeTween(tween); } var l = arguments.length; if (l > 1) { for (var i=0; i 0) { d *= tween.loop+1; } if (d > this.duration) { this.duration = d; } if (this.rawPosition >= 0) { tween.setPosition(this.rawPosition); } 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= this.duration) { this.updateDuration(); } return true; } } return false; }; /** * 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 0) { d *= tween.loop+1; } if (d > this.duration) { this.duration = d; } } }; /** * 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: // Docced in AbstractTween p._updatePosition = function(jump, end) { var t = this.position; for (var i=0, l=this.tweens.length; ispark table demo for an * overview of the different ease types on TweenJS.com. * * Equations derived from work by Robert Penner. * @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 Adobe Flash/Animate. * @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; } else 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. Defined paths which objects can follow or orient along. * * To use the plugin, install the plugin after TweenJS has loaded. To define a path, add * * createjs.MotionGuidePlugin.install(); * *

    Example

    * * // 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:
      *
    • path: Required, Array : The x/y points used to draw the path with a moveTo and 1 to n curveTo calls.
    • *
    • start: Optional, 0-1 : Initial position, default 0 except for when continuing along the same path.
    • *
    • end: Optional, 0-1 : Final position, default 1 if not specified.
    • *
    • orient: Optional, string : "fixed"/"auto"/"cw"/"ccw"
        *
      • "fixed" forces the object to face down the path all movement (relative to start rotation),
      • *
      • "auto" rotates the object along the path relative to the line.
      • *
      • "cw"/"ccw" force clockwise or counter clockwise rotations including Adobe Flash/Animate-like * behaviour. This may override your end rotation value.
      • *
    • *
    * 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.") } var s = MotionGuidePlugin; // static properties: /** * @property priority * @protected * @static */ s.priority = 0; // high priority, should run sooner /** * READ-ONLY. A unique identifying string for this plugin. Used by TweenJS to ensure duplicate plugins are not installed on a tween. * @property ID * @type {String} * @static * @readonly */ s.ID = "MotionGuide"; // static methods /** * Installs this plugin for use with TweenJS. Call this once after TweenJS is loaded to enable this plugin. * @method install * @static */ s.install = function() { createjs.Tween._installPlugin(MotionGuidePlugin); return createjs.Tween.IGNORE; }; /** * Called by TweenJS when a new property initializes on a tween. * See {{#crossLink "SamplePlugin/init"}}{{/crossLink}} for more info. * @method init * @param {Tween} tween * @param {String} prop * @param {any} value * @return {any} * @static */ s.init = function(tween, prop, value) { if(prop == "guide") { tween._addPlugin(s); } }; /** * Called when a new step is added to a tween (ie. a new "to" action is added to a tween). * See {{#crossLink "SamplePlugin/step"}}{{/crossLink}} for more info. * @method step * @param {Tween} tween * @param {TweenStep} step * @param {Object} props * @static */ s.step = function(tween, step, props) { for (var n in props) { if(n !== "guide") { continue; } var guideData = step.props.guide; var error = s._solveGuideData(props.guide, guideData); guideData.valid = !error; var end = guideData.endData; tween._injectProp("x", end.x); tween._injectProp("y", end.y); if(error || !guideData.orient) { break; } var initRot = step.prev.props.rotation === undefined ? (tween.target.rotation || 0) : step.prev.props.rotation; guideData.startOffsetRot = initRot - guideData.startData.rotation; if(guideData.orient == "fixed") { // controlled rotation guideData.endAbsRot = end.rotation + guideData.startOffsetRot; guideData.deltaRotation = 0; } else { // interpreted rotation var finalRot = props.rotation === undefined ? (tween.target.rotation || 0) : props.rotation; var deltaRot = (finalRot - guideData.endData.rotation) - guideData.startOffsetRot; var modRot = deltaRot % 360; guideData.endAbsRot = finalRot; switch(guideData.orient) { case "auto": guideData.deltaRotation = deltaRot; break; case "cw": guideData.deltaRotation = ((modRot + 360) % 360) + (360 * Math.abs((deltaRot/360) |0)); break; case "ccw": guideData.deltaRotation = ((modRot - 360) % 360) + (-360 * Math.abs((deltaRot/360) |0)); break; } } tween._injectProp("rotation", guideData.endAbsRot); } }; /** * Called before a property is updated by the tween. * See {{#crossLink "SamplePlugin/change"}}{{/crossLink}} for more info. * @method change * @param {Tween} tween * @param {TweenStep} step * @param {String} prop * @param {any} value * @param {Number} ratio * @param {Boolean} end * @return {any} * @static */ s.change = function(tween, step, prop, value, ratio, end) { var guideData = step.props.guide; if( !guideData || // Missing data (step.props === step.prev.props) || // In a wait() (guideData === step.prev.props.guide) // Guide hasn't changed ) { return; // have no business making decisions } if( (prop === "guide" && !guideData.valid) || // this data is broken (prop == "x" || prop == "y") || // these always get over-written (prop === "rotation" && guideData.orient) // currently over-written ){ return createjs.Tween.IGNORE; } s._ratioToPositionData(ratio, guideData, tween.target); }; // public methods /** * Provide potentially useful debugging information, like running the error detection system, and rendering the path * defined in the guide data. * * NOTE: you will need to transform your context 2D to the local space of the guide if you wish to line it up. * @param {Object} guideData All the information describing the guide to be followed. * @param {DrawingContext2D} [ctx=undefined] The context to draw the object into. * @param {Array} [higlight=undefined] Array of ratio positions to highlight * @returns {undefined|String} */ s.debug = function(guideData, ctx, higlight) { guideData = guideData.guide || guideData; // errors var err = s._findPathProblems(guideData); if(err) { console.error("MotionGuidePlugin Error found: \n" + err); } // drawing if(!ctx){ return err; } var i; var path = guideData.path; var pathLength = path.length; var width = 3; var length = 9; ctx.save(); //ctx.resetTransform(); ctx.lineCap = "round"; ctx.lineJoin = "miter"; ctx.beginPath(); // curve ctx.moveTo(path[0], path[1]); for(i=2; i < pathLength; i+=4) { ctx.quadraticCurveTo( path[i], path[i+1], path[i+2], path[i+3] ); } ctx.strokeStyle = "black"; ctx.lineWidth = width*1.5; ctx.stroke(); ctx.strokeStyle = "white"; ctx.lineWidth = width; ctx.stroke(); ctx.closePath(); // highlights var hiCount = higlight.length; if(higlight && hiCount) { var tempStore = {}; var tempLook = {}; s._solveGuideData(guideData, tempStore); for(var i=0; i= effRatio){ target = i; break; } look += test; } if(target === undefined) { target = l-1; look -= test; } // find midline weighting var subLines = lineSegments[target].weightings; var portion = test; l = subLines.length; for(i=0; i= effRatio){ break; } look += test; } // translate the subline index into a position in the path data target = (target*4) + 2; // take the distance we've covered in our ratio, and scale it to distance into the weightings t = (i/precision) + (((effRatio-look) / test) * (1/precision)); // position var pathData = guideData.path; s._getParamsForCurve( pathData[target-2], pathData[target-1], pathData[target], pathData[target+1], pathData[target+2], pathData[target+3], t, guideData.orient, output ); if(guideData.orient) { if(ratio >= 0.99999 && ratio <= 1.00001 && guideData.endAbsRot !== undefined) { output.rotation = guideData.endAbsRot; } else { output.rotation += guideData.startOffsetRot + (ratio * guideData.deltaRotation); } } return output; }; /** * For a given quadratic bezier t-value, what is the position and rotation. Save it onto the output object. * @param {Number} sx Start x. * @param {Number} sy Start y. * @param {Number} cx Control x. * @param {Number} cy Control y. * @param {Number} ex End x. * @param {Number} ey End y. * @param {Number} t T value (parametric distance into curve). * @param {Boolean} orient Save rotation data. * @param {Object} output Object to save output properties of x,y, and rotation onto. * @private */ s._getParamsForCurve = function(sx,sy, cx,cy, ex,ey, t, orient, output) { var inv = 1 - t; // finding a point on a bezier curve output.x = inv*inv * sx + 2 * inv * t * cx + t*t * ex; output.y = inv*inv * sy + 2 * inv * t * cy + t*t * ey; // finding an angle on a bezier curve if(orient) { // convert from radians back to degrees output.rotation = 57.2957795 * Math.atan2( (cy - sy)*inv + (ey - cy)*t, (cx - sx)*inv + (ex - cx)*t ); } }; /** * Perform a check to validate path information so plugin can avoid later error checking. * @param {Object} guideData All the information describing the guide to be followed. * @returns {undefined|String} The problem found, or undefined if no problems. * @private */ s._findPathProblems = function(guideData) { var path = guideData.path; var valueCount = (path && path.length) || 0; // ensure this is a number to simplify later logic if(valueCount < 6 || (valueCount-2) % 4) { var message = "\tCannot parse 'path' array due to invalid number of entries in path. "; message += "There should be an odd number of points, at least 3 points, and 2 entries per point (x & y). "; message += "See 'CanvasRenderingContext2D.quadraticCurveTo' for details as 'path' models a quadratic bezier.\n\n"; message += "Only [ "+ valueCount +" ] values found. Expected: "+ Math.max(Math.ceil((valueCount-2)/4)*4+2, 6); //6, 10, 14,... return message; } for(var i=0; i 1*/) { // outside 0-1 is unpredictable, but not breaking return "'start' out of bounds. Expected 0 to 1, got: "+ start; } var end = guideData.end; if(isNaN(end) && (end !== undefined)/* || end < 0 || end > 1*/) { // outside 0-1 is unpredictable, but not breaking return "'end' out of bounds. Expected 0 to 1, got: "+ end; } var orient = guideData.orient; if(orient) { // mirror the check used elsewhere if(orient != "fixed" && orient != "auto" && orient != "cw" && orient != "ccw") { return 'Invalid orientation value. Expected ["fixed", "auto", "cw", "ccw", undefined], got: '+ orient; } } return undefined; }; 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*/"1.0.0"; // injected by build process /** * The build date for this release in UTC format. * @property buildDate * @type String * @static **/ s.buildDate = /*=date*/"Thu, 14 Sep 2017 19:47:47 GMT"; // injected by build process })();