/******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var _array_visualization = __webpack_require__(1); var _array_visualization2 = _interopRequireDefault(_array_visualization); var _zoom_control = __webpack_require__(6); var _zoom_control2 = _interopRequireDefault(_zoom_control); var _overlay_control = __webpack_require__(7); var _overlay_control2 = _interopRequireDefault(_overlay_control); var _seismic_control = __webpack_require__(8); var _seismic_control2 = _interopRequireDefault(_seismic_control); var _subarray_display = __webpack_require__(9); var _subarray_display2 = _interopRequireDefault(_subarray_display); var _auto_upload = __webpack_require__(10); var _auto_upload2 = _interopRequireDefault(_auto_upload); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } $(document).ready(function () { (0, _auto_upload2.default)(); var subarrayDisplay = new _subarray_display2.default(); subarrayDisplay.init($('#current_anchors'), $('#needed_anchors'), $('#subarray_weight'), panel_data); var arrayVisualization = new _array_visualization2.default(panel_data, is_dual_tilt, subarrayDisplay, buildings_coordinates); arrayVisualization.init(); new _zoom_control2.default(arrayVisualization).init($('#zoom_control')); new _overlay_control2.default(arrayVisualization).init($('#overlay_control'), $('#legend_container')); new _seismic_control2.default(arrayVisualization, subarrayDisplay).init($('.seismic_anchor_control'), $("#seismic_save")); window.arrayVisualization = arrayVisualization; }); /***/ }), /* 1 */ /***/ (function(module, exports, __webpack_require__) { 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); __webpack_require__(2); var _jquery = __webpack_require__(3); var _jquery2 = _interopRequireDefault(_jquery); var _panel = __webpack_require__(4); var _colors = __webpack_require__(5); var _colors2 = _interopRequireDefault(_colors); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var ArrayVisualization = function () { function ArrayVisualization(panelData, isDualTilt, subarrayDisplay, buildings) { _classCallCheck(this, ArrayVisualization); this.panelData = panelData; this.isDualTilt = isDualTilt; this.subarrayDisplay = subarrayDisplay; this.buildings = buildings; // Default options this.scale = 10; this.panels = []; } _createClass(ArrayVisualization, [{ key: 'init', value: function init() { this.stage = new createjs.Stage("arrayCanvas"); this.container = new createjs.Container(); var background = new createjs.Shape(); background.graphics.beginFill(_colors2.default.canvas_background).drawRect(0, 0, 850, 850); this.stage.addChild(background); this.stage.mouseMoveOutside = true; this.adjustScale(this.buildings); this.drawArray(this.container, this.panelData); this.container.x = 0; this.container.y = 0; this.stage.addChild(this.container); this.drawBuildings(this.buildings, this.scale); this.stage.update(); var lastMove = undefined; var self = this; // Panning this.stage.on("pressmove", function (event) { var x = event.stageX; var y = event.stageY; if (lastMove != undefined) { var deltaX = x - lastMove.x; var deltaY = y - lastMove.y; self.container.x += deltaX; self.container.y += deltaY; self.stage.update(); } lastMove = { x: x, y: y }; }); this.stage.on("pressup", function () { lastMove = undefined; }); } }, { key: 'adjustScale', value: function adjustScale(buildings) { var _ref, _this = this, _ref2; if (!buildings || buildings.length === 0) return; // leave scale as default // we cannot determine canvas size // we are in a test or in a very impossible state // so we better not touch anything if (!this.stage.canvas) return; var all_x = (_ref = []).concat.apply(_ref, _toConsumableArray(buildings)).map(function (building) { return building.x * _this.scale; }); var all_y = (_ref2 = []).concat.apply(_ref2, _toConsumableArray(buildings)).map(function (building) { return building.y * _this.scale; }); var max_x = Math.max.apply(Math, _toConsumableArray(all_x)); var max_y = Math.max.apply(Math, _toConsumableArray(all_y)); var ratio_y = this.stage.canvas.height * 1.0 / max_y; var ratio_x = this.stage.canvas.width * 1.0 / max_x; var MARGIN = 0.05; this.scale = this.scale * Math.min(ratio_y, ratio_x) * (1 - MARGIN); } }, { key: 'drawBuildings', value: function drawBuildings(buildings) { if (!buildings || buildings.length === 0) { console.log("No Buildings!"); return; } if (!this.scale) { console.log("No Scale - don't know how big the buildings should be!"); return; } var line = new createjs.Shape(); var color = createjs.Graphics.getRGB(0x010101, 1); line.graphics.setStrokeStyle(3); for (var i = 0; i < buildings.length; i++) { var building = buildings[i]; var firstPoint = building[0]; var nextPoint = null; line.graphics.beginStroke(color); line.graphics.moveTo(firstPoint.x * this.scale, firstPoint.y * this.scale); for (var j = 1; j < building.length; j++) { nextPoint = building[j]; line.graphics.lineTo(nextPoint.x * this.scale, nextPoint.y * this.scale); line.graphics.moveTo(nextPoint.x * this.scale, nextPoint.y * this.scale); } line.graphics.lineTo(firstPoint.x * this.scale, firstPoint.y * this.scale); line.graphics.endStroke(); } this.container.addChild(line); } }, { key: 'refreshPanels', value: function refreshPanels(panelData) { this.panelData = panelData; for (var i = 0; i < this.panels.length; i++) { this.container.removeChild(this.panels[i]); } this.drawArray(this.container, this.panelData); var selectedPanel = this.selectedPanel; this.selectedPanel = undefined; this.selectPanel(selectedPanel); this.setOverlay(this.overlay); this.subarrayDisplay.didModifyPanels(panelData); this.stage.update(); } }, { key: 'drawArray', value: function drawArray(container, panels) { var _this2 = this; var treatCoordinatesAsCenterpoints = this.buildings && this.buildings.length > 0; var _loop = function _loop(i) { var box = new _panel.Panel(panels[i], _this2.isDualTilt, _this2.scale, treatCoordinatesAsCenterpoints); container.addChild(box); _this2.panels.push(box); box.on("click", function () { _this2.selectPanel(i); }); }; for (var i = 0; i < panels.length; i++) { _loop(i); } } }, { key: 'selectPanel', value: function selectPanel(panelIndex) { var panel = this.panels[panelIndex]; if (this.selectedPanel !== undefined) { var previousPanel = this.panels[this.selectedPanel]; previousPanel.deselect(); } if (this.selectedPanel === panelIndex) { this.selectedPanel = undefined; } else { this.selectedPanel = panelIndex; panel.select(); } this.stage.update(); } }, { key: 'setZoom', value: function setZoom(zoomLevel) { this.container.scaleX = zoomLevel; this.container.scaleY = zoomLevel; this.stage.update(); } }, { key: 'setOverlay', value: function setOverlay(overlay) { this.overlay = overlay; this.panels.forEach(function (panel) { panel.setOverlay(overlay); }); this.stage.update(); } }, { key: 'addSeismicAnchor', value: function addSeismicAnchor() { if (this.selectedPanel !== undefined) { this.panelData[this.selectedPanel].data.seismic_anchors++; this.panels[this.selectedPanel].redrawOverlays(); this.stage.update(); this.subarrayDisplay.didModifyPanels(this.panelData); } } }, { key: 'removeSeismicAnchor', value: function removeSeismicAnchor() { if (this.selectedPanel !== undefined) { var seismicAnchors = this.panelData[this.selectedPanel].data.seismic_anchors; if (seismicAnchors > 0) { this.panelData[this.selectedPanel].data.seismic_anchors--; this.panels[this.selectedPanel].redrawOverlays(); this.stage.update(); this.subarrayDisplay.didModifyPanels(this.panelData); } } } }]); return ArrayVisualization; }(); exports.default = ArrayVisualization; /***/ }), /* 2 */ /***/ (function(module, exports) { "use strict"; /*** IMPORTS FROM imports-loader ***/ (function () { /*! * EaselJS * Visit http://createjs.com/ for documentation, updates and examples. * * Copyright (c) 2010 gskinner.com, inc. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ //############################################################################## // extend.js //############################################################################## this.createjs = this.createjs || {}; /** * @class Utility Methods */ /** * Sets up the prototype chain and constructor property for a new class. * * This should be called right after creating the class constructor. * * function MySubClass() {} * createjs.extend(MySubClass, MySuperClass); * MySubClass.prototype.doSomething = function() { } * * var foo = new MySubClass(); * console.log(foo instanceof MySuperClass); // true * console.log(foo.prototype.constructor === MySubClass); // true * * @method extend * @param {Function} subclass The subclass. * @param {Function} superclass The superclass to extend. * @return {Function} Returns the subclass's new prototype. */ createjs.extend = function (subclass, superclass) { "use strict"; function o() { this.constructor = subclass; } o.prototype = superclass.prototype; return subclass.prototype = new o(); }; //############################################################################## // promote.js //############################################################################## this.createjs = this.createjs || {}; /** * @class Utility Methods */ /** * Promotes any methods on the super class that were overridden, by creating an alias in the format `prefix_methodName`. * It is recommended to use the super class's name as the prefix. * An alias to the super class's constructor is always added in the format `prefix_constructor`. * This allows the subclass to call super class methods without using `function.call`, providing better performance. * * For example, if `MySubClass` extends `MySuperClass`, and both define a `draw` method, then calling `promote(MySubClass, "MySuperClass")` * would add a `MySuperClass_constructor` method to MySubClass and promote the `draw` method on `MySuperClass` to the * prototype of `MySubClass` as `MySuperClass_draw`. * * This should be called after the class's prototype is fully defined. * * function ClassA(name) { * this.name = name; * } * ClassA.prototype.greet = function() { * return "Hello "+this.name; * } * * function ClassB(name, punctuation) { * this.ClassA_constructor(name); * this.punctuation = punctuation; * } * createjs.extend(ClassB, ClassA); * ClassB.prototype.greet = function() { * return this.ClassA_greet()+this.punctuation; * } * createjs.promote(ClassB, "ClassA"); * * var foo = new ClassB("World", "!?!"); * console.log(foo.greet()); // Hello World!?! * * @method promote * @param {Function} subclass The class to promote super class methods on. * @param {String} prefix The prefix to add to the promoted method names. Usually the name of the superclass. * @return {Function} Returns the subclass. */ createjs.promote = function (subclass, prefix) { "use strict"; var subP = subclass.prototype, supP = Object.getPrototypeOf && Object.getPrototypeOf(subP) || subP.__proto__; if (supP) { subP[(prefix += "_") + "constructor"] = supP.constructor; // constructor is not always innumerable for (var n in supP) { if (subP.hasOwnProperty(n) && typeof supP[n] == "function") { subP[prefix + n] = supP[n]; } } } return subclass; }; //############################################################################## // 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; i < l; i++) { if (arr[i] == listener) { if (l == 1) { delete listeners[type]; } // allows for faster checks. else { arr.splice(i, 1); } break; } } }; /** * A shortcut to the removeEventListener method, with the same parameters and return value. This is a companion to the * .on method. * * IMPORTANT: 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; i < l && !eventObj.propagationStopped; i++) { list[i]._dispatchEvent(eventObj, 3); } } return !eventObj.defaultPrevented; }; /** * Indicates whether there is at least one listener for the specified event type. * @method hasEventListener * @param {String} type The string type of the event. * @return {Boolean} Returns true if there is at least one listener for the specified event. **/ p.hasEventListener = function (type) { var listeners = this._listeners, captureListeners = this._captureListeners; return !!(listeners && listeners[type] || captureListeners && captureListeners[type]); }; /** * Indicates whether there is at least one listener for the specified event type on this object or any of its * ancestors (parent, parent's parent, etc). A return value of true indicates that if a bubbling event of the * specified type is dispatched from this object, it will trigger at least one listener. * * This is similar to {{#crossLink "EventDispatcher/hasEventListener"}}{{/crossLink}}, but it searches the entire * event flow for a listener, not just this object. * @method willTrigger * @param {String} type The string type of the event. * @return {Boolean} Returns `true` if there is at least one listener for the specified event. **/ p.willTrigger = function (type) { var o = this; while (o) { if (o.hasEventListener(type)) { return true; } o = o.parent; } return false; }; /** * @method toString * @return {String} a string representation of the instance. **/ p.toString = function () { return "[EventDispatcher]"; }; // private methods: /** * @method _dispatchEvent * @param {Object | String | Event} eventObj * @param {Object} eventPhase * @protected **/ p._dispatchEvent = function (eventObj, eventPhase) { var l, listeners = eventPhase == 1 ? this._captureListeners : this._listeners; if (eventObj && listeners) { var arr = listeners[eventObj.type]; if (!arr || !(l = arr.length)) { return; } try { eventObj.currentTarget = this; } catch (e) {} try { eventObj.eventPhase = eventPhase; } catch (e) {} eventObj.removed = false; arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch for (var i = 0; i < l && !eventObj.immediatePropagationStopped; i++) { var o = arr[i]; if (o.handleEvent) { o.handleEvent(eventObj); } else { o(eventObj); } if (eventObj.removed) { this.off(eventObj.type, o, eventPhase == 1); eventObj.removed = false; } } } }; createjs.EventDispatcher = EventDispatcher; })(); //############################################################################## // Ticker.js //############################################################################## this.createjs = this.createjs || {}; (function () { "use strict"; // constructor: /** * The Ticker provides a centralized tick or heartbeat broadcast at a set interval. Listeners can subscribe to the tick * event to be notified when a set time interval has elapsed. * * Note that the interval that the tick event is called is a target interval, and may be broadcast at a slower interval * when under high CPU load. The Ticker class uses a static interface (ex. `Ticker.framerate = 30;`) and * can not be instantiated. * *

Example

* * 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 < ticks; i++) { ttl += times[i]; } return ttl / ticks; }; /** * Returns the actual frames / ticks per second. * @method getMeasuredFPS * @static * @param {Number} [ticks] The number of previous ticks over which to measure the actual frames / ticks per second. * Defaults to the number of ticks per second. * @return {Number} The actual frames / ticks per second. Depending on performance, this may differ * from the target frames per second. **/ Ticker.getMeasuredFPS = function (ticks) { var times = Ticker._times; if (!times || times.length < 2) { return -1; } // by default, calculate fps for the past ~1 second: ticks = Math.min(times.length - 1, ticks || Ticker.getFPS() | 0); return 1000 / ((times[0] - times[ticks]) / ticks); }; /** * Use the {{#crossLink "Ticker/paused:property"}}{{/crossLink}} property instead. * @method setPaused * @static * @param {Boolean} value * @deprecated **/ Ticker.setPaused = function (value) { // TODO: deprecated. Ticker.paused = value; }; /** * Use the {{#crossLink "Ticker/paused:property"}}{{/crossLink}} property instead. * @method getPaused * @static * @return {Boolean} * @deprecated **/ Ticker.getPaused = function () { // TODO: deprecated. return Ticker.paused; }; /** * Returns the number of milliseconds that have elapsed since Ticker was initialized via {{#crossLink "Ticker/init"}}. * Returns -1 if Ticker has not been initialized. For example, you could use * this in a time synchronized animation to determine the exact amount of time that has elapsed. * @method getTime * @static * @param {Boolean} [runTime=false] If true only time elapsed while Ticker was not paused will be returned. * If false, the value returned will be total time elapsed since the first tick event listener was added. * @return {Number} Number of milliseconds that have elapsed since Ticker was initialized or -1. **/ Ticker.getTime = function (runTime) { return Ticker._startTime ? Ticker._getTime() - (runTime ? Ticker._pausedTime : 0) : -1; }; /** * Similar to the {{#crossLink "Ticker/getTime"}}{{/crossLink}} method, but returns the time on the most recent {{#crossLink "Ticker/tick:event"}}{{/crossLink}} * event object. * @method getEventTime * @static * @param runTime {Boolean} [runTime=false] If true, the runTime property will be returned instead of time. * @returns {number} The time or runTime property from the most recent tick event or -1. */ Ticker.getEventTime = function (runTime) { return Ticker._startTime ? (Ticker._lastTime || Ticker._startTime) - (runTime ? Ticker._pausedTime : 0) : -1; }; /** * Returns the number of ticks that have been broadcast by Ticker. * @method getTicks * @static * @param {Boolean} pauseable Indicates whether to include ticks that would have been broadcast * while Ticker was paused. If true only tick events broadcast while Ticker is not paused will be returned. * If false, tick events that would have been broadcast while Ticker was paused will be included in the return * value. The default value is false. * @return {Number} of ticks that have been broadcast. **/ Ticker.getTicks = function (pauseable) { return Ticker._ticks - (pauseable ? Ticker._pausedTicks : 0); }; // private static methods: /** * @method _handleSynch * @static * @protected **/ Ticker._handleSynch = function () { Ticker._timerId = null; Ticker._setupTick(); // run if enough time has elapsed, with a little bit of flexibility to be early: if (Ticker._getTime() - Ticker._lastTime >= (Ticker._interval - 1) * 0.97) { Ticker._tick(); } }; /** * @method _handleRAF * @static * @protected **/ Ticker._handleRAF = function () { Ticker._timerId = null; Ticker._setupTick(); Ticker._tick(); }; /** * @method _handleTimeout * @static * @protected **/ Ticker._handleTimeout = function () { Ticker._timerId = null; Ticker._setupTick(); Ticker._tick(); }; /** * @method _setupTick * @static * @protected **/ Ticker._setupTick = function () { if (Ticker._timerId != null) { return; } // avoid duplicates var mode = Ticker.timingMode || Ticker.useRAF && Ticker.RAF_SYNCHED; if (mode == Ticker.RAF_SYNCHED || mode == Ticker.RAF) { var f = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame; if (f) { Ticker._timerId = f(mode == Ticker.RAF ? Ticker._handleRAF : Ticker._handleSynch); Ticker._raf = true; return; } } Ticker._raf = false; Ticker._timerId = setTimeout(Ticker._handleTimeout, Ticker._interval); }; /** * @method _tick * @static * @protected **/ Ticker._tick = function () { var paused = Ticker.paused; var time = Ticker._getTime(); var elapsedTime = time - Ticker._lastTime; Ticker._lastTime = time; Ticker._ticks++; if (paused) { Ticker._pausedTicks++; Ticker._pausedTime += elapsedTime; } if (Ticker.hasEventListener("tick")) { var event = new createjs.Event("tick"); var maxDelta = Ticker.maxDelta; event.delta = maxDelta && elapsedTime > maxDelta ? maxDelta : elapsedTime; event.paused = paused; event.time = time; event.runTime = time - Ticker._pausedTime; Ticker.dispatchEvent(event); } Ticker._tickTimes.unshift(Ticker._getTime() - time); while (Ticker._tickTimes.length > 100) { Ticker._tickTimes.pop(); } Ticker._times.unshift(time); while (Ticker._times.length > 100) { Ticker._times.pop(); } }; /** * @method _getTime * @static * @protected **/ var now = window.performance && (performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow); Ticker._getTime = function () { return (now && now.call(performance) || new Date().getTime()) - Ticker._startTime; }; createjs.Ticker = Ticker; })(); //############################################################################## // 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. * * * * 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: * * * * 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. * * *

Cross Origin Issues

* Warning: Images loaded cross-origin will throw cross-origin security errors when interacted with * using: * * 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: * @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: * @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 < l; i++) { var img = data.images[i]; if (typeof img == "string") { var src = img; img = document.createElement("img"); img.src = src; } a.push(img); if (!img.getContext && !img.naturalWidth) { this._loadCount++; this.complete = false; (function (o, src) { img.onload = function () { o._handleImageLoad(src); }; })(this, src); (function (o, src) { img.onerror = function () { o._handleImageError(src); }; })(this, src); } } } // parse frames: if (data.frames == null) {// nothing } else if (Array.isArray(data.frames)) { this._frames = []; a = data.frames; for (i = 0, l = a.length; i < l; i++) { var arr = a[i]; this._frames.push({ image: this._images[arr[4] ? arr[4] : 0], rect: new createjs.Rectangle(arr[0], arr[1], arr[2], arr[3]), regX: arr[5] || 0, regY: arr[6] || 0 }); } } else { o = data.frames; this._frameWidth = o.width; this._frameHeight = o.height; this._regX = o.regX || 0; this._regY = o.regY || 0; this._spacing = o.spacing || 0; this._margin = o.margin || 0; this._numFrames = o.count; if (this._loadCount == 0) { this._calculateFrames(); } } // parse animations: this._animations = []; if ((o = data.animations) != null) { this._data = {}; var name; for (name in o) { var anim = { name: name }; var obj = o[name]; if (typeof obj == "number") { // single frame a = anim.frames = [obj]; } else if (Array.isArray(obj)) { // simple if (obj.length == 1) { anim.frames = [obj[0]]; } else { anim.speed = obj[3]; anim.next = obj[2]; a = anim.frames = []; for (i = obj[0]; i <= obj[1]; i++) { a.push(i); } } } else { // complex anim.speed = obj.speed; anim.next = obj.next; var frames = obj.frames; a = anim.frames = typeof frames == "number" ? [frames] : frames.slice(0); } if (anim.next === true || anim.next === undefined) { anim.next = name; } // loop if (anim.next === false || a.length < 2 && anim.next == name) { anim.next = null; } // stop if (!anim.speed) { anim.speed = 1; } this._animations.push(name); this._data[name] = anim; } } }; /** * @method _handleImageLoad * @protected **/ p._handleImageLoad = function (src) { if (--this._loadCount == 0) { this._calculateFrames(); this.complete = true; this.dispatchEvent("complete"); } }; /** * @method _handleImageError * @protected */ p._handleImageError = function (src) { var errorEvent = new createjs.Event("error"); errorEvent.src = src; this.dispatchEvent(errorEvent); // Complete is still dispatched. if (--this._loadCount == 0) { this.dispatchEvent("complete"); } }; /** * @method _calculateFrames * @protected **/ p._calculateFrames = function () { if (this._frames || this._frameWidth == 0) { return; } this._frames = []; var maxFrames = this._numFrames || 100000; // if we go over this, something is wrong. var frameCount = 0, frameWidth = this._frameWidth, frameHeight = this._frameHeight; var spacing = this._spacing, margin = this._margin; imgLoop: for (var i = 0, imgs = this._images; i < imgs.length; i++) { var img = imgs[i], imgW = img.width, imgH = img.height; var y = margin; while (y <= imgH - margin - frameHeight) { var x = margin; while (x <= imgW - margin - frameWidth) { if (frameCount >= 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() : 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; i < l; i++) { instr[i].exec(ctx, data); } }; /** * Draws only the path described for this Graphics instance, skipping any non-path instructions, including fill and * stroke descriptions. Used for DisplayObject.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 < l; i++) { // the first command is always a beginPath command. if ((instr = instrs[i]).path !== false) { instr.exec(ctx); } } }; // public methods that map directly to context 2D calls: /** * Moves the drawing point to the specified position. A tiny API method "mt" also exists. * @method moveTo * @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 **/ p.moveTo = function (x, y) { return this.append(new G.MoveTo(x, y), true); }; /** * Draws a line from the current drawing point to the specified position, which become the new current drawing * point. Note that you *must* call {{#crossLink "Graphics/moveTo"}}{{/crossLink}} before the first `lineTo()`. * A tiny API method "lt" also exists. * * For detailed information, read the * * 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 < l) { var c = str.charAt(i); var n = base64[c]; var fi = n >> 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 < pl; p++) { var num = base64[str.charAt(i)]; var sign = num >> 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 < l; i++) { instr[i + ll] = active[i]; } if (this._fill) { instr.push(this._fill); } if (this._stroke) { // doesn't need to be re-applied if it hasn't changed. if (this._strokeDash !== this._oldStrokeDash) { this._oldStrokeDash = this._strokeDash; instr.push(this._strokeDash); } if (this._strokeStyle !== this._oldStrokeStyle) { this._oldStrokeStyle = this._strokeStyle; instr.push(this._strokeStyle); } instr.push(this._stroke); } this._dirty = false; } if (commit) { active.length = 0; this._commitIndex = instr.length; } }; /** * @method _setFill * @param fill * @protected **/ p._setFill = function (fill) { this._updateInstructions(true); this.command = this._fill = fill; return this; }; /** * @method _setStroke * @param stroke * @protected **/ p._setStroke = function (stroke) { this._updateInstructions(true); if (this.command = this._stroke = stroke) { stroke.ignoreScale = this._strokeIgnoreScale; } return this; }; // Command Objects: /** * @namespace Graphics */ /** * Graphics command object. See {{#crossLink "Graphics/lineTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. See {{#crossLink "Graphics"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. * @class LineTo * @constructor * @param {Number} x * @param {Number} y **/ /** * @property x * @type Number */ /** * @property y * @type Number */ /** * Execute the Graphics command in the provided Canvas context. * @method exec * @param {CanvasRenderingContext2D} ctx The canvas rendering context */ (G.LineTo = function (x, y) { this.x = x;this.y = y; }).prototype.exec = function (ctx) { ctx.lineTo(this.x, this.y); }; /** * Graphics command object. See {{#crossLink "Graphics/moveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. * @class MoveTo * @constructor * @param {Number} x * @param {Number} y **/ /** * @property x * @type Number */ /** * @property y * @type Number */ /** * @method exec * @param {CanvasRenderingContext2D} ctx */ (G.MoveTo = function (x, y) { this.x = x;this.y = y; }).prototype.exec = function (ctx) { ctx.moveTo(this.x, this.y); }; /** * Graphics command object. See {{#crossLink "Graphics/arcTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. * @class ArcTo * @constructor * @param {Number} x1 * @param {Number} y1 * @param {Number} x2 * @param {Number} y2 * @param {Number} radius **/ /** * @property x1 * @type Number */ /** * @property y1 * @type Number */ /** * @property x2 * @type Number */ /** * @property y2 * @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.ArcTo = function (x1, y1, x2, y2, radius) { this.x1 = x1;this.y1 = y1; this.x2 = x2;this.y2 = y2; this.radius = radius; }).prototype.exec = function (ctx) { ctx.arcTo(this.x1, this.y1, this.x2, this.y2, this.radius); }; /** * Graphics command object. See {{#crossLink "Graphics/arc"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. * @class Arc * @constructor * @param {Number} x * @param {Number} y * @param {Number} radius * @param {Number} startAngle * @param {Number} endAngle * @param {Number} anticlockwise **/ /** * @property x * @type Number */ /** * @property y * @type Number */ /** * @property radius * @type Number */ /** * @property startAngle * @type Number */ /** * @property endAngle * @type Number */ /** * @property anticlockwise * @type Number */ /** * Execute the Graphics command in the provided Canvas context. * @method exec * @param {CanvasRenderingContext2D} ctx The canvas rendering context */ (G.Arc = function (x, y, radius, startAngle, endAngle, anticlockwise) { this.x = x;this.y = y; this.radius = radius; this.startAngle = startAngle;this.endAngle = endAngle; this.anticlockwise = !!anticlockwise; }).prototype.exec = function (ctx) { ctx.arc(this.x, this.y, this.radius, this.startAngle, this.endAngle, this.anticlockwise); }; /** * Graphics command object. See {{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. * @class QuadraticCurveTo * @constructor * @param {Number} cpx * @param {Number} cpy * @param {Number} x * @param {Number} y **/ /** * @property cpx * @type Number */ /** * @property cpy * @type Number */ /** * @property x * @type Number */ /** * @property y * @type Number */ /** * Execute the Graphics command in the provided Canvas context. * @method exec * @param {CanvasRenderingContext2D} ctx The canvas rendering context */ (G.QuadraticCurveTo = function (cpx, cpy, x, y) { this.cpx = cpx;this.cpy = cpy; this.x = x;this.y = y; }).prototype.exec = function (ctx) { ctx.quadraticCurveTo(this.cpx, this.cpy, this.x, this.y); }; /** * Graphics command object. See {{#crossLink "Graphics/bezierCurveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. * @class BezierCurveTo * @constructor * @param {Number} cp1x * @param {Number} cp1y * @param {Number} cp2x * @param {Number} cp2y * @param {Number} x * @param {Number} y **/ /** * @property cp1x * @type Number */ /** * @property cp1y * @type Number */ /** * @property cp2x * @type Number */ /** * @property cp2y * @type Number */ /** * @property x * @type Number */ /** * @property y * @type Number */ /** * Execute the Graphics command in the provided Canvas context. * @method exec * @param {CanvasRenderingContext2D} ctx The canvas rendering context */ (G.BezierCurveTo = function (cp1x, cp1y, cp2x, cp2y, x, y) { this.cp1x = cp1x;this.cp1y = cp1y; this.cp2x = cp2x;this.cp2y = cp2y; this.x = x;this.y = y; }).prototype.exec = function (ctx) { ctx.bezierCurveTo(this.cp1x, this.cp1y, this.cp2x, this.cp2y, this.x, this.y); }; /** * Graphics command object. See {{#crossLink "Graphics/rect"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. * @class Rect * @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.Rect = function (x, y, w, h) { this.x = x;this.y = y; this.w = w;this.h = h; }).prototype.exec = function (ctx) { ctx.rect(this.x, this.y, this.w, this.h); }; /** * Graphics command object. See {{#crossLink "Graphics/closePath"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. * @class ClosePath * @constructor **/ /** * Execute the Graphics command in the provided Canvas context. * @method exec * @param {CanvasRenderingContext2D} ctx The canvas rendering context */ (G.ClosePath = function () {}).prototype.exec = function (ctx) { ctx.closePath(); }; /** * Graphics command object to begin a new path. See {{#crossLink "Graphics"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. * @class BeginPath * @constructor **/ /** * Execute the Graphics command in the provided Canvas context. * @method exec * @param {CanvasRenderingContext2D} ctx The canvas rendering context */ (G.BeginPath = function () {}).prototype.exec = function (ctx) { ctx.beginPath(); }; /** * Graphics command object. See {{#crossLink "Graphics/beginFill"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. * @class Fill * @constructor * @param {Object} style A valid Context2D fillStyle. * @param {Matrix2D} matrix **/ /** * A valid Context2D fillStyle. * @property style * @type Object */ /** * @property matrix * @type Matrix2D */ /** * Execute the Graphics command in the provided Canvas context. * @method exec * @param {CanvasRenderingContext2D} ctx The canvas rendering context */ p = (G.Fill = function (style, matrix) { this.style = style; this.matrix = matrix; }).prototype; p.exec = function (ctx) { if (!this.style) { return; } ctx.fillStyle = this.style; var mtx = this.matrix; if (mtx) { ctx.save();ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty); } ctx.fill(); if (mtx) { ctx.restore(); } }; /** * Creates a linear gradient style and assigns it to {{#crossLink "Fill/style:property"}}{{/crossLink}}. * See {{#crossLink "Graphics/beginLinearGradientFill"}}{{/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 Fill object for chaining or assignment. */ p.linearGradient = function (colors, ratios, x0, y0, x1, y1) { var o = this.style = Graphics._ctx.createLinearGradient(x0, y0, x1, y1); for (var i = 0, l = colors.length; i < l; i++) { o.addColorStop(ratios[i], colors[i]); } o.props = { colors: colors, ratios: ratios, x0: x0, y0: y0, x1: x1, y1: y1, type: "linear" }; return this; }; /** * Creates a radial gradient style and assigns it to {{#crossLink "Fill/style:property"}}{{/crossLink}}. * See {{#crossLink "Graphics/beginRadialGradientFill"}}{{/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 Fill object for chaining or assignment. */ p.radialGradient = function (colors, ratios, x0, y0, r0, x1, y1, r1) { var o = this.style = Graphics._ctx.createRadialGradient(x0, y0, r0, x1, y1, r1); for (var i = 0, l = colors.length; i < l; i++) { o.addColorStop(ratios[i], colors[i]); } o.props = { colors: colors, ratios: ratios, x0: x0, y0: y0, r0: r0, x1: x1, y1: y1, r1: r1, type: "radial" }; return this; }; /** * Creates a bitmap fill style and assigns it to the {{#crossLink "Fill/style:property"}}{{/crossLink}}. * See {{#crossLink "Graphics/beginBitmapFill"}}{{/crossLink}} for more information. * @method bitmap * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image Must be loaded prior to creating a bitmap fill, or the fill will be empty. * @param {String} [repetition] One of: repeat, repeat-x, repeat-y, or no-repeat. * @return {Fill} Returns this Fill object for chaining or assignment. */ p.bitmap = function (image, repetition) { if (image.naturalWidth || image.getContext || image.readyState >= 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 < h ? w : h) / 2; var mTL = 0, mTR = 0, mBR = 0, mBL = 0; var x = this.x, y = this.y, w = this.w, h = this.h; var rTL = this.radiusTL, rTR = this.radiusTR, rBR = this.radiusBR, rBL = this.radiusBL; if (rTL < 0) { rTL *= mTL = -1; } if (rTL > 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; i < sides; i++) { angle += a; if (ps != 1) { ctx.lineTo(x + Math.cos(angle) * radius * ps, y + Math.sin(angle) * radius * ps); } angle += a; ctx.lineTo(x + Math.cos(angle) * radius, y + Math.sin(angle) * radius); } ctx.closePath(); }; // docced above. Graphics.beginCmd = new G.BeginPath(); // so we don't have to instantiate multiple instances. createjs.Graphics = Graphics; })(); //############################################################################## // DisplayObject.js //############################################################################## this.createjs = this.createjs || {}; (function () { "use strict"; // constructor: /** * DisplayObject is an abstract class that should not be constructed directly. Instead construct subclasses such as * {{#crossLink "Container"}}{{/crossLink}}, {{#crossLink "Bitmap"}}{{/crossLink}}, and {{#crossLink "Shape"}}{{/crossLink}}. * DisplayObject is the base class for all display classes in the EaselJS library. It defines the core properties and * methods that are shared between all display objects, such as transformation properties (x, y, scaleX, scaleY, etc), * caching, and mouse handlers. * @class DisplayObject * @extends EventDispatcher * @constructor **/ function DisplayObject() { this.EventDispatcher_constructor(); // public properties: /** * The alpha (transparency) for this display object. 0 is fully transparent, 1 is fully opaque. * @property alpha * @type {Number} * @default 1 **/ this.alpha = 1; /** * If a cache is active, this returns the canvas that holds the cached version of this display object. See {{#crossLink "cache"}}{{/crossLink}} * for more information. * @property cacheCanvas * @type {HTMLCanvasElement | Object} * @default null * @readonly **/ this.cacheCanvas = null; /** * Returns an ID number that uniquely identifies the current cache for this display object. This can be used to * determine if the cache has changed since a previous check. * @property cacheID * @type {Number} * @default 0 */ this.cacheID = 0; /** * Unique ID for this display object. Makes display objects easier for some uses. * @property id * @type {Number} * @default -1 **/ this.id = createjs.UID.get(); /** * Indicates whether to include this object when running mouse interactions. Setting this to `false` for children * of a {{#crossLink "Container"}}{{/crossLink}} will cause events on the Container to not fire when that child is * clicked. Setting this property to `false` does not prevent the {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}} * method from returning the child. * * Note: 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() : 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() : 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 < l; i++) { this.filters[i].applyFilter(ctx, 0, 0, w, h); } }; /** * @method _getFilterBounds * @return {Rectangle} * @protected **/ p._getFilterBounds = function (rect) { var l, filters = this.filters, bounds = this._rectangle.setValues(0, 0, 0, 0); if (!filters || !(l = filters.length)) { return bounds; } for (var i = 0; i < l; i++) { var f = this.filters[i]; f.getBounds && f.getBounds(bounds); } return bounds; }; /** * @method _getBounds * @param {Matrix2D} matrix * @param {Boolean} ignoreTransform If true, does not apply this object's transform. * @return {Rectangle} * @protected **/ p._getBounds = function (matrix, ignoreTransform) { return this._transformBounds(this.getBounds(), matrix, ignoreTransform); }; /** * @method _transformBounds * @param {Rectangle} bounds * @param {Matrix2D} matrix * @param {Boolean} ignoreTransform * @return {Rectangle} * @protected **/ p._transformBounds = function (bounds, matrix, ignoreTransform) { if (!bounds) { return bounds; } var x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height, mtx = this._props.matrix; mtx = ignoreTransform ? mtx.identity() : this.getMatrix(mtx); if (x || y) { mtx.appendTransform(0, 0, 1, 1, 0, 0, 0, -x, -y); } // TODO: simplify this. if (matrix) { mtx.prependMatrix(matrix); } var x_a = width * mtx.a, x_b = width * mtx.b; var y_c = height * mtx.c, y_d = height * mtx.d; var tx = mtx.tx, ty = mtx.ty; var minX = tx, maxX = tx, minY = ty, maxY = ty; if ((x = x_a + tx) < minX) { minX = x; } else if (x > 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; i < l; i++) { if (this.hasEventListener(evts[i])) { return true; } } return !!this.cursor; }; createjs.DisplayObject = createjs.promote(DisplayObject, "EventDispatcher"); })(); //############################################################################## // Container.js //############################################################################## this.createjs = this.createjs || {}; (function () { "use strict"; // constructor: /** * A Container is a nestable display list that allows you to work with compound display elements. For example you could * group arm, leg, torso and head {{#crossLink "Bitmap"}}{{/crossLink}} instances together into a Person Container, and * transform them as a group, while still being able to move the individual parts relative to each other. Children of * containers have their transform 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; i < l; i++) { var child = list[i]; if (!child.isVisible()) { continue; } // draw the child: ctx.save(); child.updateContext(ctx); child.draw(ctx); ctx.restore(); } return true; }; /** * Adds a child to the top of the display list. * *

Example

* * 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; i < l; i++) { this.addChild(arguments[i]); } return arguments[l - 1]; } if (child.parent) { child.parent.removeChild(child); } child.parent = this; this.children.push(child); child.dispatchEvent("added"); return child; }; /** * Adds a child to the display list at the specified index, bumping children at equal or greater indexes up one, and * setting its parent to this Container. * *

Example

* * 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; i < l - 1; i++) { this.addChildAt(arguments[i], indx + i); } return arguments[l - 2]; } if (child.parent) { child.parent.removeChild(child); } child.parent = this; this.children.splice(index, 0, child); child.dispatchEvent("added"); return child; }; /** * Removes the specified child from the display list. Note that it is faster to use removeChildAt() if the index is * already known. * *

Example

* * 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; i < l; i++) { good = good && this.removeChild(arguments[i]); } return good; } return this.removeChildAt(createjs.indexOf(this.children, child)); }; /** * Removes the child at the specified index from the display list, and sets its parent to null. * *

Example

* * 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 < l; i++) { a[i] = arguments[i]; } a.sort(function (a, b) { return b - a; }); var good = true; for (var i = 0; i < l; i++) { good = good && this.removeChildAt(a[i]); } return good; } if (index < 0 || index > 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; i < l; i++) { if (kids[i].name == name) { return kids[i]; } } return null; }; /** * Performs an array sort operation on the child list. * *

Example: 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 * 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; i++) { if (kids[i] == child1) { index1 = i; } if (kids[i] == child2) { index2 = i; } if (index1 != null && index2 != null) { break; } } if (i == l) { return; } // TODO: throw error? kids[index1] = child2; kids[index2] = child1; }; /** * Changes the depth of the specified child. Fails silently if the child is not a child of this container, or the index is out of range. * @param {DisplayObject} child * @param {Number} index * @method setChildIndex **/ p.setChildIndex = function (child, index) { var kids = this.children, l = kids.length; if (child.parent != this || index < 0 || index >= l) { return; } for (var i = 0; i < l; i++) { if (kids[i] == child) { break; } } if (i == l || i == index) { return; } kids.splice(i, 1); kids.splice(index, 0, child); }; /** * Returns true if the specified display object either is this container or is a descendent (child, grandchild, etc) * of this container. * @method contains * @param {DisplayObject} child The DisplayObject to be checked. * @return {Boolean} true if the specified display object either is this container or is a descendent. **/ p.contains = function (child) { while (child) { if (child == this) { return true; } child = child.parent; } return false; }; /** * Tests whether the display object intersects the specified local point (ie. draws a pixel with alpha > 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. * *