From 5c9a616252c807e9905c7dcc2a93310458ab4bf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikkel=20N=C3=B8rgaard?= Date: Sat, 16 Apr 2016 20:29:04 +0200 Subject: [PATCH 1/3] added node-webkit(nw) compability --- lib/easeljs-nw.combined.js | 13413 +++++++++++++++++++++++++++++++++++ 1 file changed, 13413 insertions(+) create mode 100644 lib/easeljs-nw.combined.js diff --git a/lib/easeljs-nw.combined.js b/lib/easeljs-nw.combined.js new file mode 100644 index 000000000..a1f67c606 --- /dev/null +++ b/lib/easeljs-nw.combined.js @@ -0,0 +1,13413 @@ +/*! +* EaselJS +* Visit http://createjs.com/ for window.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 window.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; +}; + +//############################################################################## +// indexOf.js +//############################################################################## + +this.createjs = this.createjs||{}; + +/** + * @class Utility Methods + */ + +/** + * Finds the first occurrence of a specified value searchElement in the passed in array, and returns the index of + * that value. Returns -1 if value is not found. + * + * var i = createjs.indexOf(myArray, myElementToFind); + * + * @method indexOf + * @param {Array} array Array to search for searchElement + * @param searchElement Element to find in array. + * @return {Number} The first index of searchElement in array. + */ +createjs.indexOf = function (array, searchElement){ + "use strict"; + + for (var i = 0,l=array.length; i < l; i++) { + if (searchElement === array[i]) { + return i; + } + } + return -1; +}; + +//############################################################################## +// 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; + + /** + * REMOVED. Removed in favor of using `MySuperClass_constructor`. + * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} + * for details. + * + * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. + * + * @method initialize + * @protected + * @deprecated + */ + // p.initialize = function() {}; // searchable for devs wondering where it is. + +// public methods: + /** + * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true if the event is cancelable. + * Mirrors the DOM level 2 event standard. In general, cancelable events that have `preventDefault()` called will + * cancel the default behaviour associated with the event. + * @method preventDefault + **/ + p.preventDefault = function() { + this.defaultPrevented = this.cancelable&&true; + }; + + /** + * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} to true. + * Mirrors the DOM event standard. + * @method stopPropagation + **/ + p.stopPropagation = function() { + this.propagationStopped = true; + }; + + /** + * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} and + * {{#crossLink "Event/immediatePropagationStopped"}}{{/crossLink}} to true. + * Mirrors the DOM event standard. + * @method stopImmediatePropagation + **/ + p.stopImmediatePropagation = function() { + this.immediatePropagationStopped = this.propagationStopped = true; + }; + + /** + * Causes the active listener to be removed via removeEventListener(); + * + * myBtn.addEventListener("click", function(evt) { + * // do stuff... + * evt.remove(); // removes this listener. + * }); + * + * @method remove + **/ + p.remove = function() { + this.removed = true; + }; + + /** + * Returns a clone of the Event instance. + * @method clone + * @return {Event} a clone of the Event instance. + **/ + p.clone = function() { + return new Event(this.type, this.bubbles, this.cancelable); + }; + + /** + * Provides a chainable shortcut method for setting a number of properties on the instance. + * + * @method set + * @param {Object} props A generic object containing properties to copy to the instance. + * @return {Event} Returns the instance the method is called on (useful for chaining calls.) + * @chainable + */ + p.set = function(props) { + for (var n in props) { this[n] = props[n]; } + return this; + }; + + /** + * Returns a string representation of this object. + * @method toString + * @return {String} a string representation of the instance. + **/ + p.toString = function() { + return "[Event (type="+this.type+")]"; + }; + + createjs.Event = Event; +}()); + +//############################################################################## +// EventDispatcher.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + + +// constructor: + /** + * EventDispatcher provides methods for managing queues of event listeners and dispatching events. + * + * You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the + * EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method. + * + * Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the + * DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports + * bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent. + * + * EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier + * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The + * {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to + * {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}. + * + * Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}} + * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also + * includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener. + * + *

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; + + /** + * REMOVED. Removed in favor of using `MySuperClass_constructor`. + * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} + * for details. + * + * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. + * + * @method initialize + * @protected + * @deprecated + */ + // p.initialize = function() {}; // searchable for devs wondering where it is. + + +// static public methods: + /** + * Static initializer to mix EventDispatcher methods into a target object or prototype. + * + * EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class + * EventDispatcher.initialize(myObject); // add to a specific instance + * + * @method initialize + * @static + * @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a + * prototype. + **/ + EventDispatcher.initialize = function(target) { + target.addEventListener = p.addEventListener; + target.on = p.on; + target.removeEventListener = target.off = p.removeEventListener; + target.removeAllEventListeners = p.removeAllEventListeners; + target.hasEventListener = p.hasEventListener; + target.dispatchEvent = p.dispatchEvent; + target._dispatchEvent = p._dispatchEvent; + target.willTrigger = p.willTrigger; + }; + + +// public methods: + /** + * Adds the specified event listener. Note that adding multiple listeners to the same function will result in + * multiple callbacks getting fired. + * + *

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/setPaused"}}{{/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: + /** + * Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}, and will be removed in a future version. If true, timingMode will + * use {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} by default. + * @deprecated Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}. + * @property useRAF + * @static + * @type {Boolean} + * @default false + **/ + Ticker.useRAF = false; + + /** + * Specifies the timing api (setTimeout or requestAnimationFrame) and mode to use. See + * {{#crossLink "Ticker/TIMEOUT"}}{{/crossLink}}, {{#crossLink "Ticker/RAF"}}{{/crossLink}}, and + * {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} for mode details. + * @property timingMode + * @static + * @type {String} + * @default Ticker.TIMEOUT + **/ + Ticker.timingMode = null; + + /** + * Specifies a maximum value for the delta property in the tick event object. This is useful when building time + * based animations and systems to prevent issues caused by large time gaps caused by background tabs, system sleep, + * alert dialogs, or other blocking routines. Double the expected frame duration is often an effective value + * (ex. maxDelta=50 when running at 40fps). + * + * This does not impact any other values (ex. time, runTime, etc), so you may experience issues if you enable maxDelta + * when using both delta and other values. + * + * If 0, there is no maximum. + * @property maxDelta + * @static + * @type {number} + * @default 0 + */ + Ticker.maxDelta = 0; + + /** + * When the ticker is paused, all listeners will still receive a tick event, but the 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} + * @protected + **/ + Ticker._inited = false; + + /** + * @property _startTime + * @static + * @type {Number} + * @protected + **/ + Ticker._startTime = 0; + + /** + * @property _pausedTime + * @static + * @type {Number} + * @protected + **/ + Ticker._pausedTime=0; + + /** + * The number of ticks that have passed + * @property _ticks + * @static + * @type {Number} + * @protected + **/ + Ticker._ticks = 0; + + /** + * The number of ticks that have passed while Ticker has been paused + * @property _pausedTicks + * @static + * @type {Number} + * @protected + **/ + Ticker._pausedTicks = 0; + + /** + * @property _interval + * @static + * @type {Number} + * @protected + **/ + Ticker._interval = 50; + + /** + * @property _lastTime + * @static + * @type {Number} + * @protected + **/ + Ticker._lastTime = 0; + + /** + * @property _times + * @static + * @type {Array} + * @protected + **/ + Ticker._times = null; + + /** + * @property _tickTimes + * @static + * @type {Array} + * @protected + **/ + Ticker._tickTimes = null; + + /** + * Stores the timeout or requestAnimationFrame id. + * @property _timerId + * @static + * @type {Number} + * @protected + **/ + Ticker._timerId = null; + + /** + * True if currently using requestAnimationFrame, false if using setTimeout. This may be different than timingMode + * if that property changed and a tick hasn't fired. + * @property _raf + * @static + * @type {Boolean} + * @protected + **/ + Ticker._raf = true; + + +// static getter / setters: + /** + * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead. + * @method setInterval + * @static + * @param {Number} interval + * @deprecated + **/ + Ticker.setInterval = function(interval) { + Ticker._interval = interval; + if (!Ticker._inited) { return; } + Ticker._setupTick(); + }; + + /** + * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead. + * @method getInterval + * @static + * @return {Number} + * @deprecated + **/ + Ticker.getInterval = function() { + return Ticker._interval; + }; + + /** + * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead. + * @method setFPS + * @static + * @param {Number} value + * @deprecated + **/ + Ticker.setFPS = function(value) { + Ticker.setInterval(1000/value); + }; + + /** + * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead. + * @method getFPS + * @static + * @return {Number} + * @deprecated + **/ + Ticker.getFPS = function() { + return 1000/Ticker._interval; + }; + + /** + * Indicates the target time (in milliseconds) between ticks. Default is 50 (20 FPS). + * Note that actual time between ticks may be more than specified depending on CPU load. + * This property is ignored if the ticker is using the `RAF` timing mode. + * @property interval + * @static + * @type {Number} + **/ + + /** + * Indicates the target frame rate in frames per second (FPS). Effectively just a shortcut to `interval`, where + * `framerate == 1000/interval`. + * @property framerate + * @static + * @type {Number} + **/ + try { + Object.defineProperties(Ticker, { + interval: { get: Ticker.getInterval, set: Ticker.setInterval }, + framerate: { get: Ticker.getFPS, set: Ticker.setFPS } + }); + } catch (e) { console.log(e); } + + +// public static methods: + /** + * Starts the tick. This is called automatically when the first listener is added. + * @method init + * @static + **/ + Ticker.init = function() { + if (Ticker._inited) { return; } + Ticker._inited = true; + Ticker._times = []; + Ticker._tickTimes = []; + Ticker._startTime = Ticker._getTime(); + Ticker._times.push(Ticker._lastTime = 0); + Ticker.interval = Ticker._interval; + }; + + /** + * Stops the Ticker and removes all listeners. Use init() to restart the Ticker. + * @method reset + * @static + **/ + Ticker.reset = function() { + if (Ticker._raf) { + var f = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame; + f&&f(Ticker._timerId); + } else { + clearTimeout(Ticker._timerId); + } + Ticker.removeAllEventListeners("tick"); + Ticker._timerId = Ticker._times = Ticker._tickTimes = null; + Ticker._startTime = Ticker._lastTime = Ticker._ticks = 0; + Ticker._inited = false; + }; + + /** + * Returns the average time spent within a tick. This can vary significantly from the value provided by getMeasuredFPS + * because it only measures the time spent within the tick execution stack. + * + * Example 1: With a target FPS of 20, getMeasuredFPS() returns 20fps, which indicates an average of 50ms between + * the end of one tick and the end of the next. However, getMeasuredTickTime() returns 15ms. This indicates that + * there may be up to 35ms of "idle" time between the end of one tick and the start of the next. + * + * Example 2: With a target FPS of 30, getFPS() returns 10fps, which indicates an average of 100ms between the end of + * one tick and the end of the next. However, getMeasuredTickTime() returns 20ms. This would indicate that something + * other than the tick is using ~80ms (another script, DOM rendering, etc). + * @method getMeasuredTickTime + * @static + * @param {Number} [ticks] The number of previous ticks over which to measure the average time spent in a tick. + * Defaults to the number of ticks per second. To get only the last tick's time, pass in 1. + * @return {Number} The average time spent in a tick in milliseconds. + **/ + Ticker.getMeasuredTickTime = function(ticks) { + var ttl=0, times=Ticker._tickTimes; + if (!times || times.length < 1) { return -1; } + + // by default, calculate average for the past ~1 second: + ticks = Math.min(times.length, ticks||(Ticker.getFPS()|0)); + for (var i=0; i= (Ticker._interval-1)*0.97) { + Ticker._tick(); + } + }; + + /** + * @method _handleRAF + * @static + * @protected + **/ + Ticker._handleRAF = function() { + Ticker._timerId = null; + Ticker._setupTick(); + Ticker._tick(); + }; + + /** + * @method _handleTimeout + * @static + * @protected + **/ + Ticker._handleTimeout = function() { + Ticker._timerId = null; + Ticker._setupTick(); + Ticker._tick(); + }; + + /** + * @method _setupTick + * @static + * @protected + **/ + Ticker._setupTick = function() { + if (Ticker._timerId != null) { return; } // avoid duplicates + + var mode = Ticker.timingMode||(Ticker.useRAF&&Ticker.RAF_SYNCHED); + if (mode == Ticker.RAF_SYNCHED || mode == Ticker.RAF) { + var f = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame; + if (f) { + Ticker._timerId = f(mode == Ticker.RAF ? Ticker._handleRAF : Ticker._handleSynch); + Ticker._raf = true; + return; + } + } + Ticker._raf = false; + Ticker._timerId = setTimeout(Ticker._handleTimeout, Ticker._interval); + }; + + /** + * @method _tick + * @static + * @protected + **/ + Ticker._tick = function() { + var paused = Ticker.paused; + var time = Ticker._getTime(); + var elapsedTime = time-Ticker._lastTime; + Ticker._lastTime = time; + Ticker._ticks++; + + if (paused) { + Ticker._pausedTicks++; + Ticker._pausedTime += elapsedTime; + } + + if (Ticker.hasEventListener("tick")) { + var event = new createjs.Event("tick"); + var maxDelta = Ticker.maxDelta; + event.delta = (maxDelta && elapsedTime > maxDelta) ? maxDelta : elapsedTime; + event.paused = paused; + event.time = time; + event.runTime = time-Ticker._pausedTime; + Ticker.dispatchEvent(event); + } + + Ticker._tickTimes.unshift(Ticker._getTime()-time); + while (Ticker._tickTimes.length > 100) { Ticker._tickTimes.pop(); } + + Ticker._times.unshift(time); + while (Ticker._times.length > 100) { Ticker._times.pop(); } + }; + + /** + * @method _getTime + * @static + * @protected + **/ + var now = window.performance && (window.performance.now || window.performance.mozNow || window.performance.msNow || window.performance.oNow || window.performance.webkitNow); + Ticker._getTime = function() { + return ((now&&now.call(window.performance))||(new Date().getTime())) - Ticker._startTime; + }; + + + createjs.Ticker = Ticker; +}()); + +//############################################################################## +// UID.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + + +// constructor: + /** + * Global utility for generating sequential unique ID numbers. The UID class uses a static interface (ex. UID.get()) + * and should not be instantiated. + * @class UID + * @static + **/ + function UID() { + throw "UID cannot be instantiated"; + } + + +// private static properties: + /** + * @property _nextID + * @type Number + * @protected + **/ + UID._nextID = 0; + + +// public static methods: + /** + * Returns the next unique id. + * @method get + * @return {Number} The next unique id + * @static + **/ + UID.get = function() { + return UID._nextID++; + }; + + + createjs.UID = UID; +}()); + +//############################################################################## +// MouseEvent.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + + +// constructor: + /** + * Passed as the parameter to all mouse/pointer/touch related events. For a listing of mouse events and their properties, + * see the {{#crossLink "DisplayObject"}}{{/crossLink}} and {{#crossLink "Stage"}}{{/crossLink}} event listings. + * @class MouseEvent + * @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. + * @param {Number} stageX The normalized x position relative to the stage. + * @param {Number} stageY The normalized y position relative to the stage. + * @param {MouseEvent} nativeEvent The native DOM event related to this mouse event. + * @param {Number} pointerID The unique id for the pointer. + * @param {Boolean} primary Indicates whether this is the primary pointer in a multitouch environment. + * @param {Number} rawX The raw x position relative to the stage. + * @param {Number} rawY The raw y position relative to the stage. + * @param {DisplayObject} relatedTarget The secondary target for the event. + * @extends Event + * @constructor + **/ + function MouseEvent(type, bubbles, cancelable, stageX, stageY, nativeEvent, pointerID, primary, rawX, rawY, relatedTarget) { + this.Event_constructor(type, bubbles, cancelable); + + + // public properties: + /** + * The normalized x position on the stage. This will always be within the range 0 to stage width. + * @property stageX + * @type Number + */ + this.stageX = stageX; + + /** + * The normalized y position on the stage. This will always be within the range 0 to stage height. + * @property stageY + * @type Number + **/ + this.stageY = stageY; + + /** + * The raw x position relative to the stage. Normally this will be the same as the stageX value, unless + * stage.mouseMoveOutside is true and the pointer is outside of the stage bounds. + * @property rawX + * @type Number + */ + this.rawX = (rawX==null)?stageX:rawX; + + /** + * The raw y position relative to the stage. Normally this will be the same as the stageY value, unless + * stage.mouseMoveOutside is true and the pointer is outside of the stage bounds. + * @property rawY + * @type Number + */ + this.rawY = (rawY==null)?stageY:rawY; + + /** + * The native MouseEvent generated by the browser. The properties and API for this + * event may differ between browsers. This property will be null if the + * EaselJS property was not directly generated from a native MouseEvent. + * @property nativeEvent + * @type HtmlMouseEvent + * @default null + **/ + this.nativeEvent = nativeEvent; + + /** + * The unique id for the pointer (touch point or cursor). This will be either -1 for the mouse, or the system + * supplied id value. + * @property pointerID + * @type {Number} + */ + this.pointerID = pointerID; + + /** + * Indicates whether this is the primary pointer in a multitouch environment. This will always be true for the mouse. + * For touch pointers, the first pointer in the current stack will be considered the primary pointer. + * @property primary + * @type {Boolean} + */ + this.primary = !!primary; + + /** + * The secondary target for the event, if applicable. This is used for mouseout/rollout + * events to indicate the object that the mouse entered from, mouseover/rollover for the object the mouse exited, + * and stagemousedown/stagemouseup events for the object that was the under the cursor, if any. + * + * Only valid interaction targets will be returned (ie. objects with mouse listeners or a cursor set). + * @property relatedTarget + * @type {DisplayObject} + */ + this.relatedTarget = relatedTarget; + } + var p = createjs.extend(MouseEvent, createjs.Event); + + // TODO: deprecated + // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. + + +// getter / setters: + /** + * Returns the x position of the mouse in the local coordinate system of the current target (ie. the dispatcher). + * @property localX + * @type {Number} + * @readonly + */ + p._get_localX = function() { + return this.currentTarget.globalToLocal(this.rawX, this.rawY).x; + }; + + /** + * Returns the y position of the mouse in the local coordinate system of the current target (ie. the dispatcher). + * @property localY + * @type {Number} + * @readonly + */ + p._get_localY = function() { + return this.currentTarget.globalToLocal(this.rawX, this.rawY).y; + }; + + /** + * Indicates whether the event was generated by a touch input (versus a mouse input). + * @property isTouch + * @type {Boolean} + * @readonly + */ + p._get_isTouch = function() { + return this.pointerID !== -1; + }; + + + try { + Object.defineProperties(p, { + localX: { get: p._get_localX }, + localY: { get: p._get_localY }, + isTouch: { get: p._get_isTouch } + }); + } catch (e) {} // TODO: use Log + + +// public methods: + /** + * Returns a clone of the MouseEvent instance. + * @method clone + * @return {MouseEvent} a clone of the MouseEvent instance. + **/ + p.clone = function() { + return new MouseEvent(this.type, this.bubbles, this.cancelable, this.stageX, this.stageY, this.nativeEvent, this.pointerID, this.primary, this.rawX, this.rawY); + }; + + /** + * Returns a string representation of this object. + * @method toString + * @return {String} a string representation of the instance. + **/ + p.toString = function() { + return "[MouseEvent (type="+this.type+" stageX="+this.stageX+" stageY="+this.stageY+")]"; + }; + + + createjs.MouseEvent = createjs.promote(MouseEvent, "Event"); +}()); + +//############################################################################## +// Matrix2D.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + + +// constructor: + /** + * Represents an affine transformation matrix, and provides tools for constructing and concatenating matrices. + * + * This matrix can be visualized as: + * + * [ a c tx + * b d ty + * 0 0 1 ] + * + * Note the locations of b and c. + * + * @class Matrix2D + * @param {Number} [a=1] Specifies the a property for the new matrix. + * @param {Number} [b=0] Specifies the b property for the new matrix. + * @param {Number} [c=0] Specifies the c property for the new matrix. + * @param {Number} [d=1] Specifies the d property for the new matrix. + * @param {Number} [tx=0] Specifies the tx property for the new matrix. + * @param {Number} [ty=0] Specifies the ty property for the new matrix. + * @constructor + **/ + function Matrix2D(a, b, c, d, tx, ty) { + this.setValues(a,b,c,d,tx,ty); + + // public properties: + // assigned in the setValues method. + /** + * Position (0, 0) in a 3x3 affine transformation matrix. + * @property a + * @type Number + **/ + + /** + * Position (0, 1) in a 3x3 affine transformation matrix. + * @property b + * @type Number + **/ + + /** + * Position (1, 0) in a 3x3 affine transformation matrix. + * @property c + * @type Number + **/ + + /** + * Position (1, 1) in a 3x3 affine transformation matrix. + * @property d + * @type Number + **/ + + /** + * Position (2, 0) in a 3x3 affine transformation matrix. + * @property tx + * @type Number + **/ + + /** + * Position (2, 1) in a 3x3 affine transformation matrix. + * @property ty + * @type Number + **/ + } + var p = Matrix2D.prototype; + + /** + * REMOVED. Removed in favor of using `MySuperClass_constructor`. + * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} + * for details. + * + * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. + * + * @method initialize + * @protected + * @deprecated + */ + // p.initialize = function() {}; // searchable for devs wondering where it is. + + +// constants: + /** + * Multiplier for converting degrees to radians. Used internally by Matrix2D. + * @property DEG_TO_RAD + * @static + * @final + * @type Number + * @readonly + **/ + Matrix2D.DEG_TO_RAD = Math.PI/180; + + +// static public properties: + /** + * An identity matrix, representing a null transformation. + * @property identity + * @static + * @type Matrix2D + * @readonly + **/ + Matrix2D.identity = null; // set at bottom of class definition. + + +// public methods: + /** + * Sets the specified values on this instance. + * @method setValues + * @param {Number} [a=1] Specifies the a property for the new matrix. + * @param {Number} [b=0] Specifies the b property for the new matrix. + * @param {Number} [c=0] Specifies the c property for the new matrix. + * @param {Number} [d=1] Specifies the d property for the new matrix. + * @param {Number} [tx=0] Specifies the tx property for the new matrix. + * @param {Number} [ty=0] Specifies the ty property for the new matrix. + * @return {Matrix2D} This instance. Useful for chaining method calls. + */ + p.setValues = function(a, b, c, d, tx, ty) { + // don't forget to update docs in the constructor if these change: + this.a = (a == null) ? 1 : a; + this.b = b || 0; + this.c = c || 0; + this.d = (d == null) ? 1 : d; + this.tx = tx || 0; + this.ty = ty || 0; + return this; + }; + + /** + * Appends the specified matrix properties to this matrix. All parameters are required. + * This is the equivalent of multiplying `(this matrix) * (specified matrix)`. + * @method append + * @param {Number} a + * @param {Number} b + * @param {Number} c + * @param {Number} d + * @param {Number} tx + * @param {Number} ty + * @return {Matrix2D} This matrix. Useful for chaining method calls. + **/ + p.append = function(a, b, c, d, tx, ty) { + var a1 = this.a; + var b1 = this.b; + var c1 = this.c; + var d1 = this.d; + if (a != 1 || b != 0 || c != 0 || d != 1) { + this.a = a1*a+c1*b; + this.b = b1*a+d1*b; + this.c = a1*c+c1*d; + this.d = b1*c+d1*d; + } + this.tx = a1*tx+c1*ty+this.tx; + this.ty = b1*tx+d1*ty+this.ty; + return this; + }; + + /** + * Prepends the specified matrix properties to this matrix. + * This is the equivalent of multiplying `(specified matrix) * (this matrix)`. + * All parameters are required. + * @method prepend + * @param {Number} a + * @param {Number} b + * @param {Number} c + * @param {Number} d + * @param {Number} tx + * @param {Number} ty + * @return {Matrix2D} This matrix. Useful for chaining method calls. + **/ + p.prepend = function(a, b, c, d, tx, ty) { + var a1 = this.a; + var c1 = this.c; + var tx1 = this.tx; + + this.a = a*a1+c*this.b; + this.b = b*a1+d*this.b; + this.c = a*c1+c*this.d; + this.d = b*c1+d*this.d; + this.tx = a*tx1+c*this.ty+tx; + this.ty = b*tx1+d*this.ty+ty; + return this; + }; + + /** + * Appends the specified matrix to this matrix. + * This is the equivalent of multiplying `(this matrix) * (specified matrix)`. + * @method appendMatrix + * @param {Matrix2D} matrix + * @return {Matrix2D} This matrix. Useful for chaining method calls. + **/ + p.appendMatrix = function(matrix) { + return this.append(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty); + }; + + /** + * Prepends the specified matrix to this matrix. + * This is the equivalent of multiplying `(specified matrix) * (this matrix)`. + * For example, you could calculate the combined transformation for a child object using: + * + * var o = myDisplayObject; + * var mtx = o.getMatrix(); + * while (o = o.parent) { + * // prepend each parent's transformation in turn: + * o.prependMatrix(o.getMatrix()); + * } + * @method prependMatrix + * @param {Matrix2D} matrix + * @return {Matrix2D} This matrix. Useful for chaining method calls. + **/ + p.prependMatrix = function(matrix) { + return this.prepend(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty); + }; + + /** + * Generates matrix properties from the specified display object transform properties, and appends them to this matrix. + * For example, you can use this to generate a matrix representing the transformations of a display object: + * + * var mtx = new createjs.Matrix2D(); + * mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation); + * @method appendTransform + * @param {Number} x + * @param {Number} y + * @param {Number} scaleX + * @param {Number} scaleY + * @param {Number} rotation + * @param {Number} skewX + * @param {Number} skewY + * @param {Number} regX Optional. + * @param {Number} regY Optional. + * @return {Matrix2D} This matrix. Useful for chaining method calls. + **/ + p.appendTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) { + if (rotation%360) { + var r = rotation*Matrix2D.DEG_TO_RAD; + var cos = Math.cos(r); + var sin = Math.sin(r); + } else { + cos = 1; + sin = 0; + } + + if (skewX || skewY) { + // TODO: can this be combined into a single append operation? + skewX *= Matrix2D.DEG_TO_RAD; + skewY *= Matrix2D.DEG_TO_RAD; + this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y); + this.append(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, 0, 0); + } else { + this.append(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, x, y); + } + + if (regX || regY) { + // append the registration offset: + this.tx -= regX*this.a+regY*this.c; + this.ty -= regX*this.b+regY*this.d; + } + return this; + }; + + /** + * Generates matrix properties from the specified display object transform properties, and prepends them to this matrix. + * For example, you could calculate the combined transformation for a child object using: + * + * var o = myDisplayObject; + * var mtx = new createjs.Matrix2D(); + * do { + * // prepend each parent's transformation in turn: + * mtx.prependTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.regX, o.regY); + * } while (o = o.parent); + * + * Note that the above example would not account for {{#crossLink "DisplayObject/transformMatrix:property"}}{{/crossLink}} + * values. See {{#crossLink "Matrix2D/prependMatrix"}}{{/crossLink}} for an example that does. + * @method prependTransform + * @param {Number} x + * @param {Number} y + * @param {Number} scaleX + * @param {Number} scaleY + * @param {Number} rotation + * @param {Number} skewX + * @param {Number} skewY + * @param {Number} regX Optional. + * @param {Number} regY Optional. + * @return {Matrix2D} This matrix. Useful for chaining method calls. + **/ + p.prependTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) { + if (rotation%360) { + var r = rotation*Matrix2D.DEG_TO_RAD; + var cos = Math.cos(r); + var sin = Math.sin(r); + } else { + cos = 1; + sin = 0; + } + + if (regX || regY) { + // prepend the registration offset: + this.tx -= regX; this.ty -= regY; + } + if (skewX || skewY) { + // TODO: can this be combined into a single prepend operation? + skewX *= Matrix2D.DEG_TO_RAD; + skewY *= Matrix2D.DEG_TO_RAD; + this.prepend(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, 0, 0); + this.prepend(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y); + } else { + this.prepend(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, x, y); + } + return this; + }; + + /** + * Applies a clockwise rotation transformation to the matrix. + * @method rotate + * @param {Number} angle The angle to rotate by, in degrees. To use a value in radians, multiply it by `180/Math.PI`. + * @return {Matrix2D} This matrix. Useful for chaining method calls. + **/ + p.rotate = function(angle) { + angle = angle*Matrix2D.DEG_TO_RAD; + var cos = Math.cos(angle); + var sin = Math.sin(angle); + + var a1 = this.a; + var b1 = this.b; + + this.a = a1*cos+this.c*sin; + this.b = b1*cos+this.d*sin; + this.c = -a1*sin+this.c*cos; + this.d = -b1*sin+this.d*cos; + return this; + }; + + /** + * Applies a skew transformation to the matrix. + * @method skew + * @param {Number} skewX The amount to skew horizontally in degrees. To use a value in radians, multiply it by `180/Math.PI`. + * @param {Number} skewY The amount to skew vertically in degrees. + * @return {Matrix2D} This matrix. Useful for chaining method calls. + */ + p.skew = function(skewX, skewY) { + skewX = skewX*Matrix2D.DEG_TO_RAD; + skewY = skewY*Matrix2D.DEG_TO_RAD; + this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), 0, 0); + return this; + }; + + /** + * Applies a scale transformation to the matrix. + * @method scale + * @param {Number} x The amount to scale horizontally. E.G. a value of 2 will double the size in the X direction, and 0.5 will halve it. + * @param {Number} y The amount to scale vertically. + * @return {Matrix2D} This matrix. Useful for chaining method calls. + **/ + p.scale = function(x, y) { + this.a *= x; + this.b *= x; + this.c *= y; + this.d *= y; + //this.tx *= x; + //this.ty *= y; + return this; + }; + + /** + * Translates the matrix on the x and y axes. + * @method translate + * @param {Number} x + * @param {Number} y + * @return {Matrix2D} This matrix. Useful for chaining method calls. + **/ + p.translate = function(x, y) { + this.tx += this.a*x + this.c*y; + this.ty += this.b*x + this.d*y; + return this; + }; + + /** + * Sets the properties of the matrix to those of an identity matrix (one that applies a null transformation). + * @method identity + * @return {Matrix2D} This matrix. Useful for chaining method calls. + **/ + p.identity = function() { + this.a = this.d = 1; + this.b = this.c = this.tx = this.ty = 0; + return this; + }; + + /** + * Inverts the matrix, causing it to perform the opposite transformation. + * @method invert + * @return {Matrix2D} This matrix. Useful for chaining method calls. + **/ + p.invert = function() { + var a1 = this.a; + var b1 = this.b; + var c1 = this.c; + var d1 = this.d; + var tx1 = this.tx; + var n = a1*d1-b1*c1; + + this.a = d1/n; + this.b = -b1/n; + this.c = -c1/n; + this.d = a1/n; + this.tx = (c1*this.ty-d1*tx1)/n; + this.ty = -(a1*this.ty-b1*tx1)/n; + return this; + }; + + /** + * Returns true if the matrix is an identity matrix. + * @method isIdentity + * @return {Boolean} + **/ + p.isIdentity = function() { + return this.tx === 0 && this.ty === 0 && this.a === 1 && this.b === 0 && this.c === 0 && this.d === 1; + }; + + /** + * Returns true if this matrix is equal to the specified matrix (all property values are equal). + * @method equals + * @param {Matrix2D} matrix The matrix to compare. + * @return {Boolean} + **/ + p.equals = function(matrix) { + return this.tx === matrix.tx && this.ty === matrix.ty && this.a === matrix.a && this.b === matrix.b && this.c === matrix.c && this.d === matrix.d; + }; + + /** + * Transforms a point according to this matrix. + * @method transformPoint + * @param {Number} x The x component of the point to transform. + * @param {Number} y The y component of the point to transform. + * @param {Point | Object} [pt] An object to copy the result into. If omitted a generic object with x/y properties will be returned. + * @return {Point} This matrix. Useful for chaining method calls. + **/ + p.transformPoint = function(x, y, pt) { + pt = pt||{}; + pt.x = x*this.a+y*this.c+this.tx; + pt.y = x*this.b+y*this.d+this.ty; + return pt; + }; + + /** + * Decomposes the matrix into transform properties (x, y, scaleX, scaleY, and rotation). Note that these values + * may not match the transform properties you used to generate the matrix, though they will produce the same visual + * results. + * @method decompose + * @param {Object} target The object to apply the transform properties to. If null, then a new object will be returned. + * @return {Object} The target, or a new generic object with the transform properties applied. + */ + p.decompose = function(target) { + // TODO: it would be nice to be able to solve for whether the matrix can be decomposed into only scale/rotation even when scale is negative + if (target == null) { target = {}; } + target.x = this.tx; + target.y = this.ty; + target.scaleX = Math.sqrt(this.a * this.a + this.b * this.b); + target.scaleY = Math.sqrt(this.c * this.c + this.d * this.d); + + var skewX = Math.atan2(-this.c, this.d); + var skewY = Math.atan2(this.b, this.a); + + var delta = Math.abs(1-skewX/skewY); + if (delta < 0.00001) { // effectively identical, can use rotation: + target.rotation = skewY/Matrix2D.DEG_TO_RAD; + if (this.a < 0 && this.d >= 0) { + target.rotation += (target.rotation <= 0) ? 180 : -180; + } + target.skewX = target.skewY = 0; + } else { + target.skewX = skewX/Matrix2D.DEG_TO_RAD; + target.skewY = skewY/Matrix2D.DEG_TO_RAD; + } + return target; + }; + + /** + * Copies all properties from the specified matrix to this matrix. + * @method copy + * @param {Matrix2D} matrix The matrix to copy properties from. + * @return {Matrix2D} This matrix. Useful for chaining method calls. + */ + p.copy = function(matrix) { + return this.setValues(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty); + }; + + /** + * Returns a clone of the Matrix2D instance. + * @method clone + * @return {Matrix2D} a clone of the Matrix2D instance. + **/ + p.clone = function() { + return new Matrix2D(this.a, this.b, this.c, this.d, this.tx, this.ty); + }; + + /** + * Returns a string representation of this object. + * @method toString + * @return {String} a string representation of the instance. + **/ + p.toString = function() { + return "[Matrix2D (a="+this.a+" b="+this.b+" c="+this.c+" d="+this.d+" tx="+this.tx+" ty="+this.ty+")]"; + }; + + // this has to be populated after the class is defined: + Matrix2D.identity = new Matrix2D(); + + + createjs.Matrix2D = Matrix2D; +}()); + +//############################################################################## +// DisplayProps.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + + /** + * Used for calculating and encapsulating display related properties. + * @class DisplayProps + * @param {Number} [visible=true] Visible value. + * @param {Number} [alpha=1] Alpha value. + * @param {Number} [shadow=null] A Shadow instance or null. + * @param {Number} [compositeOperation=null] A compositeOperation value or null. + * @param {Number} [matrix] A transformation matrix. Defaults to a new identity matrix. + * @constructor + **/ + function DisplayProps(visible, alpha, shadow, compositeOperation, matrix) { + this.setValues(visible, alpha, shadow, compositeOperation, matrix); + + // public properties: + // assigned in the setValues method. + /** + * Property representing the alpha that will be applied to a display object. + * @property alpha + * @type Number + **/ + + /** + * Property representing the shadow that will be applied to a display object. + * @property shadow + * @type Shadow + **/ + + /** + * Property representing the compositeOperation that will be applied to a display object. + * You can find a list of valid composite operations at: + * https://developer.mozilla.org/en/Canvas_tutorial/Compositing + * @property compositeOperation + * @type String + **/ + + /** + * Property representing the value for visible that will be applied to a display object. + * @property visible + * @type Boolean + **/ + + /** + * The transformation matrix that will be applied to a display object. + * @property matrix + * @type Matrix2D + **/ + } + var p = DisplayProps.prototype; + +// initialization: + /** + * Reinitializes the instance with the specified values. + * @method setValues + * @param {Number} [visible=true] Visible value. + * @param {Number} [alpha=1] Alpha value. + * @param {Number} [shadow=null] A Shadow instance or null. + * @param {Number} [compositeOperation=null] A compositeOperation value or null. + * @param {Number} [matrix] A transformation matrix. Defaults to an identity matrix. + * @return {DisplayProps} This instance. Useful for chaining method calls. + * @chainable + */ + p.setValues = function (visible, alpha, shadow, compositeOperation, matrix) { + this.visible = visible == null ? true : !!visible; + this.alpha = alpha == null ? 1 : alpha; + this.shadow = shadow; + this.compositeOperation = compositeOperation; + this.matrix = matrix || (this.matrix&&this.matrix.identity()) || new createjs.Matrix2D(); + return this; + }; + +// public methods: + /** + * Appends the specified display properties. This is generally used to apply a child's properties its parent's. + * @method append + * @param {Boolean} visible desired visible value + * @param {Number} alpha desired alpha value + * @param {Shadow} shadow desired shadow value + * @param {String} compositeOperation desired composite operation value + * @param {Matrix2D} [matrix] a Matrix2D instance + * @return {DisplayProps} This instance. Useful for chaining method calls. + * @chainable + */ + p.append = function(visible, alpha, shadow, compositeOperation, matrix) { + this.alpha *= alpha; + this.shadow = shadow || this.shadow; + this.compositeOperation = compositeOperation || this.compositeOperation; + this.visible = this.visible && visible; + matrix&&this.matrix.appendMatrix(matrix); + return this; + }; + + /** + * Prepends the specified display properties. This is generally used to apply a parent's properties to a child's. + * For example, to get the combined display properties that would be applied to a child, you could use: + * + * var o = myDisplayObject; + * var props = new createjs.DisplayProps(); + * do { + * // prepend each parent's props in turn: + * props.prepend(o.visible, o.alpha, o.shadow, o.compositeOperation, o.getMatrix()); + * } while (o = o.parent); + * + * @method prepend + * @param {Boolean} visible desired visible value + * @param {Number} alpha desired alpha value + * @param {Shadow} shadow desired shadow value + * @param {String} compositeOperation desired composite operation value + * @param {Matrix2D} [matrix] a Matrix2D instance + * @return {DisplayProps} This instance. Useful for chaining method calls. + * @chainable + */ + p.prepend = function(visible, alpha, shadow, compositeOperation, matrix) { + this.alpha *= alpha; + this.shadow = this.shadow || shadow; + this.compositeOperation = this.compositeOperation || compositeOperation; + this.visible = this.visible && visible; + matrix&&this.matrix.prependMatrix(matrix); + return this; + }; + + /** + * Resets this instance and its matrix to default values. + * @method identity + * @return {DisplayProps} This instance. Useful for chaining method calls. + * @chainable + */ + p.identity = function() { + this.visible = true; + this.alpha = 1; + this.shadow = this.compositeOperation = null; + this.matrix.identity(); + return this; + }; + + /** + * Returns a clone of the DisplayProps instance. Clones the associated matrix. + * @method clone + * @return {DisplayProps} a clone of the DisplayProps instance. + **/ + p.clone = function() { + return new DisplayProps(this.alpha, this.shadow, this.compositeOperation, this.visible, this.matrix.clone()); + }; + +// private methods: + + createjs.DisplayProps = DisplayProps; +})(); + +//############################################################################## +// Point.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + + +// constructor: + /** + * Represents a point on a 2 dimensional x / y coordinate system. + * + *

Example

+ * + * var point = new createjs.Point(0, 100); + * + * @class Point + * @param {Number} [x=0] X position. + * @param {Number} [y=0] Y position. + * @constructor + **/ + function Point(x, y) { + this.setValues(x, y); + + + // public properties: + // assigned in the setValues method. + /** + * X position. + * @property x + * @type Number + **/ + + /** + * Y position. + * @property y + * @type Number + **/ + } + var p = Point.prototype; + + /** + * REMOVED. Removed in favor of using `MySuperClass_constructor`. + * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} + * for details. + * + * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. + * + * @method initialize + * @protected + * @deprecated + */ + // p.initialize = function() {}; // searchable for devs wondering where it is. + + +// public methods: + /** + * Sets the specified values on this instance. + * @method setValues + * @param {Number} [x=0] X position. + * @param {Number} [y=0] Y position. + * @return {Point} This instance. Useful for chaining method calls. + * @chainable + */ + p.setValues = function(x, y) { + this.x = x||0; + this.y = y||0; + return this; + }; + + /** + * Copies all properties from the specified point to this point. + * @method copy + * @param {Point} point The point to copy properties from. + * @return {Point} This point. Useful for chaining method calls. + * @chainable + */ + p.copy = function(point) { + this.x = point.x; + this.y = point.y; + return this; + }; + + /** + * Returns a clone of the Point instance. + * @method clone + * @return {Point} a clone of the Point instance. + **/ + p.clone = function() { + return new Point(this.x, this.y); + }; + + /** + * Returns a string representation of this object. + * @method toString + * @return {String} a string representation of the instance. + **/ + p.toString = function() { + return "[Point (x="+this.x+" y="+this.y+")]"; + }; + + + createjs.Point = Point; +}()); + +//############################################################################## +// Rectangle.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + + +// constructor: + /** + * Represents a rectangle as defined by the points (x, y) and (x+width, y+height). + * + *

Example

+ * + * var rect = new createjs.Rectangle(0, 0, 100, 100); + * + * @class Rectangle + * @param {Number} [x=0] X position. + * @param {Number} [y=0] Y position. + * @param {Number} [width=0] The width of the Rectangle. + * @param {Number} [height=0] The height of the Rectangle. + * @constructor + **/ + function Rectangle(x, y, width, height) { + this.setValues(x, y, width, height); + + + // public properties: + // assigned in the setValues method. + /** + * X position. + * @property x + * @type Number + **/ + + /** + * Y position. + * @property y + * @type Number + **/ + + /** + * Width. + * @property width + * @type Number + **/ + + /** + * Height. + * @property height + * @type Number + **/ + } + var p = Rectangle.prototype; + + /** + * REMOVED. Removed in favor of using `MySuperClass_constructor`. + * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} + * for details. + * + * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. + * + * @method initialize + * @protected + * @deprecated + */ + // p.initialize = function() {}; // searchable for devs wondering where it is. + + +// public methods: + /** + * Sets the specified values on this instance. + * @method setValues + * @param {Number} [x=0] X position. + * @param {Number} [y=0] Y position. + * @param {Number} [width=0] The width of the Rectangle. + * @param {Number} [height=0] The height of the Rectangle. + * @return {Rectangle} This instance. Useful for chaining method calls. + * @chainable + */ + p.setValues = function(x, y, width, height) { + // don't forget to update docs in the constructor if these change: + this.x = x||0; + this.y = y||0; + this.width = width||0; + this.height = height||0; + return this; + }; + + /** + * Extends the rectangle's bounds to include the described point or rectangle. + * @method extend + * @param {Number} x X position of the point or rectangle. + * @param {Number} y Y position of the point or rectangle. + * @param {Number} [width=0] The width of the rectangle. + * @param {Number} [height=0] The height of the rectangle. + * @return {Rectangle} This instance. Useful for chaining method calls. + * @chainable + */ + p.extend = function(x, y, width, height) { + width = width||0; + height = height||0; + if (x+width > this.x+this.width) { this.width = x+width-this.x; } + if (y+height > this.y+this.height) { this.height = y+height-this.y; } + if (x < this.x) { this.width += this.x-x; this.x = x; } + if (y < this.y) { this.height += this.y-y; this.y = y; } + return this; + }; + + /** + * Adds the specified padding to the rectangle's bounds. + * @method pad + * @param {Number} top + * @param {Number} left + * @param {Number} right + * @param {Number} bottom + * @return {Rectangle} This instance. Useful for chaining method calls. + * @chainable + */ + p.pad = function(top, left, bottom, right) { + this.x -= left; + this.y -= top; + this.width += left+right; + this.height += top+bottom; + return this; + }; + + /** + * Copies all properties from the specified rectangle to this rectangle. + * @method copy + * @param {Rectangle} rectangle The rectangle to copy properties from. + * @return {Rectangle} This rectangle. Useful for chaining method calls. + * @chainable + */ + p.copy = function(rectangle) { + return this.setValues(rectangle.x, rectangle.y, rectangle.width, rectangle.height); + }; + + /** + * Returns true if this rectangle fully encloses the described point or rectangle. + * @method contains + * @param {Number} x X position of the point or rectangle. + * @param {Number} y Y position of the point or rectangle. + * @param {Number} [width=0] The width of the rectangle. + * @param {Number} [height=0] The height of the rectangle. + * @return {Boolean} True if the described point or rectangle is contained within this rectangle. + */ + p.contains = function(x, y, width, height) { + width = width||0; + height = height||0; + return (x >= this.x && x+width <= this.x+this.width && y >= this.y && y+height <= this.y+this.height); + }; + + /** + * Returns a new rectangle which contains this rectangle and the specified rectangle. + * @method union + * @param {Rectangle} rect The rectangle to calculate a union with. + * @return {Rectangle} A new rectangle describing the union. + */ + p.union = function(rect) { + return this.clone().extend(rect.x, rect.y, rect.width, rect.height); + }; + + /** + * Returns a new rectangle which describes the intersection (overlap) of this rectangle and the specified rectangle, + * or null if they do not intersect. + * @method intersection + * @param {Rectangle} rect The rectangle to calculate an intersection with. + * @return {Rectangle} A new rectangle describing the intersection or null. + */ + p.intersection = function(rect) { + var x1 = rect.x, y1 = rect.y, x2 = x1+rect.width, y2 = y1+rect.height; + if (this.x > x1) { x1 = this.x; } + if (this.y > y1) { y1 = this.y; } + if (this.x + this.width < x2) { x2 = this.x + this.width; } + if (this.y + this.height < y2) { y2 = this.y + this.height; } + return (x2 <= x1 || y2 <= y1) ? null : new Rectangle(x1, y1, x2-x1, y2-y1); + }; + + /** + * Returns true if the specified rectangle intersects (has any overlap) with this rectangle. + * @method intersects + * @param {Rectangle} rect The rectangle to compare. + * @return {Boolean} True if the rectangles intersect. + */ + p.intersects = function(rect) { + return (rect.x <= this.x+this.width && this.x <= rect.x+rect.width && rect.y <= this.y+this.height && this.y <= rect.y + rect.height); + }; + + /** + * Returns true if the width or height are equal or less than 0. + * @method isEmpty + * @return {Boolean} True if the rectangle is empty. + */ + p.isEmpty = function() { + return this.width <= 0 || this.height <= 0; + }; + + /** + * Returns a clone of the Rectangle instance. + * @method clone + * @return {Rectangle} a clone of the Rectangle instance. + **/ + p.clone = function() { + return new Rectangle(this.x, this.y, this.width, this.height); + }; + + /** + * Returns a string representation of this object. + * @method toString + * @return {String} a string representation of the instance. + **/ + p.toString = function() { + return "[Rectangle (x="+this.x+" y="+this.y+" width="+this.width+" height="+this.height+")]"; + }; + + + createjs.Rectangle = Rectangle; +}()); + +//############################################################################## +// ButtonHelper.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + + +// constructor: + /** + * The ButtonHelper is a helper class to create interactive buttons from {{#crossLink "MovieClip"}}{{/crossLink}} or + * {{#crossLink "Sprite"}}{{/crossLink}} instances. This class will intercept mouse events from an object, and + * automatically call {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} or {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}}, + * to the respective animation labels, add a pointer cursor, and allows the user to define a hit state frame. + * + * The ButtonHelper instance does not need to be added to the stage, but a reference should be maintained to prevent + * garbage collection. + * + * Note that over states will not work unless you call {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. + * + *

Example

+ * + * var helper = new createjs.ButtonHelper(myInstance, "out", "over", "down", false, myInstance, "hit"); + * myInstance.addEventListener("click", handleClick); + * function handleClick(event) { + * // Click Happened. + * } + * + * @class ButtonHelper + * @param {Sprite|MovieClip} target The instance to manage. + * @param {String} [outLabel="out"] The label or animation to go to when the user rolls out of the button. + * @param {String} [overLabel="over"] The label or animation to go to when the user rolls over the button. + * @param {String} [downLabel="down"] The label or animation to go to when the user presses the button. + * @param {Boolean} [play=false] If the helper should call "gotoAndPlay" or "gotoAndStop" on the button when changing + * states. + * @param {DisplayObject} [hitArea] An optional item to use as the hit state for the button. If this is not defined, + * then the button's visible states will be used instead. Note that the same instance as the "target" argument can be + * used for the hitState. + * @param {String} [hitLabel] The label or animation on the hitArea instance that defines the hitArea bounds. If this is + * null, then the default state of the hitArea will be used. * + * @constructor + */ + function ButtonHelper(target, outLabel, overLabel, downLabel, play, hitArea, hitLabel) { + if (!target.addEventListener) { return; } + + + // public properties: + /** + * The target for this button helper. + * @property target + * @type MovieClip | Sprite + * @readonly + **/ + this.target = target; + + /** + * The label name or frame number to display when the user mouses out of the target. Defaults to "over". + * @property overLabel + * @type String | Number + **/ + this.overLabel = overLabel == null ? "over" : overLabel; + + /** + * The label name or frame number to display when the user mouses over the target. Defaults to "out". + * @property outLabel + * @type String | Number + **/ + this.outLabel = outLabel == null ? "out" : outLabel; + + /** + * The label name or frame number to display when the user presses on the target. Defaults to "down". + * @property downLabel + * @type String | Number + **/ + this.downLabel = downLabel == null ? "down" : downLabel; + + /** + * If true, then ButtonHelper will call gotoAndPlay, if false, it will use gotoAndStop. Default is false. + * @property play + * @default false + * @type Boolean + **/ + this.play = play; + + + // private properties + /** + * @property _isPressed + * @type Boolean + * @protected + **/ + this._isPressed = false; + + /** + * @property _isOver + * @type Boolean + * @protected + **/ + this._isOver = false; + + /** + * @property _enabled + * @type Boolean + * @protected + **/ + this._enabled = false; + + // setup: + target.mouseChildren = false; // prevents issues when children are removed from the display list when state changes. + this.enabled = true; + this.handleEvent({}); + if (hitArea) { + if (hitLabel) { + hitArea.actionsEnabled = false; + hitArea.gotoAndStop&&hitArea.gotoAndStop(hitLabel); + } + target.hitArea = hitArea; + } + } + var p = ButtonHelper.prototype; + + /** + * REMOVED. Removed in favor of using `MySuperClass_constructor`. + * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} + * for details. + * + * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. + * + * @method initialize + * @protected + * @deprecated + */ + // p.initialize = function() {}; // searchable for devs wondering where it is. + + +// getter / setters: + /** + * Use the {{#crossLink "ButtonHelper/enabled:property"}}{{/crossLink}} property instead. + * @method setEnabled + * @param {Boolean} value + * @deprecated + **/ + p.setEnabled = function(value) { // TODO: deprecated. + if (value == this._enabled) { return; } + var o = this.target; + this._enabled = value; + if (value) { + o.cursor = "pointer"; + o.addEventListener("rollover", this); + o.addEventListener("rollout", this); + o.addEventListener("mousedown", this); + o.addEventListener("pressup", this); + if (o._reset) { o.__reset = o._reset; o._reset = this._reset;} + } else { + o.cursor = null; + o.removeEventListener("rollover", this); + o.removeEventListener("rollout", this); + o.removeEventListener("mousedown", this); + o.removeEventListener("pressup", this); + if (o.__reset) { o._reset = o.__reset; delete(o.__reset); } + } + }; + /** + * Use the {{#crossLink "ButtonHelper/enabled:property"}}{{/crossLink}} property instead. + * @method getEnabled + * @return {Boolean} + * @deprecated + **/ + p.getEnabled = function() { + return this._enabled; + }; + + /** + * Enables or disables the button functionality on the target. + * @property enabled + * @type {Boolean} + **/ + try { + Object.defineProperties(p, { + enabled: { get: p.getEnabled, set: p.setEnabled } + }); + } catch (e) {} // TODO: use Log + + +// public methods: + /** + * Returns a string representation of this object. + * @method toString + * @return {String} a string representation of the instance. + **/ + p.toString = function() { + return "[ButtonHelper]"; + }; + + +// private methods: + /** + * @method handleEvent + * @param {Object} evt The mouse event to handle. + * @protected + **/ + p.handleEvent = function(evt) { + var label, t = this.target, type = evt.type; + if (type == "mousedown") { + this._isPressed = true; + label = this.downLabel; + } else if (type == "pressup") { + this._isPressed = false; + label = this._isOver ? this.overLabel : this.outLabel; + } else if (type == "rollover") { + this._isOver = true; + label = this._isPressed ? this.downLabel : this.overLabel; + } else { // rollout and default + this._isOver = false; + label = this._isPressed ? this.overLabel : this.outLabel; + } + if (this.play) { + t.gotoAndPlay&&t.gotoAndPlay(label); + } else { + t.gotoAndStop&&t.gotoAndStop(label); + } + }; + + /** + * Injected into target. Preserves the paused state through a reset. + * @method _reset + * @protected + **/ + p._reset = function() { + // TODO: explore better ways to handle this issue. This is hacky & disrupts object signatures. + var p = this.paused; + this.__reset(); + this.paused = p; + }; + + + createjs.ButtonHelper = ButtonHelper; +}()); + +//############################################################################## +// Shadow.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + + +// constructor: + /** + * This class encapsulates the properties required to define a shadow to apply to a {{#crossLink "DisplayObject"}}{{/crossLink}} + * via its shadow property. + * + *

Example

+ * + * myImage.shadow = new createjs.Shadow("#000000", 5, 5, 10); + * + * @class Shadow + * @constructor + * @param {String} color The color of the shadow. This can be any valid CSS color value. + * @param {Number} offsetX The x offset of the shadow in pixels. + * @param {Number} offsetY The y offset of the shadow in pixels. + * @param {Number} blur The size of the blurring effect. + **/ + function Shadow(color, offsetX, offsetY, blur) { + + + // public properties: + /** + * The color of the shadow. This can be any valid CSS color value. + * @property color + * @type String + * @default null + */ + this.color = color||"black"; + + /** The x offset of the shadow. + * @property offsetX + * @type Number + * @default 0 + */ + this.offsetX = offsetX||0; + + /** The y offset of the shadow. + * @property offsetY + * @type Number + * @default 0 + */ + this.offsetY = offsetY||0; + + /** The blur of the shadow. + * @property blur + * @type Number + * @default 0 + */ + this.blur = blur||0; + } + var p = Shadow.prototype; + + /** + * REMOVED. Removed in favor of using `MySuperClass_constructor`. + * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} + * for details. + * + * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. + * + * @method initialize + * @protected + * @deprecated + */ + // p.initialize = function() {}; // searchable for devs wondering where it is. + + +// static public properties: + /** + * An identity shadow object (all properties are set to 0). + * @property identity + * @type Shadow + * @static + * @final + * @readonly + **/ + Shadow.identity = new Shadow("transparent", 0, 0, 0); + + +// public methods: + /** + * Returns a string representation of this object. + * @method toString + * @return {String} a string representation of the instance. + **/ + p.toString = function() { + return "[Shadow]"; + }; + + /** + * Returns a clone of this Shadow instance. + * @method clone + * @return {Shadow} A clone of the current Shadow instance. + **/ + p.clone = function() { + return new Shadow(this.color, this.offsetX, this.offsetY, this.blur); + }; + + + createjs.Shadow = Shadow; +}()); + +//############################################################################## +// SpriteSheet.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + + +// constructor: + /** + * Encapsulates the properties and methods associated with a sprite sheet. A sprite sheet is a series of images (usually + * animation frames) combined into a larger image (or images). For example, an animation consisting of eight 100x100 + * images could be combined into a single 400x200 sprite sheet (4 frames across by 2 high). + * + * The data passed to the SpriteSheet constructor defines: + *
    + *
  1. The source image or images to use.
  2. + *
  3. The positions of individual image frames.
  4. + *
  5. Sequences of frames that form named animations. Optional.
  6. + *
  7. The target playback framerate. Optional.
  8. + *
+ *

SpriteSheet Format

+ * SpriteSheets are an object with two required properties (`images` and `frames`), and two optional properties + * (`framerate` and `animations`). This makes them easy to define in javascript code, or in JSON. + * + *

images

+ * An array of source images. Images can be either an HTMlimage + * instance, or a uri to an image. The former is recommended to control preloading. + * + * images: [image1, "path/to/image2.png"], + * + *

frames

+ * Defines the individual frames. There are two supported formats for frame data: + * When all of the frames are the same size (in a grid), use an object with `width`, `height`, `regX`, `regY`, + * and `count` properties. + * + *
    + *
  • `width` & `height` are required and specify the dimensions of the frames
  • + *
  • `regX` & `regY` indicate the registration point or "origin" of the frames
  • + *
  • `spacing` indicate the spacing between frames
  • + *
  • `margin` specify the margin around the image(s)
  • + *
  • `count` allows you to specify the total number of frames in the spritesheet; if omitted, this will + * be calculated based on the dimensions of the source images and the frames. Frames will be assigned + * indexes based on their position in the source images (left to right, top to bottom).
  • + *
+ * + * frames: {width:64, height:64, count:20, regX: 32, regY:64, spacing:0, margin:0} + * + * If the frames are of different sizes, use an array of frame definitions. Each definition is itself an array + * with 4 required and 3 optional entries, in the order: + * + *
    + *
  • The first four, `x`, `y`, `width`, and `height` are required and define the frame rectangle.
  • + *
  • The fifth, `imageIndex`, specifies the index of the source image (defaults to 0)
  • + *
  • The last two, `regX` and `regY` specify the registration point of the frame
  • + *
+ * + * frames: [ + * // x, y, width, height, imageIndex*, regX*, regY* + * [64, 0, 96, 64], + * [0, 0, 64, 64, 1, 32, 32] + * // etc. + * ] + * + *

animations

+ * Optional. An object defining sequences of frames to play as named animations. Each property corresponds to an + * animation of the same name. Each animation must specify the frames to play, and may + * also include a relative playback `speed` (ex. 2 would playback at double speed, 0.5 at half), and + * the name of the `next` animation to sequence to after it completes. + * + * There are three formats supported for defining the frames in an animation, which can be mixed and matched as appropriate: + *
    + *
  1. for a single frame animation, you can simply specify the frame index + * + * animations: { + * sit: 7 + * } + * + *
  2. + *
  3. + * for an animation of consecutive frames, you can use an array with two required, and two optional entries + * in the order: `start`, `end`, `next`, and `speed`. This will play the frames from start to end inclusive. + * + * animations: { + * // start, end, next*, speed* + * run: [0, 8], + * jump: [9, 12, "run", 2] + * } + * + *
  4. + *
  5. + * for non-consecutive frames, you can use an object with a `frames` property defining an array of frame + * indexes to play in order. The object can also specify `next` and `speed` properties. + * + * animations: { + * walk: { + * frames: [1,2,3,3,2,1] + * }, + * shoot: { + * frames: [1,4,5,6], + * next: "walk", + * speed: 0.5 + * } + * } + * + *
  6. + *
+ * Note: the `speed` property was added in EaselJS 0.7.0. Earlier versions had a `frequency` + * property instead, which was the inverse of `speed`. For example, a value of "4" would be 1/4 normal speed in + * earlier versions, but is 4x normal speed in EaselJS 0.7.0+. + * + *

framerate

+ * Optional. Indicates the default framerate to play this spritesheet at in frames per second. See + * {{#crossLink "SpriteSheet/framerate:property"}}{{/crossLink}} for more information. + * + * framerate: 20 + * + * Note that the Sprite framerate will only work if the stage update method is provided with the {{#crossLink "Ticker/tick:event"}}{{/crossLink}} + * event generated by the {{#crossLink "Ticker"}}{{/crossLink}}. + * + * createjs.Ticker.on("tick", handleTick); + * function handleTick(event) { + * stage.update(event); + * } + * + *

Example

+ * To define a simple sprite sheet, with a single image "sprites.jpg" arranged in a regular 50x50 grid with three + * animations: "stand" showing the first frame, "run" looping frame 1-5 inclusive, and "jump" playing frame 6-8 and + * sequencing back to run. + * + * var data = { + * images: ["sprites.jpg"], + * frames: {width:50, height:50}, + * animations: { + * stand:0, + * run:[1,5], + * jump:[6,8,"run"] + * } + * }; + * var spriteSheet = new createjs.SpriteSheet(data); + * var animation = new createjs.Sprite(spriteSheet, "run"); + * + *

Generating SpriteSheet Images

+ * Spritesheets can be created manually by combining images in PhotoShop, and specifying the frame size or + * coordinates manually, however there are a number of tools that facilitate this. + *
    + *
  • Exporting SpriteSheets or HTML5 content from Flash Pro supports the EaselJS SpriteSheet format.
  • + *
  • The popular Texture Packer has + * EaselJS support. + *
  • SWF animations in Flash can be exported to SpriteSheets using
  • + *
+ * + *

Cross Origin Issues

+ * Warning: Images loaded cross-origin will throw cross-origin security errors when interacted with + * using: + *
    + *
  • a mouse
  • + *
  • methods such as {{#crossLink "Container/getObjectUnderPoint"}}{{/crossLink}}
  • + *
  • Filters (see {{#crossLink "Filter"}}{{/crossLink}})
  • + *
  • caching (see {{#crossLink "DisplayObject/cache"}}{{/crossLink}})
  • + *
+ * You can get around this by setting `crossOrigin` property on your images before passing them to EaselJS, or + * setting the `crossOrigin` property on PreloadJS' LoadQueue or LoadItems. + * + * var image = new Image(); + * img.crossOrigin="Anonymous"; + * img.src = "http://server-with-CORS-support.com/path/to/image.jpg"; + * + * If you pass string paths to SpriteSheets, they will not work cross-origin. The server that stores the image must + * support cross-origin requests, or this will not work. For more information, check out + * CORS overview on MDN. + * + * @class SpriteSheet + * @constructor + * @param {Object} data An object describing the SpriteSheet data. + * @extends EventDispatcher + **/ + function SpriteSheet(data) { + this.EventDispatcher_constructor(); + + + // public properties: + /** + * Indicates whether all images are finished loading. + * @property complete + * @type Boolean + * @readonly + **/ + this.complete = true; + + /** + * Specifies the framerate to use by default for Sprite instances using the SpriteSheet. See the Sprite class + * {{#crossLink "Sprite/framerate:property"}}{{/crossLink}} for more information. + * @property framerate + * @type Number + **/ + this.framerate = 0; + + + // private properties: + /** + * @property _animations + * @protected + * @type Array + **/ + this._animations = null; + + /** + * @property _frames + * @protected + * @type Array + **/ + this._frames = null; + + /** + * @property _images + * @protected + * @type Array + **/ + this._images = null; + + /** + * @property _data + * @protected + * @type Object + **/ + this._data = null; + + /** + * @property _loadCount + * @protected + * @type Number + **/ + this._loadCount = 0; + + // only used for simple frame defs: + /** + * @property _frameHeight + * @protected + * @type Number + **/ + this._frameHeight = 0; + + /** + * @property _frameWidth + * @protected + * @type Number + **/ + this._frameWidth = 0; + + /** + * @property _numFrames + * @protected + * @type Number + **/ + this._numFrames = 0; + + /** + * @property _regX + * @protected + * @type Number + **/ + this._regX = 0; + + /** + * @property _regY + * @protected + * @type Number + **/ + this._regY = 0; + + /** + * @property _spacing + * @protected + * @type Number + **/ + this._spacing = 0; + + /** + * @property _margin + * @protected + * @type Number + **/ + this._margin = 0; + + // setup: + this._parseData(data); + } + var p = createjs.extend(SpriteSheet, createjs.EventDispatcher); + + // TODO: deprecated + // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. + + +// events: + /** + * Dispatched when all images are loaded. Note that this only fires if the images + * were not fully loaded when the sprite sheet was initialized. You should check the complete property + * to prior to adding a listener. Ex. + * + * var sheet = new createjs.SpriteSheet(data); + * if (!sheet.complete) { + * // not preloaded, listen for the complete event: + * sheet.addEventListener("complete", handler); + * } + * + * @event complete + * @param {Object} target The object that dispatched the event. + * @param {String} type The event type. + * @since 0.6.0 + */ + + /** + * Dispatched when getFrame is called with a valid frame index. This is primarily intended for use by {{#crossLink "SpriteSheetBuilder"}}{{/crossLink}} + * when doing on-demand rendering. + * @event getframe + * @param {Number} index The frame index. + * @param {Object} frame The frame object that getFrame will return. + */ + + /** + * Dispatched when an image encounters an error. A SpriteSheet will dispatch an error event for each image that + * encounters an error, and will still dispatch a {{#crossLink "SpriteSheet/complete:event"}}{{/crossLink}} + * event once all images are finished processing, even if an error is encountered. + * @event error + * @param {String} src The source of the image that failed to load. + * @since 0.8.2 + */ + + +// getter / setters: + /** + * Use the {{#crossLink "SpriteSheet/animations:property"}}{{/crossLink}} property instead. + * @method getAnimations + * @return {Array} + * @deprecated + **/ + p.getAnimations = function() { + return this._animations.slice(); + }; + + /** + * Returns an array of all available animation names available on this sprite sheet as strings. + * @property animations + * @type {Array} + * @readonly + **/ + try { + Object.defineProperties(p, { + animations: { get: p.getAnimations } + }); + } catch (e) {} + + +// public methods: + /** + * Returns the total number of frames in the specified animation, or in the whole sprite + * sheet if the animation param is omitted. Returns 0 if the spritesheet relies on calculated frame counts, and + * the images have not been fully loaded. + * @method getNumFrames + * @param {String} animation The name of the animation to get a frame count for. + * @return {Number} The number of frames in the animation, or in the entire sprite sheet if the animation param is omitted. + */ + p.getNumFrames = function(animation) { + if (animation == null) { + return this._frames ? this._frames.length : this._numFrames || 0; + } else { + var data = this._data[animation]; + if (data == null) { return 0; } + else { return data.frames.length; } + } + }; + + /** + * Returns an object defining the specified animation. The returned object contains:
    + *
  • frames: an array of the frame ids in the animation
  • + *
  • speed: the playback speed for this animation
  • + *
  • name: the name of the animation
  • + *
  • next: the default animation to play next. If the animation loops, the name and next property will be the + * same.
  • + *
+ * @method getAnimation + * @param {String} name The name of the animation to get. + * @return {Object} a generic object with frames, speed, name, and next properties. + **/ + p.getAnimation = function(name) { + return this._data[name]; + }; + + /** + * Returns an object specifying the image and source rect of the specified frame. The returned object has:
    + *
  • an image property holding a reference to the image object in which the frame is found
  • + *
  • a rect property containing a Rectangle instance which defines the boundaries for the frame within that + * image.
  • + *
  • A regX and regY property corresponding to the regX/Y values for the frame. + *
+ * @method getFrame + * @param {Number} frameIndex The index of the frame. + * @return {Object} a generic object with image and rect properties. Returns null if the frame does not exist. + **/ + p.getFrame = function(frameIndex) { + var frame; + if (this._frames && (frame=this._frames[frameIndex])) { return frame; } + return null; + }; + + /** + * Returns a {{#crossLink "Rectangle"}}{{/crossLink}} instance defining the bounds of the specified frame relative + * to the origin. For example, a 90 x 70 frame with a regX of 50 and a regY of 40 would return: + * + * [x=-50, y=-40, width=90, height=70] + * + * @method getFrameBounds + * @param {Number} frameIndex The index of the frame. + * @param {Rectangle} [rectangle] A Rectangle instance to copy the values into. By default a new instance is created. + * @return {Rectangle} A Rectangle instance. Returns null if the frame does not exist, or the image is not fully loaded. + **/ + p.getFrameBounds = function(frameIndex, rectangle) { + var frame = this.getFrame(frameIndex); + return frame ? (rectangle||new createjs.Rectangle()).setValues(-frame.regX, -frame.regY, frame.rect.width, frame.rect.height) : null; + }; + + /** + * Returns a string representation of this object. + * @method toString + * @return {String} a string representation of the instance. + **/ + p.toString = function() { + return "[SpriteSheet]"; + }; + + /** + * SpriteSheet cannot be cloned. A SpriteSheet can be shared by multiple Sprite instances without cloning it. + * @method clone + **/ + p.clone = function() { + throw("SpriteSheet cannot be cloned.") + }; + +// private methods: + /** + * @method _parseData + * @param {Object} data An object describing the SpriteSheet data. + * @protected + **/ + p._parseData = function(data) { + var i,l,o,a; + if (data == null) { return; } + + this.framerate = data.framerate||0; + + // parse images: + if (data.images && (l=data.images.length) > 0) { + a = this._images = []; + for (i=0; i= maxFrames) { break imgLoop; } + frameCount++; + this._frames.push({ + image: img, + rect: new createjs.Rectangle(x, y, frameWidth, frameHeight), + regX: this._regX, + regY: this._regY + }); + x += frameWidth+spacing; + } + y += frameHeight+spacing; + } + } + this._numFrames = frameCount; + }; + + + createjs.SpriteSheet = createjs.promote(SpriteSheet, "EventDispatcher"); +}()); + +//############################################################################## +// Graphics.js +//############################################################################## + +this.createjs = this.createjs||{}; + +(function() { + "use strict"; + + +// constructor: + /** + * The Graphics class exposes an easy to use API for generating vector drawing instructions and drawing them to a + * specified context. Note that you can use Graphics without any dependency on the EaselJS framework by calling {{#crossLink "Graphics/draw"}}{{/crossLink}} + * directly, or it can be used with the {{#crossLink "Shape"}}{{/crossLink}} object to draw vector graphics within the + * context of an EaselJS display list. + * + * There are two approaches to working with Graphics object: calling methods on a Graphics instance (the "Graphics API"), or + * instantiating Graphics command objects and adding them to the graphics queue via {{#crossLink "Graphics/append"}}{{/crossLink}}. + * The former abstracts the latter, simplifying beginning and ending paths, fills, and strokes. + * + * var g = new createjs.Graphics(); + * g.setStrokeStyle(1); + * g.beginStroke("#000000"); + * g.beginFill("red"); + * g.drawCircle(0,0,30); + * + * All drawing methods in Graphics return the Graphics instance, so they can be chained together. For example, + * the following line of code would generate the instructions to draw a rectangle with a red stroke and blue fill: + * + * myGraphics.beginStroke("red").beginFill("blue").drawRect(20, 20, 100, 50); + * + * Each graphics API call generates a command object (see below). The last command to be created can be accessed via + * {{#crossLink "Graphics/command:property"}}{{/crossLink}}: + * + * var fillCommand = myGraphics.beginFill("red").command; + * // ... later, update the fill style/color: + * fillCommand.style = "blue"; + * // or change it to a bitmap fill: + * fillCommand.bitmap(myImage); + * + * For more direct control of rendering, you can instantiate and append command objects to the graphics queue directly. In this case, you + * need to manage path creation manually, and ensure that fill/stroke is applied to a defined path: + * + * // start a new path. Graphics.beginCmd is a reusable BeginPath instance: + * myGraphics.append(createjs.Graphics.beginCmd); + * // we need to define the path before applying the fill: + * var circle = new createjs.Graphics.Circle(0,0,30); + * myGraphics.append(circle); + * // fill the path we just defined: + * var fill = new createjs.Graphics.Fill("red"); + * myGraphics.append(fill); + * + * These approaches can be used together, for example to insert a custom command: + * + * myGraphics.beginFill("red"); + * var customCommand = new CustomSpiralCommand(etc); + * myGraphics.append(customCommand); + * myGraphics.beginFill("blue"); + * myGraphics.drawCircle(0, 0, 30); + * + * See {{#crossLink "Graphics/append"}}{{/crossLink}} for more info on creating custom commands. + * + *

Tiny API

+ * The Graphics class also includes a "tiny API", which is one or two-letter methods that are shortcuts for all of the + * Graphics methods. These methods are great for creating compact instructions, and is used by the Toolkit for CreateJS + * to generate readable code. All tiny methods are marked as protected, so you can view them by enabling protected + * descriptions in the docs. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
TinyMethodTinyMethod
mt{{#crossLink "Graphics/moveTo"}}{{/crossLink}} lt {{#crossLink "Graphics/lineTo"}}{{/crossLink}}
a/at{{#crossLink "Graphics/arc"}}{{/crossLink}} / {{#crossLink "Graphics/arcTo"}}{{/crossLink}} bt{{#crossLink "Graphics/bezierCurveTo"}}{{/crossLink}}
qt{{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} (also curveTo)r{{#crossLink "Graphics/rect"}}{{/crossLink}}
cp{{#crossLink "Graphics/closePath"}}{{/crossLink}} c{{#crossLink "Graphics/clear"}}{{/crossLink}}
f{{#crossLink "Graphics/beginFill"}}{{/crossLink}} lf{{#crossLink "Graphics/beginLinearGradientFill"}}{{/crossLink}}
rf{{#crossLink "Graphics/beginRadialGradientFill"}}{{/crossLink}} bf{{#crossLink "Graphics/beginBitmapFill"}}{{/crossLink}}
ef{{#crossLink "Graphics/endFill"}}{{/crossLink}} ss / sd{{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} / {{#crossLink "Graphics/setStrokeDash"}}{{/crossLink}}
s{{#crossLink "Graphics/beginStroke"}}{{/crossLink}} ls{{#crossLink "Graphics/beginLinearGradientStroke"}}{{/crossLink}}
rs{{#crossLink "Graphics/beginRadialGradientStroke"}}{{/crossLink}} bs{{#crossLink "Graphics/beginBitmapStroke"}}{{/crossLink}}
es{{#crossLink "Graphics/endStroke"}}{{/crossLink}} dr{{#crossLink "Graphics/drawRect"}}{{/crossLink}}
rr{{#crossLink "Graphics/drawRoundRect"}}{{/crossLink}} rc{{#crossLink "Graphics/drawRoundRectComplex"}}{{/crossLink}}
dc{{#crossLink "Graphics/drawCircle"}}{{/crossLink}} de{{#crossLink "Graphics/drawEllipse"}}{{/crossLink}}
dp{{#crossLink "Graphics/drawPolyStar"}}{{/crossLink}} p{{#crossLink "Graphics/decodePath"}}{{/crossLink}}
+ * + * Here is the above example, using the tiny API instead. + * + * myGraphics.s("red").f("blue").r(20, 20, 100, 50); + * + * @class Graphics + * @constructor + **/ + function Graphics() { + + + // public properties + /** + * Holds a reference to the last command that was created or appended. For example, you could retain a reference + * to a Fill command in order to dynamically update the color later by using: + * + * var myFill = myGraphics.beginFill("red").command; + * // update color later: + * myFill.style = "yellow"; + * + * @property command + * @type Object + **/ + this.command = null; + + + // private properties + /** + * @property _stroke + * @protected + * @type {Stroke} + **/ + this._stroke = null; + + /** + * @property _strokeStyle + * @protected + * @type {StrokeStyle} + **/ + this._strokeStyle = null; + + /** + * @property _oldStrokeStyle + * @protected + * @type {StrokeStyle} + **/ + this._oldStrokeStyle = null; + + /** + * @property _strokeDash + * @protected + * @type {StrokeDash} + **/ + this._strokeDash = null; + + /** + * @property _oldStrokeDash + * @protected + * @type {StrokeDash} + **/ + this._oldStrokeDash = null; + + /** + * @property _strokeIgnoreScale + * @protected + * @type Boolean + **/ + this._strokeIgnoreScale = false; + + /** + * @property _fill + * @protected + * @type {Fill} + **/ + this._fill = null; + + /** + * @property _instructions + * @protected + * @type {Array} + **/ + this._instructions = []; + + /** + * Indicates the last instruction index that was committed. + * @property _commitIndex + * @protected + * @type {Number} + **/ + this._commitIndex = 0; + + /** + * Uncommitted instructions. + * @property _activeInstructions + * @protected + * @type {Array} + **/ + this._activeInstructions = []; + + /** + * This indicates that there have been changes to the activeInstruction list since the last updateInstructions call. + * @property _dirty + * @protected + * @type {Boolean} + * @default false + **/ + this._dirty = false; + + /** + * Index to draw from if a store operation has happened. + * @property _storeIndex + * @protected + * @type {Number} + * @default 0 + **/ + this._storeIndex = 0; + + // setup: + this.clear(); + } + var p = Graphics.prototype; + var G = Graphics; // shortcut + + /** + * REMOVED. Removed in favor of using `MySuperClass_constructor`. + * See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}} + * for details. + * + * There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance. + * + * @method initialize + * @protected + * @deprecated + */ + // p.initialize = function() {}; // searchable for devs wondering where it is. + + +// static public methods: + /** + * Returns a CSS compatible color string based on the specified RGB numeric color values in the format + * "rgba(255,255,255,1.0)", or if alpha is null then in the format "rgb(255,255,255)". For example, + * + * createjs.Graphics.getRGB(50, 100, 150, 0.5); + * // Returns "rgba(50,100,150,0.5)" + * + * It also supports passing a single hex color value as the first param, and an optional alpha value as the second + * param. For example, + * + * createjs.Graphics.getRGB(0xFF00FF, 0.2); + * // Returns "rgba(255,0,255,0.2)" + * + * @method getRGB + * @static + * @param {Number} r The red component for the color, between 0 and 0xFF (255). + * @param {Number} g The green component for the color, between 0 and 0xFF (255). + * @param {Number} b The blue component for the color, between 0 and 0xFF (255). + * @param {Number} [alpha] The alpha component for the color where 0 is fully transparent and 1 is fully opaque. + * @return {String} A CSS compatible color string based on the specified RGB numeric color values in the format + * "rgba(255,255,255,1.0)", or if alpha is null then in the format "rgb(255,255,255)". + **/ + Graphics.getRGB = function(r, g, b, alpha) { + if (r != null && b == null) { + alpha = g; + b = r&0xFF; + g = r>>8&0xFF; + r = r>>16&0xFF; + } + if (alpha == null) { + return "rgb("+r+","+g+","+b+")"; + } else { + return "rgba("+r+","+g+","+b+","+alpha+")"; + } + }; + + /** + * Returns a CSS compatible color string based on the specified HSL numeric color values in the format "hsla(360,100,100,1.0)", + * or if alpha is null then in the format "hsl(360,100,100)". + * + * createjs.Graphics.getHSL(150, 100, 70); + * // Returns "hsl(150,100,70)" + * + * @method getHSL + * @static + * @param {Number} hue The hue component for the color, between 0 and 360. + * @param {Number} saturation The saturation component for the color, between 0 and 100. + * @param {Number} lightness The lightness component for the color, between 0 and 100. + * @param {Number} [alpha] The alpha component for the color where 0 is fully transparent and 1 is fully opaque. + * @return {String} A CSS compatible color string based on the specified HSL numeric color values in the format + * "hsla(360,100,100,1.0)", or if alpha is null then in the format "hsl(360,100,100)". + **/ + Graphics.getHSL = function(hue, saturation, lightness, alpha) { + if (alpha == null) { + return "hsl("+(hue%360)+","+saturation+"%,"+lightness+"%)"; + } else { + return "hsla("+(hue%360)+","+saturation+"%,"+lightness+"%,"+alpha+")"; + } + }; + + +// static properties: + /** + * A reusable instance of {{#crossLink "Graphics/BeginPath"}}{{/crossLink}} to avoid + * unnecessary instantiation. + * @property beginCmd + * @type {Graphics.BeginPath} + * @static + **/ + // defined at the bottom of this file. + + /** + * Map of Base64 characters to values. Used by {{#crossLink "Graphics/decodePath"}}{{/crossLink}}. + * @property BASE_64 + * @static + * @final + * @readonly + * @type {Object} + **/ + Graphics.BASE_64 = {"A":0,"B":1,"C":2,"D":3,"E":4,"F":5,"G":6,"H":7,"I":8,"J":9,"K":10,"L":11,"M":12,"N":13,"O":14,"P":15,"Q":16,"R":17,"S":18,"T":19,"U":20,"V":21,"W":22,"X":23,"Y":24,"Z":25,"a":26,"b":27,"c":28,"d":29,"e":30,"f":31,"g":32,"h":33,"i":34,"j":35,"k":36,"l":37,"m":38,"n":39,"o":40,"p":41,"q":42,"r":43,"s":44,"t":45,"u":46,"v":47,"w":48,"x":49,"y":50,"z":51,"0":52,"1":53,"2":54,"3":55,"4":56,"5":57,"6":58,"7":59,"8":60,"9":61,"+":62,"/":63}; + + /** + * Maps numeric values for the caps parameter of {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} to + * corresponding string values. This is primarily for use with the tiny API. The mappings are as follows: 0 to + * "butt", 1 to "round", and 2 to "square". + * For example, to set the line caps to "square": + * + * myGraphics.ss(16, 2); + * + * @property STROKE_CAPS_MAP + * @static + * @final + * @readonly + * @type {Array} + **/ + Graphics.STROKE_CAPS_MAP = ["butt", "round", "square"]; + + /** + * Maps numeric values for the joints parameter of {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} to + * corresponding string values. This is primarily for use with the tiny API. The mappings are as follows: 0 to + * "miter", 1 to "round", and 2 to "bevel". + * For example, to set the line joints to "bevel": + * + * myGraphics.ss(16, 0, 2); + * + * @property STROKE_JOINTS_MAP + * @static + * @final + * @readonly + * @type {Array} + **/ + Graphics.STROKE_JOINTS_MAP = ["miter", "round", "bevel"]; + + /** + * @property _ctx + * @static + * @protected + * @type {CanvasRenderingContext2D} + **/ + var canvas = (createjs.createCanvas?createjs.createCanvas():window.document.createElement("canvas")); + if (canvas.getContext) { + Graphics._ctx = canvas.getContext("2d"); + canvas.width = canvas.height = 1; + } + + +// getter / setters: + /** + * Use the {{#crossLink "Graphics/instructions:property"}}{{/crossLink}} property instead. + * @method getInstructions + * @return {Array} + * @deprecated + **/ + p.getInstructions = function() { + this._updateInstructions(); + return this._instructions; + }; + + /** + * Returns the graphics instructions array. Each entry is a graphics command object (ex. Graphics.Fill, Graphics.Rect) + * Modifying the returned array directly is not recommended, and is likely to result in unexpected behaviour. + * + * This property is mainly intended for introspection of the instructions (ex. for graphics export). + * @property instructions + * @type {Array} + * @readonly + **/ + try { + Object.defineProperties(p, { + instructions: { get: p.getInstructions } + }); + } catch (e) {} + + +// public methods: + /** + * Returns true if this Graphics instance has no drawing commands. + * @method isEmpty + * @return {Boolean} Returns true if this Graphics instance has no drawing commands. + **/ + p.isEmpty = function() { + return !(this._instructions.length || this._activeInstructions.length); + }; + + /** + * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. + * Returns true if the draw was handled (useful for overriding functionality). + * + * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. + * @method draw + * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. + * @param {Object} data Optional data that is passed to graphics command exec methods. When called from a Shape instance, the shape passes itself as the data parameter. This can be used by custom graphic commands to insert contextual data. + **/ + p.draw = function(ctx, data) { + this._updateInstructions(); + var instr = this._instructions; + for (var i=this._storeIndex, l=instr.length; iDisplayObject.mask to draw the clipping path, for example. + * + * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. + * @method drawAsPath + * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. + **/ + p.drawAsPath = function(ctx) { + this._updateInstructions(); + var instr, instrs = this._instructions; + for (var i=this._storeIndex, l=instrs.length; i + * whatwg spec. + * @method lineTo + * @param {Number} x The x coordinate the drawing point should draw to. + * @param {Number} y The y coordinate the drawing point should draw to. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.lineTo = function(x, y) { + return this.append(new G.LineTo(x,y)); + }; + + /** + * Draws an arc with the specified control points and radius. For detailed information, read the + * + * whatwg spec. A tiny API method "at" also exists. + * @method arcTo + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} radius + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.arcTo = function(x1, y1, x2, y2, radius) { + return this.append(new G.ArcTo(x1, y1, x2, y2, radius)); + }; + + /** + * Draws an arc defined by the radius, startAngle and endAngle arguments, centered at the position (x, y). For + * example, to draw a full circle with a radius of 20 centered at (100, 100): + * + * arc(100, 100, 20, 0, Math.PI*2); + * + * For detailed information, read the + * whatwg spec. + * A tiny API method "a" also exists. + * @method arc + * @param {Number} x + * @param {Number} y + * @param {Number} radius + * @param {Number} startAngle Measured in radians. + * @param {Number} endAngle Measured in radians. + * @param {Boolean} anticlockwise + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.arc = function(x, y, radius, startAngle, endAngle, anticlockwise) { + return this.append(new G.Arc(x, y, radius, startAngle, endAngle, anticlockwise)); + }; + + /** + * Draws a quadratic curve from the current drawing point to (x, y) using the control point (cpx, cpy). For detailed + * information, read the + * whatwg spec. A tiny API method "qt" also exists. + * @method quadraticCurveTo + * @param {Number} cpx + * @param {Number} cpy + * @param {Number} x + * @param {Number} y + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.quadraticCurveTo = function(cpx, cpy, x, y) { + return this.append(new G.QuadraticCurveTo(cpx, cpy, x, y)); + }; + + /** + * Draws a bezier curve from the current drawing point to (x, y) using the control points (cp1x, cp1y) and (cp2x, + * cp2y). For detailed information, read the + * + * whatwg spec. A tiny API method "bt" also exists. + * @method bezierCurveTo + * @param {Number} cp1x + * @param {Number} cp1y + * @param {Number} cp2x + * @param {Number} cp2y + * @param {Number} x + * @param {Number} y + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.bezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) { + return this.append(new G.BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)); + }; + + /** + * Draws a rectangle at (x, y) with the specified width and height using the current fill and/or stroke. + * For detailed information, read the + * + * whatwg spec. A tiny API method "r" also exists. + * @method rect + * @param {Number} x + * @param {Number} y + * @param {Number} w Width of the rectangle + * @param {Number} h Height of the rectangle + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.rect = function(x, y, w, h) { + return this.append(new G.Rect(x, y, w, h)); + }; + + /** + * Closes the current path, effectively drawing a line from the current drawing point to the first drawing point specified + * since the fill or stroke was last set. A tiny API method "cp" also exists. + * @method closePath + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.closePath = function() { + return this._activeInstructions.length ? this.append(new G.ClosePath()) : this; + }; + + +// public methods that roughly map to Flash graphics APIs: + /** + * Clears all drawing instructions, effectively resetting this Graphics instance. Any line and fill styles will need + * to be redefined to draw shapes following a clear call. A tiny API method "c" also exists. + * @method clear + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.clear = function() { + this._instructions.length = this._activeInstructions.length = this._commitIndex = 0; + this._strokeStyle = this._oldStrokeStyle = this._stroke = this._fill = this._strokeDash = this._oldStrokeDash = null; + this._dirty = this._strokeIgnoreScale = false; + return this; + }; + + /** + * Begins a fill with the specified color. This ends the current sub-path. A tiny API method "f" also exists. + * @method beginFill + * @param {String} color A CSS compatible color value (ex. "red", "#FF0000", or "rgba(255,0,0,0.5)"). Setting to + * null will result in no fill. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.beginFill = function(color) { + return this._setFill(color ? new G.Fill(color) : null); + }; + + /** + * Begins a linear gradient fill defined by the line (x0, y0) to (x1, y1). This ends the current sub-path. For + * example, the following code defines a black to white vertical gradient ranging from 20px to 120px, and draws a + * square to display it: + * + * myGraphics.beginLinearGradientFill(["#000","#FFF"], [0, 1], 0, 20, 0, 120).drawRect(20, 20, 120, 120); + * + * A tiny API method "lf" also exists. + * @method beginLinearGradientFill + * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define a gradient + * drawing from red to blue. + * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 0.9] would draw + * the first color to 10% then interpolating to the second color at 90%. + * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. + * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. + * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. + * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.beginLinearGradientFill = function(colors, ratios, x0, y0, x1, y1) { + return this._setFill(new G.Fill().linearGradient(colors, ratios, x0, y0, x1, y1)); + }; + + /** + * Begins a radial gradient fill. This ends the current sub-path. For example, the following code defines a red to + * blue radial gradient centered at (100, 100), with a radius of 50, and draws a circle to display it: + * + * myGraphics.beginRadialGradientFill(["#F00","#00F"], [0, 1], 100, 100, 0, 100, 100, 50).drawCircle(100, 100, 50); + * + * A tiny API method "rf" also exists. + * @method beginRadialGradientFill + * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define + * a gradient drawing from red to blue. + * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, + * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. + * @param {Number} x0 Center position of the inner circle that defines the gradient. + * @param {Number} y0 Center position of the inner circle that defines the gradient. + * @param {Number} r0 Radius of the inner circle that defines the gradient. + * @param {Number} x1 Center position of the outer circle that defines the gradient. + * @param {Number} y1 Center position of the outer circle that defines the gradient. + * @param {Number} r1 Radius of the outer circle that defines the gradient. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.beginRadialGradientFill = function(colors, ratios, x0, y0, r0, x1, y1, r1) { + return this._setFill(new G.Fill().radialGradient(colors, ratios, x0, y0, r0, x1, y1, r1)); + }; + + /** + * Begins a pattern fill using the specified image. This ends the current sub-path. A tiny API method "bf" also + * exists. + * @method beginBitmapFill + * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use + * as the pattern. Must be loaded prior to creating a bitmap fill, or the fill will be empty. + * @param {String} repetition Optional. Indicates whether to repeat the image in the fill area. One of "repeat", + * "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". Note that Firefox does not support "repeat-x" or + * "repeat-y" (latest tests were in FF 20.0), and will default to "repeat". + * @param {Matrix2D} matrix Optional. Specifies a transformation matrix for the bitmap fill. This transformation + * will be applied relative to the parent transform. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.beginBitmapFill = function(image, repetition, matrix) { + return this._setFill(new G.Fill(null,matrix).bitmap(image, repetition)); + }; + + /** + * Ends the current sub-path, and begins a new one with no fill. Functionally identical to beginFill(null). + * A tiny API method "ef" also exists. + * @method endFill + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.endFill = function() { + return this.beginFill(); + }; + + /** + * Sets the stroke style. Like all drawing methods, this can be chained, so you can define + * the stroke style and color in a single line of code like so: + * + * myGraphics.setStrokeStyle(8,"round").beginStroke("#F00"); + * + * A tiny API method "ss" also exists. + * @method setStrokeStyle + * @param {Number} thickness The width of the stroke. + * @param {String | Number} [caps=0] Indicates the type of caps to use at the end of lines. One of butt, + * round, or square. Defaults to "butt". Also accepts the values 0 (butt), 1 (round), and 2 (square) for use with + * the tiny API. + * @param {String | Number} [joints=0] Specifies the type of joints that should be used where two lines meet. + * One of bevel, round, or miter. Defaults to "miter". Also accepts the values 0 (miter), 1 (round), and 2 (bevel) + * for use with the tiny API. + * @param {Number} [miterLimit=10] If joints is set to "miter", then you can specify a miter limit ratio which + * controls at what point a mitered joint will be clipped. + * @param {Boolean} [ignoreScale=false] If true, the stroke will be drawn at the specified thickness regardless + * of active transformations. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.setStrokeStyle = function(thickness, caps, joints, miterLimit, ignoreScale) { + this._updateInstructions(true); + this._strokeStyle = this.command = new G.StrokeStyle(thickness, caps, joints, miterLimit, ignoreScale); + + // ignoreScale lives on Stroke, not StrokeStyle, so we do a little trickery: + if (this._stroke) { this._stroke.ignoreScale = ignoreScale; } + this._strokeIgnoreScale = ignoreScale; + return this; + }; + + /** + * Sets or clears the stroke dash pattern. + * + * myGraphics.setStrokeDash([20, 10], 0); + * + * A tiny API method `sd` also exists. + * @method setStrokeDash + * @param {Array} [segments] An array specifying the dash pattern, alternating between line and gap. + * For example, `[20,10]` would create a pattern of 20 pixel lines with 10 pixel gaps between them. + * Passing null or an empty array will clear the existing stroke dash. + * @param {Number} [offset=0] The offset of the dash pattern. For example, you could increment this value to create a "marching ants" effect. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.setStrokeDash = function(segments, offset) { + this._updateInstructions(true); + this._strokeDash = this.command = new G.StrokeDash(segments, offset); + return this; + }; + + /** + * Begins a stroke with the specified color. This ends the current sub-path. A tiny API method "s" also exists. + * @method beginStroke + * @param {String} color A CSS compatible color value (ex. "#FF0000", "red", or "rgba(255,0,0,0.5)"). Setting to + * null will result in no stroke. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.beginStroke = function(color) { + return this._setStroke(color ? new G.Stroke(color) : null); + }; + + /** + * Begins a linear gradient stroke defined by the line (x0, y0) to (x1, y1). This ends the current sub-path. For + * example, the following code defines a black to white vertical gradient ranging from 20px to 120px, and draws a + * square to display it: + * + * myGraphics.setStrokeStyle(10). + * beginLinearGradientStroke(["#000","#FFF"], [0, 1], 0, 20, 0, 120).drawRect(20, 20, 120, 120); + * + * A tiny API method "ls" also exists. + * @method beginLinearGradientStroke + * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define + * a gradient drawing from red to blue. + * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, + * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. + * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. + * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. + * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. + * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.beginLinearGradientStroke = function(colors, ratios, x0, y0, x1, y1) { + return this._setStroke(new G.Stroke().linearGradient(colors, ratios, x0, y0, x1, y1)); + }; + + /** + * Begins a radial gradient stroke. This ends the current sub-path. For example, the following code defines a red to + * blue radial gradient centered at (100, 100), with a radius of 50, and draws a rectangle to display it: + * + * myGraphics.setStrokeStyle(10) + * .beginRadialGradientStroke(["#F00","#00F"], [0, 1], 100, 100, 0, 100, 100, 50) + * .drawRect(50, 90, 150, 110); + * + * A tiny API method "rs" also exists. + * @method beginRadialGradientStroke + * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define + * a gradient drawing from red to blue. + * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, + * 0.9] would draw the first color to 10% then interpolating to the second color at 90%, then draw the second color + * to 100%. + * @param {Number} x0 Center position of the inner circle that defines the gradient. + * @param {Number} y0 Center position of the inner circle that defines the gradient. + * @param {Number} r0 Radius of the inner circle that defines the gradient. + * @param {Number} x1 Center position of the outer circle that defines the gradient. + * @param {Number} y1 Center position of the outer circle that defines the gradient. + * @param {Number} r1 Radius of the outer circle that defines the gradient. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.beginRadialGradientStroke = function(colors, ratios, x0, y0, r0, x1, y1, r1) { + return this._setStroke(new G.Stroke().radialGradient(colors, ratios, x0, y0, r0, x1, y1, r1)); + }; + + /** + * Begins a pattern fill using the specified image. This ends the current sub-path. Note that unlike bitmap fills, + * strokes do not currently support a matrix parameter due to limitations in the canvas API. A tiny API method "bs" + * also exists. + * @method beginBitmapStroke + * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use + * as the pattern. Must be loaded prior to creating a bitmap fill, or the fill will be empty. + * @param {String} [repetition=repeat] Optional. Indicates whether to repeat the image in the fill area. One of + * "repeat", "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.beginBitmapStroke = function(image, repetition) { + // NOTE: matrix is not supported for stroke because transforms on strokes also affect the drawn stroke width. + return this._setStroke(new G.Stroke().bitmap(image, repetition)); + }; + + /** + * Ends the current sub-path, and begins a new one with no stroke. Functionally identical to beginStroke(null). + * A tiny API method "es" also exists. + * @method endStroke + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.endStroke = function() { + return this.beginStroke(); + }; + + /** + * Maps the familiar ActionScript curveTo() method to the functionally similar {{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} + * method. + * @method quadraticCurveTo + * @param {Number} cpx + * @param {Number} cpy + * @param {Number} x + * @param {Number} y + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.curveTo = p.quadraticCurveTo; + + /** + * + * Maps the familiar ActionScript drawRect() method to the functionally similar {{#crossLink "Graphics/rect"}}{{/crossLink}} + * method. + * @method drawRect + * @param {Number} x + * @param {Number} y + * @param {Number} w Width of the rectangle + * @param {Number} h Height of the rectangle + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.drawRect = p.rect; + + /** + * Draws a rounded rectangle with all corners with the specified radius. + * @method drawRoundRect + * @param {Number} x + * @param {Number} y + * @param {Number} w + * @param {Number} h + * @param {Number} radius Corner radius. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.drawRoundRect = function(x, y, w, h, radius) { + return this.drawRoundRectComplex(x, y, w, h, radius, radius, radius, radius); + }; + + /** + * Draws a rounded rectangle with different corner radii. Supports positive and negative corner radii. A tiny API + * method "rc" also exists. + * @method drawRoundRectComplex + * @param {Number} x The horizontal coordinate to draw the round rect. + * @param {Number} y The vertical coordinate to draw the round rect. + * @param {Number} w The width of the round rect. + * @param {Number} h The height of the round rect. + * @param {Number} radiusTL Top left corner radius. + * @param {Number} radiusTR Top right corner radius. + * @param {Number} radiusBR Bottom right corner radius. + * @param {Number} radiusBL Bottom left corner radius. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.drawRoundRectComplex = function(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL) { + return this.append(new G.RoundRect(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL)); + }; + + /** + * Draws a circle with the specified radius at (x, y). + * + * var g = new createjs.Graphics(); + * g.setStrokeStyle(1); + * g.beginStroke(createjs.Graphics.getRGB(0,0,0)); + * g.beginFill(createjs.Graphics.getRGB(255,0,0)); + * g.drawCircle(0,0,3); + * + * var s = new createjs.Shape(g); + * s.x = 100; + * s.y = 100; + * + * stage.addChild(s); + * stage.update(); + * + * A tiny API method "dc" also exists. + * @method drawCircle + * @param {Number} x x coordinate center point of circle. + * @param {Number} y y coordinate center point of circle. + * @param {Number} radius Radius of circle. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.drawCircle = function(x, y, radius) { + return this.append(new G.Circle(x, y, radius)); + }; + + /** + * Draws an ellipse (oval) with a specified width (w) and height (h). Similar to {{#crossLink "Graphics/drawCircle"}}{{/crossLink}}, + * except the width and height can be different. A tiny API method "de" also exists. + * @method drawEllipse + * @param {Number} x The left coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} + * which draws from center. + * @param {Number} y The top coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} + * which draws from the center. + * @param {Number} w The height (horizontal diameter) of the ellipse. The horizontal radius will be half of this + * number. + * @param {Number} h The width (vertical diameter) of the ellipse. The vertical radius will be half of this number. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.drawEllipse = function(x, y, w, h) { + return this.append(new G.Ellipse(x, y, w, h)); + }; + + /** + * Draws a star if pointSize is greater than 0, or a regular polygon if pointSize is 0 with the specified number of + * points. For example, the following code will draw a familiar 5 pointed star shape centered at 100, 100 and with a + * radius of 50: + * + * myGraphics.beginFill("#FF0").drawPolyStar(100, 100, 50, 5, 0.6, -90); + * // Note: -90 makes the first point vertical + * + * A tiny API method "dp" also exists. + * + * @method drawPolyStar + * @param {Number} x Position of the center of the shape. + * @param {Number} y Position of the center of the shape. + * @param {Number} radius The outer radius of the shape. + * @param {Number} sides The number of points on the star or sides on the polygon. + * @param {Number} pointSize The depth or "pointy-ness" of the star points. A pointSize of 0 will draw a regular + * polygon (no points), a pointSize of 1 will draw nothing because the points are infinitely pointy. + * @param {Number} angle The angle of the first point / corner. For example a value of 0 will draw the first point + * directly to the right of the center. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.drawPolyStar = function(x, y, radius, sides, pointSize, angle) { + return this.append(new G.PolyStar(x, y, radius, sides, pointSize, angle)); + }; + + // TODO: deprecated. + /** + * Removed in favour of using custom command objects with {{#crossLink "Graphics/append"}}{{/crossLink}}. + * @method inject + * @deprecated + **/ + + /** + * Appends a graphics command object to the graphics queue. Command objects expose an "exec" method + * that accepts two parameters: the Context2D to operate on, and an arbitrary data object passed into + * {{#crossLink "Graphics/draw"}}{{/crossLink}}. The latter will usually be the Shape instance that called draw. + * + * This method is used internally by Graphics methods, such as drawCircle, but can also be used directly to insert + * built-in or custom graphics commands. For example: + * + * // attach data to our shape, so we can access it during the draw: + * myShape.color = "red"; + * + * // append a Circle command object: + * myShape.graphics.append(new createjs.Graphics.Circle(50, 50, 30)); + * + * // append a custom command object with an exec method that sets the fill style + * // based on the shape's data, and then fills the circle. + * myShape.graphics.append({exec:function(ctx, shape) { + * ctx.fillStyle = shape.color; + * ctx.fill(); + * }}); + * + * @method append + * @param {Object} command A graphics command object exposing an "exec" method. + * @param {boolean} clean The clean param is primarily for internal use. A value of true indicates that a command does not generate a path that should be stroked or filled. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.append = function(command, clean) { + this._activeInstructions.push(command); + this.command = command; + if (!clean) { this._dirty = true; } + return this; + }; + + /** + * Decodes a compact encoded path string into a series of draw instructions. + * This format is not intended to be human readable, and is meant for use by authoring tools. + * The format uses a base64 character set, with each character representing 6 bits, to define a series of draw + * commands. + * + * Each command is comprised of a single "header" character followed by a variable number of alternating x and y + * position values. Reading the header bits from left to right (most to least significant): bits 1 to 3 specify the + * type of operation (0-moveTo, 1-lineTo, 2-quadraticCurveTo, 3-bezierCurveTo, 4-closePath, 5-7 unused). Bit 4 + * indicates whether position values use 12 bits (2 characters) or 18 bits (3 characters), with a one indicating the + * latter. Bits 5 and 6 are currently unused. + * + * Following the header is a series of 0 (closePath), 2 (moveTo, lineTo), 4 (quadraticCurveTo), or 6 (bezierCurveTo) + * parameters. These parameters are alternating x/y positions represented by 2 or 3 characters (as indicated by the + * 4th bit in the command char). These characters consist of a 1 bit sign (1 is negative, 0 is positive), followed + * by an 11 (2 char) or 17 (3 char) bit integer value. All position values are in tenths of a pixel. Except in the + * case of move operations which are absolute, this value is a delta from the previous x or y position (as + * appropriate). + * + * For example, the string "A3cAAMAu4AAA" represents a line starting at -150,0 and ending at 150,0. + *
A - bits 000000. First 3 bits (000) indicate a moveTo operation. 4th bit (0) indicates 2 chars per + * parameter. + *
n0 - 110111011100. Absolute x position of -150.0px. First bit indicates a negative value, remaining bits + * indicate 1500 tenths of a pixel. + *
AA - 000000000000. Absolute y position of 0. + *
I - 001100. First 3 bits (001) indicate a lineTo operation. 4th bit (1) indicates 3 chars per parameter. + *
Au4 - 000000101110111000. An x delta of 300.0px, which is added to the previous x value of -150.0px to + * provide an absolute position of +150.0px. + *
AAA - 000000000000000000. A y delta value of 0. + * + * A tiny API method "p" also exists. + * @method decodePath + * @param {String} str The path string to decode. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.decodePath = function(str) { + var instructions = [this.moveTo, this.lineTo, this.quadraticCurveTo, this.bezierCurveTo, this.closePath]; + var paramCount = [2, 2, 4, 6, 0]; + var i=0, l=str.length; + var params = []; + var x=0, y=0; + var base64 = Graphics.BASE_64; + + while (i>3; // highest order bits 1-3 code for operation. + var f = instructions[fi]; + // check that we have a valid instruction & that the unused bits are empty: + if (!f || (n&3)) { throw("bad path data (@"+i+"): "+c); } + var pl = paramCount[fi]; + if (!fi) { x=y=0; } // move operations reset the position. + params.length = 0; + i++; + var charCount = (n>>2&1)+2; // 4th header bit indicates number size for this operation. + for (var p=0; p>5) ? -1 : 1; + num = ((num&31)<<6)|(base64[str.charAt(i+1)]); + if (charCount == 3) { num = (num<<6)|(base64[str.charAt(i+2)]); } + num = sign*num/10; + if (p%2) { x = (num += x); } + else { y = (num += y); } + params[p] = num; + i += charCount; + } + f.apply(this,params); + } + return this; + }; + + /** + * Stores all graphics commands so they won't be executed in future draws. Calling store() a second time adds to + * the existing store. This also affects `drawAsPath()`. + * + * This is useful in cases where you are creating vector graphics in an iterative manner (ex. generative art), so + * that only new graphics need to be drawn (which can provide huge performance benefits), but you wish to retain all + * of the vector instructions for later use (ex. scaling, modifying, or exporting). + * + * Note that calling store() will force the active path (if any) to be ended in a manner similar to changing + * the fill or stroke. + * + * For example, consider a application where the user draws lines with the mouse. As each line segment (or collection of + * segments) are added to a Shape, it can be rasterized using {{#crossLink "DisplayObject/updateCache"}}{{/crossLink}}, + * and then stored, so that it can be redrawn at a different scale when the application is resized, or exported to SVG. + * + * // set up cache: + * myShape.cache(0,0,500,500,scale); + * + * // when the user drags, draw a new line: + * myShape.graphics.moveTo(oldX,oldY).lineTo(newX,newY); + * // then draw it into the existing cache: + * myShape.updateCache("source-over"); + * // store the new line, so it isn't redrawn next time: + * myShape.store(); + * + * // then, when the window resizes, we can re-render at a different scale: + * // first, unstore all our lines: + * myShape.unstore(); + * // then cache using the new scale: + * myShape.cache(0,0,500,500,newScale); + * // finally, store the existing commands again: + * myShape.store(); + * + * @method store + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.store = function() { + this._updateInstructions(true); + this._storeIndex = this._instructions.length; + return this; + }; + + /** + * Unstores any graphics commands that were previously stored using {{#crossLink "Graphics/store"}}{{/crossLink}} + * so that they will be executed in subsequent draw calls. + * + * @method unstore + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + **/ + p.unstore = function() { + this._storeIndex = 0; + return this; + }; + + /** + * Returns a clone of this Graphics instance. Note that the individual command objects are not cloned. + * @method clone + * @return {Graphics} A clone of the current Graphics instance. + **/ + p.clone = function() { + var o = new Graphics(); + o.command = this.command; + o._stroke = this._stroke; + o._strokeStyle = this._strokeStyle; + o._strokeDash = this._strokeDash; + o._strokeIgnoreScale = this._strokeIgnoreScale; + o._fill = this._fill; + o._instructions = this._instructions.slice(); + o._commitIndex = this._commitIndex; + o._activeInstructions = this._activeInstructions.slice(); + o._dirty = this._dirty; + o._storeIndex = this._storeIndex; + return o; + }; + + /** + * Returns a string representation of this object. + * @method toString + * @return {String} a string representation of the instance. + **/ + p.toString = function() { + return "[Graphics]"; + }; + + +// tiny API: + /** + * Shortcut to moveTo. + * @method mt + * @param {Number} x The x coordinate the drawing point should move to. + * @param {Number} y The y coordinate the drawing point should move to. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls). + * @chainable + * @protected + **/ + p.mt = p.moveTo; + + /** + * Shortcut to lineTo. + * @method lt + * @param {Number} x The x coordinate the drawing point should draw to. + * @param {Number} y The y coordinate the drawing point should draw to. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.lt = p.lineTo; + + /** + * Shortcut to arcTo. + * @method at + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} radius + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.at = p.arcTo; + + /** + * Shortcut to bezierCurveTo. + * @method bt + * @param {Number} cp1x + * @param {Number} cp1y + * @param {Number} cp2x + * @param {Number} cp2y + * @param {Number} x + * @param {Number} y + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.bt = p.bezierCurveTo; + + /** + * Shortcut to quadraticCurveTo / curveTo. + * @method qt + * @param {Number} cpx + * @param {Number} cpy + * @param {Number} x + * @param {Number} y + * @protected + * @chainable + **/ + p.qt = p.quadraticCurveTo; + + /** + * Shortcut to arc. + * @method a + * @param {Number} x + * @param {Number} y + * @param {Number} radius + * @param {Number} startAngle Measured in radians. + * @param {Number} endAngle Measured in radians. + * @param {Boolean} anticlockwise + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @protected + * @chainable + **/ + p.a = p.arc; + + /** + * Shortcut to rect. + * @method r + * @param {Number} x + * @param {Number} y + * @param {Number} w Width of the rectangle + * @param {Number} h Height of the rectangle + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.r = p.rect; + + /** + * Shortcut to closePath. + * @method cp + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.cp = p.closePath; + + /** + * Shortcut to clear. + * @method c + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.c = p.clear; + + /** + * Shortcut to beginFill. + * @method f + * @param {String} color A CSS compatible color value (ex. "red", "#FF0000", or "rgba(255,0,0,0.5)"). Setting to + * null will result in no fill. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.f = p.beginFill; + + /** + * Shortcut to beginLinearGradientFill. + * @method lf + * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define a gradient + * drawing from red to blue. + * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 0.9] would draw + * the first color to 10% then interpolating to the second color at 90%. + * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. + * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. + * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. + * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.lf = p.beginLinearGradientFill; + + /** + * Shortcut to beginRadialGradientFill. + * @method rf + * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define + * a gradient drawing from red to blue. + * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, + * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. + * @param {Number} x0 Center position of the inner circle that defines the gradient. + * @param {Number} y0 Center position of the inner circle that defines the gradient. + * @param {Number} r0 Radius of the inner circle that defines the gradient. + * @param {Number} x1 Center position of the outer circle that defines the gradient. + * @param {Number} y1 Center position of the outer circle that defines the gradient. + * @param {Number} r1 Radius of the outer circle that defines the gradient. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.rf = p.beginRadialGradientFill; + + /** + * Shortcut to beginBitmapFill. + * @method bf + * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use + * as the pattern. + * @param {String} repetition Optional. Indicates whether to repeat the image in the fill area. One of "repeat", + * "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". Note that Firefox does not support "repeat-x" or + * "repeat-y" (latest tests were in FF 20.0), and will default to "repeat". + * @param {Matrix2D} matrix Optional. Specifies a transformation matrix for the bitmap fill. This transformation + * will be applied relative to the parent transform. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.bf = p.beginBitmapFill; + + /** + * Shortcut to endFill. + * @method ef + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.ef = p.endFill; + + /** + * Shortcut to setStrokeStyle. + * @method ss + * @param {Number} thickness The width of the stroke. + * @param {String | Number} [caps=0] Indicates the type of caps to use at the end of lines. One of butt, + * round, or square. Defaults to "butt". Also accepts the values 0 (butt), 1 (round), and 2 (square) for use with + * the tiny API. + * @param {String | Number} [joints=0] Specifies the type of joints that should be used where two lines meet. + * One of bevel, round, or miter. Defaults to "miter". Also accepts the values 0 (miter), 1 (round), and 2 (bevel) + * for use with the tiny API. + * @param {Number} [miterLimit=10] If joints is set to "miter", then you can specify a miter limit ratio which + * controls at what point a mitered joint will be clipped. + * @param {Boolean} [ignoreScale=false] If true, the stroke will be drawn at the specified thickness regardless + * of active transformations. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.ss = p.setStrokeStyle; + + /** + * Shortcut to setStrokeDash. + * @method sd + * @param {Array} [segments] An array specifying the dash pattern, alternating between line and gap. + * For example, [20,10] would create a pattern of 20 pixel lines with 10 pixel gaps between them. + * Passing null or an empty array will clear any existing dash. + * @param {Number} [offset=0] The offset of the dash pattern. For example, you could increment this value to create a "marching ants" effect. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.sd = p.setStrokeDash; + + /** + * Shortcut to beginStroke. + * @method s + * @param {String} color A CSS compatible color value (ex. "#FF0000", "red", or "rgba(255,0,0,0.5)"). Setting to + * null will result in no stroke. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.s = p.beginStroke; + + /** + * Shortcut to beginLinearGradientStroke. + * @method ls + * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define + * a gradient drawing from red to blue. + * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, + * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. + * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. + * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. + * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. + * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.ls = p.beginLinearGradientStroke; + + /** + * Shortcut to beginRadialGradientStroke. + * @method rs + * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define + * a gradient drawing from red to blue. + * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, + * 0.9] would draw the first color to 10% then interpolating to the second color at 90%, then draw the second color + * to 100%. + * @param {Number} x0 Center position of the inner circle that defines the gradient. + * @param {Number} y0 Center position of the inner circle that defines the gradient. + * @param {Number} r0 Radius of the inner circle that defines the gradient. + * @param {Number} x1 Center position of the outer circle that defines the gradient. + * @param {Number} y1 Center position of the outer circle that defines the gradient. + * @param {Number} r1 Radius of the outer circle that defines the gradient. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.rs = p.beginRadialGradientStroke; + + /** + * Shortcut to beginBitmapStroke. + * @method bs + * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use + * as the pattern. + * @param {String} [repetition=repeat] Optional. Indicates whether to repeat the image in the fill area. One of + * "repeat", "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.bs = p.beginBitmapStroke; + + /** + * Shortcut to endStroke. + * @method es + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.es = p.endStroke; + + /** + * Shortcut to drawRect. + * @method dr + * @param {Number} x + * @param {Number} y + * @param {Number} w Width of the rectangle + * @param {Number} h Height of the rectangle + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.dr = p.drawRect; + + /** + * Shortcut to drawRoundRect. + * @method rr + * @param {Number} x + * @param {Number} y + * @param {Number} w + * @param {Number} h + * @param {Number} radius Corner radius. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.rr = p.drawRoundRect; + + /** + * Shortcut to drawRoundRectComplex. + * @method rc + * @param {Number} x The horizontal coordinate to draw the round rect. + * @param {Number} y The vertical coordinate to draw the round rect. + * @param {Number} w The width of the round rect. + * @param {Number} h The height of the round rect. + * @param {Number} radiusTL Top left corner radius. + * @param {Number} radiusTR Top right corner radius. + * @param {Number} radiusBR Bottom right corner radius. + * @param {Number} radiusBL Bottom left corner radius. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.rc = p.drawRoundRectComplex; + + /** + * Shortcut to drawCircle. + * @method dc + * @param {Number} x x coordinate center point of circle. + * @param {Number} y y coordinate center point of circle. + * @param {Number} radius Radius of circle. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.dc = p.drawCircle; + + /** + * Shortcut to drawEllipse. + * @method de + * @param {Number} x The left coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} + * which draws from center. + * @param {Number} y The top coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} + * which draws from the center. + * @param {Number} w The height (horizontal diameter) of the ellipse. The horizontal radius will be half of this + * number. + * @param {Number} h The width (vertical diameter) of the ellipse. The vertical radius will be half of this number. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.de = p.drawEllipse; + + /** + * Shortcut to drawPolyStar. + * @method dp + * @param {Number} x Position of the center of the shape. + * @param {Number} y Position of the center of the shape. + * @param {Number} radius The outer radius of the shape. + * @param {Number} sides The number of points on the star or sides on the polygon. + * @param {Number} pointSize The depth or "pointy-ness" of the star points. A pointSize of 0 will draw a regular + * polygon (no points), a pointSize of 1 will draw nothing because the points are infinitely pointy. + * @param {Number} angle The angle of the first point / corner. For example a value of 0 will draw the first point + * directly to the right of the center. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.dp = p.drawPolyStar; + + /** + * Shortcut to decodePath. + * @method p + * @param {String} str The path string to decode. + * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) + * @chainable + * @protected + **/ + p.p = p.decodePath; + + +// private methods: + /** + * @method _updateInstructions + * @param commit + * @protected + **/ + p._updateInstructions = function(commit) { + var instr = this._instructions, active = this._activeInstructions, commitIndex = this._commitIndex; + + if (this._dirty && active.length) { + instr.length = commitIndex; // remove old, uncommitted commands + instr.push(Graphics.beginCmd); + + var l = active.length, ll = instr.length; + instr.length = ll+l; + for (var i=0; i= 2) { + var o = this.style = Graphics._ctx.createPattern(image, repetition || ""); + o.props = {image: image, repetition: repetition, type: "bitmap"}; + } + return this; + }; + p.path = false; + + /** + * Graphics command object. See {{#crossLink "Graphics/beginStroke"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. + * @class Stroke + * @constructor + * @param {Object} style A valid Context2D fillStyle. + * @param {Boolean} ignoreScale + **/ + /** + * A valid Context2D strokeStyle. + * @property style + * @type Object + */ + /** + * @property ignoreScale + * @type Boolean + */ + /** + * Execute the Graphics command in the provided Canvas context. + * @method exec + * @param {CanvasRenderingContext2D} ctx The canvas rendering context + */ + p = (G.Stroke = function(style, ignoreScale) { + this.style = style; + this.ignoreScale = ignoreScale; + }).prototype; + p.exec = function(ctx) { + if (!this.style) { return; } + ctx.strokeStyle = this.style; + if (this.ignoreScale) { ctx.save(); ctx.setTransform(1,0,0,1,0,0); } + ctx.stroke(); + if (this.ignoreScale) { ctx.restore(); } + }; + /** + * Creates a linear gradient style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}. + * See {{#crossLink "Graphics/beginLinearGradientStroke"}}{{/crossLink}} for more information. + * @method linearGradient + * @param {Array} colors + * @param {Array} ratios + * @param {Number} x0 + * @param {Number} y0 + * @param {Number} x1 + * @param {Number} y1 + * @return {Fill} Returns this Stroke object for chaining or assignment. + */ + p.linearGradient = G.Fill.prototype.linearGradient; + /** + * Creates a radial gradient style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}. + * See {{#crossLink "Graphics/beginRadialGradientStroke"}}{{/crossLink}} for more information. + * @method radialGradient + * @param {Array} colors + * @param {Array} ratios + * @param {Number} x0 + * @param {Number} y0 + * @param {Number} r0 + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} r1 + * @return {Fill} Returns this Stroke object for chaining or assignment. + */ + p.radialGradient = G.Fill.prototype.radialGradient; + /** + * Creates a bitmap fill style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}. + * See {{#crossLink "Graphics/beginBitmapStroke"}}{{/crossLink}} for more information. + * @method bitmap + * @param {HTMLImageElement} image + * @param {String} [repetition] One of: repeat, repeat-x, repeat-y, or no-repeat. + * @return {Fill} Returns this Stroke object for chaining or assignment. + */ + p.bitmap = G.Fill.prototype.bitmap; + p.path = false; + + /** + * Graphics command object. See {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. + * @class StrokeStyle + * @constructor + * @param {Number} width + * @param {String} [caps=butt] + * @param {String} [joints=miter] + * @param {Number} [miterLimit=10] + * @param {Boolean} [ignoreScale=false] + **/ + /** + * @property width + * @type Number + */ + /** + * One of: butt, round, square + * @property caps + * @type String + */ + /** + * One of: round, bevel, miter + * @property joints + * @type String + */ + /** + * @property miterLimit + * @type Number + */ + /** + * Execute the Graphics command in the provided Canvas context. + * @method exec + * @param {CanvasRenderingContext2D} ctx The canvas rendering context + */ + p = (G.StrokeStyle = function(width, caps, joints, miterLimit, ignoreScale) { + this.width = width; + this.caps = caps; + this.joints = joints; + this.miterLimit = miterLimit; + this.ignoreScale = ignoreScale; + }).prototype; + p.exec = function(ctx) { + ctx.lineWidth = (this.width == null ? "1" : this.width); + ctx.lineCap = (this.caps == null ? "butt" : (isNaN(this.caps) ? this.caps : Graphics.STROKE_CAPS_MAP[this.caps])); + ctx.lineJoin = (this.joints == null ? "miter" : (isNaN(this.joints) ? this.joints : Graphics.STROKE_JOINTS_MAP[this.joints])); + ctx.miterLimit = (this.miterLimit == null ? "10" : this.miterLimit); + ctx.ignoreScale = (this.ignoreScale == null ? false : this.ignoreScale); + }; + p.path = false; + + /** + * Graphics command object. See {{#crossLink "Graphics/setStrokeDash"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. + * @class StrokeDash + * @constructor + * @param {Array} [segments] + * @param {Number} [offset=0] + **/ + /** + * @property segments + * @type Array + */ + /** + * @property offset + * @type Number + */ + /** + * Execute the Graphics command in the provided Canvas context. + * @method exec + * @param {CanvasRenderingContext2D} ctx The canvas rendering context + */ + (G.StrokeDash = function(segments, offset) { + this.segments = segments; + this.offset = offset||0; + }).prototype.exec = function(ctx) { + if (ctx.setLineDash) { // feature detection. + ctx.setLineDash(this.segments|| G.StrokeDash.EMPTY_SEGMENTS); // instead of [] to reduce churn. + ctx.lineDashOffset = this.offset||0; + } + }; + /** + * The default value for segments (ie. no dash). + * @property EMPTY_SEGMENTS + * @static + * @final + * @readonly + * @protected + * @type {Array} + **/ + G.StrokeDash.EMPTY_SEGMENTS = []; + + /** + * Graphics command object. See {{#crossLink "Graphics/drawRoundRectComplex"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. + * @class RoundRect + * @constructor + * @param {Number} x + * @param {Number} y + * @param {Number} w + * @param {Number} h + * @param {Number} radiusTL + * @param {Number} radiusTR + * @param {Number} radiusBR + * @param {Number} radiusBL + **/ + /** + * @property x + * @type Number + */ + /** + * @property y + * @type Number + */ + /** + * @property w + * @type Number + */ + /** + * @property h + * @type Number + */ + /** + * @property radiusTL + * @type Number + */ + /** + * @property radiusTR + * @type Number + */ + /** + * @property radiusBR + * @type Number + */ + /** + * @property radiusBL + * @type Number + */ + /** + * Execute the Graphics command in the provided Canvas context. + * @method exec + * @param {CanvasRenderingContext2D} ctx The canvas rendering context + */ + (G.RoundRect = function(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL) { + this.x = x; this.y = y; + this.w = w; this.h = h; + this.radiusTL = radiusTL; this.radiusTR = radiusTR; + this.radiusBR = radiusBR; this.radiusBL = radiusBL; + }).prototype.exec = function(ctx) { + var max = (w max) { rTL = max; } + if (rTR < 0) { rTR *= (mTR=-1); } + if (rTR > max) { rTR = max; } + if (rBR < 0) { rBR *= (mBR=-1); } + if (rBR > max) { rBR = max; } + if (rBL < 0) { rBL *= (mBL=-1); } + if (rBL > max) { rBL = max; } + + ctx.moveTo(x+w-rTR, y); + ctx.arcTo(x+w+rTR*mTR, y-rTR*mTR, x+w, y+rTR, rTR); + ctx.lineTo(x+w, y+h-rBR); + ctx.arcTo(x+w+rBR*mBR, y+h+rBR*mBR, x+w-rBR, y+h, rBR); + ctx.lineTo(x+rBL, y+h); + ctx.arcTo(x-rBL*mBL, y+h+rBL*mBL, x, y+h-rBL, rBL); + ctx.lineTo(x, y+rTL); + ctx.arcTo(x-rTL*mTL, y-rTL*mTL, x+rTL, y, rTL); + ctx.closePath(); + }; + + /** + * Graphics command object. See {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. + * @class Circle + * @constructor + * @param {Number} x + * @param {Number} y + * @param {Number} radius + **/ + /** + * @property x + * @type Number + */ + /** + * @property y + * @type Number + */ + /** + * @property radius + * @type Number + */ + /** + * Execute the Graphics command in the provided Canvas context. + * @method exec + * @param {CanvasRenderingContext2D} ctx The canvas rendering context + */ + (G.Circle = function(x, y, radius) { + this.x = x; this.y = y; + this.radius = radius; + }).prototype.exec = function(ctx) { ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2); }; + + /** + * Graphics command object. See {{#crossLink "Graphics/drawEllipse"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. + * @class Ellipse + * @constructor + * @param {Number} x + * @param {Number} y + * @param {Number} w + * @param {Number} h + **/ + /** + * @property x + * @type Number + */ + /** + * @property y + * @type Number + */ + /** + * @property w + * @type Number + */ + /** + * @property h + * @type Number + */ + /** + * Execute the Graphics command in the provided Canvas context. + * @method exec + * @param {CanvasRenderingContext2D} ctx The canvas rendering context + */ + (G.Ellipse = function(x, y, w, h) { + this.x = x; this.y = y; + this.w = w; this.h = h; + }).prototype.exec = function(ctx) { + var x = this.x, y = this.y; + var w = this.w, h = this.h; + + var k = 0.5522848; + var ox = (w / 2) * k; + var oy = (h / 2) * k; + var xe = x + w; + var ye = y + h; + var xm = x + w / 2; + var ym = y + h / 2; + + ctx.moveTo(x, ym); + ctx.bezierCurveTo(x, ym-oy, xm-ox, y, xm, y); + ctx.bezierCurveTo(xm+ox, y, xe, ym-oy, xe, ym); + ctx.bezierCurveTo(xe, ym+oy, xm+ox, ye, xm, ye); + ctx.bezierCurveTo(xm-ox, ye, x, ym+oy, x, ym); + }; + + /** + * Graphics command object. See {{#crossLink "Graphics/drawPolyStar"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. + * @class PolyStar + * @constructor + * @param {Number} x + * @param {Number} y + * @param {Number} radius + * @param {Number} sides + * @param {Number} pointSize + * @param {Number} angle + **/ + /** + * @property x + * @type Number + */ + /** + * @property y + * @type Number + */ + /** + * @property radius + * @type Number + */ + /** + * @property sides + * @type Number + */ + /** + * @property pointSize + * @type Number + */ + /** + * @property angle + * @type Number + */ + /** + * Execute the Graphics command in the provided Canvas context. + * @method exec + * @param {CanvasRenderingContext2D} ctx The canvas rendering context + */ + (G.PolyStar = function(x, y, radius, sides, pointSize, angle) { + this.x = x; this.y = y; + this.radius = radius; + this.sides = sides; + this.pointSize = pointSize; + this.angle = angle; + }).prototype.exec = function(ctx) { + var x = this.x, y = this.y; + var radius = this.radius; + var angle = (this.angle||0)/180*Math.PI; + var sides = this.sides; + var ps = 1-(this.pointSize||0); + var a = Math.PI/sides; + + ctx.moveTo(x+Math.cos(angle)*radius, y+Math.sin(angle)*radius); + for (var i=0; iNote: In EaselJS 0.7.0, the mouseEnabled property will not work properly with nested Containers. Please + * check out the latest NEXT version in GitHub for an updated version with this issue resolved. The fix will be + * provided in the next release of EaselJS. + * @property mouseEnabled + * @type {Boolean} + * @default true + **/ + this.mouseEnabled = true; + + /** + * If false, the tick will not run on this display object (or its children). This can provide some performance benefits. + * In addition to preventing the "tick" event from being dispatched, it will also prevent tick related updates + * on some display objects (ex. Sprite & MovieClip frame advancing, DOMElement visibility handling). + * @property tickEnabled + * @type Boolean + * @default true + **/ + this.tickEnabled = true; + + /** + * An optional name for this display object. Included in {{#crossLink "DisplayObject/toString"}}{{/crossLink}} . Useful for + * debugging. + * @property name + * @type {String} + * @default null + **/ + this.name = null; + + /** + * A reference to the {{#crossLink "Container"}}{{/crossLink}} or {{#crossLink "Stage"}}{{/crossLink}} object that + * contains this display object, or null if it has not been added + * to one. + * @property parent + * @final + * @type {Container} + * @default null + * @readonly + **/ + this.parent = null; + + /** + * The left offset for this display object's registration point. For example, to make a 100x100px Bitmap rotate + * around its center, you would set regX and {{#crossLink "DisplayObject/regY:property"}}{{/crossLink}} to 50. + * @property regX + * @type {Number} + * @default 0 + **/ + this.regX = 0; + + /** + * The y offset for this display object's registration point. For example, to make a 100x100px Bitmap rotate around + * its center, you would set {{#crossLink "DisplayObject/regX:property"}}{{/crossLink}} and regY to 50. + * @property regY + * @type {Number} + * @default 0 + **/ + this.regY = 0; + + /** + * The rotation in degrees for this display object. + * @property rotation + * @type {Number} + * @default 0 + **/ + this.rotation = 0; + + /** + * The factor to stretch this display object horizontally. For example, setting scaleX to 2 will stretch the display + * object to twice its nominal width. To horizontally flip an object, set the scale to a negative number. + * @property scaleX + * @type {Number} + * @default 1 + **/ + this.scaleX = 1; + + /** + * The factor to stretch this display object vertically. For example, setting scaleY to 0.5 will stretch the display + * object to half its nominal height. To vertically flip an object, set the scale to a negative number. + * @property scaleY + * @type {Number} + * @default 1 + **/ + this.scaleY = 1; + + /** + * The factor to skew this display object horizontally. + * @property skewX + * @type {Number} + * @default 0 + **/ + this.skewX = 0; + + /** + * The factor to skew this display object vertically. + * @property skewY + * @type {Number} + * @default 0 + **/ + this.skewY = 0; + + /** + * A shadow object that defines the shadow to render on this display object. Set to `null` to remove a shadow. If + * null, this property is inherited from the parent container. + * @property shadow + * @type {Shadow} + * @default null + **/ + this.shadow = null; + + /** + * Indicates whether this display object should be rendered to the canvas and included when running the Stage + * {{#crossLink "Stage/getObjectsUnderPoint"}}{{/crossLink}} method. + * @property visible + * @type {Boolean} + * @default true + **/ + this.visible = true; + + /** + * The x (horizontal) position of the display object, relative to its parent. + * @property x + * @type {Number} + * @default 0 + **/ + this.x = 0; + + /** The y (vertical) position of the display object, relative to its parent. + * @property y + * @type {Number} + * @default 0 + **/ + this.y = 0; + + /** + * If set, defines the transformation for this display object, overriding all other transformation properties + * (x, y, rotation, scale, skew). + * @property transformMatrix + * @type {Matrix2D} + * @default null + **/ + this.transformMatrix = null; + + /** + * The composite operation indicates how the pixels of this display object will be composited with the elements + * behind it. If `null`, this property is inherited from the parent container. For more information, read the + * + * whatwg spec on compositing. + * @property compositeOperation + * @type {String} + * @default null + **/ + this.compositeOperation = null; + + /** + * Indicates whether the display object should be drawn to a whole pixel when + * {{#crossLink "Stage/snapToPixelEnabled"}}{{/crossLink}} is true. To enable/disable snapping on whole + * categories of display objects, set this value on the prototype (Ex. Text.prototype.snapToPixel = true). + * @property snapToPixel + * @type {Boolean} + * @default true + **/ + this.snapToPixel = true; + + /** + * An array of Filter objects to apply to this display object. Filters are only applied / updated when {{#crossLink "cache"}}{{/crossLink}} + * or {{#crossLink "updateCache"}}{{/crossLink}} is called on the display object, and only apply to the area that is + * cached. + * @property filters + * @type {Array} + * @default null + **/ + this.filters = null; + + /** + * A Shape instance that defines a vector mask (clipping path) for this display object. The shape's transformation + * will be applied relative to the display object's parent coordinates (as if it were a child of the parent). + * @property mask + * @type {Shape} + * @default null + */ + this.mask = null; + + /** + * A display object that will be tested when checking mouse interactions or testing {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}}. + * The hit area will have its transformation applied relative to this display object's coordinate space (as though + * the hit test object were a child of this display object and relative to its regX/Y). The hitArea will be tested + * using only its own `alpha` value regardless of the alpha value on the target display object, or the target's + * ancestors (parents). + * + * If set on a {{#crossLink "Container"}}{{/crossLink}}, children of the Container will not receive mouse events. + * This is similar to setting {{#crossLink "mouseChildren"}}{{/crossLink}} to false. + * + * Note that hitArea is NOT currently used by the `hitTest()` method, nor is it supported for {{#crossLink "Stage"}}{{/crossLink}}. + * @property hitArea + * @type {DisplayObject} + * @default null + */ + this.hitArea = null; + + /** + * A CSS cursor (ex. "pointer", "help", "text", etc) that will be displayed when the user hovers over this display + * object. You must enable mouseover events using the {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}} method to + * use this property. Setting a non-null cursor on a Container will override the cursor set on its descendants. + * @property cursor + * @type {String} + * @default null + */ + this.cursor = null; + + + // private properties: + /** + * @property _cacheOffsetX + * @protected + * @type {Number} + * @default 0 + **/ + this._cacheOffsetX = 0; + + /** + * @property _cacheOffsetY + * @protected + * @type {Number} + * @default 0 + **/ + this._cacheOffsetY = 0; + + /** + * @property _filterOffsetX + * @protected + * @type {Number} + * @default 0 + **/ + this._filterOffsetX = 0; + + /** + * @property _filterOffsetY + * @protected + * @type {Number} + * @default 0 + **/ + this._filterOffsetY = 0; + + /** + * @property _cacheScale + * @protected + * @type {Number} + * @default 1 + **/ + this._cacheScale = 1; + + /** + * @property _cacheDataURLID + * @protected + * @type {Number} + * @default 0 + */ + this._cacheDataURLID = 0; + + /** + * @property _cacheDataURL + * @protected + * @type {String} + * @default null + */ + this._cacheDataURL = null; + + /** + * @property _props + * @protected + * @type {DisplayObject} + * @default null + **/ + this._props = new createjs.DisplayProps(); + + /** + * @property _rectangle + * @protected + * @type {Rectangle} + * @default null + **/ + this._rectangle = new createjs.Rectangle(); + + /** + * @property _bounds + * @protected + * @type {Rectangle} + * @default null + **/ + this._bounds = null; + } + var p = createjs.extend(DisplayObject, createjs.EventDispatcher); + + // TODO: deprecated + // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. + +// static properties: + /** + * Listing of mouse event names. Used in _hasMouseEventListener. + * @property _MOUSE_EVENTS + * @protected + * @static + * @type {Array} + **/ + DisplayObject._MOUSE_EVENTS = ["click","dblclick","mousedown","mouseout","mouseover","pressmove","pressup","rollout","rollover"]; + + /** + * Suppresses errors generated when using features like hitTest, mouse events, and {{#crossLink "getObjectsUnderPoint"}}{{/crossLink}} + * with cross domain content. + * @property suppressCrossDomainErrors + * @static + * @type {Boolean} + * @default false + **/ + DisplayObject.suppressCrossDomainErrors = false; + + /** + * @property _snapToPixelEnabled + * @protected + * @static + * @type {Boolean} + * @default false + **/ + DisplayObject._snapToPixelEnabled = false; // stage.snapToPixelEnabled is temporarily copied here during a draw to provide global access. + + /** + * @property _hitTestCanvas + * @type {HTMLCanvasElement | Object} + * @static + * @protected + **/ + /** + * @property _hitTestContext + * @type {CanvasRenderingContext2D} + * @static + * @protected + **/ + var canvas = createjs.createCanvas?createjs.createCanvas():window.document.createElement("canvas"); // prevent errors on load in browsers without canvas. + if (canvas.getContext) { + DisplayObject._hitTestCanvas = canvas; + DisplayObject._hitTestContext = canvas.getContext("2d"); + canvas.width = canvas.height = 1; + } + + /** + * @property _nextCacheID + * @type {Number} + * @static + * @protected + **/ + DisplayObject._nextCacheID = 1; + + +// events: + /** + * Dispatched when the user presses their left mouse button over the display object. See the + * {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. + * @event mousedown + * @since 0.6.0 + */ + + /** + * Dispatched when the user presses their left mouse button and then releases it while over the display object. + * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. + * @event click + * @since 0.6.0 + */ + + /** + * Dispatched when the user double clicks their left mouse button over this display object. + * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. + * @event dblclick + * @since 0.6.0 + */ + + /** + * Dispatched when the user's mouse enters this display object. This event must be enabled using + * {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. See also {{#crossLink "DisplayObject/rollover:event"}}{{/crossLink}}. + * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. + * @event mouseover + * @since 0.6.0 + */ + + /** + * Dispatched when the user's mouse leaves this display object. This event must be enabled using + * {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. See also {{#crossLink "DisplayObject/rollout:event"}}{{/crossLink}}. + * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. + * @event mouseout + * @since 0.6.0 + */ + + /** + * This event is similar to {{#crossLink "DisplayObject/mouseover:event"}}{{/crossLink}}, with the following + * differences: it does not bubble, and it considers {{#crossLink "Container"}}{{/crossLink}} instances as an + * aggregate of their content. + * + * For example, myContainer contains two overlapping children: shapeA and shapeB. The user moves their mouse over + * shapeA and then directly on to shapeB. With a listener for {{#crossLink "mouseover:event"}}{{/crossLink}} on + * myContainer, two events would be received, each targeting a child element:
    + *
  1. when the mouse enters shapeA (target=shapeA)
  2. + *
  3. when the mouse enters shapeB (target=shapeB)
  4. + *
+ * However, with a listener for "rollover" instead, only a single event is received when the mouse first enters + * the aggregate myContainer content (target=myContainer). + * + * This event must be enabled using {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. + * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. + * @event rollover + * @since 0.7.0 + */ + + /** + * This event is similar to {{#crossLink "DisplayObject/mouseout:event"}}{{/crossLink}}, with the following + * differences: it does not bubble, and it considers {{#crossLink "Container"}}{{/crossLink}} instances as an + * aggregate of their content. + * + * For example, myContainer contains two overlapping children: shapeA and shapeB. The user moves their mouse over + * shapeA, then directly on to shapeB, then off both. With a listener for {{#crossLink "mouseout:event"}}{{/crossLink}} + * on myContainer, two events would be received, each targeting a child element:
    + *
  1. when the mouse leaves shapeA (target=shapeA)
  2. + *
  3. when the mouse leaves shapeB (target=shapeB)
  4. + *
+ * However, with a listener for "rollout" instead, only a single event is received when the mouse leaves + * the aggregate myContainer content (target=myContainer). + * + * This event must be enabled using {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. + * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. + * @event rollout + * @since 0.7.0 + */ + + /** + * After a {{#crossLink "DisplayObject/mousedown:event"}}{{/crossLink}} occurs on a display object, a pressmove + * event will be generated on that object whenever the mouse moves until the mouse press is released. This can be + * useful for dragging and similar operations. + * @event pressmove + * @since 0.7.0 + */ + + /** + * After a {{#crossLink "DisplayObject/mousedown:event"}}{{/crossLink}} occurs on a display object, a pressup event + * will be generated on that object when that mouse press is released. This can be useful for dragging and similar + * operations. + * @event pressup + * @since 0.7.0 + */ + + /** + * Dispatched when the display object is added to a parent container. + * @event added + */ + + /** + * Dispatched when the display object is removed from its parent container. + * @event removed + */ + + /** + * Dispatched on each display object on a stage whenever the stage updates. This occurs immediately before the + * rendering (draw) pass. When {{#crossLink "Stage/update"}}{{/crossLink}} is called, first all display objects on + * the stage dispatch the tick event, then all of the display objects are drawn to stage. Children will have their + * {{#crossLink "tick:event"}}{{/crossLink}} event dispatched in order of their depth prior to the event being + * dispatched on their parent. + * @event tick + * @param {Object} target The object that dispatched the event. + * @param {String} type The event type. + * @param {Array} params An array containing any arguments that were passed to the Stage.update() method. For + * example if you called stage.update("hello"), then the params would be ["hello"]. + * @since 0.6.0 + */ + + +// getter / setters: + /** + * Use the {{#crossLink "DisplayObject/stage:property"}}{{/crossLink}} property instead. + * @method getStage + * @return {Stage} + * @deprecated + **/ + p.getStage = function() { + // uses dynamic access to avoid circular dependencies; + var o = this, _Stage = createjs["Stage"]; + while (o.parent) { o = o.parent; } + if (o instanceof _Stage) { return o; } + return null; + }; + + /** + * Returns the Stage instance that this display object will be rendered on, or null if it has not been added to one. + * @property stage + * @type {Stage} + * @readonly + **/ + try { + Object.defineProperties(p, { + stage: { get: p.getStage } + }); + } catch (e) {} + + +// public methods: + /** + * Returns true or false indicating whether the display object would be visible if drawn to a canvas. + * This does not account for whether it would be visible within the boundaries of the stage. + * + * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. + * @method isVisible + * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas + **/ + p.isVisible = function() { + return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0); + }; + + /** + * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. + * Returns true if the draw was handled (useful for overriding functionality). + * + * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. + * @method draw + * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. + * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. For example, + * used for drawing the cache (to prevent it from simply drawing an existing cache back into itself). + * @return {Boolean} + **/ + p.draw = function(ctx, ignoreCache) { + var cacheCanvas = this.cacheCanvas; + if (ignoreCache || !cacheCanvas) { return false; } + var scale = this._cacheScale; + ctx.drawImage(cacheCanvas, this._cacheOffsetX+this._filterOffsetX, this._cacheOffsetY+this._filterOffsetY, cacheCanvas.width/scale, cacheCanvas.height/scale); + return true; + }; + + /** + * Applies this display object's transformation, alpha, globalCompositeOperation, clipping path (mask), and shadow + * to the specified context. This is typically called prior to {{#crossLink "DisplayObject/draw"}}{{/crossLink}}. + * @method updateContext + * @param {CanvasRenderingContext2D} ctx The canvas 2D to update. + **/ + p.updateContext = function(ctx) { + var o=this, mask=o.mask, mtx= o._props.matrix; + + if (mask && mask.graphics && !mask.graphics.isEmpty()) { + mask.getMatrix(mtx); + ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty); + + mask.graphics.drawAsPath(ctx); + ctx.clip(); + + mtx.invert(); + ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty); + } + + this.getMatrix(mtx); + var tx = mtx.tx, ty = mtx.ty; + if (DisplayObject._snapToPixelEnabled && o.snapToPixel) { + tx = tx + (tx < 0 ? -0.5 : 0.5) | 0; + ty = ty + (ty < 0 ? -0.5 : 0.5) | 0; + } + ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, tx, ty); + ctx.globalAlpha *= o.alpha; + if (o.compositeOperation) { ctx.globalCompositeOperation = o.compositeOperation; } + if (o.shadow) { this._applyShadow(ctx, o.shadow); } + }; + + /** + * Draws the display object into a new canvas, which is then used for subsequent draws. For complex content + * that does not change frequently (ex. a Container with many children that do not move, or a complex vector Shape), + * this can provide for much faster rendering because the content does not need to be re-rendered each tick. The + * cached display object can be moved, rotated, faded, etc freely, however if its content changes, you must + * manually update the cache by calling updateCache() or cache() again. You must specify + * the cache area via the x, y, w, and h parameters. This defines the rectangle that will be rendered and cached + * using this display object's coordinates. + * + *

Example

+ * For example if you defined a Shape that drew a circle at 0, 0 with a radius of 25: + * + * var shape = new createjs.Shape(); + * shape.graphics.beginFill("#ff0000").drawCircle(0, 0, 25); + * myShape.cache(-25, -25, 50, 50); + * + * Note that filters need to be defined before the cache is applied. Check out the {{#crossLink "Filter"}}{{/crossLink}} + * class for more information. Some filters (ex. BlurFilter) will not work as expected in conjunction with the scale param. + * + * Usually, the resulting cacheCanvas will have the dimensions width*scale by height*scale, however some filters (ex. BlurFilter) + * will add padding to the canvas dimensions. + * + * @method cache + * @param {Number} x The x coordinate origin for the cache region. + * @param {Number} y The y coordinate origin for the cache region. + * @param {Number} width The width of the cache region. + * @param {Number} height The height of the cache region. + * @param {Number} [scale=1] The scale at which the cache will be created. For example, if you cache a vector shape using + * myShape.cache(0,0,100,100,2) then the resulting cacheCanvas will be 200x200 px. This lets you scale and rotate + * cached elements with greater fidelity. Default is 1. + **/ + p.cache = function(x, y, width, height, scale) { + // draw to canvas. + scale = scale||1; + if (!this.cacheCanvas) { this.cacheCanvas = createjs.createCanvas?createjs.createCanvas():window.document.createElement("canvas"); } + this._cacheWidth = width; + this._cacheHeight = height; + this._cacheOffsetX = x; + this._cacheOffsetY = y; + this._cacheScale = scale; + this.updateCache(); + }; + + /** + * Redraws the display object to its cache. Calling updateCache without an active cache will throw an error. + * If compositeOperation is null the current cache will be cleared prior to drawing. Otherwise the display object + * will be drawn over the existing cache using the specified compositeOperation. + * + *

Example

+ * Clear the current graphics of a cached shape, draw some new instructions, and then update the cache. The new line + * will be drawn on top of the old one. + * + * // Not shown: Creating the shape, and caching it. + * shapeInstance.clear(); + * shapeInstance.setStrokeStyle(3).beginStroke("#ff0000").moveTo(100, 100).lineTo(200,200); + * shapeInstance.updateCache(); + * + * @method updateCache + * @param {String} compositeOperation The compositeOperation to use, or null to clear the cache and redraw it. + * + * whatwg spec on compositing. + **/ + p.updateCache = function(compositeOperation) { + var cacheCanvas = this.cacheCanvas; + if (!cacheCanvas) { throw "cache() must be called before updateCache()"; } + var scale = this._cacheScale, offX = this._cacheOffsetX*scale, offY = this._cacheOffsetY*scale; + var w = this._cacheWidth, h = this._cacheHeight, ctx = cacheCanvas.getContext("2d"); + + var fBounds = this._getFilterBounds(); + offX += (this._filterOffsetX = fBounds.x); + offY += (this._filterOffsetY = fBounds.y); + + w = Math.ceil(w*scale) + fBounds.width; + h = Math.ceil(h*scale) + fBounds.height; + if (w != cacheCanvas.width || h != cacheCanvas.height) { + // TODO: it would be nice to preserve the content if there is a compositeOperation. + cacheCanvas.width = w; + cacheCanvas.height = h; + } else if (!compositeOperation) { + ctx.clearRect(0, 0, w+1, h+1); + } + + ctx.save(); + ctx.globalCompositeOperation = compositeOperation; + ctx.setTransform(scale, 0, 0, scale, -offX, -offY); + this.draw(ctx, true); + // TODO: filters and cache scale don't play well together at present. + this._applyFilters(); + ctx.restore(); + this.cacheID = DisplayObject._nextCacheID++; + }; + + /** + * Clears the current cache. See {{#crossLink "DisplayObject/cache"}}{{/crossLink}} for more information. + * @method uncache + **/ + p.uncache = function() { + this._cacheDataURL = this.cacheCanvas = null; + this.cacheID = this._cacheOffsetX = this._cacheOffsetY = this._filterOffsetX = this._filterOffsetY = 0; + this._cacheScale = 1; + }; + + /** + * Returns a data URL for the cache, or null if this display object is not cached. + * Uses cacheID to ensure a new data URL is not generated if the cache has not changed. + * @method getCacheDataURL + * @return {String} The image data url for the cache. + **/ + p.getCacheDataURL = function() { + if (!this.cacheCanvas) { return null; } + if (this.cacheID != this._cacheDataURLID) { this._cacheDataURL = this.cacheCanvas.toDataURL(); } + return this._cacheDataURL; + }; + + /** + * Transforms the specified x and y position from the coordinate space of the display object + * to the global (stage) coordinate space. For example, this could be used to position an HTML label + * over a specific point on a nested display object. Returns a Point instance with x and y properties + * correlating to the transformed coordinates on the stage. + * + *

Example

+ * + * displayObject.x = 300; + * displayObject.y = 200; + * stage.addChild(displayObject); + * var point = displayObject.localToGlobal(100, 100); + * // Results in x=400, y=300 + * + * @method localToGlobal + * @param {Number} x The x position in the source display object to transform. + * @param {Number} y The y position in the source display object to transform. + * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. + * @return {Point} A Point instance with x and y properties correlating to the transformed coordinates + * on the stage. + **/ + p.localToGlobal = function(x, y, pt) { + return this.getConcatenatedMatrix(this._props.matrix).transformPoint(x,y, pt||new createjs.Point()); + }; + + /** + * Transforms the specified x and y position from the global (stage) coordinate space to the + * coordinate space of the display object. For example, this could be used to determine + * the current mouse position within the display object. Returns a Point instance with x and y properties + * correlating to the transformed position in the display object's coordinate space. + * + *

Example

+ * + * displayObject.x = 300; + * displayObject.y = 200; + * stage.addChild(displayObject); + * var point = displayObject.globalToLocal(100, 100); + * // Results in x=-200, y=-100 + * + * @method globalToLocal + * @param {Number} x The x position on the stage to transform. + * @param {Number} y The y position on the stage to transform. + * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. + * @return {Point} A Point instance with x and y properties correlating to the transformed position in the + * display object's coordinate space. + **/ + p.globalToLocal = function(x, y, pt) { + return this.getConcatenatedMatrix(this._props.matrix).invert().transformPoint(x,y, pt||new createjs.Point()); + }; + + /** + * Transforms the specified x and y position from the coordinate space of this display object to the coordinate + * space of the target display object. Returns a Point instance with x and y properties correlating to the + * transformed position in the target's coordinate space. Effectively the same as using the following code with + * {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}} and {{#crossLink "DisplayObject/globalToLocal"}}{{/crossLink}}. + * + * var pt = this.localToGlobal(x, y); + * pt = target.globalToLocal(pt.x, pt.y); + * + * @method localToLocal + * @param {Number} x The x position in the source display object to transform. + * @param {Number} y The y position on the source display object to transform. + * @param {DisplayObject} target The target display object to which the coordinates will be transformed. + * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. + * @return {Point} Returns a Point instance with x and y properties correlating to the transformed position + * in the target's coordinate space. + **/ + p.localToLocal = function(x, y, target, pt) { + pt = this.localToGlobal(x, y, pt); + return target.globalToLocal(pt.x, pt.y, pt); + }; + + /** + * Shortcut method to quickly set the transform properties on the display object. All parameters are optional. + * Omitted parameters will have the default value set. + * + *

Example

+ * + * displayObject.setTransform(100, 100, 2, 2); + * + * @method setTransform + * @param {Number} [x=0] The horizontal translation (x position) in pixels + * @param {Number} [y=0] The vertical translation (y position) in pixels + * @param {Number} [scaleX=1] The horizontal scale, as a percentage of 1 + * @param {Number} [scaleY=1] the vertical scale, as a percentage of 1 + * @param {Number} [rotation=0] The rotation, in degrees + * @param {Number} [skewX=0] The horizontal skew factor + * @param {Number} [skewY=0] The vertical skew factor + * @param {Number} [regX=0] The horizontal registration point in pixels + * @param {Number} [regY=0] The vertical registration point in pixels + * @return {DisplayObject} Returns this instance. Useful for chaining commands. + * @chainable + */ + p.setTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) { + this.x = x || 0; + this.y = y || 0; + this.scaleX = scaleX == null ? 1 : scaleX; + this.scaleY = scaleY == null ? 1 : scaleY; + this.rotation = rotation || 0; + this.skewX = skewX || 0; + this.skewY = skewY || 0; + this.regX = regX || 0; + this.regY = regY || 0; + return this; + }; + + /** + * Returns a matrix based on this object's current transform. + * @method getMatrix + * @param {Matrix2D} matrix Optional. A Matrix2D object to populate with the calculated values. If null, a new + * Matrix object is returned. + * @return {Matrix2D} A matrix representing this display object's transform. + **/ + p.getMatrix = function(matrix) { + var o = this, mtx = matrix&&matrix.identity() || new createjs.Matrix2D(); + return o.transformMatrix ? mtx.copy(o.transformMatrix) : mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.regX, o.regY); + }; + + /** + * Generates a Matrix2D object representing the combined transform of the display object and all of its + * parent Containers up to the highest level ancestor (usually the {{#crossLink "Stage"}}{{/crossLink}}). This can + * be used to transform positions between coordinate spaces, such as with {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}} + * and {{#crossLink "DisplayObject/globalToLocal"}}{{/crossLink}}. + * @method getConcatenatedMatrix + * @param {Matrix2D} [matrix] A {{#crossLink "Matrix2D"}}{{/crossLink}} object to populate with the calculated values. + * If null, a new Matrix2D object is returned. + * @return {Matrix2D} The combined matrix. + **/ + p.getConcatenatedMatrix = function(matrix) { + var o = this, mtx = this.getMatrix(matrix); + while (o = o.parent) { + mtx.prependMatrix(o.getMatrix(o._props.matrix)); + } + return mtx; + }; + + /** + * Generates a DisplayProps object representing the combined display properties of the object and all of its + * parent Containers up to the highest level ancestor (usually the {{#crossLink "Stage"}}{{/crossLink}}). + * @method getConcatenatedDisplayProps + * @param {DisplayProps} [props] A {{#crossLink "DisplayProps"}}{{/crossLink}} object to populate with the calculated values. + * If null, a new DisplayProps object is returned. + * @return {DisplayProps} The combined display properties. + **/ + p.getConcatenatedDisplayProps = function(props) { + props = props ? props.identity() : new createjs.DisplayProps(); + var o = this, mtx = o.getMatrix(props.matrix); + do { + props.prepend(o.visible, o.alpha, o.shadow, o.compositeOperation); + + // we do this to avoid problems with the matrix being used for both operations when o._props.matrix is passed in as the props param. + // this could be simplified (ie. just done as part of the prepend above) if we switched to using a pool. + if (o != this) { mtx.prependMatrix(o.getMatrix(o._props.matrix)); } + } while (o = o.parent); + return props; + }; + + /** + * Tests whether the display object intersects the specified point in local coordinates (ie. draws a pixel + * with alpha > 0 at the specified position). This ignores the alpha, shadow, hitArea, mask, and compositeOperation + * of the display object. + * + *

Example

+ * + * var myShape = new createjs.Shape(); + * myShape.graphics.beginFill("red").drawRect(100, 100, 20, 50); + * + * console.log(myShape.hitTest(10,10); // false + * console.log(myShape.hitTest(110, 25); // true + * + * Note that to use Stage coordinates (such as {{#crossLink "Stage/mouseX:property"}}{{/crossLink}}), they must + * first be converted to local coordinates: + * + * stage.addEventListener("stagemousedown", handleMouseDown); + * function handleMouseDown(event) { + * var p = myShape.globalToLocal(stage.mouseX, stage.mouseY); + * var hit = myShape.hitTest(p.x, p.y); + * } + * + * Shape-to-shape collision is not currently supported by EaselJS. + * + * @method hitTest + * @param {Number} x The x position to check in the display object's local coordinates. + * @param {Number} y The y position to check in the display object's local coordinates. + * @return {Boolean} A Boolean indicating whether a visible portion of the DisplayObject intersect the specified + * local Point. + */ + p.hitTest = function(x, y) { + var ctx = DisplayObject._hitTestContext; + ctx.setTransform(1, 0, 0, 1, -x, -y); + this.draw(ctx); + + var hit = this._testHit(ctx); + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.clearRect(0, 0, 2, 2); + return hit; + }; + + /** + * Provides a chainable shortcut method for setting a number of properties on the instance. + * + *

Example

+ * + * var myGraphics = new createjs.Graphics().beginFill("#ff0000").drawCircle(0, 0, 25); + * var shape = stage.addChild(new createjs.Shape()).set({graphics:myGraphics, x:100, y:100, alpha:0.5}); + * + * @method set + * @param {Object} props A generic object containing properties to copy to the DisplayObject instance. + * @return {DisplayObject} 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 rectangle representing this object's bounds in its local coordinate system (ie. with no transformation). + * Objects that have been cached will return the bounds of the cache. + * + * Not all display objects can calculate their own bounds (ex. Shape). For these objects, you can use + * {{#crossLink "DisplayObject/setBounds"}}{{/crossLink}} so that they are included when calculating Container + * bounds. + * + * + * + * + * + * + * + * + * + *
All + * All display objects support setting bounds manually using setBounds(). Likewise, display objects that + * have been cached using cache() will return the bounds of their cache. Manual and cache bounds will override + * the automatic calculations listed below. + *
Bitmap + * Returns the width and height of the sourceRect (if specified) or image, extending from (x=0,y=0). + *
Sprite + * Returns the bounds of the current frame. May have non-zero x/y if a frame registration point was specified + * in the spritesheet data. See also {{#crossLink "SpriteSheet/getFrameBounds"}}{{/crossLink}} + *
Container + * Returns the aggregate (combined) bounds of all children that return a non-null value from getBounds(). + *
Shape + * Does not currently support automatic bounds calculations. Use setBounds() to manually define bounds. + *
Text + * Returns approximate bounds. Horizontal values (x/width) are quite accurate, but vertical values (y/height) are + * not, especially when using textBaseline values other than "top". + *
BitmapText + * Returns approximate bounds. Values will be more accurate if spritesheet frame registration points are close + * to (x=0,y=0). + *
+ * + * Bounds can be expensive to calculate for some objects (ex. text, or containers with many children), and + * are recalculated each time you call getBounds(). You can prevent recalculation on static objects by setting the + * bounds explicitly: + * + * var bounds = obj.getBounds(); + * obj.setBounds(bounds.x, bounds.y, bounds.width, bounds.height); + * // getBounds will now use the set values, instead of recalculating + * + * To reduce memory impact, the returned Rectangle instance may be reused internally; clone the instance or copy its + * values if you need to retain it. + * + * var myBounds = obj.getBounds().clone(); + * // OR: + * myRect.copy(obj.getBounds()); + * + * @method getBounds + * @return {Rectangle} A Rectangle instance representing the bounds, or null if bounds are not available for this + * object. + **/ + p.getBounds = function() { + if (this._bounds) { return this._rectangle.copy(this._bounds); } + var cacheCanvas = this.cacheCanvas; + if (cacheCanvas) { + var scale = this._cacheScale; + return this._rectangle.setValues(this._cacheOffsetX, this._cacheOffsetY, cacheCanvas.width/scale, cacheCanvas.height/scale); + } + return null; + }; + + /** + * Returns a rectangle representing this object's bounds in its parent's coordinate system (ie. with transformations applied). + * Objects that have been cached will return the transformed bounds of the cache. + * + * Not all display objects can calculate their own bounds (ex. Shape). For these objects, you can use + * {{#crossLink "DisplayObject/setBounds"}}{{/crossLink}} so that they are included when calculating Container + * bounds. + * + * To reduce memory impact, the returned Rectangle instance may be reused internally; clone the instance or copy its + * values if you need to retain it. + * + * Container instances calculate aggregate bounds for all children that return bounds via getBounds. + * @method getTransformedBounds + * @return {Rectangle} A Rectangle instance representing the bounds, or null if bounds are not available for this object. + **/ + p.getTransformedBounds = function() { + return this._getBounds(); + }; + + /** + * Allows you to manually specify the bounds of an object that either cannot calculate their own bounds (ex. Shape & + * Text) for future reference, or so the object can be included in Container bounds. Manually set bounds will always + * override calculated bounds. + * + * The bounds should be specified in the object's local (untransformed) coordinates. For example, a Shape instance + * with a 25px radius circle centered at 0,0 would have bounds of (-25, -25, 50, 50). + * @method setBounds + * @param {Number} x The x origin of the bounds. Pass null to remove the manual bounds. + * @param {Number} y The y origin of the bounds. + * @param {Number} width The width of the bounds. + * @param {Number} height The height of the bounds. + **/ + p.setBounds = function(x, y, width, height) { + if (x == null) { this._bounds = x; } + this._bounds = (this._bounds || new createjs.Rectangle()).setValues(x, y, width, height); + }; + + /** + * Returns a clone of this DisplayObject. Some properties that are specific to this instance's current context are + * reverted to their defaults (for example .parent). Caches are not maintained across clones, and some elements + * are copied by reference (masks, individual filter instances, hit area) + * @method clone + * @return {DisplayObject} A clone of the current DisplayObject instance. + **/ + p.clone = function() { + return this._cloneProps(new DisplayObject()); + }; + + /** + * Returns a string representation of this object. + * @method toString + * @return {String} a string representation of the instance. + **/ + p.toString = function() { + return "[DisplayObject (name="+ this.name +")]"; + }; + + +// private methods: + // separated so it can be used more easily in subclasses: + /** + * @method _cloneProps + * @param {DisplayObject} o The DisplayObject instance which will have properties from the current DisplayObject + * instance copied into. + * @return {DisplayObject} o + * @protected + **/ + p._cloneProps = function(o) { + o.alpha = this.alpha; + o.mouseEnabled = this.mouseEnabled; + o.tickEnabled = this.tickEnabled; + o.name = this.name; + o.regX = this.regX; + o.regY = this.regY; + o.rotation = this.rotation; + o.scaleX = this.scaleX; + o.scaleY = this.scaleY; + o.shadow = this.shadow; + o.skewX = this.skewX; + o.skewY = this.skewY; + o.visible = this.visible; + o.x = this.x; + o.y = this.y; + o.compositeOperation = this.compositeOperation; + o.snapToPixel = this.snapToPixel; + o.filters = this.filters==null?null:this.filters.slice(0); + o.mask = this.mask; + o.hitArea = this.hitArea; + o.cursor = this.cursor; + o._bounds = this._bounds; + return o; + }; + + /** + * @method _applyShadow + * @protected + * @param {CanvasRenderingContext2D} ctx + * @param {Shadow} shadow + **/ + p._applyShadow = function(ctx, shadow) { + shadow = shadow || Shadow.identity; + ctx.shadowColor = shadow.color; + ctx.shadowOffsetX = shadow.offsetX; + ctx.shadowOffsetY = shadow.offsetY; + ctx.shadowBlur = shadow.blur; + }; + + + /** + * @method _tick + * @param {Object} evtObj An event object that will be dispatched to all tick listeners. This object is reused between dispatchers to reduce construction & GC costs. + * @protected + **/ + p._tick = function(evtObj) { + // because tick can be really performance sensitive, check for listeners before calling dispatchEvent. + var ls = this._listeners; + if (ls && ls["tick"]) { + // reset & reuse the event object to avoid construction / GC costs: + evtObj.target = null; + evtObj.propagationStopped = evtObj.immediatePropagationStopped = false; + this.dispatchEvent(evtObj); + } + }; + + /** + * @method _testHit + * @protected + * @param {CanvasRenderingContext2D} ctx + * @return {Boolean} + **/ + p._testHit = function(ctx) { + try { + var hit = ctx.getImageData(0, 0, 1, 1).data[3] > 1; + } catch (e) { + if (!DisplayObject.suppressCrossDomainErrors) { + throw "An error has occurred. This is most likely due to security restrictions on reading canvas pixel data with local or cross-domain images."; + } + } + return hit; + }; + + /** + * @method _applyFilters + * @protected + **/ + p._applyFilters = function() { + if (!this.filters || this.filters.length == 0 || !this.cacheCanvas) { return; } + var l = this.filters.length; + var ctx = this.cacheCanvas.getContext("2d"); + var w = this.cacheCanvas.width; + var h = this.cacheCanvas.height; + for (var i=0; i maxX) { maxX = x; } + if ((x = x_a + y_c + tx) < minX) { minX = x; } else if (x > maxX) { maxX = x; } + if ((x = y_c + tx) < minX) { minX = x; } else if (x > maxX) { maxX = x; } + + if ((y = x_b + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; } + if ((y = x_b + y_d + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; } + if ((y = y_d + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; } + + return bounds.setValues(minX, minY, maxX-minX, maxY-minY); + }; + + /** + * Indicates whether the display object has any mouse event listeners or a cursor. + * @method _isMouseOpaque + * @return {Boolean} + * @protected + **/ + p._hasMouseEventListener = function() { + var evts = DisplayObject._MOUSE_EVENTS; + for (var i= 0, l=evts.length; itransform and alpha properties concatenated with their parent + * Container. + * + * For example, a {{#crossLink "Shape"}}{{/crossLink}} with x=100 and alpha=0.5, placed in a Container with x=50 + * and alpha=0.7 will be rendered to the canvas at x=150 and alpha=0.35. + * Containers have some overhead, so you generally shouldn't create a Container to hold a single child. + * + *

Example

+ * + * var container = new createjs.Container(); + * container.addChild(bitmapInstance, shapeInstance); + * container.x = 100; + * + * @class Container + * @extends DisplayObject + * @constructor + **/ + function Container() { + this.DisplayObject_constructor(); + + // public properties: + /** + * The array of children in the display list. You should usually use the child management methods such as + * {{#crossLink "Container/addChild"}}{{/crossLink}}, {{#crossLink "Container/removeChild"}}{{/crossLink}}, + * {{#crossLink "Container/swapChildren"}}{{/crossLink}}, etc, rather than accessing this directly, but it is + * included for advanced uses. + * @property children + * @type Array + * @default null + **/ + this.children = []; + + /** + * Indicates whether the children of this container are independently enabled for mouse/pointer interaction. + * If false, the children will be aggregated under the container - for example, a click on a child shape would + * trigger a click event on the container. + * @property mouseChildren + * @type Boolean + * @default true + **/ + this.mouseChildren = true; + + /** + * If false, the tick will not be propagated to children of this Container. This can provide some performance benefits. + * In addition to preventing the "tick" event from being dispatched, it will also prevent tick related updates + * on some display objects (ex. Sprite & MovieClip frame advancing, DOMElement visibility handling). + * @property tickChildren + * @type Boolean + * @default true + **/ + this.tickChildren = true; + } + var p = createjs.extend(Container, createjs.DisplayObject); + + +// getter / setters: + /** + * Use the {{#crossLink "Container/numChildren:property"}}{{/crossLink}} property instead. + * @method getNumChildren + * @return {Number} + * @deprecated + **/ + p.getNumChildren = function() { + return this.children.length; + }; + + /** + * Returns the number of children in the container. + * @property numChildren + * @type {Number} + * @readonly + **/ + try { + Object.defineProperties(p, { + numChildren: { get: p.getNumChildren } + }); + } catch (e) {} + + +// public methods: + /** + * Constructor alias for backwards compatibility. This method will be removed in future versions. + * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}. + * @method initialize + * @deprecated in favour of `createjs.promote()` + **/ + p.initialize = Container; // TODO: deprecated. + + /** + * Returns true or false indicating whether the display object would be visible if drawn to a canvas. + * This does not account for whether it would be visible within the boundaries of the stage. + * + * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. + * @method isVisible + * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas + **/ + p.isVisible = function() { + var hasContent = this.cacheCanvas || this.children.length; + return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent); + }; + + /** + * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. + * Returns true if the draw was handled (useful for overriding functionality). + * + * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. + * @method draw + * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. + * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. + * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back + * into itself). + **/ + p.draw = function(ctx, ignoreCache) { + if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } + + // this ensures we don't have issues with display list changes that occur during a draw: + var list = this.children.slice(); + for (var i=0,l=list.length; iExample + * + * container.addChild(bitmapInstance); + * + * You can also add multiple children at once: + * + * container.addChild(bitmapInstance, shapeInstance, textInstance); + * + * @method addChild + * @param {DisplayObject} child The display object to add. + * @return {DisplayObject} The child that was added, or the last child if multiple children were added. + **/ + p.addChild = function(child) { + if (child == null) { return child; } + var l = arguments.length; + if (l > 1) { + for (var i=0; iExample + * + * addChildAt(child1, index); + * + * You can also add multiple children, such as: + * + * addChildAt(child1, child2, ..., index); + * + * The index must be between 0 and numChildren. For example, to add myShape under otherShape in the display list, + * you could use: + * + * container.addChildAt(myShape, container.getChildIndex(otherShape)); + * + * This would also bump otherShape's index up by one. Fails silently if the index is out of range. + * + * @method addChildAt + * @param {DisplayObject} child The display object to add. + * @param {Number} index The index to add the child at. + * @return {DisplayObject} Returns the last child that was added, or the last child if multiple children were added. + **/ + p.addChildAt = function(child, index) { + var l = arguments.length; + var indx = arguments[l-1]; // can't use the same name as the index param or it replaces arguments[1] + if (indx < 0 || indx > this.children.length) { return arguments[l-2]; } + if (l > 2) { + for (var i=0; iExample + * + * container.removeChild(child); + * + * You can also remove multiple children: + * + * removeChild(child1, child2, ...); + * + * Returns true if the child (or children) was removed, or false if it was not in the display list. + * @method removeChild + * @param {DisplayObject} child The child to remove. + * @return {Boolean} true if the child (or children) was removed, or false if it was not in the display list. + **/ + p.removeChild = function(child) { + var l = arguments.length; + if (l > 1) { + var good = true; + for (var i=0; iExample + * + * container.removeChildAt(2); + * + * You can also remove multiple children: + * + * container.removeChild(2, 7, ...) + * + * Returns true if the child (or children) was removed, or false if any index was out of range. + * @method removeChildAt + * @param {Number} index The index of the child to remove. + * @return {Boolean} true if the child (or children) was removed, or false if any index was out of range. + **/ + p.removeChildAt = function(index) { + var l = arguments.length; + if (l > 1) { + var a = []; + for (var i=0; i this.children.length-1) { return false; } + var child = this.children[index]; + if (child) { child.parent = null; } + this.children.splice(index, 1); + child.dispatchEvent("removed"); + return true; + }; + + /** + * Removes all children from the display list. + * + *

Example

+ * + * container.removeAllChildren(); + * + * @method removeAllChildren + **/ + p.removeAllChildren = function() { + var kids = this.children; + while (kids.length) { this.removeChildAt(0); } + }; + + /** + * Returns the child at the specified index. + * + *

Example

+ * + * container.getChildAt(2); + * + * @method getChildAt + * @param {Number} index The index of the child to return. + * @return {DisplayObject} The child at the specified index. Returns null if there is no child at the index. + **/ + p.getChildAt = function(index) { + return this.children[index]; + }; + + /** + * Returns the child with the specified name. + * @method getChildByName + * @param {String} name The name of the child to return. + * @return {DisplayObject} The child with the specified name. + **/ + p.getChildByName = function(name) { + var kids = this.children; + for (var i=0,l=kids.length;iExample: Display children with a higher y in front. + * + * var sortFunction = function(obj1, obj2, options) { + * if (obj1.y > obj2.y) { return 1; } + * if (obj1.y < obj2.y) { return -1; } + * return 0; + * } + * container.sortChildren(sortFunction); + * + * @method sortChildren + * @param {Function} sortFunction the function to use to sort the child list. See JavaScript's Array.sort + * window.documentation for details. + **/ + p.sortChildren = function(sortFunction) { + this.children.sort(sortFunction); + }; + + /** + * Returns the index of the specified child in the display list, or -1 if it is not in the display list. + * + *

Example

+ * + * var index = container.getChildIndex(child); + * + * @method getChildIndex + * @param {DisplayObject} child The child to return the index of. + * @return {Number} The index of the specified child. -1 if the child is not found. + **/ + p.getChildIndex = function(child) { + return createjs.indexOf(this.children, child); + }; + + /** + * Swaps the children at the specified indexes. Fails silently if either index is out of range. + * @method swapChildrenAt + * @param {Number} index1 + * @param {Number} index2 + **/ + p.swapChildrenAt = function(index1, index2) { + var kids = this.children; + var o1 = kids[index1]; + var o2 = kids[index2]; + if (!o1 || !o2) { return; } + kids[index1] = o2; + kids[index2] = o1; + }; + + /** + * Swaps the specified children's depth in the display list. Fails silently if either child is not a child of this + * Container. + * @method swapChildren + * @param {DisplayObject} child1 + * @param {DisplayObject} child2 + **/ + p.swapChildren = function(child1, child2) { + var kids = this.children; + var index1,index2; + for (var i=0,l=kids.length;i= l) { return; } + for (var i=0;i 0 at the + * specified position). This ignores the alpha, shadow and compositeOperation of the display object, and all + * transform properties including regX/Y. + * @method hitTest + * @param {Number} x The x position to check in the display object's local coordinates. + * @param {Number} y The y position to check in the display object's local coordinates. + * @return {Boolean} A Boolean indicating whether there is a visible section of a DisplayObject that overlaps the specified + * coordinates. + **/ + p.hitTest = function(x, y) { + // TODO: optimize to use the fast cache check where possible. + return (this.getObjectUnderPoint(x, y) != null); + }; + + /** + * Returns an array of all display objects under the specified coordinates that are in this container's display + * list. This routine ignores any display objects with {{#crossLink "DisplayObject/mouseEnabled:property"}}{{/crossLink}} + * set to `false`. The array will be sorted in order of visual depth, with the top-most display object at index 0. + * This uses shape based hit detection, and can be an expensive operation to run, so it is best to use it carefully. + * For example, if testing for objects under the mouse, test on tick (instead of on {{#crossLink "DisplayObject/mousemove:event"}}{{/crossLink}}), + * and only if the mouse's position has changed. + * + *