1/*! 2* EaselJS 3* Visit http://createjs.com/ for documentation, updates and examples. 4* 5* Copyright (c) 2010 gskinner.com, inc. 6* 7* Permission is hereby granted, free of charge, to any person 8* obtaining a copy of this software and associated documentation 9* files (the "Software"), to deal in the Software without 10* restriction, including without limitation the rights to use, 11* copy, modify, merge, publish, distribute, sublicense, and/or sell 12* copies of the Software, and to permit persons to whom the 13* Software is furnished to do so, subject to the following 14* conditions: 15* 16* The above copyright notice and this permission notice shall be 17* included in all copies or substantial portions of the Software. 18* 19* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26* OTHER DEALINGS IN THE SOFTWARE. 27*/ 28 29 30//############################################################################## 31// extend.js 32//############################################################################## 33 34this.createjs = this.createjs||{}; 35 36/** 37 * @class Utility Methods 38 */ 39 40/** 41 * Sets up the prototype chain and constructor property for a new class. 42 * 43 * This should be called right after creating the class constructor. 44 * 45 * function MySubClass() {} 46 * createjs.extend(MySubClass, MySuperClass); 47 * MySubClass.prototype.doSomething = function() { } 48 * 49 * var foo = new MySubClass(); 50 * console.log(foo instanceof MySuperClass); // true 51 * console.log(foo.prototype.constructor === MySubClass); // true 52 * 53 * @method extend 54 * @param {Function} subclass The subclass. 55 * @param {Function} superclass The superclass to extend. 56 * @return {Function} Returns the subclass's new prototype. 57 */ 58createjs.extend = function(subclass, superclass) { 59 "use strict"; 60 61 function o() { this.constructor = subclass; } 62 o.prototype = superclass.prototype; 63 return (subclass.prototype = new o()); 64}; 65 66//############################################################################## 67// promote.js 68//############################################################################## 69 70this.createjs = this.createjs||{}; 71 72/** 73 * @class Utility Methods 74 */ 75 76/** 77 * Promotes any methods on the super class that were overridden, by creating an alias in the format `prefix_methodName`. 78 * It is recommended to use the super class's name as the prefix. 79 * An alias to the super class's constructor is always added in the format `prefix_constructor`. 80 * This allows the subclass to call super class methods without using `function.call`, providing better performance. 81 * 82 * For example, if `MySubClass` extends `MySuperClass`, and both define a `draw` method, then calling `promote(MySubClass, "MySuperClass")` 83 * would add a `MySuperClass_constructor` method to MySubClass and promote the `draw` method on `MySuperClass` to the 84 * prototype of `MySubClass` as `MySuperClass_draw`. 85 * 86 * This should be called after the class's prototype is fully defined. 87 * 88 * function ClassA(name) { 89 * this.name = name; 90 * } 91 * ClassA.prototype.greet = function() { 92 * return "Hello "+this.name; 93 * } 94 * 95 * function ClassB(name, punctuation) { 96 * this.ClassA_constructor(name); 97 * this.punctuation = punctuation; 98 * } 99 * createjs.extend(ClassB, ClassA); 100 * ClassB.prototype.greet = function() { 101 * return this.ClassA_greet()+this.punctuation; 102 * } 103 * createjs.promote(ClassB, "ClassA"); 104 * 105 * var foo = new ClassB("World", "!?!"); 106 * console.log(foo.greet()); // Hello World!?! 107 * 108 * @method promote 109 * @param {Function} subclass The class to promote super class methods on. 110 * @param {String} prefix The prefix to add to the promoted method names. Usually the name of the superclass. 111 * @return {Function} Returns the subclass. 112 */ 113createjs.promote = function(subclass, prefix) { 114 "use strict"; 115 116 var subP = subclass.prototype, supP = (Object.getPrototypeOf&&Object.getPrototypeOf(subP))||subP.__proto__; 117 if (supP) { 118 subP[(prefix+="_") + "constructor"] = supP.constructor; // constructor is not always innumerable 119 for (var n in supP) { 120 if (subP.hasOwnProperty(n) && (typeof supP[n] == "function")) { subP[prefix + n] = supP[n]; } 121 } 122 } 123 return subclass; 124}; 125 126//############################################################################## 127// indexOf.js 128//############################################################################## 129 130this.createjs = this.createjs||{}; 131 132/** 133 * @class Utility Methods 134 */ 135 136/** 137 * Finds the first occurrence of a specified value searchElement in the passed in array, and returns the index of 138 * that value. Returns -1 if value is not found. 139 * 140 * var i = createjs.indexOf(myArray, myElementToFind); 141 * 142 * @method indexOf 143 * @param {Array} array Array to search for searchElement 144 * @param searchElement Element to find in array.
145 * @return {Number} The first index of searchElement in array. 146 */ 147createjs.indexOf = function (array, searchElement){ 148 "use strict"; 149 150 for (var i = 0,l=array.length; i < l; i++) { 151 if (searchElement === array[i]) { 152 return i; 153 } 154 } 155 return -1; 156}; 157 158//############################################################################## 159// UID.js 160//############################################################################## 161 162this.createjs = this.createjs||{}; 163 164(function() { 165 "use strict"; 166 167 168// constructor: 169 /** 170 * Global utility for generating sequential unique ID numbers. The UID class uses a static interface (ex. <code>UID.get()</code>) 171 * and should not be instantiated. 172 * @class UID 173 * @static 174 **/ 175 function UID() { 176 throw "UID cannot be instantiated"; 177 } 178 179 180// private static properties: 181 /** 182 * @property _nextID 183 * @type Number 184 * @protected 185 **/ 186 UID._nextID = 0; 187 188 189// public static methods: 190 /** 191 * Returns the next unique id. 192 * @method get 193 * @return {Number} The next unique id 194 * @static 195 **/ 196 UID.get = function() { 197 return UID._nextID++; 198 }; 199 200 201 createjs.UID = UID; 202}()); 203 204//############################################################################## 205// deprecate.js 206//############################################################################## 207 208this.createjs = this.createjs||{}; 209 210/** 211 * @class Utility Methods 212 */ 213 214/** 215 * Wraps deprecated methods so they still be used, but throw warnings to developers. 216 * 217 * obj.deprecatedMethod = createjs.deprecate("Old Method Name", obj._fallbackMethod); 218 * 219 * The recommended approach for deprecated properties is: 220 * 221 * try { 222 * Obj ect.defineProperties(object, { 223 * readyOnlyProp: { get: createjs.deprecate("readOnlyProp", function() { return this.alternateProp; }) }, 224 * readWriteProp: { 225 * get: createjs.deprecate("readOnlyProp", function() { return this.alternateProp; }), 226 * set: createjs.deprecate("readOnlyProp", function(val) { this.alternateProp = val; }) 227 * }); 228 * } catch (e) {} 229 * 230 * @method deprecate 231 * @param {Function} [fallbackMethod=null] A method to call when the deprecated method is used. See the example for how 232 * @param {String} [name=null] The name of the method or property to display in the console warning. 233 * to deprecate properties. 234 * @return {Function} If a fallbackMethod is supplied, returns a closure that will call the fallback method after 235 * logging the warning in the console. 236 */ 237createjs.deprecate = function(fallbackMethod, name) { 238 "use strict"; 239 return function() { 240 var msg = "Deprecated property or method '"+name+"'. See docs for info."; 241 console && (console.warn ? console.warn(msg) : console.log(msg)); 242 return fallbackMethod && fallbackMethod.apply(this, arguments); 243 } 244}; 245 246//############################################################################## 247// Event.js 248//############################################################################## 249 250this.createjs = this.createjs||{}; 251 252(function() { 253 "use strict"; 254 255// constructor: 256 /** 257 * Contains properties and methods shared by all events for use with 258 * {{#crossLink "EventDispatcher"}}{{/crossLink}}. 259 * 260 * Note that Event objects are often reused, so you should never 261 * rely on an event object's state outside of the call stack it was received in. 262 * @class Event 263 * @param {String} type The event type. 264 * @param {Boolean} bubbles Indicates whether the event will bubble through the display list. 265 * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled. 266 * @constructor 267 **/ 268 function Event(type, bubbles, cancelable) { 269 270 271 // public properties: 272 /** 273 * The type of event. 274 * @property type
275 * @type String 276 **/ 277 this.type = type; 278 279 /** 280 * The object that generated an event. 281 * @property target 282 * @type Object 283 * @default null 284 * @readonly 285 */ 286 this.target = null; 287 288 /** 289 * The current target that a bubbling event is being dispatched from. For non-bubbling events, this will 290 * always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event 291 * is generated from childObj, then a listener on parentObj would receive the event with 292 * target=childObj (the original target) and currentTarget=parentObj (where the listener was added). 293 * @property currentTarget 294 * @type Object 295 * @default null 296 * @readonly 297 */ 298 this.currentTarget = null; 299 300 /** 301 * For bubbling events, this indicates the current event phase:<OL> 302 * <LI> capture phase: starting from the top parent to the target</LI> 303 * <LI> at target phase: currently being dispatched from the target</LI> 304 * <LI> bubbling phase: from the target to the top parent</LI> 305 * </OL> 306 * @property eventPhase 307 * @type Number 308 * @default 0 309 * @readonly 310 */ 311 this.eventPhase = 0; 312 313 /** 314 * Indicates whether the event will bubble through the display list. 315 * @property bubbles 316 * @type Boolean 317 * @default false 318 * @readonly 319 */ 320 this.bubbles = !!bubbles; 321 322 /** 323 * Indicates whether the default behaviour of this event can be cancelled via 324 * {{#crossLink "Event/preventDefault"}}{{/crossLink}}. This is set via the Event constructor. 325 * @property cancelable 326 * @type Boolean 327 * @default false 328 * @readonly 329 */ 330 this.cancelable = !!cancelable; 331 332 /** 333 * The epoch time at which this event was created. 334 * @property timeStamp 335 * @type Number 336 * @default 0 337 * @readonly 338 */ 339 this.timeStamp = (new Date()).getTime(); 340 341 /** 342 * Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called 343 * on this event. 344 * @property defaultPrevented 345 * @type Boolean 346 * @default false 347 * @readonly 348 */ 349 this.defaultPrevented = false; 350 351 /** 352 * Indicates if {{#crossLink "Event/stopPropagation"}}{{/crossLink}} or 353 * {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called on this event. 354 * @property propagationStopped 355 * @type Boolean 356 * @default false 357 * @readonly 358 */ 359 this.propagationStopped = false; 360 361 /** 362 * Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called 363 * on this event. 364 * @property immediatePropagationStopped 365 * @type Boolean 366 * @default false 367 * @readonly 368 */ 369 this.immediatePropagationStopped = false; 370 371 /** 372 * Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event. 373 * @property removed 374 * @type Boolean 375 * @default false 376 * @readonly 377 */ 378 this.removed = false; 379 } 380 var p = Event.prototype; 381 382// public methods: 383 /** 384 * Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true if the event is cancelable. 385 * Mirrors the DOM level 2 event standard. In general, cancelable events that have `preventDefault()` called will 386 * cancel the default behaviour associated with the event. 387 * @method preventDefault 388 **/ 389 p.preventDefault = function() { 390 this.defaultPrevented = this.cancelable&&true; 391 }; 392 393 /** 394 * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} to true. 395 * Mirrors the DOM event standard. 396 * @method stopPropagation 397 **/ 398 p.stopPropagation = function() { 399 this.propagationStopped = true; 400 }; 401 402 /** 403 * Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} and 404 * {{#crossLink "Event/immediatePropagationStopped"}}{{/crossLink}} to true. 405 * Mirrors the DOM event standard. 406 * @method stopImmediatePropagation 407 **/ 408 p.stopImmediatePropagation = function() {
409 this.immediatePropagationStopped = this.propagationStopped = true; 410 }; 411 412 /** 413 * Causes the active listener to be removed via removeEventListener(); 414 * 415 * myBtn.addEventListener("click", function(evt) { 416 * // do stuff... 417 * evt.remove(); // removes this listener. 418 * }); 419 * 420 * @method remove 421 **/ 422 p.remove = function() { 423 this.removed = true; 424 }; 425 426 /** 427 * Returns a clone of the Event instance. 428 * @method clone 429 * @return {Event} a clone of the Event instance. 430 **/ 431 p.clone = function() { 432 return new Event(this.type, this.bubbles, this.cancelable); 433 }; 434 435 /** 436 * Provides a chainable shortcut method for setting a number of properties on the instance. 437 * 438 * @method set 439 * @param {Object} props A generic object containing properties to copy to the instance. 440 * @return {Event} Returns the instance the method is called on (useful for chaining calls.) 441 * @chainable 442 */ 443 p.set = function(props) { 444 for (var n in props) { this[n] = props[n]; } 445 return this; 446 }; 447 448 /** 449 * Returns a string representation of this object. 450 * @method toString 451 * @return {String} a string representation of the instance. 452 **/ 453 p.toString = function() { 454 return "[Event (type="+this.type+")]"; 455 }; 456 457 createjs.Event = Event; 458}()); 459 460//############################################################################## 461// EventDispatcher.js 462//############################################################################## 463 464this.createjs = this.createjs||{}; 465 466(function() { 467 "use strict"; 468 469 470// constructor: 471 /** 472 * EventDispatcher provides methods for managing queues of event listeners and dispatching events. 473 * 474 * You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the 475 * EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method. 476 * 477 * Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the 478 * DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports 479 * bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent. 480 * 481 * EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier 482 * to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The 483 * {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to 484 * {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}. 485 * 486 * Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}} 487 * method, which can be used to listeners for all events, or listeners for a specific event. The Event object also 488 * includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener. 489 * 490 * <h4>Example</h4> 491 * Add EventDispatcher capabilities to the "MyClass" class. 492 * 493 * EventDispatcher.initialize(MyClass.prototype); 494 * 495 * Add an event (see {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}}). 496 * 497 * instance.addEventListener("eventName", handlerMethod); 498 * function handlerMethod(event) { 499 * console.log(event.target + " Was Clicked"); 500 * } 501 * 502 * <b>Maintaining proper scope</b><br /> 503 * Scope (ie. "this") can be be a challenge with events. Using the {{#crossLink "EventDispatcher/on"}}{{/crossLink}} 504 * method to subscribe to events simplifies this. 505 * 506 * instance.addEventListener("click", function(event) { 507 * console.log(instance == this); // false, scope is ambiguous. 508 * }); 509 * 510 * instance.on("click", function(event) { 511 * console.log(instance == this); // true, "on" uses dispatcher scope by default. 512 * }); 513 * 514 * If you want to use addEventListener instead, you may want to use function.bind() or a similar proxy to manage 515 * scope. 516 * 517 * <b>Browser support</b> 518 * The event model in CreateJS can be used separately from the suite in any project, however the inheritance model 519 * requires modern browsers (IE9+). 520 * 521 * 522 * @class EventDispatcher 523 * @constructor 524 **/ 525 function EventDispatcher() { 526 527 528 // private properties: 529 /** 530 * @protected 531 * @property _listeners 532 * @type Object 533 **/ 534 this._listeners = null; 535 536 /** 537 * @protected 538 * @property _captureListeners 539 * @type Object 540 **/ 541 this._captureListeners = null; 542 } 543 var p = EventDispatcher.prototype; 544 545// static public methods: 546 /** 547 * Static initializer to mix EventDispatcher methods into a target object or prototype. 548 * 549 * EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class 550 * EventDispatcher.initialize(myObject);
550 // add to a specific instance 551 * 552 * @method initialize 553 * @static 554 * @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a 555 * prototype. 556 **/ 557 EventDispatcher.initialize = function(target) { 558 target.addEventListener = p.addEventListener; 559 target.on = p.on; 560 target.removeEventListener = target.off = p.removeEventListener; 561 target.removeAllEventListeners = p.removeAllEventListeners; 562 target.hasEventListener = p.hasEventListener; 563 target.dispatchEvent = p.dispatchEvent; 564 target._dispatchEvent = p._dispatchEvent; 565 target.willTrigger = p.willTrigger; 566 }; 567 568 569// public methods: 570 /** 571 * Adds the specified event listener. Note that adding multiple listeners to the same function will result in 572 * multiple callbacks getting fired. 573 * 574 * <h4>Example</h4> 575 * 576 * displayObject.addEventListener("click", handleClick); 577 * function handleClick(event) { 578 * // Click happened. 579 * } 580 * 581 * @method addEventListener 582 * @param {String} type The string type of the event. 583 * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when 584 * the event is dispatched. 585 * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. 586 * @return {Function | Object} Returns the listener for chaining or assignment. 587 **/ 588 p.addEventListener = function(type, listener, useCapture) { 589 var listeners; 590 if (useCapture) { 591 listeners = this._captureListeners = this._captureListeners||{}; 592 } else { 593 listeners = this._listeners = this._listeners||{}; 594 } 595 var arr = listeners[type]; 596 if (arr) { this.removeEventListener(type, listener, useCapture); } 597 arr = listeners[type]; // remove may have deleted the array 598 if (!arr) { listeners[type] = [listener]; } 599 else { arr.push(listener); } 600 return listener; 601 }; 602 603 /** 604 * A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener 605 * only run once, associate arbitrary data with the listener, and remove the listener. 606 * 607 * This method works by creating an anonymous wrapper function and subscribing it with addEventListener. 608 * The wrapper function is returned for use with `removeEventListener` (or `off`). 609 * 610 * <b>IMPORTANT:</b> To remove a listener added with `on`, you must pass in the returned wrapper function as the listener, or use 611 * {{#crossLink "Event/remove"}}{{/crossLink}}. Likewise, each time you call `on` a NEW wrapper function is subscribed, so multiple calls 612 * to `on` with the same params will create multiple listeners. 613 * 614 * <h4>Example</h4> 615 * 616 * var listener = myBtn.on("click", handleClick, null, false, {count:3}); 617 * function handleClick(evt, data) { 618 * data.count -= 1; 619 * console.log(this == myBtn); // true - scope defaults to the dispatcher 620 * if (data.count == 0) { 621 * alert("clicked 3 times!"); 622 * myBtn.off("click", listener); 623 * // alternately: evt.remove(); 624 * } 625 * } 626 * 627 * @method on 628 * @param {String} type The string type of the event. 629 * @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when 630 * the event is dispatched. 631 * @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). 632 * @param {Boolean} [once=false] If true, the listener will remove itself after the first time it is triggered. 633 * @param {*} [data] Arbitrary data that will be included as the second parameter when the listener is called. 634 * @param {Boolean} [useCapture=false] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. 635 * @return {Function} Returns the anonymous function that was created and assigned as the listener. This is needed to remove the listener later using .removeEventListener. 636 **/ 637 p.on = function(type, listener, scope, once, data, useCapture) { 638 if (listener.handleEvent) { 639 scope = scope||listener; 640 listener = listener.handleEvent; 641 } 642 scope = scope||this; 643 return this.addEventListener(type, function(evt) { 644 listener.call(scope, evt, data); 645 once&&evt.remove(); 646 }, useCapture); 647 }; 648 649 /** 650 * Removes the specified event listener. 651 * 652 * <b>Important Note:</b> that you must pass the exact function reference used when the event was added. If a proxy 653 * function, or function closure is used as the callback, the proxy/closure reference must be used - a new proxy or 654 * closure will not work. 655 * 656 * <h4>Example</h4> 657 * 658 * displayObject.removeEventListener("click", handleClick); 659 * 660 * @method removeEventListener 661 * @param {String} type The string type of the event. 662 * @param {Function | Object} listener The listener function or object. 663 * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. 664 **/ 665 p.removeEventListener = function(type, listener, useCapture) { 666 var listeners = useCapture ? this._captureListeners : this._listeners; 667 if (!listeners) { return; } 668 var arr = listeners[type]; 669 if (!arr) { return; } 670 for (var i=0,l=arr.length; i<l; i++) { 671 if (arr[i] == listener) { 672 if (l==1) { delete(listeners[type]); } // allows for faster checks. 673 else { arr.splice(i,1); } 674 break; 675 } 676 } 677 }; 678 679 /** 680 * A shortcut to the removeEventListener method, with the same parameters and return value. This is a companion to the 681 * .on method. 682 * 683 * <b>IMPORTANT:</b> To remove a listener added with `on`, you must pass in the returned wrapper function as the listener. See 684 * {{#crossLink "EventDispatcher/on"}}{{/crossLink}} for an example. 685 * 686 * @method off 687 * @param {String} type The string type of the event. 688 * @param {Function | Object} listener The listener function or object. 689 * @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase. 690 **/ 691 p.off = p.removeEventListener; 692 693 /** 694 * Removes all listeners for the specified type, or all listeners of all types. 695 * 696 * <h4>Example</h4> 697 * 698 * // Remove all listeners 699 * displayObject.removeAllEventListeners(); 700 * 701 * // Remove all click listeners 702 * displayObject.removeAllEventListeners("click"); 703 * 704 * @method removeAllEventListeners 705 * @param {String} [type] The string type of the event. If omitted, all listeners for all types will be removed. 706 **/ 707 p.removeAllEventListeners = function(type) { 708 if (!type) { this._listeners = this._captureListeners = null; } 709 else { 710 if (this._listeners) { delete(this._listeners[type]); } 711 if (this._captureListeners) { delete(this._captureListeners[type]); } 712 } 713 }; 714 715 /**
716 * Dispatches the specified event to all listeners. 717 * 718 * <h4>Example</h4> 719 * 720 * // Use a string event 721 * this.dispatchEvent("complete"); 722 * 723 * // Use an Event instance 724 * var event = new createjs.Event("progress"); 725 * this.dispatchEvent(event); 726 * 727 * @method dispatchEvent 728 * @param {Object | String | Event} eventObj An object with a "type" property, or a string type. 729 * While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used, 730 * dispatchEvent will construct an Event instance if necessary with the specified type. This latter approach can 731 * be used to avoid event object instantiation for non-bubbling events that may not have any listeners. 732 * @param {Boolean} [bubbles] Specifies the `bubbles` value when a string was passed to eventObj. 733 * @param {Boolean} [cancelable] Specifies the `cancelable` value when a string was passed to eventObj. 734 * @return {Boolean} Returns false if `preventDefault()` was called on a cancelable event, true otherwise. 735 **/ 736 p.dispatchEvent = function(eventObj, bubbles, cancelable) { 737 if (typeof eventObj == "string") { 738 // skip everything if there's no listeners and it doesn't bubble: 739 var listeners = this._listeners; 740 if (!bubbles && (!listeners || !listeners[eventObj])) { return true; } 741 eventObj = new createjs.Event(eventObj, bubbles, cancelable); 742 } else if (eventObj.target && eventObj.clone) { 743 // redispatching an active event object, so clone it: 744 eventObj = eventObj.clone(); 745 } 746 747 // TODO: it would be nice to eliminate this. Maybe in favour of evtObj instanceof Event? Or !!evtObj.createEvent 748 try { eventObj.target = this; } catch (e) {} // try/catch allows redispatching of native events 749 750 if (!eventObj.bubbles || !this.parent) { 751 this._dispatchEvent(eventObj, 2); 752 } else { 753 var top=this, list=[top]; 754 while (top.parent) { list.push(top = top.parent); } 755 var i, l=list.length; 756 757 // capture & atTarget 758 for (i=l-1; i>=0 && !eventObj.propagationStopped; i--) { 759 list[i]._dispatchEvent(eventObj, 1+(i==0)); 760 } 761 // bubbling 762 for (i=1; i<l && !eventObj.propagationStopped; i++) { 763 list[i]._dispatchEvent(eventObj, 3); 764 } 765 } 766 return !eventObj.defaultPrevented; 767 }; 768 769 /** 770 * Indicates whether there is at least one listener for the specified event type. 771 * @method hasEventListener 772 * @param {String} type The string type of the event. 773 * @return {Boolean} Returns true if there is at least one listener for the specified event. 774 **/ 775 p.hasEventListener = function(type) { 776 var listeners = this._listeners, captureListeners = this._captureListeners; 777 return !!((listeners && listeners[type]) || (captureListeners && captureListeners[type])); 778 }; 779 780 /** 781 * Indicates whether there is at least one listener for the specified event type on this object or any of its 782 * ancestors (parent, parent's parent, etc). A return value of true indicates that if a bubbling event of the 783 * specified type is dispatched from this object, it will trigger at least one listener. 784 * 785 * This is similar to {{#crossLink "EventDispatcher/hasEventListener"}}{{/crossLink}}, but it searches the entire 786 * event flow for a listener, not just this object. 787 * @method willTrigger 788 * @param {String} type The string type of the event. 789 * @return {Boolean} Returns `true` if there is at least one listener for the specified event. 790 **/ 791 p.willTrigger = function(type) { 792 var o = this; 793 while (o) { 794 if (o.hasEventListener(type)) { return true; } 795 o = o.parent; 796 } 797 return false; 798 }; 799 800 /** 801 * @method toString 802 * @return {String} a string representation of the instance. 803 **/ 804 p.toString = function() { 805 return "[EventDispatcher]"; 806 }; 807 808 809// private methods: 810 /** 811 * @method _dispatchEvent 812 * @param {Object | Event} eventObj 813 * @param {Object} eventPhase 814 * @protected 815 **/ 816 p._dispatchEvent = function(eventObj, eventPhase) { 817 var l, arr, listeners = (eventPhase <= 2) ? this._captureListeners : this._listeners; 818 if (eventObj && listeners && (arr = listeners[eventObj.type]) && (l=
818arr.length)) { 819 try { eventObj.currentTarget = this; } catch (e) {} 820 try { eventObj.eventPhase = eventPhase|0; } catch (e) {} 821 eventObj.removed = false; 822 823 arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch 824 for (var i=0; i<l && !eventObj.immediatePropagationStopped; i++) { 825 var o = arr[i]; 826 if (o.handleEvent) { o.handleEvent(eventObj); } 827 else { o(eventObj); } 828 if (eventObj.removed) { 829 this.off(eventObj.type, o, eventPhase==1); 830 eventObj.removed = false; 831 } 832 } 833 } 834 if (eventPhase === 2) { this._dispatchEvent(eventObj, 2.1); } 835 }; 836 837 838 createjs.EventDispatcher = EventDispatcher; 839}()); 840 841//############################################################################## 842// Ticker.js 843//############################################################################## 844 845this.createjs = this.createjs||{}; 846 847(function() { 848 "use strict"; 849 850 851// constructor: 852 /** 853 * The Ticker provides a centralized tick or heartbeat broadcast at a set interval. Listeners can subscribe to the tick 854 * event to be notified when a set time interval has elapsed. 855 * 856 * Note that the interval that the tick event is called is a target interval, and may be broadcast at a slower interval 857 * when under high CPU load. The Ticker class uses a static interface (ex. `Ticker.framerate = 30;`) and 858 * can not be instantiated. 859 * 860 * <h4>Example</h4> 861 * 862 * createjs.Ticker.addEventListener("tick", handleTick); 863 * function handleTick(event) { 864 * // Actions carried out each tick (aka frame) 865 * if (!event.paused) { 866 * // Actions carried out when the Ticker is not paused. 867 * } 868 * } 869 * 870 * @class Ticker 871 * @uses EventDispatcher 872 * @static 873 **/ 874 function Ticker() { 875 throw "Ticker cannot be instantiated."; 876 } 877 878 879// constants: 880 /** 881 * In this mode, Ticker uses the requestAnimationFrame API, but attempts to synch the ticks to target framerate. It 882 * uses a simple heuristic that compares the time of the RAF return to the target time for the current frame and 883 * dispatches the tick when the time is within a certain threshold. 884 * 885 * This mode has a higher variance for time between frames than {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}}, 886 * but does not require that content be time based as with {{#crossLink "Ticker/RAF:property"}}{{/crossLink}} while 887 * gaining the benefits of that API (screen synch, background throttling). 888 * 889 * Variance is usually lowest for framerates that are a divisor of the RAF frequency. This is usually 60, so 890 * framerates of 10, 12, 15, 20, and 30 work well. 891 * 892 * Falls back to {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}} if the requestAnimationFrame API is not 893 * supported. 894 * @property RAF_SYNCHED 895 * @static 896 * @type {String} 897 * @default "synched" 898 * @readonly 899 **/ 900 Ticker.RAF_SYNCHED = "synched"; 901 902 /** 903 * In this mode, Ticker passes through the requestAnimationFrame heartbeat, ignoring the target framerate completely. 904 * Because requestAnimationFrame frequency is not deterministic, any content using this mode should be time based. 905 * You can leverage {{#crossLink "Ticker/getTime"}}{{/crossLink}} and the {{#crossLink "Ticker/tick:event"}}{{/crossLink}} 906 * event object's "delta" properties to make this easier. 907 * 908 * Falls back on {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}} if the requestAnimationFrame API is not 909 * supported. 910 * @property RAF 911 * @static 912 * @type {String} 913 * @default "raf" 914 * @readonly 915 **/ 916 Ticker.RAF = "raf"; 917 918 /** 919 * In this mode, Ticker uses the setTimeout API. This provides predictable, adaptive frame timing, but does not 920 * provide the benefits of requestAnimationFrame (screen synch, background throttling). 921 * @property TIMEOUT 922 * @static 923 * @type {String} 924 * @default "timeout" 925 * @readonly 926 **/ 927 Ticker.TIMEOUT = "timeout"; 928 929 930// static events: 931 /**
932 * Dispatched each tick. The event will be dispatched to each listener even when the Ticker has been paused using 933 * {{#crossLink "Ticker/paused:property"}}{{/crossLink}}. 934 * 935 * <h4>Example</h4> 936 * 937 * createjs.Ticker.addEventListener("tick", handleTick); 938 * function handleTick(event) { 939 * console.log("Paused:", event.paused, event.delta); 940 * } 941 * 942 * @event tick 943 * @param {Object} target The object that dispatched the event. 944 * @param {String} type The event type. 945 * @param {Boolean} paused Indicates whether the ticker is currently paused. 946 * @param {Number} delta The time elapsed in ms since the last tick. 947 * @param {Number} time The total time in ms since Ticker was initialized. 948 * @param {Number} runTime The total time in ms that Ticker was not paused since it was initialized. For example, 949 * you could determine the amount of time that the Ticker has been paused since initialization with `time-runTime`. 950 * @since 0.6.0 951 */ 952 953 954// public static properties: 955 /** 956 * Specifies the timing api (setTimeout or requestAnimationFrame) and mode to use. See 957 * {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}}, {{#crossLink "Ticker/RAF:property"}}{{/crossLink}}, and 958 * {{#crossLink "Ticker/RAF_SYNCHED:property"}}{{/crossLink}} for mode details. 959 * @property timingMode 960 * @static 961 * @type {String} 962 * @default Ticker.TIMEOUT 963 **/ 964 Ticker.timingMode = null; 965 966 /** 967 * Specifies a maximum value for the delta property in the tick event object. This is useful when building time 968 * based animations and systems to prevent issues caused by large time gaps caused by background tabs, system sleep, 969 * alert dialogs, or other blocking routines. Double the expected frame duration is often an effective value 970 * (ex. maxDelta=50 when running at 40fps). 971 * 972 * This does not impact any other values (ex. time, runTime, etc), so you may experience issues if you enable maxDelta 973 * when using both delta and other values. 974 * 975 * If 0, there is no maximum. 976 * @property maxDelta 977 * @static 978 * @type {number} 979 * @default 0 980 */ 981 Ticker.maxDelta = 0; 982 983 /** 984 * When the ticker is paused, all listeners will still receive a tick event, but the <code>paused</code> property 985 * of the event will be `true`. Also, while paused the `runTime` will not increase. See {{#crossLink "Ticker/tick:event"}}{{/crossLink}}, 986 * {{#crossLink "Ticker/getTime"}}{{/crossLink}}, and {{#crossLink "Ticker/getEventTime"}}{{/crossLink}} for more 987 * info. 988 * 989 * <h4>Example</h4> 990 * 991 * createjs.Ticker.addEventListener("tick", handleTick); 992 * createjs.Ticker.paused = true; 993 * function handleTick(event) { 994 * console.log(event.paused, 995 * createjs.Ticker.getTime(false), 996 * createjs.Ticker.getTime(true)); 997 * } 998 * 999 * @property paused 1000 * @static 1001 * @type {Boolean} 1002 * @default false 1003 **/ 1004 Ticker.paused = false; 1005 1006 1007// mix-ins: 1008 // EventDispatcher methods: 1009 Ticker.removeEventListener = null; 1010 Ticker.removeAllEventListeners = null; 1011 Ticker.dispatchEvent = null; 1012 Ticker.hasEventListener = null; 1013 Ticker._listeners = null; 1014 createjs.EventDispatcher.initialize(Ticker); // inject EventDispatcher methods. 1015 Ticker._addEventListener = Ticker.addEventListener; 1016 Ticker.addEventListener = function() { 1017 !Ticker._inited&&Ticker.init(); 1018 return Ticker._addEventListener.apply(Ticker, arguments); 1019 }; 1020 1021 1022// private static properties: 1023 /** 1024 * @property _inited 1025 * @static 1026 * @type {Boolean} 1027 * @private 1028 **/ 1029 Ticker._inited = false; 1030 1031 /** 1032 * @property _startTime 1033 * @static 1034 * @type {Number} 1035 * @private 1036 **/ 1037 Ticker._startTime = 0; 1038 1039 /** 1040 * @property _pausedTime 1041 * @static 1042 * @type {Number} 1043 * @private 1044 **/ 1045 Ticker._pausedTime=0; 1046 1047 /** 1048 * The number of ticks that have passed 1049 * @property _ticks 1050 * @static 1051 * @type {Number} 1052 * @private 1053 **/ 1054 Ticker._ticks = 0; 1055 1056 /** 1057 * The number of ticks that have passed while Ticker has been paused 1058 * @property _pausedTicks 1059 * @static 1060 * @type {Number} 1061 * @private 1062 **/ 1063 Ticker._pausedTicks = 0; 1064 1065 /** 1066 * @property _interval 1067 * @static 1068 * @type {Number} 1069 * @private 1070 **/ 1071 Ticker._interval = 50; 1072 1073 /** 1074 * @property _lastTime 1075 * @static 1076 * @type {Number} 1077 * @private 1078 **/ 1079 Ticker._lastTime = 0; 1080 1081 /** 1082 * @property _times 1083 * @static 1084 * @type {Array} 1085 * @private 1086 **/ 1087 Ticker._times = null; 1088 1089 /** 1090 * @property _tickTimes 1091 * @static 1092 * @type {Array} 1093 * @private 1094 **/ 1095 Ticker._tickTimes = null; 1096 1097 /** 1098 * Stores the timeout or requestAnimationFrame id. 1099 * @property _timerId 1100 * @static 1101 * @type {Number} 1102 * @private 1103 **/ 1104 Ticker._timerId = null; 1105 1106 /** 1107 * True if currently using requestAnimationFrame, false if using setTimeout. This may be different than timingMode 1108 * if that property changed and a tick hasn't fired. 1109 * @property _raf 1110 * @static 1111 * @type {Boolean} 1112 * @private 1113 **/ 1114 Ticker._raf = true; 1115 1116 1117// static getter / setters: 1118 /** 1119 * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead. 1120 * @method _setInterval 1121 * @private 1122 * @static 1123 * @param {Number} interval 1124 **/ 1125 Ticker._setInterval = function(interval) { 1126 Ticker._interval = interval; 1127 if (!Ticker._inited) { return; } 1128 Ticker._setupTick(); 1129 }; 1130 // Ticker.setInterval is @deprecated. Remove for 1.1+ 1131 Ticker.setInterval = createjs.deprecate(Ticker._setInterval, "Ticker.setInterval"); 1132 1133 /** 1134 * Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead. 1135 * @method _getInterval 1136 * @private 1137 * @static 1138 * @return {Number} 1139 **/ 1140 Ticker._getInterval = function() { 1141 return Ticker._interval; 1142 }; 1143 // Ticker.getInterval is @deprecated. Remove for 1.1+ 1144 Ticker.getInterval = createjs.deprecate(Ticker._getInterval, "Ticker.getInterval"); 1145 1146 /** 1147 * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead. 1148 * @method _setFPS 1149 * @private 1150 * @static 1151 * @param {Number} value 1152 **/ 1153 Ticker._setFPS = function(value) { 1154 Ticker._setInterval(1000/value); 1155 }; 1156 // Ticker.setFPS is @deprecated. Remove for 1.1+ 1157 Ticker.setFPS = createjs.deprecate(Ticker._setFPS, "Ticker.setFPS"); 1158 1159 /** 1160 * Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead. 1161 * @method _getFPS 1162 * @static 1163 * @private 1164 * @return {Number} 1165 **/ 1166 Ticker._getFPS = function() { 1167 return 1000/Ticker._interval; 1168 }; 1169 // Ticker.getFPS is @deprecated. Remove for 1.1+ 1170 Ticker.getFPS = createjs.deprecate(Ticker._getFPS, "Ticker.getFPS"); 1171 1172 /** 1173 * Indicates the target time (in milliseconds) between ticks. Default is 50 (20 FPS). 1174 * Note that actual time between ticks may be more than specified depending on CPU load. 1175 * This property is ignored if the ticker is using the `RAF` timing mode. 1176 * @property interval 1177 * @static 1178 * @type {Number} 1179 **/ 1180 1181 /** 1182 * Indicates the target frame rate in frames per second (FPS). Effe
1182ctively just a shortcut to `interval`, where 1183 * `framerate == 1000/interval`. 1184 * @property framerate 1185 * @static 1186 * @type {Number} 1187 **/ 1188 try { 1189 Object.defineProperties(Ticker, { 1190 interval: { get: Ticker._getInterval, set: Ticker._setInterval }, 1191 framerate: { get: Ticker._getFPS, set: Ticker._setFPS } 1192 }); 1193 } catch (e) { console.log(e); } 1194 1195 1196// public static methods: 1197 /** 1198 * Starts the tick. This is called automatically when the first listener is added. 1199 * @method init 1200 * @static 1201 **/ 1202 Ticker.init = function() { 1203 if (Ticker._inited) { return; } 1204 Ticker._inited = true; 1205 Ticker._times = []; 1206 Ticker._tickTimes = []; 1207 Ticker._startTime = Ticker._getTime(); 1208 Ticker._times.push(Ticker._lastTime = 0); 1209 Ticker.interval = Ticker._interval; 1210 }; 1211 1212 /** 1213 * Stops the Ticker and removes all listeners. Use init() to restart the Ticker. 1214 * @method reset 1215 * @static 1216 **/ 1217 Ticker.reset = function() { 1218 if (Ticker._raf) { 1219 var f = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame; 1220 f&&f(Ticker._timerId); 1221 } else { 1222 clearTimeout(Ticker._timerId); 1223 } 1224 Ticker.removeAllEventListeners("tick"); 1225 Ticker._timerId = Ticker._times = Ticker._tickTimes = null; 1226 Ticker._startTime = Ticker._lastTime = Ticker._ticks = Ticker._pausedTime = 0; 1227 Ticker._inited = false; 1228 }; 1229 1230 /** 1231 * Returns the average time spent within a tick. This can vary significantly from the value provided by getMeasuredFPS 1232 * because it only measures the time spent within the tick execution stack. 1233 * 1234 * Example 1: With a target FPS of 20, getMeasuredFPS() returns 20fps, which indicates an average of 50ms between 1235 * the end of one tick and the end of the next. However, getMeasuredTickTime() returns 15ms. This indicates that 1236 * there may be up to 35ms of "idle" time between the end of one tick and the start of the next. 1237 * 1238 * Example 2: With a target FPS of 30, {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} returns 10fps, which 1239 * indicates an average of 100ms between the end of one tick and the end of the next. However, {{#crossLink "Ticker/getMeasuredTickTime"}}{{/crossLink}} 1240 * returns 20ms. This would indicate that something other than the tick is using ~80ms (another script, DOM 1241 * rendering, etc). 1242 * @method getMeasuredTickTime 1243 * @static 1244 * @param {Number} [ticks] The number of previous ticks over which to measure the average time spent in a tick. 1245 * Defaults to the number of ticks per second. To get only the last tick's time, pass in 1. 1246 * @return {Number} The average time spent in a tick in milliseconds. 1247 **/ 1248 Ticker.getMeasuredTickTime = function(ticks) { 1249 var ttl=0, times=Ticker._tickTimes; 1250 if (!times || times.length < 1) { return -1; } 1251 1252 // by default, calculate average for the past ~1 second: 1253 ticks = Math.min(times.length, ticks||(Ticker._getFPS()|0)); 1254 for (var i=0; i<ticks; i++) { ttl += times[i]; } 1255 return ttl/ticks; 1256 }; 1257 1258 /** 1259 * Returns the actual frames / ticks per second. 1260 * @method getMeasuredFPS 1261 * @static 1262 * @param {Number} [ticks] The number of previous ticks over which to measure the actual frames / ticks per second. 1263 * Defaults to the number of ticks per second. 1264 * @return {Number} The actual frames / ticks per second. Depending on performance, this may differ 1265 * from the target frames per second. 1266 **/ 1267 Ticker.getMeasuredFPS = function(ticks) { 1268 var times = Ticker._times; 1269 if (!times || times.length < 2) { return -1; } 1270 1271 // by default, calculate fps for the past ~1 second: 1272 ticks = Math.min(times.length-1, ticks||(Ticker._getFPS()|0)); 1273 return 1000/((times[0]-times[ticks])/ticks); 1274 }; 1275 1276 /** 1277 * Returns the number of milliseconds that have elapsed since Ticker was initialized via {{#crossLink "Ticker/init"}}. 1278 * Returns -1 if Ticker has not been initialized. For example, you could use 1279 * this in a time synchronized animation to determine the exact amount of time that has elapsed. 1280 * @method getTime 1281 * @static 1282 * @param {Boolean} [runTime=false] If true only time elapsed while Ticker was not paused will be returned. 1283 * If false, the value returned will be total time elapsed since the first tick event listener was added. 1284 * @return {Number} Number of milliseconds that have elapsed since Ticker was initialized or -1. 1285 **/ 1286 Ticker.getTime = function(runTime) { 1287 return Ticker._startTime ? Ticker._getTime() - (runTime ? Ticker._pausedTime : 0) : -1; 1288 }; 1289 1290 /** 1291 * Similar to the {{#crossLink "Ticker/getTime"}}{{/crossLink}} method, but returns the time on the most recent {{#crossLink "Ticker/tick:event"}}{{/crossLink}} 1292 * event object. 1293 * @method getEventTime 1294 * @static 1295 * @param runTime {Boolean} [runTime=false] If true, the runTime property will be returned instead of time. 1296 * @returns {number} The time or runTime property from the most recent tick event or -1. 1297 */ 1298 Ticker.getEventTime = function(runTime) { 1299 return Ticker._startTime ? (Ticker._lastTime || Ticker._startTime) - (runTime ? Ticker._pausedTime : 0) : -1; 1300 }; 1301 1302 /** 1303 * Returns the number of ticks that have been broadcast by Ticker. 1304 * @method getTicks 1305 * @static 1306 * @param {Boolean} pauseable Indicates whether to include ticks that would have been broadcast 1307 * while Ticker was paused. If true only tick events broadcast while Ticker is not paused will be returned. 1308 * If false, tick events that would have been broadcast while Ticker was paused will be included in the return 1309 * value. The default value is false. 1310 * @return {Number} of ticks that have been broadcast. 1311 **/ 1312 Ticker.getTicks = function(pauseable) { 1313 return Ticker._ticks - (pauseable ? Ticker._pausedTicks : 0); 1314 }; 1315 1316 1317// private static methods: 1318 /** 1319 * @method _handleSynch 1320 * @static 1321 * @private 1322 **/ 1323 Ticker._handleSynch = function() { 1324 Ticker._timerId = null; 1325 Ticker._setupTick(); 1326 1327 // run if enough time has elapsed, with a little bit of flexibility to be early: 1328 if (Ticker._getTime() - Ticker._lastTime >= (Ticker._interval-1)*0.97) { 1329 Ticker._tick(); 1330 } 1331 }; 1332 1333 /** 1334 * @method _handleRAF 1335 * @static 1336 * @private 1337 **/ 1338 Ticker._handleRAF = function() { 1339 Ticker._timerId = null; 1340 Ticker._setupTick(); 1341 Ticker._tick(); 1342 }; 1343 1344 /** 1345 * @method _handleTimeout 1346 * @static 1347 * @private 1348 **/ 1349 Ticker._handleTimeout = function() { 1350 Ticker._timerId = null; 1351 Ticker._setupTick(); 1352 Ticker._tick(); 1353 }; 1354 1355 /** 1356 * @method _setupTick 1357 * @static 1358 * @private 1359 **/ 1360 Ticker._setupTick = function() { 1361 if (Ticker._timerId != null) { return; } // avoid duplicates 1362 1363 var mode = Ticker.timingMode; 1364 if (mode == Ticker.RAF_SYNCHED || mode == Ticker.RAF) { 1365 var f = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame; 1366 if (f) { 1367 Ticker._timerId = f(mode == Ticker.RAF ? Ticker._handleRAF : Ticker._handleSynch); 1368 Ticker._raf = true; 1369 return; 1370 } 1371 } 1372 Ticker._raf = false;
1373 Ticker._timerId = setTimeout(Ticker._handleTimeout, Ticker._interval); 1374 }; 1375 1376 /** 1377 * @method _tick 1378 * @static 1379 * @private 1380 **/ 1381 Ticker._tick = function() { 1382 var paused = Ticker.paused; 1383 var time = Ticker._getTime(); 1384 var elapsedTime = time-Ticker._lastTime; 1385 Ticker._lastTime = time; 1386 Ticker._ticks++; 1387 1388 if (paused) { 1389 Ticker._pausedTicks++; 1390 Ticker._pausedTime += elapsedTime; 1391 } 1392 1393 if (Ticker.hasEventListener("tick")) { 1394 var event = new createjs.Event("tick"); 1395 var maxDelta = Ticker.maxDelta; 1396 event.delta = (maxDelta && elapsedTime > maxDelta) ? maxDelta : elapsedTime; 1397 event.paused = paused; 1398 event.time = time; 1399 event.runTime = time-Ticker._pausedTime; 1400 Ticker.dispatchEvent(event); 1401 } 1402 1403 Ticker._tickTimes.unshift(Ticker._getTime()-time); 1404 while (Ticker._tickTimes.length > 100) { Ticker._tickTimes.pop(); } 1405 1406 Ticker._times.unshift(time); 1407 while (Ticker._times.length > 100) { Ticker._times.pop(); } 1408 }; 1409 1410 /** 1411 * @method _getTime 1412 * @static 1413 * @private 1414 **/ 1415 var w=window, now=w.performance.now || w.performance.mozNow || w.performance.msNow || w.performance.oNow || w.performance.webkitNow; 1416 Ticker._getTime = function() { 1417 return ((now&&now.call(w.performance))||(new Date().getTime())) - Ticker._startTime; 1418 }; 1419 1420 1421 createjs.Ticker = Ticker; 1422}()); 1423 1424//############################################################################## 1425// VideoBuffer.js 1426//############################################################################## 1427 1428this.createjs = this.createjs||{}; 1429 1430(function() { 1431 "use strict"; 1432 1433 1434// constructor: 1435 /** 1436 * When an HTML video seeks, including when looping, there is an indeterminate period before a new frame is available. 1437 * This can result in the video blinking or flashing when it is drawn to a canvas. The VideoBuffer class resolves 1438 * this issue by drawing each frame to an off-screen canvas and preserving the prior frame during a seek. 1439 * 1440 * var myBuffer = new createjs.VideoBuffer(myVideo); 1441 * var myBitmap = new Bitmap(myBuffer); 1442 * 1443 * @class VideoBuffer 1444 * @param {HTMLVideoElement} video The HTML video element to buffer. 1445 * @constructor 1446 **/ 1447 function VideoBuffer(video) { 1448 1449 // private properties: 1450 /** 1451 * Used by Bitmap to determine when the video buffer is ready to be drawn. Not intended for general use. 1452 * @property readyState 1453 * @protected 1454 * @type {Number} 1455 * @default 0 1456 **/ 1457 this.readyState = video.readyState; 1458 1459 /** 1460 * @property _video 1461 * @protected 1462 * @type {HTMLVideoElement} 1463 * @default 0 1464 **/ 1465 this._video = video; 1466 1467 /** 1468 * @property _canvas 1469 * @protected 1470 * @type {HTMLCanvasElement} 1471 * @default 0 1472 **/ 1473 this._canvas = null; 1474 1475 /** 1476 * @property _lastTime 1477 * @protected 1478 * @type {Number} 1479 * @default -1 1480 **/ 1481 this._lastTime = -1; 1482 1483 if (this.readyState < 2) { video.addEventListener("canplaythrough", this._videoReady.bind(this)); } //once:true isn't supported everywhere, but its a non-critical optimization here. 1484 } 1485 var p = VideoBuffer.prototype; 1486 1487 1488// public methods: 1489 /** 1490 * Gets an HTML canvas element showing the current video frame, or the previous frame if in a seek / loop. 1491 * Primarily for use by {{#crossLink "Bitmap"}}{{/crossLink}}. 1492 * @method getImage 1493 **/ 1494 p.getImage = function() { 1495 if (this.readyState < 2) { return; } 1496 var canvas=this._canvas, video = this._video; 1497 if (!canvas) { 1498 canvas = this._canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); 1499 canvas.width = video.videoWidth; 1500 canvas.height = video.videoHeight; 1501 } 1502 if (video.readyState >= 2 && video.currentTime !== this._lastTime) { 1503 var ctx = canvas.getContext("2d"); 1504 ctx.clearRect(0,0,canvas.width,canvas.height); 1505 ctx.drawImage(video,0,0,canvas.width,canvas.height); 1506 this._lastTime = video.currentTime; 1507 } 1508 return canvas; 1509 }; 1510 1511// private methods: 1512 /** 1513 * @method _videoReady 1514 * @protected 1515 **/ 1516 p._videoReady = function() { 1517 this.readyState = 2; 1518 }; 1519 1520 1521 createjs.VideoBuffer = VideoBuffer; 1522}()); 1523 1524//############################################################################## 1525// MouseEvent.js 1526//############################################################################## 1527 1528this.createjs = this.createjs||{}; 1529 1530(function() { 1531 "use strict"; 1532 1533 1534// constructor: 1535 /** 1536 * Passed as the parameter to all mouse/pointer/touch related events. For a listing of mouse events and their properties, 1537 * see the {{#crossLink "DisplayObject"}}{{/crossLink}} and {{#crossLink "Stage"}}{{/crossLink}} event listings. 1538 * @class MouseEvent 1539 * @param {String} type The event type. 1540 * @param {Boolean} bubbles Indicates whether the event will bubble through the display list. 1541 * @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled. 1542 * @param {Number} stageX The normalized x position relative to the stage. 1543 * @param {Number} stageY The normalized y position relative to the stage. 1544 * @param {MouseEvent}
1544 nativeEvent The native DOM event related to this mouse event. 1545 * @param {Number} pointerID The unique id for the pointer. 1546 * @param {Boolean} primary Indicates whether this is the primary pointer in a multitouch environment. 1547 * @param {Number} rawX The raw x position relative to the stage. 1548 * @param {Number} rawY The raw y position relative to the stage. 1549 * @param {DisplayObject} relatedTarget The secondary target for the event. 1550 * @extends Event 1551 * @constructor 1552 **/ 1553 function MouseEvent(type, bubbles, cancelable, stageX, stageY, nativeEvent, pointerID, primary, rawX, rawY, relatedTarget) { 1554 this.Event_constructor(type, bubbles, cancelable); 1555 1556 1557 // public properties: 1558 /** 1559 * The normalized x position on the stage. This will always be within the range 0 to stage width. 1560 * @property stageX 1561 * @type Number 1562 */ 1563 this.stageX = stageX; 1564 1565 /** 1566 * The normalized y position on the stage. This will always be within the range 0 to stage height. 1567 * @property stageY 1568 * @type Number 1569 **/ 1570 this.stageY = stageY; 1571 1572 /** 1573 * The raw x position relative to the stage. Normally this will be the same as the stageX value, unless 1574 * stage.mouseMoveOutside is true and the pointer is outside of the stage bounds. 1575 * @property rawX 1576 * @type Number 1577 */ 1578 this.rawX = (rawX==null)?stageX:rawX; 1579 1580 /** 1581 * The raw y position relative to the stage. Normally this will be the same as the stageY value, unless 1582 * stage.mouseMoveOutside is true and the pointer is outside of the stage bounds. 1583 * @property rawY 1584 * @type Number 1585 */ 1586 this.rawY = (rawY==null)?stageY:rawY; 1587 1588 /** 1589 * The native MouseEvent generated by the browser. The properties and API for this 1590 * event may differ between browsers. This property will be null if the 1591 * EaselJS property was not directly generated from a native MouseEvent. 1592 * @property nativeEvent 1593 * @type HtmlMouseEvent 1594 * @default null 1595 **/ 1596 this.nativeEvent = nativeEvent; 1597 1598 /** 1599 * The unique id for the pointer (touch point or cursor). This will be either -1 for the mouse, or the system 1600 * supplied id value. 1601 * @property pointerID 1602 * @type {Number} 1603 */ 1604 this.pointerID = pointerID; 1605 1606 /** 1607 * Indicates whether this is the primary pointer in a multitouch environment. This will always be true for the mouse. 1608 * For touch pointers, the first pointer in the current stack will be considered the primary pointer. 1609 * @property primary 1610 * @type {Boolean} 1611 */ 1612 this.primary = !!primary; 1613 1614 /** 1615 * The secondary target for the event, if applicable. This is used for mouseout/rollout 1616 * events to indicate the object that the mouse entered from, mouseover/rollover for the object the mouse exited, 1617 * and stagemousedown/stagemouseup events for the object that was the under the cursor, if any. 1618 * 1619 * Only valid interaction targets will be returned (ie. objects with mouse listeners or a cursor set). 1620 * @property relatedTarget 1621 * @type {DisplayObject} 1622 */ 1623 this.relatedTarget = relatedTarget; 1624 } 1625 var p = createjs.extend(MouseEvent, createjs.Event); 1626 1627 // TODO: deprecated 1628 // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. 1629 1630 1631// getter / setters: 1632 /** 1633 * Returns the x position of the mouse in the local coordinate system of the current target (ie. the dispatcher). 1634 * @property localX 1635 * @type {Number} 1636 * @readonly 1637 */ 1638 p._get_localX = function() { 1639 return this.currentTarget.globalToLocal(this.rawX, this.rawY).x; 1640 }; 1641 1642 /** 1643 * Returns the y position of the mouse in the local coordinate system of the current target (ie. the dispatcher). 1644 * @property localY 1645 * @type {Number} 1646 * @readonly 1647 */ 1648 p._get_localY = function() { 1649 return this.currentTarget.globalToLocal(this.rawX, this.rawY).y; 1650 }; 1651 1652 /** 1653 * Indicates whether the event was generated by a touch input (versus a mouse input). 1654 * @property isTouch 1655 * @type {Boolean} 1656 * @readonly 1657 */ 1658 p._get_isTouch = function() { 1659 return this.pointerID !== -1; 1660 }; 1661 1662 1663 try { 1664 Object.defineProperties(p, { 1665 localX: { get: p._get_localX }, 1666 localY: { get: p._get_localY }, 1667 isTouch: { get: p._get_isTouch } 1668 }); 1669 } catch (e) {} // TODO: use Log 1670 1671 1672// public methods: 1673 /** 1674 * Returns a clone of the MouseEvent instance. 1675 * @method clone 1676 * @return {MouseEvent} a clone of the MouseEvent instance. 1677 **/ 1678 p.clone = function() {
1679 return new MouseEvent(this.type, this.bubbles, this.cancelable, this.stageX, this.stageY, this.nativeEvent, this.pointerID, this.primary, this.rawX, this.rawY); 1680 }; 1681 1682 /** 1683 * Returns a string representation of this object. 1684 * @method toString 1685 * @return {String} a string representation of the instance. 1686 **/ 1687 p.toString = function() { 1688 return "[MouseEvent (type="+this.type+" stageX="+this.stageX+" stageY="+this.stageY+")]"; 1689 }; 1690 1691 1692 createjs.MouseEvent = createjs.promote(MouseEvent, "Event"); 1693}()); 1694 1695//############################################################################## 1696// Matrix2D.js 1697//############################################################################## 1698 1699this.createjs = this.createjs||{}; 1700 1701(function() { 1702 "use strict"; 1703 1704 1705// constructor: 1706 /** 1707 * Represents an affine transformation matrix, and provides tools for constructing and concatenating matrices. 1708 * 1709 * This matrix can be visualized as: 1710 * 1711 * [ a c tx 1712 * b d ty 1713 * 0 0 1 ] 1714 * 1715 * Note the locations of b and c. 1716 * 1717 * @class Matrix2D 1718 * @param {Number} [a=1] Specifies the a property for the new matrix. 1719 * @param {Number} [b=0] Specifies the b property for the new matrix. 1720 * @param {Number} [c=0] Specifies the c property for the new matrix. 1721 * @param {Number} [d=1] Specifies the d property for the new matrix. 1722 * @param {Number} [tx=0] Specifies the tx property for the new matrix. 1723 * @param {Number} [ty=0] Specifies the ty property for the new matrix. 1724 * @constructor 1725 **/ 1726 function Matrix2D(a, b, c, d, tx, ty) { 1727 this.setValues(a,b,c,d,tx,ty); 1728 1729 // public properties: 1730 // assigned in the setValues method. 1731 /** 1732 * Position (0, 0) in a 3x3 affine transformation matrix. 1733 * @property a 1734 * @type Number 1735 **/ 1736 1737 /** 1738 * Position (0, 1) in a 3x3 affine transformation matrix. 1739 * @property b 1740 * @type Number 1741 **/ 1742 1743 /** 1744 * Position (1, 0) in a 3x3 affine transformation matrix. 1745 * @property c 1746 * @type Number 1747 **/ 1748 1749 /** 1750 * Position (1, 1) in a 3x3 affine transformation matrix. 1751 * @property d 1752 * @type Number 1753 **/ 1754 1755 /** 1756 * Position (2, 0) in a 3x3 affine transformation matrix. 1757 * @property tx 1758 * @type Number 1759 **/ 1760 1761 /** 1762 * Position (2, 1) in a 3x3 affine transformation matrix. 1763 * @property ty 1764 * @type Number 1765 **/ 1766 } 1767 var p = Matrix2D.prototype; 1768 1769// constants: 1770 /** 1771 * Multiplier for converting degrees to radians. Used internally by Matrix2D. 1772 * @property DEG_TO_RAD 1773 * @static 1774 * @final 1775 * @type Number 1776 * @readonly 1777 **/ 1778 Matrix2D.DEG_TO_RAD = Math.PI/180; 1779 1780 1781// static public properties: 1782 /** 1783 * An identity matrix, representing a null transformation. 1784 * @property identity 1785 * @static 1786 * @type Matrix2D 1787 * @readonly 1788 **/ 1789 Matrix2D.identity = null; // set at bottom of class definition. 1790 1791 1792// public methods: 1793 /** 1794 * Sets the specified values on this instance. 1795 * @method setValues 1796 * @param {Number} [a=1] Specifies the a property for the new matrix. 1797 * @param {Number} [b=0] Specifies the b property for the new matrix. 1798 * @param {Number} [c=0] Specifies the c property for the new matrix. 1799 * @param {Number} [d=1] Specifies the d property for the new matrix. 1800 * @param {Number} [tx=0] Specifies the tx property for the new matrix. 1801 * @param {Number} [ty=0] Specifies the ty property for the new matrix. 1802 * @return {Matrix2D} This instance. Useful for chaining method calls. 1803 */ 1804 p.setValues = function(a, b, c, d, tx, ty) { 1805 // don't forget to update docs in the constructor if these change: 1806 this.a = (a == null) ? 1 : a; 1807 this.b = b || 0; 1808 this.c = c || 0; 1809 this.d = (d == null) ? 1 : d; 1810 this.tx = tx || 0; 1811 this.ty = ty || 0; 1812 return this; 1813 }; 1814 1815 /** 1816 * Appends the specified matrix properties to this matrix. All parameters are required. 1817 * This is the equivalent of multiplying `(this matrix) * (specified matrix)`. 1818 * @method append 1819 * @param {Number} a 1820 * @param {Number} b 1821 * @param {Number} c 1822 * @param {Number} d 1823 * @param {Number} tx 1824 * @param {Number} ty 1825 * @return {Matrix2D} This matrix. Useful for chaining method calls. 1826 **/ 1827 p.append = function(a, b, c, d, tx, ty) { 1828 var a1 = this.a; 1829 var b1 = this.b; 1830 var c1 = this.c; 1831 var d1 = this.d; 1832 if (a != 1 || b != 0 || c != 0 || d != 1) { 1833 this.a = a1*a+c1*b; 1834 this.b = b1*a+d1*b; 1835 this.c = a1*c+c1*d; 1836 this.d = b1*c+d1*d; 1837 } 1838 this.tx = a1*tx+c1*ty+this.tx; 1839 this.ty = b1*tx+d1*ty+this.ty; 1840 return this; 1841 }; 1842 1843 /** 1844 * Prepends the specified matrix properties to this matrix. 1845 * This is the equivalent of multiplying `(specified matrix) * (this matrix)`. 1846 * All parameters are required. 1847 * @method prepend 1848 * @param {Number} a 1849 * @param {Number} b 1850 * @param {Number} c 1851 * @param {Number} d 1852 * @param {Number} tx 1853 * @param {Number} ty 1854 * @return {Matrix2D} This matrix. Useful for chaining method calls. 1855 **/ 1856 p.prepend = function(a, b, c, d, tx, ty) { 1857 var a1 = this.a; 1858 var c1 = this.c; 1859 var tx1 = this.tx; 1860 1861 this.a = a*a1+c*this.b; 1862 this.b = b*a1+d*this.b; 1863 this.c = a*c1+c*this.d; 1864 this.d = b*c1+d*this.d; 1865 this.tx = a*tx1+c*this.ty+tx;
1866 this.ty = b*tx1+d*this.ty+ty; 1867 return this; 1868 }; 1869 1870 /** 1871 * Appends the specified matrix to this matrix. 1872 * This is the equivalent of multiplying `(this matrix) * (specified matrix)`. 1873 * @method appendMatrix 1874 * @param {Matrix2D} matrix 1875 * @return {Matrix2D} This matrix. Useful for chaining method calls. 1876 **/ 1877 p.appendMatrix = function(matrix) { 1878 return this.append(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty); 1879 }; 1880 1881 /** 1882 * Prepends the specified matrix to this matrix. 1883 * This is the equivalent of multiplying `(specified matrix) * (this matrix)`. 1884 * For example, you could calculate the combined transformation for a child object using: 1885 * 1886 * var o = myDisplayObject; 1887 * var mtx = o.getMatrix(); 1888 * while (o = o.parent) { 1889 * // prepend each parent's transformation in turn: 1890 * o.prependMatrix(o.getMatrix()); 1891 * } 1892 * @method prependMatrix 1893 * @param {Matrix2D} matrix 1894 * @return {Matrix2D} This matrix. Useful for chaining method calls. 1895 **/ 1896 p.prependMatrix = function(matrix) { 1897 return this.prepend(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty); 1898 }; 1899 1900 /** 1901 * Generates matrix properties from the specified display object transform properties, and appends them to this matrix. 1902 * For example, you can use this to generate a matrix representing the transformations of a display object: 1903 * 1904 * var mtx = new createjs.Matrix2D(); 1905 * mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation); 1906 * @method appendTransform 1907 * @param {Number} x 1908 * @param {Number} y 1909 * @param {Number} scaleX 1910 * @param {Number} scaleY 1911 * @param {Number} rotation 1912 * @param {Number} skewX 1913 * @param {Number} skewY 1914 * @param {Number} regX Optional. 1915 * @param {Number} regY Optional. 1916 * @return {Matrix2D} This matrix. Useful for chaining method calls. 1917 **/ 1918 p.appendTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) { 1919 if (rotation%360) { 1920 var r = rotation*Matrix2D.DEG_TO_RAD; 1921 var cos = Math.cos(r); 1922 var sin = Math.sin(r); 1923 } else { 1924 cos = 1; 1925 sin = 0; 1926 } 1927 1928 if (skewX || skewY) { 1929 // TODO: can this be combined into a single append operation? 1930 skewX *= Matrix2D.DEG_TO_RAD; 1931 skewY *= Matrix2D.DEG_TO_RAD; 1932 this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y); 1933 this.append(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, 0, 0); 1934 } else { 1935 this.append(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, x, y); 1936 } 1937 1938 if (regX || regY) { 1939 // append the registration offset: 1940 this.tx -= regX*this.a+regY*this.c; 1941 this.ty -= regX*this.b+regY*this.d; 1942 } 1943 return this; 1944 }; 1945 1946 /** 1947 * Generates matrix properties from the specified display object transform properties, and prepends them to this matrix. 1948 * For example, you could calculate the combined transformation for a child object using: 1949 * 1950 * var o = myDisplayObject; 1951 * var mtx = new createjs.Matrix2D(); 1952 * do { 1953 * // prepend each parent's transformation in turn: 1954 * mtx.prependTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.regX, o.regY); 1955 * } while (o = o.parent); 1956 * 1957 * Note that the above example would not account for {{#crossLink "DisplayObject/transformMatrix:property"}}{{/crossLink}} 1958 * values. See {{#crossLink "Matrix2D/prependMatrix"}}{{/crossLink}} for an example that does. 1959 * @method prependTransform 1960 * @param {Number} x 1961 * @param {Number} y 1962 * @param {Number} scaleX 1963 * @param {Number} scaleY 1964 * @param {Number} rotation 1965 * @param {Number} skewX 1966 * @param {Number} skewY 1967 * @param {Number} regX Optional. 1968 * @param {Number} regY Optional. 1969 * @return {Matrix2D} This matrix. Useful for chaining method calls. 1970 **/ 1971 p.prependTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) { 1972 if (rotation%360) { 1973 var r = rotation*Matrix2D.DEG_TO_RAD; 1974 var cos = Math.cos(r); 1975 var sin = Math.sin(r); 1976 } else { 1977 cos = 1; 1978 sin = 0; 1979 } 1980 1981 if (regX || regY) { 1982 // prepend the registration offset: 1983 this.tx -= regX; this.ty -= regY; 1984 }
1985 if (skewX || skewY) { 1986 // TODO: can this be combined into a single prepend operation? 1987 skewX *= Matrix2D.DEG_TO_RAD; 1988 skewY *= Matrix2D.DEG_TO_RAD; 1989 this.prepend(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, 0, 0); 1990 this.prepend(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y); 1991 } else { 1992 this.prepend(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, x, y); 1993 } 1994 return this; 1995 }; 1996 1997 /** 1998 * Applies a clockwise rotation transformation to the matrix. 1999 * @method rotate 2000 * @param {Number} angle The angle to rotate by, in degrees. To use a value in radians, multiply it by `180/Math.PI`. 2001 * @return {Matrix2D} This matrix. Useful for chaining method calls. 2002 **/ 2003 p.rotate = function(angle) { 2004 angle = angle*Matrix2D.DEG_TO_RAD; 2005 var cos = Math.cos(angle); 2006 var sin = Math.sin(angle); 2007 2008 var a1 = this.a; 2009 var b1 = this.b; 2010 2011 this.a = a1*cos+this.c*sin; 2012 this.b = b1*cos+this.d*sin; 2013 this.c = -a1*sin+this.c*cos; 2014 this.d = -b1*sin+this.d*cos; 2015 return this; 2016 }; 2017 2018 /** 2019 * Applies a skew transformation to the matrix. 2020 * @method skew 2021 * @param {Number} skewX The amount to skew horizontally in degrees. To use a value in radians, multiply it by `180/Math.PI`. 2022 * @param {Number} skewY The amount to skew vertically in degrees. 2023 * @return {Matrix2D} This matrix. Useful for chaining method calls. 2024 */ 2025 p.skew = function(skewX, skewY) { 2026 skewX = skewX*Matrix2D.DEG_TO_RAD; 2027 skewY = skewY*Matrix2D.DEG_TO_RAD; 2028 this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), 0, 0); 2029 return this; 2030 }; 2031 2032 /** 2033 * Applies a scale transformation to the matrix. 2034 * @method scale 2035 * @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. 2036 * @param {Number} y The amount to scale vertically. 2037 * @return {Matrix2D} This matrix. Useful for chaining method calls. 2038 **/ 2039 p.scale = function(x, y) { 2040 this.a *= x; 2041 this.b *= x; 2042 this.c *= y; 2043 this.d *= y; 2044 //this.tx *= x; 2045 //this.ty *= y; 2046 return this; 2047 }; 2048 2049 /** 2050 * Translates the matrix on the x and y axes. 2051 * @method translate 2052 * @param {Number} x 2053 * @param {Number} y 2054 * @return {Matrix2D} This matrix. Useful for chaining method calls. 2055 **/ 2056 p.translate = function(x, y) { 2057 this.tx += this.a*x + this.c*y; 2058 this.ty += this.b*x + this.d*y; 2059 return this; 2060 }; 2061 2062 /** 2063 * Sets the properties of the matrix to those of an identity matrix (one that applies a null transformation). 2064 * @method identity 2065 * @return {Matrix2D} This matrix. Useful for chaining method calls. 2066 **/ 2067 p.identity = function() { 2068 this.a = this.d = 1; 2069 this.b = this.c = this.tx = this.ty = 0; 2070 return this; 2071 }; 2072 2073 /** 2074 * Inverts the matrix, causing it to perform the opposite transformation. 2075 * @method invert 2076 * @return {Matrix2D} This matrix. Useful for chaining method calls. 2077 **/ 2078 p.invert = function() { 2079 var a1 = this.a; 2080 var b1 = this.b; 2081 var c1 = this.c; 2082 var d1 = this.d; 2083 var tx1 = this.tx; 2084 var n = a1*d1-b1*c1; 2085 2086 this.a = d1/n; 2087 this.b = -b1/n; 2088 this.c = -c1/n; 2089 this.d = a1/n; 2090 this.tx = (c1*this.ty-d1*tx1)/n; 2091 this.ty = -(a1*this.ty-b1*tx1)/n; 2092 return this; 2093 }; 2094 2095 /** 2096 * Returns true if the matrix is an identity matrix. 2097 * @method isIdentity 2098 * @return {Boolean} 2099 **/ 2100 p.isIdentity = function() { 2101 return this.tx === 0 && this.ty === 0 && this.a === 1 && this.b === 0 && this.c === 0 && this.d === 1; 2102 }; 2103 2104 /** 2105 * Returns true if this matrix is equal to the specified matrix (all property values are equal). 2106 * @method equals 2107 * @param {Matrix2D} matrix The matrix to compare. 2108 * @return {Boolean} 2109 **/ 2110 p.equals = function(matrix) { 2111 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; 2112 }; 2113 2114 /** 2115 * Transforms a point according to this matrix. 2116 * @method transformPoint 2117 * @param {Number} x The x component of the point to transform. 2118 * @param {Number} y The y component of the point to transform. 2119 * @param {Point | Object} [pt] An object to copy the result into. If omitted a generic object with x/y properties will be returned. 2120 * @return {Point} This matrix. Useful for chaining method calls. 2121 **/ 2122 p.transformPoint = function(x, y, pt) { 2123 pt = pt||{}; 2124 pt.x = x*this.a+y*this.c+this.tx; 2125 pt.y = x*this.b+y*this.d+this.ty; 2126 return pt; 2127 }; 2128 2129 /** 2130 * Decomposes the matrix into transform properties (x, y, scaleX, scaleY, and rotation). Note that these values 2131 * may not match the transform properties you used to generate the matrix, though they will produce the same visual 2132 * results. 2133 * @method decompose 2134 * @param {Object} target The object to apply the transform properties to. If null, then a new object will be returned. 2135 * @return {Object} The target, or a new generic object with the transform properties applied. 2136 */ 2137 p.decompose = function(target) { 2138 // 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 2139 if (target == null) { target = {}; } 2140 target.x = this.tx; 2141 target.y = this.ty; 2142 target.scaleX = Math.sqrt(this.a * this.a + this.b * this.b); 2143 target.scaleY = Math.sqrt(this.c * this.c + this.d * this.d); 2144 2145 var skewX = Math.atan2(-this.c, this.d); 2146 var skewY = Math.atan2(this.b, this.a); 2147 2148 var delta = Math.abs(1-skewX/skewY); 2149 if (delta < 0.00001) { // effectively identical, can use rotation: 2150 target.rotation = skewY/Matrix2D.DEG_TO_RAD; 2151 if (this.a < 0 && this.d >= 0) { 2152 target.rotation += (target.rotation <= 0) ? 180 : -180; 2153 }
2154 target.skewX = target.skewY = 0; 2155 } else { 2156 target.skewX = skewX/Matrix2D.DEG_TO_RAD; 2157 target.skewY = skewY/Matrix2D.DEG_TO_RAD; 2158 } 2159 return target; 2160 }; 2161 2162 /** 2163 * Copies all properties from the specified matrix to this matrix. 2164 * @method copy 2165 * @param {Matrix2D} matrix The matrix to copy properties from. 2166 * @return {Matrix2D} This matrix. Useful for chaining method calls. 2167 */ 2168 p.copy = function(matrix) { 2169 return this.setValues(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty); 2170 }; 2171 2172 /** 2173 * Returns a clone of the Matrix2D instance. 2174 * @method clone 2175 * @return {Matrix2D} a clone of the Matrix2D instance. 2176 **/ 2177 p.clone = function() { 2178 return new Matrix2D(this.a, this.b, this.c, this.d, this.tx, this.ty); 2179 }; 2180 2181 /** 2182 * Returns a string representation of this object. 2183 * @method toString 2184 * @return {String} a string representation of the instance. 2185 **/ 2186 p.toString = function() { 2187 return "[Matrix2D (a="+this.a+" b="+this.b+" c="+this.c+" d="+this.d+" tx="+this.tx+" ty="+this.ty+")]"; 2188 }; 2189 2190 // this has to be populated after the class is defined: 2191 Matrix2D.identity = new Matrix2D(); 2192 2193 2194 createjs.Matrix2D = Matrix2D; 2195}()); 2196 2197//############################################################################## 2198// DisplayProps.js 2199//############################################################################## 2200 2201this.createjs = this.createjs||{}; 2202 2203(function() { 2204 "use strict"; 2205 2206 /** 2207 * Used for calculating and encapsulating display related properties. 2208 * @class DisplayProps 2209 * @param {Number} [visible=true] Visible value. 2210 * @param {Number} [alpha=1] Alpha value. 2211 * @param {Number} [shadow=null] A Shadow instance or null. 2212 * @param {Number} [compositeOperation=null] A compositeOperation value or null. 2213 * @param {Number} [matrix] A transformation matrix. Defaults to a new identity matrix. 2214 * @constructor 2215 **/ 2216 function DisplayProps(visible, alpha, shadow, compositeOperation, matrix) { 2217 this.setValues(visible, alpha, shadow, compositeOperation, matrix); 2218 2219 // public properties: 2220 // assigned in the setValues method. 2221 /** 2222 * Property representing the alpha that will be applied to a display object. 2223 * @property alpha 2224 * @type Number 2225 **/ 2226 2227 /** 2228 * Property representing the shadow that will be applied to a display object. 2229 * @property shadow 2230 * @type Shadow 2231 **/ 2232 2233 /** 2234 * Property representing the compositeOperation that will be applied to a display object. 2235 * You can find a list of valid composite operations at: 2236 * <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing">https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing</a> 2237 * @property compositeOperation
2238 * @type String 2239 **/ 2240 2241 /** 2242 * Property representing the value for visible that will be applied to a display object. 2243 * @property visible 2244 * @type Boolean 2245 **/ 2246 2247 /** 2248 * The transformation matrix that will be applied to a display object. 2249 * @property matrix 2250 * @type Matrix2D 2251 **/ 2252 } 2253 var p = DisplayProps.prototype; 2254 2255// initialization: 2256 /** 2257 * Reinitializes the instance with the specified values. 2258 * @method setValues 2259 * @param {Number} [visible=true] Visible value. 2260 * @param {Number} [alpha=1] Alpha value. 2261 * @param {Number} [shadow=null] A Shadow instance or null. 2262 * @param {Number} [compositeOperation=null] A compositeOperation value or null. 2263 * @param {Number} [matrix] A transformation matrix. Defaults to an identity matrix. 2264 * @return {DisplayProps} This instance. Useful for chaining method calls. 2265 * @chainable 2266 */ 2267 p.setValues = function (visible, alpha, shadow, compositeOperation, matrix) { 2268 this.visible = visible == null ? true : !!visible; 2269 this.alpha = alpha == null ? 1 : alpha; 2270 this.shadow = shadow; 2271 this.compositeOperation = compositeOperation; 2272 this.matrix = matrix || (this.matrix&&this.matrix.identity()) || new createjs.Matrix2D(); 2273 return this; 2274 }; 2275 2276// public methods: 2277 /** 2278 * Appends the specified display properties. This is generally used to apply a child's properties its parent's. 2279 * @method append 2280 * @param {Boolean} visible desired visible value 2281 * @param {Number} alpha desired alpha value 2282 * @param {Shadow} shadow desired shadow value 2283 * @param {String} compositeOperation desired composite operation value 2284 * @param {Matrix2D} [matrix] a Matrix2D instance 2285 * @return {DisplayProps} This instance. Useful for chaining method calls. 2286 * @chainable 2287 */ 2288 p.append = function(visible, alpha, shadow, compositeOperation, matrix) { 2289 this.alpha *= alpha; 2290 this.shadow = shadow || this.shadow; 2291 this.compositeOperation = compositeOperation || this.compositeOperation; 2292 this.visible = this.visible && visible; 2293 matrix&&this.matrix.appendMatrix(matrix); 2294 return this; 2295 }; 2296 2297 /** 2298 * Prepends the specified display properties. This is generally used to apply a parent's properties to a child's. 2299 * For example, to get the combined display properties that would be applied to a child, you could use: 2300 * 2301 * var o = myDisplayObject; 2302 * var props = new createjs.DisplayProps(); 2303 * do { 2304 * // prepend each parent's props in turn: 2305 * props.prepend(o.visible, o.alpha, o.shadow, o.compositeOperation, o.getMatrix()); 2306 * } while (o = o.parent); 2307 * 2308 * @method prepend 2309 * @param {Boolean} visible desired visible value 2310 * @param {Number} alpha desired alpha value 2311 * @param {Shadow} shadow desired shadow value 2312 * @param {String} compositeOperation desired composite operation value 2313 * @param {Matrix2D} [matrix] a Matrix2D instance 2314 * @return {DisplayProps} This instance. Useful for chaining method calls. 2315 * @chainable 2316 */ 2317 p.prepend = function(visible, alpha, shadow, compositeOperation, matrix) { 2318 this.alpha *= alpha; 2319 this.shadow = this.shadow || shadow; 2320 this.compositeOperation = this.compositeOperation || compositeOperation; 2321 this.visible = this.visible && visible; 2322 matrix&&this.matrix.prependMatrix(matrix); 2323 return this; 2324 }; 2325 2326 /** 2327 * Resets this instance and its matrix to default values. 2328 * @method identity 2329 * @return {DisplayProps} This instance. Useful for chaining method calls. 2330 * @chainable 2331 */ 2332 p.identity = function() { 2333 this.visible = true; 2334 this.alpha = 1; 2335 this.shadow = this.compositeOperation = null; 2336 this.matrix.identity(); 2337 return this; 2338 }; 2339 2340 /** 2341 * Returns a clone of the DisplayProps instance. Clones the associated matrix. 2342 * @method clone 2343 * @return {DisplayProps} a clone of the DisplayProps instance. 2344 **/ 2345 p.clone = function() { 2346 return new DisplayProps(this.alpha, this.shadow, this.compositeOperation, this.visible, this.matrix.clone()); 2347 }; 2348 2349// private methods: 2350 2351 createjs.DisplayProps = DisplayProps; 2352})(); 2353 2354//############################################################################## 2355// Point.js 2356//############################################################################## 2357 2358this.createjs = this.createjs||{}; 2359 2360(function() { 2361 "use strict"; 2362 2363 2364// constructor: 2365 /** 2366 * Represents a point on a 2 dimensional x / y coordinate system. 2367 * 2368 * <h4>Example</h4> 2369 * 2370 * var point = new createjs.Point(0, 100); 2371 * 2372 * @class Point 2373 * @param {Number} [x=0] X position. 2374 * @param {Number} [y=0] Y position. 2375 * @constructor 2376 **/ 2377 function Point(x, y) { 2378 this.setValues(x, y); 2379 2380 2381 // public properties: 2382 // assigned in the setValues method. 2383 /** 2384 * X position. 2385 * @property x 2386 * @type Number 2387 **/ 2388 2389 /** 2390 * Y position. 2391 * @property y 2392 * @type Number 2393 **/ 2394 } 2395 var p = Point.prototype; 2396 2397// public methods: 2398 /** 2399 * Sets the specified values on this instance. 2400 * @method setValues 2401 * @param {Number} [x=0] X position. 2402 * @param {Number} [y=0] Y position. 2403 * @return {Point} This instance. Useful for chaining method calls. 2404 * @chainable 2405 */ 2406 p.setValues = function(x, y) { 2407 this.x = x||0; 2408 this.y = y||0; 2409 return this; 2410 }; 2411 2412 /** 2413 * Copies all properties from the specified point to this point. 2414 * @method copy 2415 * @param {Point} point The point to copy properties from. 2416 * @return {Point} This point. Useful for chaining method calls. 2417 * @chainable 2418 */ 2419 p.copy = function(point) { 2420 this.x = point.x; 2421 this.y = point.y; 2422 return this; 2423 }; 2424 2425 /** 2426 * Returns a clone of the Point instance. 2427 * @method clone 2428 * @return {Point} a clone of the Point instance. 2429 **/ 2430 p.clone = function() { 2431 return new Point(this.x, this.y); 2432 }; 2433 2434 /** 2435 * Returns a string representation of this object. 2436 * @method toString 2437 * @return {String} a string representation of the instance. 2438 **/ 2439 p.toString = function() { 2440 return "[Point (x="+this.x+" y="+this.y+")]"; 2441 }; 2442 2443 2444 createjs.Point = Point; 2445}()); 2446 2447//############################################################################## 2448// Rectangle.js 2449//############################################################################## 2450 2451this.createjs = this.createjs||{}; 2452 2453(function() { 2454 "use strict"; 2455 2456 2457// constructor: 2458 /** 2459 * Represents a rectangle as defined by the points (x, y) and (x+width, y+height). 2460 * 2461 * <h4>Example</h4> 2462 * 2463 * var rect = new createjs.Rectangle(0, 0, 100, 100); 2464 * 2465 * @class Rectangle 2466 * @param {Number} [x=0] X position. 2467 * @param {Number} [y=0] Y position. 2468 * @param {Number} [width=0] The width of the Rectangle. 2469 * @param {Number} [height=0] The height of the Rectangle. 2470 * @constructor 2471 **/ 2472 function Rectangle(x, y, width, height) { 2473 this.setValues(x, y, width, height); 2474 2475 2476 // public properties: 2477 // assigned in the setValues method. 2478 /** 2479 * X position. 2480 * @property x 2481 * @type Number 2482 **/ 2483 2484 /** 2485 * Y position. 2486 * @property y 2487 * @type Number 2488 **/ 2489 2490 /** 2491 * Width. 2492 * @property width 2493 * @type Number 2494 **/ 2495 2496 /** 2497 * Height. 2498 * @property height 2499 * @type Number 2500 **/ 2501 } 2502 var p = Rectangle.prototype; 2503 2504// public methods: 2505 /** 2506 * Sets the specified values on this instance. 2507 * @method setValues 2508 * @param {Number} [x=0] X position. 2509 * @param {Number} [y=0] Y position. 2510 * @param {Number} [width=0] The width of the Rectangle. 2511 * @param {Number} [height=0] The height of the Rectangle. 2512 * @return {Rectangle} This instance. Useful for chaining method calls. 2513 * @chainable 2514 */ 2515 p.setValues = function(x, y, width, height) { 2516 // don't forget to update docs in the constructor if these change: 2517 this.x = x||0; 2518 this.y = y||0; 2519 this.width = width||0; 2520 this.height = height||0; 2521 return this; 2522 }; 2523 2524 /** 2525 * Extends the rectangle's bounds to include the described point or rectangle. 2526 * @method extend 2527 * @param {Number} x X position of the point or rectangle. 2528 * @param {Number} y Y position of the point or rectangle. 2529 * @param {Number} [width=0] The width of the rectangle. 2530 * @param {Number} [height=0] The height of the rectangle. 2531 * @return {Rectangle} This instance. Useful for chaining method calls. 2532 * @chainable 2533 */ 2534 p.extend = function(x, y, width, height) { 2535 width = width||0; 2536 height = height||0; 2537 if (x+width > this.x+this.width) { this.width = x+width-this.x; } 2538 if (y+height > this.y+this.height) { this.height = y+height-this.y; } 2539 if (x < this.x) { this.width += this.x-x; this.x = x; } 2540 if (y < this.y) { this.height += this.y-y; this.y = y; } 2541 return this; 2542 }; 2543 2544 /** 2545 * Adds the specified padding to the rectangle's bounds. 2546 * @method pad 2547 * @param {Number} top 2548 * @param {Number} left 2549 * @param {Number} bottom 2550 * @param {Number} right 2551 * @return {Rectangle} This instance. Useful for chaining method calls. 2552 * @chainable 2553 */ 2554 p.pad = function(top, left, bottom, right) { 2555 this.x -= left; 2556 this.y -= top; 2557 this.width += left+right; 2558 this.height += top+bottom; 2559 return this; 2560 }; 2561 2562 /**
2563 * Copies all properties from the specified rectangle to this rectangle. 2564 * @method copy 2565 * @param {Rectangle} rectangle The rectangle to copy properties from. 2566 * @return {Rectangle} This rectangle. Useful for chaining method calls. 2567 * @chainable 2568 */ 2569 p.copy = function(rectangle) { 2570 return this.setValues(rectangle.x, rectangle.y, rectangle.width, rectangle.height); 2571 }; 2572 2573 /** 2574 * Returns true if this rectangle fully encloses the described point or rectangle. 2575 * @method contains 2576 * @param {Number} x X position of the point or rectangle. 2577 * @param {Number} y Y position of the point or rectangle. 2578 * @param {Number} [width=0] The width of the rectangle. 2579 * @param {Number} [height=0] The height of the rectangle. 2580 * @return {Boolean} True if the described point or rectangle is contained within this rectangle. 2581 */ 2582 p.contains = function(x, y, width, height) { 2583 width = width||0; 2584 height = height||0; 2585 return (x >= this.x && x+width <= this.x+this.width && y >= this.y && y+height <= this.y+this.height); 2586 }; 2587 2588 /** 2589 * Returns a new rectangle which contains this rectangle and the specified rectangle. 2590 * @method union 2591 * @param {Rectangle} rect The rectangle to calculate a union with. 2592 * @return {Rectangle} A new rectangle describing the union. 2593 */ 2594 p.union = function(rect) { 2595 return this.clone().extend(rect.x, rect.y, rect.width, rect.height); 2596 }; 2597 2598 /** 2599 * Returns a new rectangle which describes the intersection (overlap) of this rectangle and the specified rectangle, 2600 * or null if they do not intersect. 2601 * @method intersection 2602 * @param {Rectangle} rect The rectangle to calculate an intersection with. 2603 * @return {Rectangle} A new rectangle describing the intersection or null. 2604 */ 2605 p.intersection = function(rect) {
2606 var x1 = rect.x, y1 = rect.y, x2 = x1+rect.width, y2 = y1+rect.height; 2607 if (this.x > x1) { x1 = this.x; } 2608 if (this.y > y1) { y1 = this.y; } 2609 if (this.x + this.width < x2) { x2 = this.x + this.width; } 2610 if (this.y + this.height < y2) { y2 = this.y + this.height; } 2611 return (x2 <= x1 || y2 <= y1) ? null : new Rectangle(x1, y1, x2-x1, y2-y1); 2612 }; 2613 2614 /** 2615 * Returns true if the specified rectangle intersects (has any overlap) with this rectangle. 2616 * @method intersects 2617 * @param {Rectangle} rect The rectangle to compare. 2618 * @return {Boolean} True if the rectangles intersect. 2619 */ 2620 p.intersects = function(rect) { 2621 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); 2622 }; 2623 2624 /** 2625 * Returns true if the width or height are equal or less than 0. 2626 * @method isEmpty 2627 * @return {Boolean} True if the rectangle is empty. 2628 */ 2629 p.isEmpty = function() { 2630 return this.width <= 0 || this.height <= 0; 2631 }; 2632 2633 /** 2634 * Returns a clone of the Rectangle instance. 2635 * @method clone 2636 * @return {Rectangle} a clone of the Rectangle instance. 2637 **/ 2638 p.clone = function() { 2639 return new Rectangle(this.x, this.y, this.width, this.height); 2640 }; 2641 2642 /** 2643 * Returns a string representation of this object. 2644 * @method toString 2645 * @return {String} a string representation of the instance. 2646 **/ 2647 p.toString = function() { 2648 return "[Rectangle (x="+this.x+" y="+this.y+" width="+this.width+" height="+this.height+")]"; 2649 }; 2650 2651 2652 createjs.Rectangle = Rectangle; 2653}()); 2654 2655//############################################################################## 2656// ButtonHelper.js 2657//############################################################################## 2658 2659this.createjs = this.createjs||{}; 2660 2661(function() { 2662 "use strict"; 2663 2664 2665// constructor: 2666 /** 2667 * The ButtonHelper is a helper class to create interactive buttons from {{#crossLink "MovieClip"}}{{/crossLink}} or 2668 * {{#crossLink "Sprite"}}{{/crossLink}} instances. This class will intercept mouse events from an object, and 2669 * automatically call {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} or {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}}, 2670 * to the respective animation labels, add a pointer cursor, and allows the user to define a hit state frame. 2671 * 2672 * The ButtonHelper instance does not need to be added to the stage, but a reference should be maintained to prevent 2673 * garbage collection. 2674 * 2675 * Note that over states will not work unless you call {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. 2676 * 2677 * <h4>Example</h4> 2678 * 2679 * var helper = new createjs.ButtonHelper(myInstance, "out", "over", "down", false, myInstance, "hit"); 2680 * myInstance.addEventListener("click", handleClick); 2681 * function handleClick(event) { 2682 * // Click Happened. 2683 * } 2684 * 2685 * @class ButtonHelper 2686 * @param {Sprite|MovieClip} target The instance to manage. 2687 * @param {String} [outLabel="out"] The label or animation to go to when the user rolls out of the button. 2688 * @param {String} [overLabel="over"] The label or animation to go to when the user rolls over the button. 2689 * @param {String} [downLabel="down"] The label or animation to go to when the user presses the button. 2690 * @param {Boolean} [play=false] If the helper should call "gotoAndPlay" or "gotoAndStop" on the button when changing 2691 * states. 2692 * @param {DisplayObject} [hitArea] An optional item to use as the hit state for the button. If this is not defined, 2693 * then the button's visible states will be used instead. Note that the same instance as the "target" argument can be 2694 * used for the hitState. 2695 * @param {String} [hitLabel] The label or animation on the hitArea instance that defines the hitArea bounds. If this is 2696 * null, then the default state of the hitArea will be used. * 2697 * @constructor 2698 */ 2699 function ButtonHelper(target, outLabel, overLabel, downLabel, play, hitArea, hitLabel) { 2700 if (!target.addEventListener) { return; } 2701 2702 2703 // public properties: 2704 /** 2705 * The target for this button helper. 2706 * @property target 2707 * @type MovieClip | Sprite 2708 * @readonly 2709 **/ 2710 this.target = target; 2711 2712 /** 2713 * The label name or frame number to display when the user mouses out of the target. Defaults to "over". 2714 * @property overLabel
2715 * @type String | Number 2716 **/ 2717 this.overLabel = overLabel == null ? "over" : overLabel; 2718 2719 /** 2720 * The label name or frame number to display when the user mouses over the target. Defaults to "out". 2721 * @property outLabel 2722 * @type String | Number 2723 **/ 2724 this.outLabel = outLabel == null ? "out" : outLabel; 2725 2726 /** 2727 * The label name or frame number to display when the user presses on the target. Defaults to "down". 2728 * @property downLabel 2729 * @type String | Number 2730 **/ 2731 this.downLabel = downLabel == null ? "down" : downLabel; 2732 2733 /** 2734 * If true, then ButtonHelper will call gotoAndPlay, if false, it will use gotoAndStop. Default is false. 2735 * @property play 2736 * @default false 2737 * @type Boolean 2738 **/ 2739 this.play = play; 2740 2741 2742 // private properties 2743 /** 2744 * @property _isPressed 2745 * @type Boolean 2746 * @protected 2747 **/ 2748 this._isPressed = false; 2749 2750 /** 2751 * @property _isOver 2752 * @type Boolean 2753 * @protected 2754 **/ 2755 this._isOver = false; 2756 2757 /** 2758 * @property _enabled 2759 * @type Boolean 2760 * @protected 2761 **/ 2762 this._enabled = false; 2763 2764 // setup: 2765 target.mouseChildren = false; // prevents issues when children are removed from the display list when state changes. 2766 this.enabled = true; 2767 this.handleEvent({}); 2768 if (hitArea) { 2769 if (hitLabel) { 2770 hitArea.actionsEnabled = false; 2771 hitArea.gotoAndStop&&hitArea.gotoAndStop(hitLabel); 2772 } 2773 target.hitArea = hitArea; 2774 } 2775 } 2776 var p = ButtonHelper.prototype; 2777 2778// getter / setters: 2779 /** 2780 * Use the {{#crossLink "ButtonHelper/enabled:property"}}{{/crossLink}} property instead. 2781 * @method setEnabled 2782 * @param {Boolean} value The enabled property to set the instance to. 2783 * @[rptected 2784 * @protected 2785 **/ 2786 p._setEnabled = function(value) { 2787 if (value == this._enabled) { return; } 2788 var o = this.target; 2789 this._enabled = value; 2790 if (value) { 2791 o.cursor = "pointer"; 2792 o.addEventListener("rollover", this); 2793 o.addEventListener("rollout", this); 2794 o.addEventListener("mousedown", this); 2795 o.addEventListener("pressup", this); 2796 if (o._reset) { o.__reset = o._reset; o._reset = this._reset;} 2797 } else { 2798 o.cursor = null; 2799 o.removeEventListener("rollover", this); 2800 o.removeEventListener("rollout", this); 2801 o.removeEventListener("mousedown", this); 2802 o.removeEventListener("pressup", this); 2803 if (o.__reset) { o._reset = o.__reset; delete(o.__reset); } 2804 } 2805 }; 2806 // ButtonHelper.setEnabled is @deprecated. Remove for 1.1+ 2807 p.setEnabled = createjs.deprecate(p._setEnabled, "ButtonHelper.setEnabled"); 2808 2809 /** 2810 * Use the {{#crossLink "ButtonHelper/enabled:property"}}{{/crossLink}} property instead. 2811 * @method getEnabled 2812 * @protected 2813 * @return {Boolean} 2814 **/ 2815 p._getEnabled = function() { 2816 return this._enabled; 2817 }; 2818 // ButtonHelper.getEnabled is @deprecated. Remove for 1.1+ 2819 p.getEnabled = createjs.deprecate(p._getEnabled, "ButtonHelper.getEnabled"); 2820 2821 /** 2822 * Enables or disables the button functionality on the target. 2823 * @property enabled 2824 * @type {Boolean} 2825 **/ 2826 try { 2827 Object.defineProperties(p, { 2828 enabled: { get: p._getEnabled, set: p._setEnabled } 2829 }); 2830 } catch (e) {} // TODO: use Log 2831 2832 2833// public methods: 2834 /** 2835 * Returns a string representation of this object. 2836 * @method toString 2837 * @return {String} a string representation of the instance. 2838 **/ 2839 p.toString = function() { 2840 return "[ButtonHelper]"; 2841 }; 2842 2843 2844// private methods: 2845 /** 2846 * @method handleEvent 2847 * @param {Object} evt The mouse event to handle. 2848 * @protected 2849 **/ 2850 p.handleEvent = function(evt) { 2851 var label, t = this.target, type = evt.type; 2852 if (type == "mousedown") { 2853 this._isPressed = true; 2854 label = this.downLabel; 2855 } else if (type == "pressup") { 2856 this._isPressed = false;
2857 label = this._isOver ? this.overLabel : this.outLabel; 2858 } else if (type == "rollover") { 2859 this._isOver = true; 2860 label = this._isPressed ? this.downLabel : this.overLabel; 2861 } else { // rollout and default 2862 this._isOver = false; 2863 label = this._isPressed ? this.overLabel : this.outLabel; 2864 } 2865 if (this.play) { 2866 t.gotoAndPlay&&t.gotoAndPlay(label); 2867 } else { 2868 t.gotoAndStop&&t.gotoAndStop(label); 2869 } 2870 }; 2871 2872 /** 2873 * Injected into target. Preserves the paused state through a reset. 2874 * @method _reset 2875 * @protected 2876 **/ 2877 p._reset = function() { 2878 // TODO: explore better ways to handle this issue. This is hacky & disrupts object signatures. 2879 var p = this.paused; 2880 this.__reset(); 2881 this.paused = p; 2882 }; 2883 2884 2885 createjs.ButtonHelper = ButtonHelper; 2886}()); 2887 2888//############################################################################## 2889// Shadow.js 2890//############################################################################## 2891 2892this.createjs = this.createjs||{}; 2893 2894(function() { 2895 "use strict"; 2896 2897 2898// constructor: 2899 /** 2900 * This class encapsulates the properties required to define a shadow to apply to a {{#crossLink "DisplayObject"}}{{/crossLink}} 2901 * via its <code>shadow</code> property. 2902 * 2903 * <h4>Example</h4> 2904 * 2905 * myImage.shadow = new createjs.Shadow("#000000", 5, 5, 10); 2906 * 2907 * @class Shadow 2908 * @constructor 2909 * @param {String} color The color of the shadow. This can be any valid CSS color value. 2910 * @param {Number} offsetX The x offset of the shadow in pixels. 2911 * @param {Number} offsetY The y offset of the shadow in pixels. 2912 * @param {Number} blur The size of the blurring effect. 2913 **/ 2914 function Shadow(color, offsetX, offsetY, blur) { 2915 2916 2917 // public properties: 2918 /** 2919 * The color of the shadow. This can be any valid CSS color value. 2920 * @property color
2921 * @type String 2922 * @default null 2923 */ 2924 this.color = color||"black"; 2925 2926 /** The x offset of the shadow. 2927 * @property offsetX 2928 * @type Number 2929 * @default 0 2930 */ 2931 this.offsetX = offsetX||0; 2932 2933 /** The y offset of the shadow. 2934 * @property offsetY 2935 * @type Number 2936 * @default 0 2937 */ 2938 this.offsetY = offsetY||0; 2939 2940 /** The blur of the shadow. 2941 * @property blur 2942 * @type Number 2943 * @default 0 2944 */ 2945 this.blur = blur||0; 2946 } 2947 var p = Shadow.prototype; 2948 2949// static public properties: 2950 /** 2951 * An identity shadow object (all properties are set to 0). 2952 * @property identity 2953 * @type Shadow 2954 * @static 2955 * @final 2956 * @readonly 2957 **/ 2958 Shadow.identity = new Shadow("transparent", 0, 0, 0); 2959 2960 2961// public methods: 2962 /** 2963 * Returns a string representation of this object. 2964 * @method toString 2965 * @return {String} a string representation of the instance. 2966 **/ 2967 p.toString = function() { 2968 return "[Shadow]"; 2969 }; 2970 2971 /** 2972 * Returns a clone of this Shadow instance. 2973 * @method clone 2974 * @return {Shadow} A clone of the current Shadow instance. 2975 **/ 2976 p.clone = function() { 2977 return new Shadow(this.color, this.offsetX, this.offsetY, this.blur); 2978 }; 2979 2980 2981 createjs.Shadow = Shadow; 2982}()); 2983 2984//############################################################################## 2985// SpriteSheet.js 2986//############################################################################## 2987 2988this.createjs = this.createjs||{}; 2989 2990(function() { 2991 "use strict"; 2992 2993 2994// constructor: 2995 /** 2996 * Encapsulates the properties and methods associated with a sprite sheet. A sprite sheet is a series of images (usually 2997 * animation frames) combined into a larger image (or images). For example, an animation consisting of eight 100x100 2998 * images could be combined into a single 400x200 sprite sheet (4 frames across by 2 high). 2999 * 3000 * The data passed to the SpriteSheet constructor defines: 3001 * <ol> 3002 * <li> The source image or images to use.</li> 3003 * <li> The positions of individual image frames.</li> 3004 * <li> Sequences of frames that form named animations. Optional.</li> 3005 * <li> The target playback framerate. Optional.</li> 3006 * </ol> 3007 * <h3>SpriteSheet Format</h3> 3008 * SpriteSheets are an object with two required properties (`images` and `frames`), and two optional properties 3009 * (`framerate` and `animations`). This makes them easy to define in javascript code, or in JSON. 3010 * 3011 * <h4>images</h4> 3012 * An array of source images. Images can be either an HTMlimage 3013 * instance, or a uri to an image. The former is recommended to control preloading. 3014 * 3015 * images: [image1, "path/to/image2.png"], 3016 * 3017 * <h4>frames</h4> 3018 * Defines the individual frames. There are two supported formats for frame data: 3019 * When all of the frames are the same size (in a grid), use an object with `width`, `height`, `regX`, `regY`, 3020 * and `count` properties. 3021 * 3022 * <ul> 3023 * <li>`width` & `height` are required and specify the dimensions of the frames</li> 3024 * <li>`regX` & `regY` indicate the registration point or "origin" of the frames</li> 3025 * <li>`spacing` indicate the spacing between frames</li> 3026 * <li>`margin` specify the margin around the image(s)</li> 3027 * <li>`count` allows you to specify the total number of frames in the spritesheet; if omitted, this will 3028 * be calculated based on the dimensions of the source images and the frames. Frames will be assigned 3029 * indexes based on their position in the source images (left to right, top to bottom).</li> 3030 * </ul> 3031 * 3032 * frames: {width:64, height:64, count:20, regX: 32, regY:64, spacing:0, margin:0} 3033 * 3034 * If the frames are of different sizes, use an array of frame definitions. Each definition is itself an array 3035 * with 4 required and 3 optional entries, in the order: 3036 * 3037 * <ul> 3038 * <li>The first four, `x`, `y`, `width`, and `height` are required and define the frame rectangle.</li> 3039 * <li>The fifth, `imageIndex`, specifies the index of the source image (defaults to 0)</li> 3040 * <li>The last two, `regX` and `regY` specify the registration point of the frame</li> 3041 * </ul> 3042 * 3043 * frames: [ 3044 * // x, y, width, height, imageIndex*, regX*, regY* 3045 * [64, 0, 96, 64], 3046 * [0, 0, 64, 64, 1, 32, 32] 3047 * // etc. 3048 * ] 3049 * 3050 * <h4>animations</h4> 3051 * Optional. An object defining sequences of frames to play as
3051named animations. Each property corresponds to an 3052 * animation of the same name. Each animation must specify the frames to play, and may 3053 * also include a relative playback `speed` (ex. 2 would playback at double speed, 0.5 at half), and 3054 * the name of the `next` animation to sequence to after it completes. 3055 * 3056 * There are three formats supported for defining the frames in an animation, which can be mixed and matched as appropriate: 3057 * <ol> 3058 * <li>for a single frame animation, you can simply specify the frame index 3059 * 3060 * animations: { 3061 * sit: 7 3062 * } 3063 * 3064 * </li> 3065 * <li> 3066 * for an animation of consecutive frames, you can use an array with two required, and two optional entries 3067 * in the order: `start`, `end`, `next`, and `speed`. This will play the frames from start to end inclusive. 3068 * 3069 * animations: { 3070 * // start, end, next*, speed* 3071 * run: [0, 8], 3072 * jump: [9, 12, "run", 2] 3073 * } 3074 * 3075 * </li> 3076 * <li> 3077 * for non-consecutive frames, you can use an object with a `frames` property defining an array of frame 3078 * indexes to play in order. The object can also specify `next` and `speed` properties. 3079 * 3080 * animations: { 3081 * walk: { 3082 * frames: [1,2,3,3,2,1] 3083 * }, 3084 * shoot: { 3085 * frames: [1,4,5,6], 3086 * next: "walk", 3087 * speed: 0.5 3088 * } 3089 * } 3090 * 3091 * </li> 3092 * </ol> 3093 * <strong>Note:</strong> the `speed` property was added in EaselJS 0.7.0. Earlier versions had a `frequency` 3094 * property instead, which was the inverse of `speed`. For example, a value of "4" would be 1/4 normal speed in 3095 * earlier versions, but is 4x normal speed in EaselJS 0.7.0+. 3096 * 3097 * <h4>framerate</h4> 3098 * Optional. Indicates the default framerate to play this spritesheet at in frames per second. See 3099 * {{#crossLink "SpriteSheet/framerate:property"}}{{/crossLink}} for more information. 3100 * 3101 * framerate: 20 3102 * 3103 * Note that the Sprite framerate will only work if the stage update method is provided with the {{#crossLink "Ticker/tick:event"}}{{/crossLink}} 3104 * event generated by the {{#crossLink "Ticker"}}{{/crossLink}}. 3105 * 3106 * createjs.Ticker.on("tick", handleTick); 3107 * function handleTick(event) { 3108 * stage.update(event); 3109 * } 3110 * 3111 * <h3>Example</h3> 3112 * To define a simple sprite sheet, with a single image "sprites.jpg" arranged in a regular 50x50 grid with three 3113 * animations: "stand" showing the first frame, "run" looping frame 1-5 inclusive, and "jump" playing frame 6-8 and 3114 * sequencing back to run. 3115 * 3116 * var data = { 3117 * images: ["sprites.jpg"], 3118 * frames: {width:50, height:50}, 3119 * animations: { 3120 * stand:0, 3121 * run:[1,5], 3122 * jump:[6,8,"run"] 3123 * } 3124 * }; 3125 * var spriteSheet = new createjs.SpriteSheet(data); 3126 * var animation = new createjs.Sprite(spriteSheet, "run"); 3127 * 3128 * <h3>Generating SpriteSheet Images</h3> 3129 * Spritesheets can be created manually by combining images in PhotoShop, and specifying the frame size or 3130 * coordinates manually, however there are a number of tools that facilitate this. 3131 * <ul> 3132 * <li>Exporting SpriteSheets or HTML5 content from Adobe Flash/Animate supports the EaselJS SpriteSheet format.</li> 3133 * <li>The popular <a href="https://www.codeandweb.com/texturepacker/easeljs" target="_blank">Texture Packer</a> has 3134 * EaselJS support. 3135 * <li>SWF animations in Adobe Flash/Animate can be exported to SpriteSheets using <a href="http://createjs.com/zoe" target="_blank">Zoë</a></li> 3136 * </ul> 3137 * 3138 * <h3>Cross Origin Issues</h3> 3139 * <strong>Warning:</strong> Images loaded cross-origin will throw cross-origin security errors when interacted with 3140 * using: 3141 * <ul> 3142 * <li>a mouse</li> 3143 * <li>methods such as {{#crossLink "Container/getObjectUnderPoint"}}{{/crossLink}}</li> 3144 * <li>Filters (see {{#crossLink "Filter"}}{{/crossLink}})</li> 3145 * <li>caching (see {{#crossLink "DisplayObject/cache"}}{{/crossLink}})</li> 3146 * </ul> 3147 * You can get around this by setting `crossOrigin` property on your images before passing them to EaselJS, or 3148 * setting the `crossOrigin` property on PreloadJS' LoadQueue or LoadItems. 3149 * 3150 * var image = new Image(); 3151 * img.crossOrigin="Anonymous"; 3152 * img.src = "http://server-with-CORS-support.com/path/to/image.jpg"; 3153 * 3154 * If you pass string paths to SpriteSheets, they will not work cross-origin. The server that stores the image must 3155 * support cross-origin requests, or this will not work. For more information, check out 3156 * <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS" target="_blank">CORS overview on MDN</a>. 3157 * 3158 * @class SpriteSheet 3159 * @constructor 3160 * @param {Object} data An object describing the SpriteSheet data.
3161 * @extends EventDispatcher 3162 **/ 3163 function SpriteSheet(data) { 3164 this.EventDispatcher_constructor(); 3165 3166 3167 // public properties: 3168 /** 3169 * Indicates whether all images are finished loading. 3170 * @property complete 3171 * @type Boolean 3172 * @readonly 3173 **/ 3174 this.complete = true; 3175 3176 /** 3177 * Specifies the framerate to use by default for Sprite instances using the SpriteSheet. See the Sprite class 3178 * {{#crossLink "Sprite/framerate:property"}}{{/crossLink}} for more information. 3179 * @property framerate 3180 * @type Number 3181 **/ 3182 this.framerate = 0; 3183 3184 3185 // private properties: 3186 /** 3187 * @property _animations 3188 * @protected 3189 * @type Array 3190 **/ 3191 this._animations = null; 3192 3193 /** 3194 * @property _frames 3195 * @protected 3196 * @type Array 3197 **/ 3198 this._frames = null; 3199 3200 /** 3201 * @property _images 3202 * @protected 3203 * @type Array 3204 **/ 3205 this._images = null; 3206 3207 /** 3208 * @property _data 3209 * @protected 3210 * @type Object 3211 **/ 3212 this._data = null; 3213 3214 /** 3215 * @property _loadCount 3216 * @protected 3217 * @type Number 3218 **/ 3219 this._loadCount = 0; 3220 3221 // only used for simple frame defs: 3222 /** 3223 * @property _frameHeight 3224 * @protected 3225 * @type Number 3226 **/ 3227 this._frameHeight = 0; 3228 3229 /** 3230 * @property _frameWidth 3231 * @protected 3232 * @type Number 3233 **/ 3234 this._frameWidth = 0; 3235 3236 /** 3237 * @property _numFrames 3238 * @protected 3239 * @type Number 3240 **/ 3241 this._numFrames = 0; 3242 3243 /** 3244 * @property _regX 3245 * @protected 3246 * @type Number 3247 **/ 3248 this._regX = 0; 3249 3250 /** 3251 * @property _regY 3252 * @protected 3253 * @type Number 3254 **/ 3255 this._regY = 0; 3256 3257 /** 3258 * @property _spacing 3259 * @protected 3260 * @type Number 3261 **/ 3262 this._spacing = 0; 3263 3264 /** 3265 * @property _margin 3266 * @protected 3267 * @type Number 3268 **/ 3269 this._margin = 0; 3270 3271 // setup: 3272 this._parseData(data); 3273 } 3274 var p = createjs.extend(SpriteSheet, createjs.EventDispatcher); 3275 3276 // TODO: deprecated 3277 // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. 3278 3279 3280// events: 3281 /** 3282 * Dispatched when all images are loaded. Note that this only fires if the images 3283 * were not fully loaded when the sprite sheet was initialized. You should check the complete property 3284 * to prior to adding a listener. Ex. 3285 * 3286 * var sheet = new createjs.SpriteSheet(data); 3287 * if (!sheet.complete) { 3288 * // not preloaded, listen for the complete event: 3289 * sheet.addEventListener("complete", handler); 3290 * } 3291 * 3292 * @event complete 3293 * @param {Object} target The object that dispatched the event. 3294 * @param {String} type The event type. 3295 * @since 0.6.0 3296 */ 3297 3298 /** 3299 * Dispatched when getFrame is called with a valid frame index. This is primarily intended for use by {{#crossLink "SpriteSheetBuilder"}}{{/crossLink}} 3300 * when doing on-demand rendering. 3301 * @event getframe 3302 * @param {Number} index The frame index. 3303 * @param {Object} frame The frame object that getFrame will return. 3304 */ 3305 3306 /** 3307 * Dispatched when an image encounters an error. A SpriteSheet will dispatch an error event for each image that 3308 * encounters an error, and will still dispatch a {{#crossLink "SpriteSheet/complete:event"}}{{/crossLink}} 3309 * event once all images are finished processing, even if an error is encountered. 3310 * @event error 3311 * @param {String} src The source of the image that failed to load. 3312 * @since 0.8.2 3313 */ 3314 3315 3316// getter / setters: 3317 /** 3318 * Use the {{#crossLink "SpriteSheet/animations:property"}}{{/crossLink}} property instead. 3319 * @method _getAnimations 3320 * @protected 3321 * @return {Array} 3322 **/ 3323 p._getAnimations = function() { 3324 return this._animations.slice(); 3325 }; 3326 // SpriteSheet.getAnimations is @deprecated. Remove for 1.1+ 3327 p.getAnimations = createjs.deprecate(p._getAnimations, "SpriteSheet.getAnimations"); 3328 3329 /** 3330 * Returns an array of all available animation names available on this sprite sheet as strings. 3331 * @property animations 3332 * @type {Array} 3333 * @readonly 3334 **/ 3335 try { 3336 Object.defineProperties(p, { 3337 animations: { get: p._getAnimations } 3338 }); 3339 } catch (e) {} 3340 3341 3342// public methods: 3343 /** 3344 * Returns the total number of frames in the specified animation, or in the whole sprite 3345 * sheet if the animation param is omitted. Returns 0 if the spritesheet relies on calculated frame counts, and 3346 * the images have not been fully loaded. 3347 * @method getNumFrames 3348 * @param {String} animation The name of the animation to get a frame count for. 3349 * @return {Number} The number of frames in the animation, or in the entire sprite sheet if the animation param is omitted. 3350 */ 3351 p.getNumFrames = function(animation) { 3352 if (animation == null) { 3353 return this._frames ? this._frames.length : this._numFrames || 0; 3354 } else { 3355 var data = this._data[animation]; 3356 if (data == null) { return 0; } 3357 else { return data.frames.length; } 3358 } 3359 }; 3360 3361 /** 3362 * Returns an object defining the specified animation. The returned object c
3362ontains:<UL> 3363 * <li>frames: an array of the frame ids in the animation</li> 3364 * <li>speed: the playback speed for this animation</li> 3365 * <li>name: the name of the animation</li> 3366 * <li>next: the default animation to play next. If the animation loops, the name and next property will be the 3367 * same.</li> 3368 * </UL> 3369 * @method getAnimation 3370 * @param {String} name The name of the animation to get. 3371 * @return {Object} a generic object with frames, speed, name, and next properties. 3372 **/ 3373 p.getAnimation = function(name) { 3374 return this._data[name]; 3375 }; 3376 3377 /** 3378 * Returns an object specifying the image and source rect of the specified frame. The returned object has:<UL> 3379 * <li>an image property holding a reference to the image object in which the frame is found</li> 3380 * <li>a rect property containing a Rectangle instance which defines the boundaries for the frame within that 3381 * image.</li> 3382 * <li> A regX and regY property corresponding to the regX/Y values for the frame. 3383 * </UL> 3384 * @method getFrame 3385 * @param {Number} frameIndex The index of the frame. 3386 * @return {Object} a generic object with image and rect properties. Returns null if the frame does not exist. 3387 **/ 3388 p.getFrame = function(frameIndex) { 3389 var frame; 3390 if (this._frames && (frame=this._frames[frameIndex])) { return frame; } 3391 return null; 3392 }; 3393 3394 /** 3395 * Returns a {{#crossLink "Rectangle"}}{{/crossLink}} instance defining the bounds of the specified frame relative 3396 * to the origin. For example, a 90 x 70 frame with a regX of 50 and a regY of 40 would return: 3397 * 3398 * [x=-50, y=-40, width=90, height=70] 3399 * 3400 * @method getFrameBounds 3401 * @param {Number} frameIndex The index of the frame. 3402 * @param {Rectangle} [rectangle] A Rectangle instance to copy the values into. By default a new instance is created. 3403 * @return {Rectangle} A Rectangle instance. Returns null if the frame does not exist, or the image is not fully loaded. 3404 **/ 3405 p.getFrameBounds = function(frameIndex, rectangle) { 3406 var frame = this.getFrame(frameIndex); 3407 return frame ? (rectangle||new createjs.Rectangle()).setValues(-frame.regX, -frame.regY, frame.rect.width, frame.rect.height) : null; 3408 }; 3409 3410 /** 3411 * Returns a string representation of this object. 3412 * @method toString 3413 * @return {String} a string representation of the instance. 3414 **/ 3415 p.toString = function() { 3416 return "[SpriteSheet]"; 3417 }; 3418 3419 /** 3420 * SpriteSheet cannot be cloned. A SpriteSheet can be shared by multiple Sprite instances without cloning it. 3421 * @method clone 3422 **/ 3423 p.clone = function() { 3424 throw("SpriteSheet cannot be cloned.") 3425 }; 3426 3427// private methods: 3428 /** 3429 * @method _parseData 3430 * @param {Object} data An object describing the SpriteSheet data. 3431 * @protected 3432 **/ 3433 p._parseData = function(data) { 3434 var i,l,o,a; 3435 if (data == null) { return; } 3436 3437 this.framerate = data.framerate||0; 3438 3439 // parse images: 3440 if (data.images && (l=data.images.length) > 0) { 3441 a = this._images = []; 3442 for (i=0; i<l; i++) { 3443 var img = data.images[i]; 3444 if (typeof img == "string") { 3445 var src = img; 3446 img = document.createElement("img"); 3447 img.src = src; 3448 } 3449 a.push(img); 3450 if (!img.getContext && !img.naturalWidth) { 3451 this._loadCount++; 3452 this.complete = false; 3453 (function(o, src) { img.onload = function() { o._handleImageLoad(src); } })(this, src); 3454 (function(o, src) { img.onerror = function() { o._handleImageError(src); } })(this, src); 3455 } 3456 } 3457 } 3458 3459 // parse frames: 3460 if (data.frames == null) { // nothing 3461 } else if (Array.isArray(data.frames)) { 3462 this._frames = []; 3463 a = data.frames; 3464 for (i=0,l=a.length;i<l;i++) { 3465 var arr = a[i]; 3466 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 }); 3467 } 3468 } else { 3469 o = data.frames; 3470 this._frameWidth = o.width; 3471 this._frameHeight = o.height; 3472 this._regX = o.regX||0; 3473 this._regY = o.regY||0; 3474 this._spacing = o.spacing||0; 3475 this._margin = o.margin||0; 3476 this._numFrames = o.count; 3477 if (this._loadCount == 0) { this._calculateFrames(); } 3478 } 3479 3480 // parse animations: 3481 this._animations = []; 3482 if ((o=data.animations) != null) { 3483 this._data = {}; 3484 var name; 3485 for (name in o) { 3486 var anim = {name:name}; 3487 var obj = o[name]; 3488 if (typeof obj == "number") { // single frame 3489 a = anim.frames = [obj]; 3490 } else if (Array.isArray(obj)) { // simple 3491 if (obj.length == 1) { anim.frames = [obj[0]]; } 3492 else { 3493 anim.speed = obj[3]; 3494 anim.next = obj[2]; 3495 a = anim.frames = []; 3496 for (i=obj[0];i<=obj[1];i++) { 3497 a.push(i); 3498 } 3499 } 3500 } else { // complex 3501 anim.speed = obj.speed; 3502 anim.next = obj.next; 3503 var frames = obj.frames; 3504 a = anim.frames = (typeof frames == "number") ? [frames] : frames.slice(0); 3505 } 3506 if (anim.next === true || anim.next === undefined) { anim.next = name; } // loop 3507 if (anim.next === false || (a.length < 2 && anim.next == name)) { anim.next = null; } // stop 3508 if (!anim.speed) { anim.speed = 1; } 3509 this._animations.push(name); 3510 this._data[name] = anim; 3511 } 3512 } 3513 }; 3514 3515 /** 3516 * @method _handleImageLoad 3517 * @protected 3518 **/ 3519 p._handleImageLoad = function(src) { 3520 if (--this._loadCount == 0) { 3521 this._calculateFrames(); 3522 this.complete = true; 3523 this.dispatchEvent("complete"); 3524 } 3525 }; 3526 3527 /** 3528 * @method _handleImageError 3529 * @protected 3530 */ 3531 p._handleImageError = function (src) { 3532 var errorEvent = new createjs.Event("error"); 3533 errorEvent.src = src; 3534 this.dispatchEvent(errorEvent); 3535 3536 // Complete is still dispatched. 3537 if (--this._loadCount == 0) { 3538 this.dispatchEvent("complete"); 3539 } 3540 }; 3541 3542 /**
3543 * @method _calculateFrames 3544 * @protected 3545 **/ 3546 p._calculateFrames = function() { 3547 if (this._frames || this._frameWidth == 0) { return; } 3548 3549 this._frames = []; 3550 3551 var maxFrames = this._numFrames || 100000; // if we go over this, something is wrong. 3552 var frameCount = 0, frameWidth = this._frameWidth, frameHeight = this._frameHeight; 3553 var spacing = this._spacing, margin = this._margin; 3554 3555 imgLoop: 3556 for (var i=0, imgs=this._images; i<imgs.length; i++) { 3557 var img = imgs[i], imgW = (img.width||img.naturalWidth), imgH = (img.height||img.naturalHeight); 3558 3559 var y = margin; 3560 while (y <= imgH-margin-frameHeight) { 3561 var x = margin; 3562 while (x <= imgW-margin-frameWidth) { 3563 if (frameCount >= maxFrames) { break imgLoop; } 3564 frameCount++; 3565 this._frames.push({ 3566 image: img, 3567 rect: new createjs.Rectangle(x, y, frameWidth, frameHeight), 3568 regX: this._regX, 3569 regY: this._regY 3570 }); 3571 x += frameWidth+spacing; 3572 } 3573 y += frameHeight+spacing; 3574 } 3575 } 3576 this._numFrames = frameCount; 3577 }; 3578 3579 3580 createjs.SpriteSheet = createjs.promote(SpriteSheet, "EventDispatcher"); 3581}()); 3582 3583//############################################################################## 3584// Graphics.js 3585//############################################################################## 3586 3587this.createjs = this.createjs||{}; 3588 3589(function() { 3590 "use strict"; 3591 3592 3593// constructor: 3594 /** 3595 * The Graphics class exposes an easy to use API for generating vector drawing instructions and drawing them to a 3596 * specified context. Note that you can use Graphics without any dependency on the EaselJS framework by calling {{#crossLink "Graphics/draw"}}{{/crossLink}} 3597 * directly, or it can be used with the {{#crossLink "Shape"}}{{/crossLink}} object to draw vector graphics within the 3598 * context of an EaselJS display list. 3599 * 3600 * There are two approaches to working with Graphics object: calling methods on a Graphics instance (the "Graphics API"), or 3601 * instantiating Graphics command objects and adding them to the graphics queue via {{#crossLink "Graphics/append"}}{{/crossLink}}. 3602 * The former abstracts the latter, simplifying beginning and ending paths, fills, and strokes. 3603 * 3604 * var g = new createjs.Graphics(); 3605 * g.setStrokeStyle(1); 3606 * g.beginStroke("#000000"); 3607 * g.beginFill("red"); 3608 * g.drawCircle(0,0,30); 3609 * 3610 * All drawing methods in Graphics return the Graphics instance, so they can be chained together. For example, 3611 * the following line of code would generate the instructions to draw a rectangle with a red stroke and blue fill: 3612 * 3613 * myGraphics.beginStroke("red").beginFill("blue").drawRect(20, 20, 100, 50); 3614 * 3615 * Each graphics API call generates a command object (see below). The last command to be created can be accessed via 3616 * {{#crossLink "Graphics/command:property"}}{{/crossLink}}: 3617 * 3618 * var fillCommand = myGraphics.beginFill("red").command; 3619 * // ... later, update the fill style/color: 3620 * fillCommand.style = "blue"; 3621 * // or change it to a bitmap fill: 3622 * fillCommand.bitmap(myImage); 3623 * 3624 * For more direct control of rendering, you can instantiate and append command objects to the graphics queue directly. In this case, you 3625 * need to manage path creation manually, and ensure that fill/stroke is applied to a defined path: 3626 * 3627 * // start a new path. Graphics.beginCmd is a reusable BeginPath instance: 3628 * myGraphics.append(createjs.Graphics.beginCmd); 3629 * // we need to define the path before applying the fill: 3630 * var circle = new createjs.Graphics.Circle(0,0,30); 3631 * myGraphics.append(circle); 3632 * // fill the path we just defined: 3633 * var fill = new createjs.Graphics.Fill("red"); 3634 * myGraphics.append(fill); 3635 * 3636 * These approaches can be used together, for example to insert a custom command: 3637 * 3638 * myGraphics.beginFill("red"); 3639 * var customCommand = new CustomSpiralCommand(etc);
3640 * myGraphics.append(customCommand); 3641 * myGraphics.beginFill("blue"); 3642 * myGraphics.drawCircle(0, 0, 30); 3643 * 3644 * See {{#crossLink "Graphics/append"}}{{/crossLink}} for more info on creating custom commands. 3645 * 3646 * <h4>Tiny API</h4> 3647 * The Graphics class also includes a "tiny API", which is one or two-letter methods that are shortcuts for all of the 3648 * Graphics methods. These methods are great for creating compact instructions, and is used by the Toolkit for CreateJS 3649 * to generate readable code. All tiny methods are marked as protected, so you can view them by enabling protected 3650 * descriptions in the docs. 3651 * 3652 * <table> 3653 * <tr><td><b>Tiny</b></td><td><b>Method</b></td><td><b>Tiny</b></td><td><b>Method</b></td></tr> 3654 * <tr><td>mt</td><td>{{#crossLink "Graphics/moveTo"}}{{/crossLink}} </td> 3655 * <td>lt</td> <td>{{#crossLink "Graphics/lineTo"}}{{/crossLink}}</td></tr> 3656 * <tr><td>a/at</td><td>{{#crossLink "Graphics/arc"}}{{/crossLink}} / {{#crossLink "Graphics/arcTo"}}{{/crossLink}} </td> 3657 * <td>bt</td><td>{{#crossLink "Graphics/bezierCurveTo"}}{{/crossLink}} </td></tr> 3658 * <tr><td>qt</td><td>{{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} (also curveTo)</td> 3659 * <td>r</td><td>{{#crossLink "Graphics/rect"}}{{/crossLink}} </td></tr> 3660 * <tr><td>cp</td><td>{{#crossLink "Graphics/closePath"}}{{/crossLink}} </td> 3661 * <td>c</td><td>{{#crossLink "Graphics/clear"}}{{/crossLink}} </td></tr> 3662 * <tr><td>f</td><td>{{#crossLink "Graphics/beginFill"}}{{/crossLink}} </td> 3663 * <td>lf</td><td>{{#crossLink "Graphics/beginLinearGradientFill"}}{{/crossLink}} </td></tr> 3664 * <tr><td>rf</td><td>{{#crossLink "Graphics/beginRadialGradientFill"}}{{/crossLink}} </td> 3665 * <td>bf</td><td>{{#crossLink "Graphics/beginBitmapFill"}}{{/crossLink}} </td></tr> 3666 * <tr><td>ef</td><td>{{#crossLink "Graphics/endFill"}}{{/crossLink}} </td> 3667 * <td>ss / sd</td><td>{{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} / {{#crossLink "Graphics/setStrokeDash"}}{{/crossLink}} </td></tr> 3668 * <tr><td>s</td><td>{{#crossLink "Graphics/beginStroke"}}{{/crossLink}} </td> 3669 * <td>ls</td><td>{{#crossLink "Graphics/beginLinearGradientStroke"}}{{/crossLink}} </td></tr> 3670 * <tr><td>rs</td><td>{{#crossLink "Graphics/beginRadialGradientStroke"}}{{/crossLink}} </td> 3671 * <td>bs</td><td>{{#crossLink "Graphics/beginBitmapStroke"}}{{/crossLink}} </td></tr> 3672 * <tr><td>es</td><td>{{#crossLink "Graphics/endStroke"}}{{/crossLink}} </td> 3673 * <td>dr</td><td>{{#crossLink "Graphics/drawRect"}}{{/crossLink}} </td></tr> 3674 * <tr><td>rr</td><td>{{#crossLink "Graphics/drawRoundRect"}}{{/crossLink}} </td> 3675 * <td>rc</td><td>{{#crossLink "Graphics/drawRoundRectComplex"}}{{/crossLink}} </td></tr> 3676 * <tr><td>dc</td><td>{{#crossLink "Graphics/drawCircle"}}{{/crossLink}} </td> 3677 * <td>de</td><td>{{#crossLink "Graphics/drawEllipse"}}{{/crossLink}} </td></tr> 3678 * <tr><td>dp</td><td>{{#crossLink "Graphics/drawPolyStar"}}{{/crossLink}} </td> 3679 * <td>p</td><td>{{#crossLink "Graphics/decodePath"}}{{/crossLink}} </td></tr> 3680 * </table> 3681 * 3682 * Here is the above example, using the tiny API instead. 3683 * 3684 * myGraphics.s("red").f("blue").r(20, 20, 100, 50); 3685 * 3686 * @class Graphics 3687 * @constructor 3688 **/ 3689 function Graphics() { 3690 3691 3692 // public properties 3693 /** 3694 * Holds a reference to the last command that was created or appended. For example, you could retain a reference 3695 * to a Fill command in order to dynamically update the color later by using: 3696 * 3697 * var myFill = myGraphics.beginFill("red").command; 3698 * // update color later: 3699 * myFill.style = "yellow"; 3700 * 3701 * @property command 3702 * @type Object 3703 **/ 3704 this.command = null; 3705 3706 3707 // private properties 3708 /** 3709 * @property _stroke 3710 * @protected 3711 * @type {Stroke} 3712 **/ 3713 this._stroke = null; 3714 3715 /** 3716 * @property _strokeStyle 3717 * @protected 3718 * @type {StrokeStyle} 3719 **/ 3720 this._strokeStyle = null; 3721 3722 /** 3723 * @property _oldStrokeStyle 3724 * @protected 3725 * @type {StrokeStyle} 3726 **/ 3727 this._oldStrokeStyle = null; 3728 3729 /** 3730 * @property _strokeDash 3731 * @protected 3732 * @type {StrokeDash} 3733 **/ 3734 this._strokeDash = null; 3735 3736 /** 3737 * @property _oldStrokeDash 3738 * @protected 3739 * @type {StrokeDash} 3740 **/ 3741 this._oldStrokeDash = null; 3742 3743 /** 3744 * @property _strokeIgnoreScale 3745 * @protected 3746 * @type Boolean 3747 **/ 3748 this._strokeIgnoreScale = false;
3749 3750 /** 3751 * @property _fill 3752 * @protected 3753 * @type {Fill} 3754 **/ 3755 this._fill = null; 3756 3757 /** 3758 * @property _instructions 3759 * @protected 3760 * @type {Array} 3761 **/ 3762 this._instructions = []; 3763 3764 /** 3765 * Indicates the last instruction index that was committed. 3766 * @property _commitIndex 3767 * @protected 3768 * @type {Number} 3769 **/ 3770 this._commitIndex = 0; 3771 3772 /** 3773 * Uncommitted instructions. 3774 * @property _activeInstructions 3775 * @protected 3776 * @type {Array} 3777 **/ 3778 this._activeInstructions = []; 3779 3780 /** 3781 * This indicates that there have been changes to the activeInstruction list since the last updateInstructions call. 3782 * @property _dirty 3783 * @protected 3784 * @type {Boolean} 3785 * @default false 3786 **/ 3787 this._dirty = false; 3788 3789 /** 3790 * Index to draw from if a store operation has happened. 3791 * @property _storeIndex 3792 * @protected 3793 * @type {Number} 3794 * @default 0 3795 **/ 3796 this._storeIndex = 0; 3797 3798 // setup: 3799 this.clear(); 3800 } 3801 var p = Graphics.prototype; 3802 var G = Graphics; // shortcut 3803 3804// static public methods: 3805 /** 3806 * Returns a CSS compatible color string based on the specified RGB numeric color values in the format 3807 * "rgba(255,255,255,1.0)", or if alpha is null then in the format "rgb(255,255,255)". For example, 3808 * 3809 * createjs.Graphics.getRGB(50, 100, 150, 0.5); 3810 * // Returns "rgba(50,100,150,0.5)" 3811 * 3812 * It also supports passing a single hex color value as the first param, and an optional alpha value as the second 3813 * param. For example, 3814 * 3815 * createjs.Graphics.getRGB(0xFF00FF, 0.2); 3816 * // Returns "rgba(255,0,255,0.2)" 3817 * 3818 * @method getRGB 3819 * @static 3820 * @param {Number} r The red component for the color, between 0 and 0xFF (255). 3821 * @param {Number} g The green component for the color, between 0 and 0xFF (255). 3822 * @param {Number} b The blue component for the color, between 0 and 0xFF (255). 3823 * @param {Number} [alpha] The alpha component for the color where 0 is fully transparent and 1 is fully opaque. 3824 * @return {String} A CSS compatible color string based on the specified RGB numeric color values in the format 3825 * "rgba(255,255,255,1.0)", or if alpha is null then in the format "rgb(255,255,255)". 3826 **/ 3827 Graphics.getRGB = function(r, g, b, alpha) { 3828 if (r != null && b == null) { 3829 alpha = g; 3830 b = r&0xFF; 3831 g = r>>8&0xFF; 3832 r = r>>16&0xFF; 3833 } 3834 if (alpha == null) { 3835 return "rgb("+r+","+g+","+b+")"; 3836 } else { 3837 return "rgba("+r+","+g+","+b+","+alpha+")"; 3838 } 3839 }; 3840 3841 /** 3842 * Returns a CSS compatible color string based on the specified HSL numeric color values in the format "hsla(360,100,100,1.0)", 3843 * or if alpha is null then in the format "hsl(360,100,100)". 3844 * 3845 * createjs.Graphics.getHSL(150, 100, 70); 3846 * // Returns "hsl(150,100,70)" 3847 * 3848 * @method getHSL 3849 * @static 3850 * @param {Number} hue The hue component for the color, between 0 and 360. 3851 * @param {Number} saturation The saturation component for the color, between 0 and 100. 3852 * @param {Number} lightness The lightness component for the color, between 0 and 100. 3853 * @param {Number} [alpha] The alpha component for the color where 0 is fully transparent and 1 is fully opaque. 3854 * @return {String} A CSS compatible color string based on the specified HSL numeric color values in the format 3855 * "hsla(360,100,100,1.0)", or if alpha is null then in the format "hsl(360,100,100)". 3856 **/ 3857 Graphics.getHSL = function(hue, saturation, lightness, alpha) { 3858 if (alpha == null) { 3859 return "hsl("+(hue%360)+","+saturation+"%,"+lightness+"%)"; 3860 } else { 3861 return "hsla("+(hue%360)+","+saturation+"%,"+lightness+"%,"+alpha+")"; 3862 } 3863 }; 3864 3865 3866// static properties: 3867 /** 3868 * A reusable instance of {{#crossLink "Graphics/BeginPath"}}{{/crossLink}} to avoid 3869 * unnecessary instantiation. 3870 * @property beginCmd 3871 * @type {Graphics.BeginPath} 3872 * @static 3873 **/ 3874 // defined at the bottom of this file. 3875 3876 /** 3877 * Map of Base64 characters to values. Used by {{#crossLink "Graphics/decodePath"}}{{/crossLink}}. 3878 * @property BASE_64 3879 * @static 3880 * @final 3881 * @readonly 3882 * @type {Object} 3883 **/ 3884 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}; 3885 3886 /** 3887 * Maps numeric values for the caps parameter of {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} to 3888 * corresponding string values. This is primarily for use with the tiny API. The mappings are as follows: 0 to
3889 * "butt", 1 to "round", and 2 to "square". 3890 * For example, to set the line caps to "square": 3891 * 3892 * myGraphics.ss(16, 2); 3893 * 3894 * @property STROKE_CAPS_MAP 3895 * @static 3896 * @final 3897 * @readonly 3898 * @type {Array} 3899 **/ 3900 Graphics.STROKE_CAPS_MAP = ["butt", "round", "square"]; 3901 3902 /** 3903 * Maps numeric values for the joints parameter of {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} to 3904 * corresponding string values. This is primarily for use with the tiny API. The mappings are as follows: 0 to 3905 * "miter", 1 to "round", and 2 to "bevel". 3906 * For example, to set the line joints to "bevel": 3907 * 3908 * myGraphics.ss(16, 0, 2); 3909 * 3910 * @property STROKE_JOINTS_MAP 3911 * @static 3912 * @final 3913 * @readonly 3914 * @type {Array} 3915 **/ 3916 Graphics.STROKE_JOINTS_MAP = ["miter", "round", "bevel"]; 3917 3918 /** 3919 * @property _ctx 3920 * @static 3921 * @protected 3922 * @type {CanvasRenderingContext2D} 3923 **/ 3924 var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")); 3925 if (canvas.getContext) { 3926 Graphics._ctx = canvas.getContext("2d"); 3927 canvas.width = canvas.height = 1; 3928 } 3929 3930 3931// getter / setters: 3932 /** 3933 * Use the {{#crossLink "Graphics/instructions:property"}}{{/crossLink}} property instead. 3934 * @method _getInstructions 3935 * @protected 3936 * @return {Array} The instructions array, useful for chaining 3937 **/ 3938 p._getInstructions = function() { 3939 this._updateInstructions(); 3940 return this._instructions; 3941 }; 3942 // Graphics.getInstructions is @deprecated. Remove for 1.1+ 3943 p.getInstructions = createjs.deprecate(p._getInstructions, "Graphics.getInstructions"); 3944 3945 /** 3946 * Returns the graphics instructions array. Each entry is a graphics command object (ex. Graphics.Fill, Graphics.Rect) 3947 * Modifying the returned array directly is not recommended, and is likely to result in unexpected behaviour. 3948 * 3949 * This property is mainly intended for introspection of the instructions (ex. for graphics export). 3950 * @property instructions 3951 * @type {Array} 3952 * @readonly 3953 **/ 3954 try { 3955 Object.defineProperties(p, { 3956 instructions: { get: p._getInstructions } 3957 }); 3958 } catch (e) {} 3959 3960 3961// public methods: 3962 /** 3963 * Returns true if this Graphics instance has no drawing commands. 3964 * @method isEmpty 3965 * @return {Boolean} Returns true if this Graphics instance has no drawing commands. 3966 **/ 3967 p.isEmpty = function() { 3968 return !(this._instructions.length || this._activeInstructions.length); 3969 }; 3970 3971 /** 3972 * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. 3973 * Returns true if the draw was handled (useful for overriding functionality). 3974 * 3975 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 3976 * @method draw 3977 * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. 3978 * @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. 3979 **/ 3980 p.draw = function(ctx, data) { 3981 this._updateInstructions(); 3982 var instr = this._instructions; 3983 for (var i=this._storeIndex, l=instr.length; i<l; i++) { 3984 instr[i].exec(ctx, data); 3985 } 3986 }; 3987 3988 /** 3989 * Draws only the path described for this Graphics instance, skipping any non-path instructions, including fill and 3990 * stroke descriptions. Used for <code>DisplayObject.mask</code> to draw the clipping path, for example. 3991 * 3992 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 3993 * @method drawAsPath 3994 * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. 3995 **/ 3996 p.drawAsPath = function(ctx) { 3997 this._updateInstructions(); 3998 var instr, instrs = this._instructions; 3999 for (var i=this._storeIndex, l=instrs.length; i<l; i++) { 4000 // the first command is always a beginPath command. 4001 if ((instr = instrs[i]).path !== false) { instr.exec(ctx); } 4002 } 4003 }; 4004 4005 4006// public methods that map directly to context 2D calls: 4007 /** 4008 * Moves the drawing point to the specified position. A tiny API method "mt" also exists. 4009 * @method moveTo 4010 * @param {Number} x The x coordinate the drawing point should move to. 4011 * @param {Number} y The y coordinate the drawing point should move to. 4012 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls). 4013 * @chainable 4014 **/ 4015 p.moveTo = function(x, y) { 4016 return this.append(new G.MoveTo(x,y), true); 4017 }; 4018 4019 /** 4020 * Draws a line from the current drawing point to the specified position, which become the new current drawing 4021 * point. Note that you *must* call {{#crossLink "Graphics/moveTo"}}{{/crossLink}} before the first `lineTo()`. 4022 * A tiny API method "lt" also exists. 4023 * 4024 * For detailed information, read the 4025 * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#complex-shapes-(paths)"> 4026 * whatwg spec</a>. 4027 * @method lineTo 4028 * @param {Number} x The x coordinate the drawing point should draw to. 4029 * @param {Number} y The y coordinate the drawing point should draw to. 4030 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4031 * @chainable 4032 **/ 4033 p.lineTo = function(x, y) { 4034 return this.append(new G.LineTo(x,y)); 4035 }; 4036 4037 /** 4038 * Draws an arc with the specified control points and radius. For detailed information, read the 4039 * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arcto"> 4040 * whatwg spec</a>. A tiny API method "at" also exists. 4041 * @method arcTo 4042 * @param {Number} x1 4043 * @param {Number} y1 4044 * @param {Number} x2 4045 * @param {Number} y2 4046 * @param {Number} radius 4047 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4048 * @chainable 4049 **/ 4050 p.arcTo = function(x1, y1, x2, y2, radius) { 4051 return this.append(new G.ArcTo(x1, y1, x2, y2, radius)); 4052 }; 4053 4054 /** 4055 * Draws an arc defined by the radius, startAngle and endAngle arguments, centered at the position (x, y). For 4056 * example, to draw a full circle with a radius of 20 centered at (100, 100): 4057 * 4058 * arc(100, 100, 20, 0, Math.PI*2); 4059 * 4060 * For detailed information, read the 4061 * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arc">whatwg spec</a>. 4062 * A tiny API method "a" also exists. 4063 * @method arc 4064 * @param {Number} x 4065 * @param {Number} y 4066 * @param {Number} radius 4067 * @param {Number} startAngle Measured in radians. 4068 * @param {Number} endAngle Measured in radians. 4069 * @param {Boolean} anticlockwise 4070 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4071 * @chainable 4072 **/ 4073 p.arc = function(x, y, radius, startAngle, endAngle, anticlockwise) { 4074 return this.append(new G.Arc(x, y, radius, startAngle, endAngle, anticlockwise)); 4075 }; 4076 4077 /** 4078 * Draws a quadratic curve from the current drawing point to (x, y) using the control point (cpx, cpy). For detailed 4079 * information, read the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-quadraticcurveto"> 4080 * whatwg spec</a>. A tiny API method "qt" also exists. 4081 * @method quadraticCurveTo 4082 * @param {Number} cpx 4083 * @param {Number} cpy 4084 * @param {Number} x 4085 * @param {Number} y 4086 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4087 * @chainable 4088 **/ 4089 p.quadraticCurveTo = function(cpx, cpy, x, y) { 4090 return this.append(new G.QuadraticCurveTo(cpx, cpy, x, y)); 4091 }; 4092 4093 /** 4094 * Draws a bezier curve from the current drawing point to (x, y) using the control points (cp1x, cp1y) and (cp2x, 4095 * cp2y). For detailed information, read the 4096 * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-beziercurveto"> 4097 * whatwg spec</a>. A tiny API method "bt" also exists. 4098 * @method bezierCurveTo 4099 * @param {Number} cp1x 4100 * @param {Number} cp1y 4101 * @param {Number} cp2x 4102 * @param {Number} cp2y 4103 * @param {Number} x 4104 * @param {Number} y 4105 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4106 * @chainable 4107 **/ 4108 p.bezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) { 4109 return this.append(new G.BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)); 4110 }; 4111 4112 /** 4113 * Draws a rectangle at (x, y) with the specified width and height using the current fill and/or stroke. 4114 * For detailed information, read the 4115 * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-rect"> 4116 * whatwg spec</a>. A tiny API method "r" also exists. 4117 * @method rect 4118 * @param {Number} x 4119 * @param {Number} y 4120 * @param {Number} w Width of the rectangle 4121 * @param {Number} h Height of the rectangle 4122 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4123 * @chainable 4124 **/ 4125 p.rect = function(x, y, w, h) { 4126 return this.append(new G.Rect(x, y, w, h)); 4127 }; 4128 4129 /** 4130 * Closes the current path, effectively drawing a line from the current drawing point to the first drawing point specified 4131 * since the fill or stroke was last set. A tiny API method "cp" also exists. 4132 * @method closePath 4133 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4134 * @chainable 4135 **/ 4136 p.closePath = function() { 4137 return this._activeInstructions.length ? this.append(new G.ClosePath()) : this; 4138 }; 4139 4140 4141// public methods that roughly map to Adobe Flash/Animate graphics APIs: 4142 /** 4143 * Clears all drawing instructions, effectively resetting this Graphics instance. Any line and fill styles will need 4144 * to be redefined to draw shapes following a clear call. A tiny API method "c" also exists. 4145 * @method clear 4146 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4147 * @chainable 4148 **/ 4149 p.clear = function() { 4150 this._instructions.length = this._activeInstructions.length = this._commitIndex = 0; 4151 this._strokeStyle = this._oldStrokeStyle = this._stroke = this._fill = this._strokeDash = this._oldStrokeDash = null; 4152 this._dirty = this._strokeIgnoreScale = false;
4153 return this; 4154 }; 4155 4156 /** 4157 * Begins a fill with the specified color. This ends the current sub-path. A tiny API method "f" also exists. 4158 * @method beginFill 4159 * @param {String} color A CSS compatible color value (ex. "red", "#FF0000", or "rgba(255,0,0,0.5)"). Setting to 4160 * null will result in no fill. 4161 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4162 * @chainable 4163 **/ 4164 p.beginFill = function(color) { 4165 return this._setFill(color ? new G.Fill(color) : null); 4166 }; 4167 4168 /** 4169 * Begins a linear gradient fill defined by the line (x0, y0) to (x1, y1). This ends the current sub-path. For 4170 * example, the following code defines a black to white vertical gradient ranging from 20px to 120px, and draws a 4171 * square to display it: 4172 * 4173 * myGraphics.beginLinearGradientFill(["#000","#FFF"], [0, 1], 0, 20, 0, 120).drawRect(20, 20, 120, 120); 4174 * 4175 * A tiny API method "lf" also exists. 4176 * @method beginLinearGradientFill 4177 * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define a gradient 4178 * drawing from red to blue. 4179 * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 0.9] would draw 4180 * the first color to 10% then interpolating to the second color at 90%. 4181 * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. 4182 * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. 4183 * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. 4184 * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. 4185 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4186 * @chainable 4187 **/ 4188 p.beginLinearGradientFill = function(colors, ratios, x0, y0, x1, y1) { 4189 return this._setFill(new G.Fill().linearGradient(colors, ratios, x0, y0, x1, y1)); 4190 }; 4191 4192 /** 4193 * Begins a radial gradient fill. This ends the current sub-path. For example, the following code defines a red to 4194 * blue radial gradient centered at (100, 100), with a radius of 50, and draws a circle to display it: 4195 * 4196 * myGraphics.beginRadialGradientFill(["#F00","#00F"], [0, 1], 100, 100, 0, 100, 100, 50).drawCircle(100, 100, 50); 4197 * 4198 * A tiny API method "rf" also exists. 4199 * @method beginRadialGradientFill 4200 * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define 4201 * a gradient drawing from red to blue. 4202 * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 4203 * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. 4204 * @param {Number} x0 Center position of the inner circle that defines the gradient. 4205 * @param {Number} y0 Center position of the inner circle that defines the gradient. 4206 * @param {Number} r0 Radius of the inner circle that defines the gradient. 4207 * @param {Number} x1 Center position of the outer circle that defines the gradient. 4208 * @param {Number} y1 Center position of the outer circle that defines the gradient. 4209 * @param {Number} r1 Radius of the outer circle that defines the gradient. 4210 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4211 * @chainable 4212 **/ 4213 p.beginRadialGradientFill = function(colors, ratios, x0, y0, r0, x1, y1, r1) { 4214 return this._setFill(new G.Fill().radialGradient(colors, ratios, x0, y0, r0, x1, y1, r1)); 4215 }; 4216 4217 /** 4218 * Begins a pattern fill using the specified image. This ends the current sub-path. A tiny API method "bf" also 4219 * exists. 4220 * @method beginBitmapFill 4221 * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use 4222 * as the pattern. Must be loaded prior to creating a bitmap fill, or the fill will be empty. 4223 * @param {String} repetition Optional. Indicates whether to repeat the image in the fill area. One of "repeat", 4224 * "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". Note that Firefox does not support "repeat-x" or 4225 * "repeat-y" (latest tests were in FF 20.0), and will default to "repeat". 4226 * @param {Matrix2D} matrix Optional. Specifies a transformation matrix for the bitmap fill. This transformation 4227 * will be applied relative to the parent transform. 4228 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4229 * @chainable 4230 **/ 4231 p.beginBitmapFill = function(image, repetition, matrix) { 4232 return this._setFill(new G.Fill(null,matrix).bitmap(image, repetition)); 4233 }; 4234 4235 /** 4236 * Ends the current sub-path, and begins a new one with no fill. Functionally identical to <code>beginFill(null)</code>. 4237 * A tiny API method "ef" also exists. 4238 * @method endFill 4239 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4240 * @chainable 4241 **/ 4242 p.endFill = function() { 4243 return this.beginFill(); 4244 }; 4245 4246 /** 4247 * Sets the stroke style. Like all drawing methods, this can be chained, so you can define 4248 * the stroke style and color in a single line of code like so: 4249 * 4250 * myGraphics.setStrokeStyle(8,"round").beginStroke("#F00"); 4251 * 4252 * A tiny API method "ss" also exists. 4253 * @method setStrokeStyle 4254 * @param {Number} thickness The width of the stroke. 4255 * @param {String | Number} [caps=0] Indicates the type of caps to use at the end of lines. One of butt, 4256 * round, or square. Defaults to "butt". Also accepts the values 0 (butt), 1 (round), and 2
4256(square) for use with 4257 * the tiny API. 4258 * @param {String | Number} [joints=0] Specifies the type of joints that should be used where two lines meet. 4259 * One of bevel, round, or miter. Defaults to "miter". Also accepts the values 0 (miter), 1 (round), and 2 (bevel) 4260 * for use with the tiny API. 4261 * @param {Number} [miterLimit=10] If joints is set to "miter", then you can specify a miter limit ratio which 4262 * controls at what point a mitered joint will be clipped. 4263 * @param {Boolean} [ignoreScale=false] If true, the stroke will be drawn at the specified thickness regardless 4264 * of active transformations. 4265 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4266 * @chainable 4267 **/ 4268 p.setStrokeStyle = function(thickness, caps, joints, miterLimit, ignoreScale) { 4269 this._updateInstructions(true); 4270 this._strokeStyle = this.command = new G.StrokeStyle(thickness, caps, joints, miterLimit, ignoreScale); 4271 4272 // ignoreScale lives on Stroke, not StrokeStyle, so we do a little trickery: 4273 if (this._stroke) { this._stroke.ignoreScale = ignoreScale; } 4274 this._strokeIgnoreScale = ignoreScale; 4275 return this; 4276 }; 4277 4278 /** 4279 * Sets or clears the stroke dash pattern. 4280 * 4281 * myGraphics.setStrokeDash([20, 10], 0); 4282 * 4283 * A tiny API method `sd` also exists. 4284 * @method setStrokeDash 4285 * @param {Array} [segments] An array specifying the dash pattern, alternating between line and gap. 4286 * For example, `[20,10]` would create a pattern of 20 pixel lines with 10 pixel gaps between them. 4287 * Passing null or an empty array will clear the existing stroke dash. 4288 * @param {Number} [offset=0] The offset of the dash pattern. For example, you could increment this value to create a "marching ants" effect. 4289 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4290 * @chainable 4291 **/ 4292 p.setStrokeDash = function(segments, offset) { 4293 this._updateInstructions(true); 4294 this._strokeDash = this.command = new G.StrokeDash(segments, offset); 4295 return this; 4296 }; 4297 4298 /** 4299 * Begins a stroke with the specified color. This ends the current sub-path. A tiny API method "s" also exists. 4300 * @method beginStroke 4301 * @param {String} color A CSS compatible color value (ex. "#FF0000", "red", or "rgba(255,0,0,0.5)"). Setting to 4302 * null will result in no stroke. 4303 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4304 * @chainable 4305 **/ 4306 p.beginStroke = function(color) { 4307 return this._setStroke(color ? new G.Stroke(color) : null); 4308 }; 4309 4310 /** 4311 * Begins a linear gradient stroke defined by the line (x0, y0) to (x1, y1). This ends the current sub-path. For 4312 * example, the following code defines a black to white vertical gradient ranging from 20px to 120px, and draws a 4313 * square to display it: 4314 * 4315 * myGraphics.setStrokeStyle(10). 4316 * beginLinearGradientStroke(["#000","#FFF"], [0, 1], 0, 20, 0, 120).drawRect(20, 20, 120, 120); 4317 * 4318 * A tiny API method "ls" also exists. 4319 * @method beginLinearGradientStroke 4320 * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define 4321 * a gradient drawing from red to blue. 4322 * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 4323 * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. 4324 * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. 4325 * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. 4326 * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. 4327 * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. 4328 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4329 * @chainable 4330 **/ 4331 p.beginLinearGradientStroke = function(colors, ratios, x0, y0, x1, y1) { 4332 return this._setStroke(new G.Stroke().linearGradient(colors, ratios, x0, y0, x1, y1)); 4333 }; 4334 4335 /** 4336 * Begins a radial gradient stroke. This ends the current sub-path. For example, the following code defines a red to 4337 * blue radial gradient centered at (100, 100), with a radius of 50, and draws a rectangle to display it: 4338 * 4339 * myGraphics.setStrokeStyle(10) 4340 * .beginRadialGradientStroke(["#F00","#00F"], [0, 1], 100, 100, 0, 100, 100, 50) 4341 * .drawRect(50, 90, 150, 110); 4342 * 4343 * A tiny API method "rs" also exists. 4344 * @method beginRadialGradientStroke 4345 * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define 4346 * a gradient drawing from red to blue. 4347 * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 4348 * 0.9] would draw the first color to 10% then interpolating to the second color at 90%, then draw the second color 4349 * to 100%. 4350 * @param {Number} x0 Center position of the inner circle that defines the gradient. 4351 * @param {Number} y0 Center position of the inner circle that defines the gradient. 4352 * @param {Number} r0 Radius of the inner circle that defines the gradient. 4353 * @param {Number} x1 Center position of the outer circle that defines the gradient. 4354 * @param {Number} y1 Center position of the outer circle that defines the gradient. 4355 * @param {Number} r1 Radius of the outer circle that defines the gradient. 4356 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4357 * @chainable 4358 **/ 4359 p.beginRadialGradientStroke = function(colors, ratios, x0, y0, r0, x1, y1, r1) { 4360 return this._setStroke(new G.Stroke().radialGradient(colors, ratios, x0, y0, r0, x1, y1, r1)); 4361 }; 4362 4363 /** 4364 * Begins a pattern fill using the specified image. This ends the current sub-path. Note that unlike bitmap fills, 4365 * strokes do not currently support a matrix parameter due to limitations in the canvas API. A tiny API method "bs" 4366 * also exists. 4367 * @method beginBitmapStroke 4368 * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use 4369 * as the pattern. Must be loaded prior to creating a bitmap fill, or the fill will be empty. 4370 * @param {String} [repetition=repeat] Optional. Indicates whether to repeat the image in the fill area. One of 4371 * "repeat", "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". 4372 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4373 * @chainable 4374 **/ 4375 p.beginBitmapStroke = function(image, repetition) { 4376 // NOTE: matrix is not supported for stroke because transforms on strokes also affect the drawn stroke width. 4377 return this._setStroke(new G.Stroke().bitmap(image, repetition)); 4378 }; 4379 4380 /** 4381 * Ends the current sub-path, and begins a new one with no stroke. Functionally identical to <code>beginStroke(null)</code>. 4382 * A tiny API method "es" also exists. 4383 * @method endStroke 4384 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4385 * @chainable 4386 **/ 4387 p.endStroke = function() { 4388 return this.beginStroke(); 4389 }; 4390 4391 /** 4392 * Maps the familiar ActionScript <code>curveTo()</code> method to the functionally similar {{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} 4393 * method. 4394 * @method curveTo 4395 * @param {Number} cpx 4396 * @param {Number} cpy 4397 * @param {Number} x 4398 * @param {Number} y 4399 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4400 * @chainable 4401 **/ 4402 p.curveTo = p.quadraticCurveTo; 4403 4404 /** 4405 * 4406 * Maps the familiar ActionScript <code>drawRect()</code> method to the functionally similar {{#crossLink "Graphics/rect"}}{{/crossLink}} 4407 * method. 4408 * @method drawRect 4409 * @param {Number} x 4410 * @param {Number} y 4411 * @param {Number} w Width of the rectangle 4412 * @param {Number} h Height of the rectangle 4413 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4414 * @chainable 4415 **/ 4416 p.drawRect = p.rect; 4417 4418 /** 4419 * Draws a rounded rectangle with all corners with the specified radius. 4420 * @method drawRoundRect 4421 * @param {Number} x 4422 * @param {Number} y 4423 * @param {Number} w 4424 * @param {Number} h 4425 * @param {Number} radius Corner radius. 4426 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4427 * @chainable 4428 **/ 4429 p.drawRoundRect = function(x, y, w, h, radius) { 4430 return this.drawRoundRectComplex(x, y, w, h, radius, radius, radius, radius); 4431 }; 4432 4433 /**
4434 * Draws a rounded rectangle with different corner radii. Supports positive and negative corner radii. A tiny API 4435 * method "rc" also exists. 4436 * @method drawRoundRectComplex 4437 * @param {Number} x The horizontal coordinate to draw the round rect. 4438 * @param {Number} y The vertical coordinate to draw the round rect. 4439 * @param {Number} w The width of the round rect. 4440 * @param {Number} h The height of the round rect. 4441 * @param {Number} radiusTL Top left corner radius. 4442 * @param {Number} radiusTR Top right corner radius. 4443 * @param {Number} radiusBR Bottom right corner radius. 4444 * @param {Number} radiusBL Bottom left corner radius. 4445 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4446 * @chainable 4447 **/ 4448 p.drawRoundRectComplex = function(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL) { 4449 return this.append(new G.RoundRect(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL)); 4450 }; 4451 4452 /** 4453 * Draws a circle with the specified radius at (x, y). 4454 * 4455 * var g = new createjs.Graphics(); 4456 * g.setStrokeStyle(1); 4457 * g.beginStroke(createjs.Graphics.getRGB(0,0,0)); 4458 * g.beginFill(createjs.Graphics.getRGB(255,0,0)); 4459 * g.drawCircle(0,0,3); 4460 * 4461 * var s = new createjs.Shape(g); 4462 * s.x = 100; 4463 * s.y = 100; 4464 * 4465 * stage.addChild(s); 4466 * stage.update(); 4467 * 4468 * A tiny API method "dc" also exists. 4469 * @method drawCircle 4470 * @param {Number} x x coordinate center point of circle. 4471 * @param {Number} y y coordinate center point of circle. 4472 * @param {Number} radius Radius of circle. 4473 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4474 * @chainable 4475 **/ 4476 p.drawCircle = function(x, y, radius) { 4477 return this.append(new G.Circle(x, y, radius)); 4478 }; 4479 4480 /** 4481 * Draws an ellipse (oval) with a specified width (w) and height (h). Similar to {{#crossLink "Graphics/drawCircle"}}{{/crossLink}}, 4482 * except the width and height can be different. A tiny API method "de" also exists. 4483 * @method drawEllipse 4484 * @param {Number} x The left coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} 4485 * which draws from center. 4486 * @param {Number} y The top coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} 4487 * which draws from the center. 4488 * @param {Number} w The height (horizontal diameter) of the ellipse. The horizontal radius will be half of this 4489 * number. 4490 * @param {Number} h The width (vertical diameter) of the ellipse. The vertical radius will be half of this number. 4491 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4492 * @chainable 4493 **/ 4494 p.drawEllipse = function(x, y, w, h) { 4495 return this.append(new G.Ellipse(x, y, w, h)); 4496 }; 4497 4498 /**
4499 * Draws a star if pointSize is greater than 0, or a regular polygon if pointSize is 0 with the specified number of 4500 * points. For example, the following code will draw a familiar 5 pointed star shape centered at 100, 100 and with a 4501 * radius of 50: 4502 * 4503 * myGraphics.beginFill("#FF0").drawPolyStar(100, 100, 50, 5, 0.6, -90); 4504 * // Note: -90 makes the first point vertical 4505 * 4506 * A tiny API method "dp" also exists. 4507 * 4508 * @method drawPolyStar 4509 * @param {Number} x Position of the center of the shape. 4510 * @param {Number} y Position of the center of the shape. 4511 * @param {Number} radius The outer radius of the shape. 4512 * @param {Number} sides The number of points on the star or sides on the polygon. 4513 * @param {Number} pointSize The depth or "pointy-ness" of the star points. A pointSize of 0 will draw a regular 4514 * polygon (no points), a pointSize of 1 will draw nothing because the points are infinitely pointy. 4515 * @param {Number} angle The angle of the first point / corner. For example a value of 0 will draw the first point 4516 * directly to the right of the center. 4517 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4518 * @chainable 4519 **/ 4520 p.drawPolyStar = function(x, y, radius, sides, pointSize, angle) { 4521 return this.append(new G.PolyStar(x, y, radius, sides, pointSize, angle)); 4522 }; 4523 4524 /** 4525 * Appends a graphics command object to the graphics queue. Command objects expose an "exec" method 4526 * that accepts two parameters: the Context2D to operate on, and an arbitrary data object passed into 4527 * {{#crossLink "Graphics/draw"}}{{/crossLink}}. The latter will usually be the Shape instance that called draw. 4528 * 4529 * This method is used internally by Graphics methods, such as drawCircle, but can also be used directly to insert 4530 * built-in or custom graphics commands. For example: 4531 * 4532 * // attach data to our shape, so we can access it during the draw: 4533 * myShape.color = "red"; 4534 * 4535 * // append a Circle command object: 4536 * myShape.graphics.append(new createjs.Graphics.Circle(50, 50, 30)); 4537 * 4538 * // append a custom command object with an exec method that sets the fill style 4539 * // based on the shape's data, and then fills the circle. 4540 * myShape.graphics.append({exec:function(ctx, shape) { 4541 * ctx.fillStyle = shape.color; 4542 * ctx.fill(); 4543 * }}); 4544 * 4545 * @method append 4546 * @param {Object} command A graphics command object exposing an "exec" method. 4547 * @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. 4548 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4549 * @chainable 4550 **/ 4551 p.append = function(command, clean) { 4552 this._activeInstructions.push(command); 4553 this.command = command; 4554 if (!clean) { this._dirty = true; } 4555 return this; 4556 }; 4557 4558 /** 4559 * Decodes a compact encoded path string into a series of draw instructions. 4560 * This format is not intended to be human readable, and is meant for use by authoring tools. 4561 * The format uses a base64 character set, with each character representing 6 bits, to define a series of draw 4562 * commands. 4563 * 4564 * Each command is comprised of a single "header" character followed by a variable number of alternating x and y 4565 * position values. Reading the header bits from left to right (most to least significant): bits 1 to 3 specify the 4566 * type of operation (0-moveTo, 1-lineTo, 2-quadraticCurveTo, 3-bezierCurveTo, 4-closePath, 5-7 unused). Bit 4 4567 * indicates whether position values use 12 bits (2 characters) or 18 bits (3 characters), with a one indicating the 4568 * latter. Bits 5 and 6 are currently unused. 4569 * 4570 * Following the header is a series of 0 (closePath), 2 (moveTo, lineTo), 4 (quadraticCurveTo), or 6 (bezierCurveTo) 4571 * parameters. These parameters are alternating x/y positions represented by 2 or 3 characters (as indicated by the 4572 * 4th bit in the command char). These characters consist of a 1 bit sign (1 is negative, 0 is positive), followed 4573 * by an 11 (2 char) or 17 (3 char) bit integer value. All position values are in tenths of a pixel. Except in the 4574 * case of move operations which are absolute, this value is a delta from the previous x or y position (as 4575 * appropriate). 4576 * 4577 * For example, the string "A3cAAMAu4AAA" represents a line starting at -150,0 and ending at 150,0. 4578 * <br />A - bits 000000. First 3 bits (000) indicate a moveTo operation. 4th bit (0) indicates 2 chars per 4579 * parameter. 4580 * <br />n0 - 110111011100. Absolute x position of -150.0px. First bit indicates a negative value, remaining bits 4581 * indicate 1500 tenths of a pixel. 4582 * <br />AA - 000000000000. Absolute y position of 0. 4583 * <br />I - 001100. First 3 bits (001) indicate a lineTo operation. 4th bit (1) indicates 3 chars per parameter. 4584 * <br />Au4 - 000000101110111000. An x delta of 300.0px, which is added to the previous x value of -150.0px to
4585 * provide an absolute position of +150.0px. 4586 * <br />AAA - 000000000000000000. A y delta value of 0. 4587 * 4588 * A tiny API method "p" also exists. 4589 * @method decodePath 4590 * @param {String} str The path string to decode. 4591 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4592 * @chainable 4593 **/ 4594 p.decodePath = function(str) { 4595 var instructions = [this.moveTo, this.lineTo, this.quadraticCurveTo, this.bezierCurveTo, this.closePath]; 4596 var paramCount = [2, 2, 4, 6, 0]; 4597 var i=0, l=str.length; 4598 var params = []; 4599 var x=0, y=0; 4600 var base64 = Graphics.BASE_64; 4601 4602 while (i<l) { 4603 var c = str.charAt(i); 4604 var n = base64[c]; 4605 var fi = n>>3; // highest order bits 1-3 code for operation. 4606 var f = instructions[fi]; 4607 // check that we have a valid instruction & that the unused bits are empty: 4608 if (!f || (n&3)) { throw("bad path data (@"+i+"): "+c); } 4609 var pl = paramCount[fi]; 4610 if (!fi) { x=y=0; } // move operations reset the position. 4611 params.length = 0; 4612 i++; 4613 var charCount = (n>>2&1)+2; // 4th header bit indicates number size for this operation. 4614 for (var p=0; p<pl; p++) { 4615 var num = base64[str.charAt(i)]; 4616 var sign = (num>>5) ? -1 : 1; 4617 num = ((num&31)<<6)|(base64[str.charAt(i+1)]); 4618 if (charCount == 3) { num = (num<<6)|(base64[str.charAt(i+2)]); } 4619 num = sign*num/10; 4620 if (p%2) { x = (num += x); } 4621 else { y = (num += y); } 4622 params[p] = num; 4623 i += charCount; 4624 } 4625 f.apply(this,params); 4626 } 4627 return this; 4628 }; 4629 4630 /** 4631 * Stores all graphics commands so they won't be executed in future draws. Calling store() a second time adds to 4632 * the existing store. This also affects `drawAsPath()`. 4633 * 4634 * This is useful in cases where you are creating vector graphics in an iterative manner (ex. generative art), so 4635 * that only new graphics need to be drawn (which can provide huge performance benefits), but you wish to retain all 4636 * of the vector instructions for later use (ex. scaling, modifying, or exporting). 4637 * 4638 * Note that calling store() will force the active path (if any) to be ended in a manner similar to changing 4639 * the fill or stroke. 4640 * 4641 * For example, consider a application where the user draws lines with the mouse. As each line segment (or collection of 4642 * segments) are added to a Shape, it can be rasterized using {{#crossLink "DisplayObject/updateCache"}}{{/crossLink}}, 4643 * and then stored, so that it can be redrawn at a different scale when the application is resized, or exported to SVG. 4644 * 4645 * // set up cache: 4646 * myShape.cache(0,0,500,500,scale); 4647 * 4648 * // when the user drags, draw a new line: 4649 * myShape.graphics.moveTo(oldX,oldY).lineTo(newX,newY); 4650 * // then draw it into the existing cache: 4651 * myShape.updateCache("source-over"); 4652 * // store the new line, so it isn't redrawn next time: 4653 * myShape.store(); 4654 * 4655 * // then, when the window resizes, we can re-render at a different scale: 4656 * // first, unstore all our lines: 4657 * myShape.unstore(); 4658 * // then cache using the new scale: 4659 * myShape.cache(0,0,500,500,newScale); 4660 * // finally, store the existing commands again: 4661 * myShape.store(); 4662 * 4663 * @method store 4664 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4665 * @chainable 4666 **/ 4667 p.store = function() { 4668 this._updateInstructions(true); 4669 this._storeIndex = this._instructions.length; 4670 return this; 4671 }; 4672 4673 /** 4674 * Unstores any graphics commands that were previously stored using {{#crossLink "Graphics/store"}}{{/crossLink}} 4675 * so that they will be executed in subsequent draw calls. 4676 * 4677 * @method unstore 4678 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4679 * @chainable 4680 **/ 4681 p.unstore = function() { 4682 this._storeIndex = 0; 4683 return this; 4684 }; 4685 4686 /** 4687 * Returns a clone of this Graphics instance. Note that the individual command objects are not cloned. 4688 * @method clone 4689 * @return {Graphics} A clone of the current Graphics instance. 4690 **/ 4691 p.clone = function() { 4692 var o = new Graphics(); 4693 o.command = this.command; 4694 o._stroke = this._stroke; 4695 o._strokeStyle = this._strokeStyle; 4696 o._strokeDash = this._strokeDash; 4697 o._strokeIgnoreScale = this._strokeIgnoreScale; 4698 o._fill = this._fill; 4699 o._instructions = this._instructions.slice(); 4700 o._commitIndex = this._commitIndex; 4701 o._activeInstructions = this._activeInstructions.slice(); 4702 o._dirty = this._dirty; 4703 o._storeIndex = this._storeIndex; 4704 return o; 4705 }; 4706 4707 /** 4708 * Returns a string representation of this object. 4709 * @method toString 4710 * @return {String} a string representation of the instance. 4711 **/ 4712 p.toString = function() { 4713 return "[Graphics]"; 4714 }; 4715 4716 4717// tiny API: 4718 /** 4719 * Shortcut to moveTo. 4720 * @method mt 4721 * @param {Number} x The x coordinate the drawing point should move to. 4722 * @param {Number} y The y coordinate the drawing point should move to. 4723 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls). 4724 * @chainable 4725 * @protected 4726 **/ 4727 p.mt = p.moveTo; 4728 4729 /** 4730 * Shortcut to lineTo. 4731 * @method lt 4732 * @param {Number} x The x coordinate the drawing point should draw to. 4733 * @param {Number} y The y coordinate the drawing point should draw to. 4734 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4735 * @chainable 4736 * @protected 4737 **/ 4738 p.lt = p.lineTo; 4739 4740 /** 4741 * Shortcut to arcTo. 4742 * @method at 4743 * @param {Number} x1 4744 * @param {Number} y1 4745 * @param {Number} x2 4746 * @param {Number} y2 4747 * @param {Number} radius 4748 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4749 * @chainable 4750 * @protected 4751 **/ 4752 p.at = p.arcTo; 4753 4754 /** 4755 * Shortcut to bezierCurveTo. 4756 * @method bt 4757 * @param {Number} cp1x 4758 * @param {Number} cp1y 4759 * @param {Number} cp2x 4760 * @param {Number} cp2y 4761 * @param {Number} x 4762 * @param {Number} y 4763 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4764 * @chainable 4765 * @protected 4766 **/ 4767 p.bt = p.bezierCurveTo; 4768 4769 /** 4770 * Shortcut to quadraticCurveTo / curveTo. 4771 * @method qt 4772 * @param {Number} cpx 4773 * @param {Number} cpy 4774 * @param {Number} x 4775 * @param {Number} y 4776 * @protected 4777 * @chainable 4778 **/ 4779 p.qt = p.quadraticCurveTo; 4780 4781 /** 4782 * Shortcut to arc. 4783 * @method a 4784 * @param {Number} x 4785 * @param {Number} y 4786 * @param {Number} radius 4787 * @param {Number} startAngle Measured in radians. 4788 * @param {Number} endAngle Measured in radians. 4789 * @param {Boolean} anticlockwise 4790 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4791 * @protected 4792 * @chainable 4793 **/ 4794 p.a = p.arc; 4795 4796 /** 4797 * Shortcut to rect. 4798 * @method r 4799 * @param {Number} x 4800 * @param {Number} y 4801 * @param {Number} w Width of the rectangle 4802 * @param {Number} h Height of the rectangle 4803 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4804 * @chainable 4805 * @protected 4806 **/ 4807 p.r = p.rect; 4808 4809 /** 4810 * Shortcut to closePath. 4811 * @method cp 4812 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4813 * @chainable 4814 * @protected 4815 **/ 4816 p.cp = p.closePath; 4817 4818 /** 4819 * Shortcut to clear. 4820 * @method c 4821 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4822 * @chainable 4823 * @protected 4824 **/ 4825 p.c = p.clear; 4826 4827 /** 4828 * Shortcut to beginFill. 4829 * @method f 4830 * @param {String} color A CSS compatible color value (ex. "red", "#FF0000", or "rgba(255,0,0,0.5)"). Setting to 4831 * null will result in no fill. 4832 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4833 * @chainable 4834 * @protected 4835 **/ 4836 p.f = p.beginFill; 4837 4838 /** 4839 * Shortcut to beginLinearGradientFill. 4840 * @method lf 4841 * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define a gradient 4842 * drawing from red to blue. 4843 * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 0.9] would draw 4844 * the first color to 10% then interpolating to the second color at 90%. 4845 * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. 4846 * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. 4847 * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. 4848 * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. 4849 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4850 * @chainable 4851 * @protected 4852 **/ 4853 p.lf = p.beginLinearGradientFill; 4854 4855 /** 4856 * Shortcut to beginRadialGradientFill. 4857 * @method rf 4858 * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define 4859 * a gradient drawing from red to blue. 4860 * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 4861 * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. 4862 * @param {Number} x0 Center position of the inner circle that defines the gradient. 4863 * @param {Number} y0 Center position of the inner circle that defines the gradient. 4864 * @param {Number} r0 Radius of the inner circle that defines the gradient. 4865 * @param {Number} x1 Center position of the outer circle that defines the gradient. 4866 * @param {Number} y1 Center position of the outer circle that defines the gradient. 4867 * @param {Number} r1 Radius of the outer circle that defines the gradient. 4868 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4869 * @chainable 4870 * @protected 4871 **/ 4872 p.rf = p.beginRadialGradientFill; 4873 4874 /** 4875 * Shortcut to beginBitmapFill. 4876 * @method bf 4877 * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use 4878 * as the pattern. 4879 * @param {String} repetition Optional. Indicates whether to repeat the image in the fill area. One of "repeat", 4880 * "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". Note that Firefox does not support "repeat-x" or 4881 * "repeat-y" (latest tests were in FF 20.0), and will default to "repeat". 4882 * @param {Matrix2D} matrix Optional. Specifies a transformation matrix for the bitmap fill. This transformation 4883 * will be applied relative to the parent transform. 4884 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4885 * @chainable 4886 * @protected 4887 **/ 4888 p.bf = p.beginBitmapFill; 4889 4890 /** 4891 * Shortcut to endFill. 4892 * @method ef 4893 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4894 * @chainable 4895 * @protected 4896 **/ 4897 p.ef = p.endFill; 4898 4899 /** 4900 * Shortcut to setStrokeStyle. 4901 * @method ss 4902 * @param {Number} thickness The width of the stroke. 4903 * @param {String | Number} [caps=0] Indicates the type of caps to use at the end of lines. One of butt, 4904 * round, or square. Defaults to "butt". Also accepts the values 0 (butt), 1 (round), and 2
4904(square) for use with 4905 * the tiny API. 4906 * @param {String | Number} [joints=0] Specifies the type of joints that should be used where two lines meet. 4907 * One of bevel, round, or miter. Defaults to "miter". Also accepts the values 0 (miter), 1 (round), and 2 (bevel) 4908 * for use with the tiny API. 4909 * @param {Number} [miterLimit=10] If joints is set to "miter", then you can specify a miter limit ratio which 4910 * controls at what point a mitered joint will be clipped. 4911 * @param {Boolean} [ignoreScale=false] If true, the stroke will be drawn at the specified thickness regardless 4912 * of active transformations. 4913 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4914 * @chainable 4915 * @protected 4916 **/ 4917 p.ss = p.setStrokeStyle; 4918 4919 /** 4920 * Shortcut to setStrokeDash. 4921 * @method sd 4922 * @param {Array} [segments] An array specifying the dash pattern, alternating between line and gap. 4923 * For example, [20,10] would create a pattern of 20 pixel lines with 10 pixel gaps between them. 4924 * Passing null or an empty array will clear any existing dash. 4925 * @param {Number} [offset=0] The offset of the dash pattern. For example, you could increment this value to create a "marching ants" effect. 4926 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4927 * @chainable 4928 * @protected 4929 **/ 4930 p.sd = p.setStrokeDash; 4931 4932 /** 4933 * Shortcut to beginStroke. 4934 * @method s 4935 * @param {String} color A CSS compatible color value (ex. "#FF0000", "red", or "rgba(255,0,0,0.5)"). Setting to 4936 * null will result in no stroke. 4937 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4938 * @chainable 4939 * @protected 4940 **/ 4941 p.s = p.beginStroke; 4942 4943 /** 4944 * Shortcut to beginLinearGradientStroke. 4945 * @method ls 4946 * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define 4947 * a gradient drawing from red to blue. 4948 * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 4949 * 0.9] would draw the first color to 10% then interpolating to the second color at 90%. 4950 * @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size. 4951 * @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size. 4952 * @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size. 4953 * @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size. 4954 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4955 * @chainable 4956 * @protected 4957 **/ 4958 p.ls = p.beginLinearGradientStroke; 4959 4960 /** 4961 * Shortcut to beginRadialGradientStroke. 4962 * @method rs 4963 * @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define 4964 * a gradient drawing from red to blue. 4965 * @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 4966 * 0.9] would draw the first color to 10% then interpolating to the second color at 90%, then draw the second color 4967 * to 100%. 4968 * @param {Number} x0 Center position of the inner circle that defines the gradient. 4969 * @param {Number} y0 Center position of the inner circle that defines the gradient. 4970 * @param {Number} r0 Radius of the inner circle that defines the gradient. 4971 * @param {Number} x1 Center position of the outer circle that defines the gradient. 4972 * @param {Number} y1 Center position of the outer circle that defines the gradient. 4973 * @param {Number} r1 Radius of the outer circle that defines the gradient. 4974 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4975 * @chainable 4976 * @protected 4977 **/ 4978 p.rs = p.beginRadialGradientStroke; 4979 4980 /** 4981 * Shortcut to beginBitmapStroke. 4982 * @method bs 4983 * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use 4984 * as the pattern. 4985 * @param {String} [repetition=repeat] Optional. Indicates whether to repeat the image in the fill area. One of 4986 * "repeat", "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". 4987 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4988 * @chainable 4989 * @protected 4990 **/ 4991 p.bs = p.beginBitmapStroke; 4992 4993 /** 4994 * Shortcut to endStroke. 4995 * @method es 4996 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 4997 * @chainable 4998 * @protected 4999 **/ 5000 p.es = p.endStroke; 5001 5002 /** 5003 * Shortcut to drawRect. 5004 * @method dr 5005 * @param {Number} x 5006 * @param {Number} y 5007 * @param {Number} w Width of the rectangle 5008 * @param {Number} h Height of the rectangle 5009 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 5010 * @chainable 5011 * @protected 5012 **/ 5013 p.dr = p.drawRect; 5014 5015 /** 5016 * Shortcut to drawRoundRect. 5017 * @method rr 5018 * @param {Number} x 5019 * @param {Number} y 5020 * @param {Number} w 5021 * @param {Number} h 5022 * @param {Number} radius Corner radius. 5023 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 5024 * @chainable 5025 * @protected 5026 **/ 5027 p.rr = p.drawRoundRect; 5028 5029 /** 5030 * Shortcut to drawRoundRectComplex. 5031 * @method rc 5032 * @param {Number} x The horizontal coordinate to draw the round rect. 5033 * @param {Number} y The vertical coordinate to draw the round rect. 5034 * @param {Number} w The width of the round rect. 5035 * @param {Number} h The height of the round rect. 5036 * @param {Number} radiusTL Top left corner radius. 5037 * @param {Number} radiusTR Top right corner radius. 5038 * @param {Number} radiusBR Bottom right corner radius. 5039 * @param {Number} radiusBL Bottom left corner radius. 5040 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 5041 * @chainable 5042 * @protected 5043 **/ 5044 p.rc = p.drawRoundRectComplex; 5045 5046 /** 5047 * Shortcut to drawCircle. 5048 * @method dc 5049 * @param {Number} x x coordinate center point of circle. 5050 * @param {Number} y y coordinate center point of circle. 5051 * @param {Number} radius Radius of circle. 5052 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 5053 * @chainable 5054 * @protected 5055 **/ 5056 p.dc = p.drawCircle; 5057 5058 /** 5059 * Shortcut to drawEllipse. 5060 * @method de 5061 * @param {Number} x The left coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} 5062 * which draws from center. 5063 * @param {Number} y The top coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} 5064 * which draws from the center. 5065 * @param {Number} w The height (horizontal diameter) of the ellipse. The horizontal radius will be half of this 5066 * number. 5067 * @param {Number} h The width (vertical diameter) of the ellipse. The vertical radius will be half of this number. 5068 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 5069 * @chainable 5070 * @protected 5071 **/ 5072 p.de = p.drawEllipse; 5073 5074 /** 5075 * Shortcut to drawPolyStar. 5076 * @method dp 5077 * @param {Number} x Position of the center of the shape. 5078 * @param {Number} y Position of the center of the shape. 5079 * @param {Number} radius The outer radius of the shape. 5080 * @param {Number} sides The number of points on the star or sides on the polygon. 5081 * @param {Number} pointSize The depth or "pointy-ness" of the star points. A pointSize of 0 will draw a regular
5082 * polygon (no points), a pointSize of 1 will draw nothing because the points are infinitely pointy. 5083 * @param {Number} angle The angle of the first point / corner. For example a value of 0 will draw the first point 5084 * directly to the right of the center. 5085 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 5086 * @chainable 5087 * @protected 5088 **/ 5089 p.dp = p.drawPolyStar; 5090 5091 /** 5092 * Shortcut to decodePath. 5093 * @method p 5094 * @param {String} str The path string to decode. 5095 * @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.) 5096 * @chainable 5097 * @protected 5098 **/ 5099 p.p = p.decodePath; 5100 5101 5102// private methods: 5103 /** 5104 * @method _updateInstructions 5105 * @param commit 5106 * @protected 5107 **/ 5108 p._updateInstructions = function(commit) { 5109 var instr = this._instructions, active = this._activeInstructions, commitIndex = this._commitIndex; 5110 5111 if (this._dirty && active.length) { 5112 instr.length = commitIndex; // remove old, uncommitted commands 5113 instr.push(Graphics.beginCmd); 5114 5115 var l = active.length, ll = instr.length; 5116 instr.length = ll+l; 5117 for (var i=0; i<l; i++) { instr[i+ll] = active[i]; } 5118 5119 if (this._fill) { instr.push(this._fill); } 5120 if (this._stroke) { 5121 // doesn't need to be re-applied if it hasn't changed. 5122 if (this._strokeDash !== this._oldStrokeDash) { 5123 instr.push(this._strokeDash); 5124 } 5125 if (this._strokeStyle !== this._oldStrokeStyle) { 5126 instr.push(this._strokeStyle); 5127 } 5128 if (commit) { 5129 this._oldStrokeStyle = this._strokeStyle; 5130 this._oldStrokeDash = this._strokeDash; 5131 } 5132 instr.push(this._stroke); 5133 } 5134 5135 this._dirty = false; 5136 } 5137 5138 if (commit) { 5139 active.length = 0; 5140 this._commitIndex = instr.length; 5141 } 5142 }; 5143 5144 /** 5145 * @method _setFill 5146 * @param fill 5147 * @protected 5148 **/ 5149 p._setFill = function(fill) { 5150 this._updateInstructions(true); 5151 this.command = this._fill = fill; 5152 return this; 5153 }; 5154 5155 /** 5156 * @method _setStroke 5157 * @param stroke 5158 * @protected 5159 **/ 5160 p._setStroke = function(stroke) { 5161 this._updateInstructions(true); 5162 if (this.command = this._stroke = stroke) { 5163 stroke.ignoreScale = this._strokeIgnoreScale; 5164 } 5165 return this; 5166 }; 5167 5168// Command Objects: 5169 /** 5170 * @namespace Graphics 5171 */ 5172 /** 5173 * 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. 5174 * @class LineTo 5175 * @constructor 5176 * @param {Number} x 5177 * @param {Number} y 5178 **/ 5179 /** 5180 * @property x 5181 * @type Number 5182 */ 5183 /** 5184 * @property y 5185 * @type Number 5186 */ 5187 /** 5188 * Execute the Graphics command in the provided Canvas context. 5189 * @method exec 5190 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5191 */ 5192 (G.LineTo = function(x, y) { 5193 this.x = x; this.y = y; 5194 }).prototype.exec = function(ctx) { ctx.lineTo(this.x,this.y); }; 5195 5196 /** 5197 * Graphics command object. See {{#crossLink "Graphics/moveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5198 * @class MoveTo 5199 * @constructor 5200 * @param {Number} x 5201 * @param {Number} y 5202 **/ 5203 /** 5204 * @property x 5205 * @type Number 5206 */ 5207 /** 5208 * @property y 5209 * @type Number 5210 */ 5211 /** 5212 * @method exec 5213 * @param {CanvasRenderingContext2D} ctx 5214 */ 5215 (G.MoveTo = function(x, y) { 5216 this.x = x; this.y = y; 5217 }).prototype.exec = function(ctx) { ctx.moveTo(this.x, this.y); }; 5218 5219 5220 /** 5221 * Graphics command object. See {{#crossLink "Graphics/arcTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5222 * @class ArcTo 5223 * @constructor 5224 * @param {Number} x1 5225 * @param {Number} y1 5226 * @param {Number} x2 5227 * @param {Number} y2 5228 * @param {Number} radius 5229 **/ 5230 /** 5231 * @property x1 5232 * @type Number 5233 */ 5234 /** 5235 * @property y1 5236 * @type Number 5237 */ 5238 /** 5239 * @property x2 5240 * @type Number 5241 */ 5242 /** 5243 * @property y2 5244 * @type Number 5245 */ 5246 /**
5247 * @property radius 5248 * @type Number 5249 */ 5250 /** 5251 * Execute the Graphics command in the provided Canvas context. 5252 * @method exec 5253 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5254 */ 5255 (G.ArcTo = function(x1, y1, x2, y2, radius) { 5256 this.x1 = x1; this.y1 = y1; 5257 this.x2 = x2; this.y2 = y2; 5258 this.radius = radius; 5259 }).prototype.exec = function(ctx) { ctx.arcTo(this.x1, this.y1, this.x2, this.y2, this.radius); }; 5260 5261 /** 5262 * Graphics command object. See {{#crossLink "Graphics/arc"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5263 * @class Arc 5264 * @constructor 5265 * @param {Number} x 5266 * @param {Number} y 5267 * @param {Number} radius 5268 * @param {Number} startAngle 5269 * @param {Number} endAngle 5270 * @param {Number} anticlockwise 5271 **/ 5272 /** 5273 * @property x 5274 * @type Number 5275 */ 5276 /** 5277 * @property y 5278 * @type Number 5279 */ 5280 /** 5281 * @property radius 5282 * @type Number 5283 */ 5284 /** 5285 * @property startAngle 5286 * @type Number 5287 */ 5288 /** 5289 * @property endAngle 5290 * @type Number 5291 */ 5292 /** 5293 * @property anticlockwise 5294 * @type Number 5295 */ 5296 /** 5297 * Execute the Graphics command in the provided Canvas context. 5298 * @method exec 5299 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5300 */ 5301 (G.Arc = function(x, y, radius, startAngle, endAngle, anticlockwise) { 5302 this.x = x; this.y = y; 5303 this.radius = radius; 5304 this.startAngle = startAngle; this.endAngle = endAngle; 5305 this.anticlockwise = !!anticlockwise; 5306 }).prototype.exec = function(ctx) { ctx.arc(this.x, this.y, this.radius, this.startAngle, this.endAngle, this.anticlockwise); }; 5307 5308 /** 5309 * Graphics command object. See {{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5310 * @class QuadraticCurveTo 5311 * @constructor 5312 * @param {Number} cpx 5313 * @param {Number} cpy 5314 * @param {Number} x 5315 * @param {Number} y 5316 **/ 5317 /** 5318 * @property cpx 5319 * @type Number 5320 */ 5321 /** 5322 * @property cpy 5323 * @type Number 5324 */ 5325 /** 5326 * @property x 5327 * @type Number 5328 */ 5329 /** 5330 * @property y 5331 * @type Number 5332 */ 5333 /** 5334 * Execute the Graphics command in the provided Canvas context. 5335 * @method exec 5336 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5337 */ 5338 (G.QuadraticCurveTo = function(cpx, cpy, x, y) { 5339 this.cpx = cpx; this.cpy = cpy; 5340 this.x = x; this.y = y; 5341 }).prototype.exec = function(ctx) { ctx.quadraticCurveTo(this.cpx, this.cpy, this.x, this.y); }; 5342 5343 /** 5344 * Graphics command object. See {{#crossLink "Graphics/bezierCurveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5345 * @class BezierCurveTo 5346 * @constructor 5347 * @param {Number} cp1x 5348 * @param {Number} cp1y 5349 * @param {Number} cp2x 5350 * @param {Number} cp2y 5351 * @param {Number} x 5352 * @param {Number} y 5353 **/ 5354 /** 5355 * @property cp1x 5356 * @type Number 5357 */ 5358 /** 5359 * @property cp1y 5360 * @type Number 5361 */ 5362 /** 5363 * @property cp2x 5364 * @type Number 5365 */ 5366 /** 5367 * @property cp2y 5368 * @type Number 5369 */ 5370 /** 5371 * @property x 5372 * @type Number 5373 */ 5374 /** 5375 * @property y 5376 * @type Number 5377 */ 5378 /** 5379 * Execute the Graphics command in the provided Canvas context. 5380 * @method exec 5381 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5382 */ 5383 (G.BezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) { 5384 this.cp1x = cp1x; this.cp1y = cp1y; 5385 this.cp2x = cp2x; this.cp2y = cp2y; 5386 this.x = x; this.y = y; 5387 }).prototype.exec = function(ctx) { ctx.bezierCurveTo(this.cp1x, this.cp1y, this.cp2x, this.cp2y, this.x, this.y); }; 5388 5389 /** 5390 * Graphics command object. See {{#crossLink "Graphics/rect"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5391 * @class Rect 5392 * @constructor 5393 * @param {Number} x 5394 * @param {Number} y 5395 * @param {Number} w 5396 * @param {Number} h 5397 **/ 5398 /** 5399 * @property x 5400 * @type Number 5401 */ 5402 /** 5403 * @property y 5404 * @type Number 5405 */ 5406 /** 5407 * @property w 5408 * @type Number 5409 */ 5410 /** 5411 * @property h 5412 * @type Number 5413 */ 5414 /** 5415 * Execute the Graphics command in the provided Canvas context. 5416 * @method exec 5417 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5418 */ 5419 (G.Rect = function(x, y, w, h) { 5420 this.x = x; this.y = y; 5421 this.w = w; this.h = h; 5422 }).prototype.exec = function(ctx) { ctx.rect(this.x, this.y, this.w, this.h); }; 5423 5424 /** 5425 * Graphics command object. See {{#crossLink "Graphics/closePath"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5426 * @class ClosePath 5427 * @constructor 5428 **/ 5429 /** 5430 * Execute the Graphics command in the provided Canvas context. 5431 * @method exec 5432 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5433 */ 5434 (G.ClosePath = function() { 5435 }).prototype.exec = function(ctx) { ctx.closePath(); }; 5436 5437 /** 5438 * Graphics command object to begin a new path. See {{#crossLink "Graphics"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5439 * @class BeginPath 5440 * @constructor 5441 **/ 5442 /** 5443 * Execute the Graphics command in the provided Canvas context. 5444 * @method exec 5445 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5446 */ 5447 (G.BeginPath = function() { 5448 }).prototype.exec = function(ctx) { ctx.beginPath(); }; 5449 5450 /** 5451 * Graphics command object. See {{#crossLink "Graphics/beginFill"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5452 * @class Fill 5453 * @constructor 5454 * @param {Object} style A valid Context2D fillStyle. 5455 * @param {Matrix2D} matrix 5456 **/ 5457 /** 5458 * A valid Context2D fillStyle. 5459 * @property style 5460 * @type Object 5461 */ 5462 /** 5463 * @property matrix 5464 * @type Matrix2D 5465 */ 5466 /** 5467 * Execute the Graphics command in the provided Canvas context. 5468 * @method exec 5469 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5470 */
5471 p = (G.Fill = function(style, matrix) { 5472 this.style = style; 5473 this.matrix = matrix; 5474 }).prototype; 5475 p.exec = function(ctx) { 5476 if (!this.style) { return; } 5477 ctx.fillStyle = this.style; 5478 var mtx = this.matrix; 5479 if (mtx) { ctx.save(); ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty); } 5480 ctx.fill(); 5481 if (mtx) { ctx.restore(); } 5482 }; 5483 /** 5484 * Creates a linear gradient style and assigns it to {{#crossLink "Fill/style:property"}}{{/crossLink}}. 5485 * See {{#crossLink "Graphics/beginLinearGradientFill"}}{{/crossLink}} for more information. 5486 * @method linearGradient 5487 * @param {Array} colors 5488 * 5489 * @param {Array} ratios 5490 * @param {Number} x0 5491 * @param {Number} y0 5492 * @param {Number} x1 5493 * @param {Number} y1 5494 * @return {Fill} Returns this Fill object for chaining or assignment. 5495 */ 5496 p.linearGradient = function(colors, ratios, x0, y0, x1, y1) { 5497 var o = this.style = Graphics._ctx.createLinearGradient(x0, y0, x1, y1); 5498 for (var i=0, l=colors.length; i<l; i++) { o.addColorStop(ratios[i], colors[i]); } 5499 o.props = {colors:colors, ratios:ratios, x0:x0, y0:y0, x1:x1, y1:y1, type:"linear"}; 5500 return this; 5501 }; 5502 /** 5503 * Creates a radial gradient style and assigns it to {{#crossLink "Fill/style:property"}}{{/crossLink}}. 5504 * See {{#crossLink "Graphics/beginRadialGradientFill"}}{{/crossLink}} for more information. 5505 * @method radialGradient 5506 * @param {Array} colors 5507 * @param {Array} ratios 5508 * @param {Number} x0 5509 * @param {Number} y0 5510 * @param {Number} r0 5511 * @param {Number} x1 5512 * @param {Number} y1 5513 * @param {Number} r1 5514 * @return {Fill} Returns this Fill object for chaining or assignment. 5515 */ 5516 p.radialGradient = function(colors, ratios, x0, y0, r0, x1, y1, r1) { 5517 var o = this.style = Graphics._ctx.createRadialGradient(x0, y0, r0, x1, y1, r1); 5518 for (var i=0, l=colors.length; i<l; i++) { o.addColorStop(ratios[i], colors[i]); } 5519 o.props = {colors:colors, ratios:ratios, x0:x0, y0:y0, r0:r0, x1:x1, y1:y1, r1:r1, type:"radial"}; 5520 return this; 5521 }; 5522 /** 5523 * Creates a bitmap fill style and assigns it to the {{#crossLink "Fill/style:property"}}{{/crossLink}}. 5524 * See {{#crossLink "Graphics/beginBitmapFill"}}{{/crossLink}} for more information. 5525 * @method bitmap 5526 * @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image Must be loaded prior to creating a bitmap fill, or the fill will be empty. 5527 * @param {String} [repetition] One of: repeat, repeat-x, repeat-y, or no-repeat. 5528 * @return {Fill} Returns this Fill object for chaining or assignment. 5529 */ 5530 p.bitmap = function(image, repetition) { 5531 if (image.naturalWidth || image.getContext || image.readyState >= 2) { 5532 var o = this.style = Graphics._ctx.createPattern(image, repetition || ""); 5533 o.props = {image: image, repetition: repetition, type: "bitmap"}; 5534 } 5535 return this; 5536 }; 5537 p.path = false; 5538 5539 /** 5540 * Graphics command object. See {{#crossLink "Graphics/beginStroke"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5541 * @class Stroke 5542 * @constructor 5543 * @param {Object} style A valid Context2D fillStyle. 5544 * @param {Boolean} ignoreScale 5545 **/ 5546 /** 5547 * A valid Context2D strokeStyle. 5548 * @property style 5549 * @type Object 5550 */ 5551 /** 5552 * @property ignoreScale 5553 * @type Boolean 5554 */ 5555 /** 5556 * Execute the Graphics command in the provided Canvas context. 5557 * @method exec 5558 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5559 */ 5560 p = (G.Stroke = function(style, ignoreScale) { 5561 this.style = style; 5562 this.ignoreScale = ignoreScale; 5563 }).prototype; 5564 p.exec = function(ctx) { 5565 if (!this.style) { return; } 5566 ctx.strokeStyle = this.style; 5567 if (this.ignoreScale) { ctx.save(); ctx.setTransform(1,0,0,1,0,0); } 5568 ctx.stroke();
5569 if (this.ignoreScale) { ctx.restore(); } 5570 }; 5571 /** 5572 * Creates a linear gradient style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}. 5573 * See {{#crossLink "Graphics/beginLinearGradientStroke"}}{{/crossLink}} for more information. 5574 * @method linearGradient 5575 * @param {Array} colors 5576 * @param {Array} ratios 5577 * @param {Number} x0 5578 * @param {Number} y0 5579 * @param {Number} x1 5580 * @param {Number} y1 5581 * @return {Fill} Returns this Stroke object for chaining or assignment. 5582 */ 5583 p.linearGradient = G.Fill.prototype.linearGradient; 5584 /** 5585 * Creates a radial gradient style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}. 5586 * See {{#crossLink "Graphics/beginRadialGradientStroke"}}{{/crossLink}} for more information. 5587 * @method radialGradient 5588 * @param {Array} colors 5589 * @param {Array} ratios 5590 * @param {Number} x0 5591 * @param {Number} y0 5592 * @param {Number} r0 5593 * @param {Number} x1 5594 * @param {Number} y1 5595 * @param {Number} r1 5596 * @return {Fill} Returns this Stroke object for chaining or assignment. 5597 */ 5598 p.radialGradient = G.Fill.prototype.radialGradient; 5599 /** 5600 * Creates a bitmap fill style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}. 5601 * See {{#crossLink "Graphics/beginBitmapStroke"}}{{/crossLink}} for more information. 5602 * @method bitmap 5603 * @param {HTMLImageElement} image 5604 * @param {String} [repetition] One of: repeat, repeat-x, repeat-y, or no-repeat. 5605 * @return {Fill} Returns this Stroke object for chaining or assignment. 5606 */ 5607 p.bitmap = G.Fill.prototype.bitmap; 5608 p.path = false; 5609 5610 /** 5611 * Graphics command object. See {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5612 * @class StrokeStyle 5613 * @constructor 5614 * @param {Number} width 5615 * @param {String} [caps=butt] 5616 * @param {String} [joints=miter] 5617 * @param {Number} [miterLimit=10] 5618 * @param {Boolean} [ignoreScale=false] 5619 **/ 5620 /** 5621 * @property width 5622 * @type Number 5623 */ 5624 /** 5625 * One of: butt, round, square 5626 * @property caps
5627 * @type String 5628 */ 5629 /** 5630 * One of: round, bevel, miter 5631 * @property joints 5632 * @type String 5633 */ 5634 /** 5635 * @property miterLimit 5636 * @type Number 5637 */ 5638 /** 5639 * Execute the Graphics command in the provided Canvas context. 5640 * @method exec 5641 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5642 */ 5643 p = (G.StrokeStyle = function(width, caps, joints, miterLimit, ignoreScale) { 5644 this.width = width; 5645 this.caps = caps; 5646 this.joints = joints; 5647 this.miterLimit = miterLimit; 5648 this.ignoreScale = ignoreScale; 5649 }).prototype; 5650 p.exec = function(ctx) { 5651 ctx.lineWidth = (this.width == null ? "1" : this.width); 5652 ctx.lineCap = (this.caps == null ? "butt" : (isNaN(this.caps) ? this.caps : Graphics.STROKE_CAPS_MAP[this.caps])); 5653 ctx.lineJoin = (this.joints == null ? "miter" : (isNaN(this.joints) ? this.joints : Graphics.STROKE_JOINTS_MAP[this.joints])); 5654 ctx.miterLimit = (this.miterLimit == null ? "10" : this.miterLimit); 5655 ctx.ignoreScale = (this.ignoreScale == null ? false : this.ignoreScale); 5656 }; 5657 p.path = false; 5658 5659 /** 5660 * Graphics command object. See {{#crossLink "Graphics/setStrokeDash"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5661 * @class StrokeDash 5662 * @constructor 5663 * @param {Array} [segments] 5664 * @param {Number} [offset=0] 5665 **/ 5666 /** 5667 * @property segments 5668 * @type Array 5669 */ 5670 /** 5671 * @property offset 5672 * @type Number 5673 */ 5674 /** 5675 * Execute the Graphics command in the provided Canvas context. 5676 * @method exec 5677 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5678 */ 5679 (G.StrokeDash = function(segments, offset) { 5680 this.segments = segments; 5681 this.offset = offset||0; 5682 }).prototype.exec = function(ctx) { 5683 if (ctx.setLineDash) { // feature detection. 5684 ctx.setLineDash(this.segments|| G.StrokeDash.EMPTY_SEGMENTS); // instead of [] to reduce churn. 5685 ctx.lineDashOffset = this.offset||0; 5686 } 5687 }; 5688 /** 5689 * The default value for segments (ie. no dash). 5690 * @property EMPTY_SEGMENTS 5691 * @static 5692 * @final 5693 * @readonly 5694 * @protected 5695 * @type {Array} 5696 **/ 5697 G.StrokeDash.EMPTY_SEGMENTS = []; 5698 5699 /** 5700 * Graphics command object. See {{#crossLink "Graphics/drawRoundRectComplex"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5701 * @class RoundRect 5702 * @constructor 5703 * @param {Number} x 5704 * @param {Number} y 5705 * @param {Number} w 5706 * @param {Number} h 5707 * @param {Number} radiusTL 5708 * @param {Number} radiusTR 5709 * @param {Number} radiusBR 5710 * @param {Number} radiusBL 5711 **/ 5712 /** 5713 * @property x 5714 * @type Number 5715 */ 5716 /** 5717 * @property y 5718 * @type Number 5719 */ 5720 /** 5721 * @property w 5722 * @type Number 5723 */ 5724 /** 5725 * @property h 5726 * @type Number 5727 */ 5728 /** 5729 * @property radiusTL 5730 * @type Number 5731 */ 5732 /** 5733 * @property radiusTR 5734 * @type Number 5735 */ 5736 /** 5737 * @property radiusBR 5738 * @type Number 5739 */ 5740 /** 5741 * @property radiusBL 5742 * @type Number 5743 */ 5744 /** 5745 * Execute the Graphics command in the provided Canvas context. 5746 * @method exec 5747 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5748 */ 5749 (G.RoundRect = function(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL) { 5750 this.x = x; this.y = y; 5751 this.w = w; this.h = h; 5752 this.radiusTL = radiusTL; this.radiusTR = radiusTR; 5753 this.radiusBR = radiusBR;
5753 this.radiusBL = radiusBL; 5754 }).prototype.exec = function(ctx) { 5755 var max = (w<h?w:h)/2; 5756 var mTL=0, mTR=0, mBR=0, mBL=0; 5757 var x = this.x, y = this.y, w = this.w, h = this.h; 5758 var rTL = this.radiusTL, rTR = this.radiusTR, rBR = this.radiusBR, rBL = this.radiusBL; 5759 5760 if (rTL < 0) { rTL *= (mTL=-1); } 5761 if (rTL > max) { rTL = max; } 5762 if (rTR < 0) { rTR *= (mTR=-1); } 5763 if (rTR > max) { rTR = max; } 5764 if (rBR < 0) { rBR *= (mBR=-1); } 5765 if (rBR > max) { rBR = max; } 5766 if (rBL < 0) { rBL *= (mBL=-1); } 5767 if (rBL > max) { rBL = max; } 5768 5769 ctx.moveTo(x+w-rTR, y); 5770 ctx.arcTo(x+w+rTR*mTR, y-rTR*mTR, x+w, y+rTR, rTR); 5771 ctx.lineTo(x+w, y+h-rBR); 5772 ctx.arcTo(x+w+rBR*mBR, y+h+rBR*mBR, x+w-rBR, y+h, rBR); 5773 ctx.lineTo(x+rBL, y+h); 5774 ctx.arcTo(x-rBL*mBL, y+h+rBL*mBL, x, y+h-rBL, rBL); 5775 ctx.lineTo(x, y+rTL); 5776 ctx.arcTo(x-rTL*mTL, y-rTL*mTL, x+rTL, y, rTL); 5777 ctx.closePath(); 5778 }; 5779 5780 /** 5781 * Graphics command object. See {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5782 * @class Circle 5783 * @constructor 5784 * @param {Number} x 5785 * @param {Number} y 5786 * @param {Number} radius 5787 **/ 5788 /** 5789 * @property x 5790 * @type Number 5791 */ 5792 /** 5793 * @property y 5794 * @type Number 5795 */ 5796 /** 5797 * @property radius 5798 * @type Number 5799 */ 5800 /** 5801 * Execute the Graphics command in the provided Canvas context. 5802 * @method exec 5803 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5804 */ 5805 (G.Circle = function(x, y, radius) { 5806 this.x = x; this.y = y; 5807 this.radius = radius; 5808 }).prototype.exec = function(ctx) { ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2); }; 5809 5810 /** 5811 * Graphics command object. See {{#crossLink "Graphics/drawEllipse"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5812 * @class Ellipse 5813 * @constructor 5814 * @param {Number} x 5815 * @param {Number} y 5816 * @param {Number} w 5817 * @param {Number} h 5818 **/ 5819 /** 5820 * @property x 5821 * @type Number 5822 */ 5823 /** 5824 * @property y 5825 * @type Number 5826 */ 5827 /** 5828 * @property w 5829 * @type Number 5830 */ 5831 /** 5832 * @property h 5833 * @type Number 5834 */ 5835 /** 5836 * Execute the Graphics command in the provided Canvas context. 5837 * @method exec 5838 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5839 */ 5840 (G.Ellipse = function(x, y, w, h) { 5841 this.x = x; this.y = y; 5842 this.w = w; this.h = h; 5843 }).prototype.exec = function(ctx) { 5844 var x = this.x, y = this.y; 5845 var w = this.w, h = this.h; 5846 5847 var k = 0.5522848; 5848 var ox = (w / 2) * k; 5849 var oy = (h / 2) * k; 5850 var xe = x + w; 5851 var ye = y + h; 5852 var xm = x + w / 2; 5853 var ym = y + h / 2; 5854 5855 ctx.moveTo(x, ym); 5856 ctx.bezierCurveTo(x, ym-oy, xm-ox, y, xm, y); 5857 ctx.bezierCurveTo(xm+ox, y, xe, ym-oy, xe, ym); 5858 ctx.bezierCurveTo(xe, ym+oy, xm+ox, ye, xm, ye); 5859 ctx.bezierCurveTo(xm-ox, ye, x, ym+oy, x, ym); 5860 }; 5861 5862 /** 5863 * Graphics command object. See {{#crossLink "Graphics/drawPolyStar"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information. 5864 * @class PolyStar 5865 * @constructor 5866 * @param {Number} x 5867 * @param {Number} y 5868 * @param {Number} radius 5869 * @param {Number} sides 5870 * @param {Number} pointSize 5871 * @param {Number} angle 5872 **/ 5873 /** 5874 * @property x 5875 * @type Number 5876 */ 5877 /** 5878 * @property y 5879 * @type Number 5880 */ 5881 /** 5882 * @property radius 5883 * @type Number 5884 */ 5885 /** 5886 * @property sides 5887 * @type Number 5888 */ 5889 /** 5890 * @property pointSize 5891 * @type Number 5892 */ 5893 /** 5894 * @property angle 5895 * @type Number 5896 */ 5897 /** 5898 * Execute the Graphics command in the provided Canvas context. 5899 * @method exec 5900 * @param {CanvasRenderingContext2D} ctx The canvas rendering context 5901 */ 5902 (G.PolyStar = function(x, y, radius, sides, pointSize, angle) { 5903 this.x = x; this.y = y;
5904 this.radius = radius; 5905 this.sides = sides; 5906 this.pointSize = pointSize; 5907 this.angle = angle; 5908 }).prototype.exec = function(ctx) { 5909 var x = this.x, y = this.y; 5910 var radius = this.radius; 5911 var angle = (this.angle||0)/180*Math.PI; 5912 var sides = this.sides; 5913 var ps = 1-(this.pointSize||0); 5914 var a = Math.PI/sides; 5915 5916 ctx.moveTo(x+Math.cos(angle)*radius, y+Math.sin(angle)*radius); 5917 for (var i=0; i<sides; i++) { 5918 angle += a; 5919 if (ps != 1) { 5920 ctx.lineTo(x+Math.cos(angle)*radius*ps, y+Math.sin(angle)*radius*ps); 5921 } 5922 angle += a; 5923 ctx.lineTo(x+Math.cos(angle)*radius, y+Math.sin(angle)*radius); 5924 } 5925 ctx.closePath(); 5926 }; 5927 5928 // docced above. 5929 Graphics.beginCmd = new G.BeginPath(); // so we don't have to instantiate multiple instances. 5930 5931 5932 createjs.Graphics = Graphics; 5933}()); 5934 5935//############################################################################## 5936// DisplayObject.js 5937//############################################################################## 5938 5939this.createjs = this.createjs||{}; 5940 5941(function() { 5942 "use strict"; 5943 5944 5945// constructor: 5946 /** 5947 * DisplayObject is an abstract class that should not be constructed directly. Instead construct subclasses such as 5948 * {{#crossLink "Container"}}{{/crossLink}}, {{#crossLink "Bitmap"}}{{/crossLink}}, and {{#crossLink "Shape"}}{{/crossLink}}. 5949 * DisplayObject is the base class for all display classes in the EaselJS library. It defines the core properties and 5950 * methods that are shared between all display objects, such as transformation properties (x, y, scaleX, scaleY, etc), 5951 * caching, and mouse handlers. 5952 * @class DisplayObject 5953 * @extends EventDispatcher 5954 * @constructor 5955 **/ 5956 function DisplayObject() { 5957 this.EventDispatcher_constructor(); 5958 5959 5960 // public properties: 5961 /** 5962 * The alpha (transparency) for this display object. 0 is fully transparent, 1 is fully opaque. 5963 * @property alpha 5964 * @type {Number} 5965 * @default 1 5966 **/ 5967 this.alpha = 1; 5968 5969 /** 5970 * If a cache is active, this returns the canvas that holds the image of this display object. See {{#crossLink "DisplayObject/cache:method"}}{{/crossLink}} 5971 * for more information. Use this to display the result of a cache. This will be a HTMLCanvasElement unless special cache rules have been deliberately enabled for this cache. 5972 * @property cacheCanvas 5973 * @type {HTMLCanvasElement | Object} 5974 * @default null 5975 * @readonly 5976 **/ 5977 this.cacheCanvas = null; 5978 5979 /** 5980 * If a cache has been made, this returns the class that is managing the cacheCanvas and its properties. See {{#crossLink "BitmapCache"}}{{/crossLink}} 5981 * for more information. Use this to control, inspect, and change the cache. In special circumstances this may be a modified or subclassed BitmapCache. 5982 * @property bitmapCache 5983 * @type {BitmapCache} 5984 * @default null 5985 * @readonly 5986 **/ 5987 this.bitmapCache = null; 5988 5989 /** 5990 * Unique ID for this display object. Makes display objects easier for some uses. 5991 * @property id 5992 * @type {Number} 5993 * @default -1 5994 **/ 5995 this.id = createjs.UID.get(); 5996 5997 /** 5998 * Indicates whether to include this object when running mouse interactions. Setting this to `false` for children 5999 * of a {{#crossLink "Container"}}{{/crossLink}} will cause events on the Container to not fire when that child is 6000 * clicked. Setting this property to `false` does not prevent the {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}} 6001 * method from returning the child. 6002 * 6003 * <strong>Note:</strong> In EaselJS 0.7.0, the mouseEnabled property will not work properly with nested Containers. Please 6004 * check out the latest NEXT version in <a href="https://github.com/CreateJS/EaselJS/tree/master/lib">GitHub</a> for an updated version with this issue resolved. The fix will be 6005 * provided in the next release of EaselJS. 6006 * @property mouseEnabled 6007 * @type {Boolean} 6008 * @default true 6009 **/ 6010 this.mouseEnabled = true; 6011 6012 /** 6013 * If false, the tick will not run on this display object (or its children). This can provide some performance benefits. 6014 * In addition to preventing the "tick" event from being dispatched, it will also prevent tick related updates 6015 * on some display objects (ex. Sprite & MovieClip frame advancing, and DOMElement display properties). 6016 * @property tickEnabled 6017 * @type Boolean 6018 * @default true 6019 **/ 6020 this.tickEnabled = true; 6021 6022 /** 6023 * An optional name for this display object. Included in {{#crossLink "DisplayObject/toString"}}{{/crossLink}} . Useful for 6024 * debugging. 6025 * @property name 6026 * @type {String} 6027 * @default null 6028 **/ 6029 this.name = null; 6030 6031 /** 6032 * A reference to the {{#crossLink "Container"}}{{/crossLink}} or {{#crossLink "Stage"}}{{/crossLink}} object that 6033 * contains this display object, or null if it has not been added 6034 * to one. 6035 * @property parent 6036 * @final 6037 * @type {Container} 6038 * @default null 6039 * @readonly 6040 **/ 6041 this.parent = null; 6042 6043 /** 6044 * The left offset for this display object's registration point. For example, to make a 100x100px Bitmap rotate 6045 * around its center, you would set regX and {{#crossLink "DisplayObject/regY:property"}}{{/crossLink}} to 50. 6046 * Cached object's registration points should be set based on pre-cache conditions, not cached size. 6047 * @property regX 6048 * @type {Number} 6049 * @default 0 6050 **/ 6051 this.regX = 0; 6052 6053 /** 6054 * The y offset for this display object's registration point. For example, to make a 100x100px Bitmap rotate around 6055 * its center, you would set {{#crossLink "DisplayObject/regX:property"}}{{/crossLink}} and regY to 50. 6056 * Cached object's registration points should be set based on pre-cache conditions, not cached size. 6057 * @property regY 6058 * @type {Number} 6059 * @default 0 6060 **/ 6061 this.regY = 0; 6062 6063 /** 6064 * The rotation in degrees for this display object. 6065 * @property rotation 6066 * @type {Number} 6067 * @default 0 6068 **/ 6069 this.rotation = 0; 6070 6071 /** 6072 * The factor to stretch this display object horizontally. For example, setting scaleX to 2 will stretch the display 6073 * object to twice its nominal width. To horizontally flip an object, set the scale to a negative number. 6074 * @property scaleX 6075 * @type {Number} 6076 * @default 1 6077 **/ 6078 this.scaleX = 1; 6079 6080 /** 6081 * The factor to stretch this display object vertically. For example, setting scaleY to 0.5 will stretch the display 6082 * object to half its nominal height. To vertically flip an object, set the scale to a negative number. 6083 * @property scaleY 6084 * @type {Number} 6085 * @default 1 6086 **/ 6087 this.scaleY = 1; 6088 6089 /** 6090 * The factor to skew this display object horizontally. 6091 * @property skewX 6092 * @type {Number} 6093 * @default 0 6094 **/ 6095 this.skewX = 0; 6096 6097 /** 6098 * The factor to skew this display object vertically. 6099 * @property skewY 6100 * @type {Number} 6101 * @default 0 6102 **/ 6103 this.skewY = 0; 6104 6105 /** 6106 * A shadow object that defines the shadow to render on this display object. Set to `null` to remove a shadow. If 6107 * null, this property is inherited from the parent container. 6108 * @property shadow 6109 * @type {Shadow} 6110 * @default null 6111 **/ 6112 this.shadow = null; 6113 6114 /** 6115 * Indicates whether this display object should be rendered to the canvas and included when running the Stage 6116 * {{#crossLink "Stage/getObjectsUnderPoint"}}{{/crossLink}} method. 6117 * @property visible 6118 * @type {Boolean} 6119 * @default true 6120 **/ 6121 this.visible = true; 6122 6123 /** 6124 * The x (horizontal) position of the display object, relative to its parent. 6125 * @property x 6126 * @type {Number} 6127 * @default 0 6128 **/ 6129 this.x = 0; 6130 6131 /** The y (vertical) position of the display object, relative to its parent. 6132 * @property y 6133 * @type {Number} 6134 * @default 0 6135 **/ 6136 this.y = 0; 6137 6138 /** 6139 * If set, defines the transformation for this display object, overriding all other transformation properties 6140 * (x, y, rotation, scale, skew). 6141 * @property transformMatrix 6142 * @type {Matrix2D} 6143 * @default null 6144 **/ 6145 this.transformMatrix = null; 6146 6147 /** 6148 * The composite operation indicates how the pixels of this display object will be composited
6148with the elements 6149 * behind it. If `null`, this property is inherited from the parent container. For more information, read the 6150 * <a href="https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-globalcompositeoperation"> 6151 * whatwg spec on compositing</a>. For a list of supported compositeOperation value, visit 6152 * <a href="https://drafts.fxtf.org/compositing/">the W3C draft on Compositing and Blending</a>. 6153 * @property compositeOperation 6154 * @type {String} 6155 * @default null 6156 **/ 6157 this.compositeOperation = null; 6158 6159 /** 6160 * Indicates whether the display object should be drawn to a whole pixel when 6161 * {{#crossLink "Stage/snapToPixelEnabled"}}{{/crossLink}} is true. To enable/disable snapping on whole 6162 * categories of display objects, set this value on the prototype (Ex. Text.prototype.snapToPixel = true). 6163 * @property snapToPixel 6164 * @type {Boolean} 6165 * @default true 6166 **/ 6167 this.snapToPixel = true; 6168 6169 /** 6170 * An array of Filter objects to apply to this display object. Filters are only applied / updated when {{#crossLink "cache"}}{{/crossLink}} 6171 * or {{#crossLink "updateCache"}}{{/crossLink}} is called on the display object, and only apply to the area that is 6172 * cached. 6173 * @property filters 6174 * @type {Array} 6175 * @default null 6176 **/ 6177 this.filters = null; 6178 6179 /** 6180 * A Shape instance that defines a vector mask (clipping path) for this display object. The shape's transformation 6181 * will be applied relative to the display object's parent coordinates (as if it were a child of the parent). 6182 * @property mask 6183 * @type {Shape} 6184 * @default null 6185 */ 6186 this.mask = null; 6187 6188 /** 6189 * A display object that will be tested when checking mouse interactions or testing {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}}. 6190 * The hit area will have its transformation applied relative to this display object's coordinate space (as though 6191 * the hit test object were a child of this display object and relative to its regX/Y). The hitArea will be tested 6192 * using only its own `alpha` value regardless of the alpha value on the target display object, or the target's 6193 * ancestors (parents). 6194 * 6195 * If set on a {{#crossLink "Container"}}{{/crossLink}}, children of the Container will not receive mouse events. 6196 * This is similar to setting {{#crossLink "mouseChildren"}}{{/crossLink}} to false. 6197 * 6198 * Note that hitArea is NOT currently used by the `hitTest()` method, nor is it supported for {{#crossLink "Stage"}}{{/crossLink}}. 6199 * @property hitArea 6200 * @type {DisplayObject} 6201 * @default null 6202 */ 6203 this.hitArea = null; 6204 6205 /** 6206 * A CSS cursor (ex. "pointer", "help", "text", etc) that will be displayed when the user hovers over this display 6207 * object. You must enable mouseover events using the {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}} method to 6208 * use this property. Setting a non-null cursor on a Container will override the cursor set on its descendants. 6209 * @property cursor 6210 * @type {String} 6211 * @default null 6212 */ 6213 this.cursor = null; 6214 6215 6216 // private properties: 6217 /** 6218 * Moved to {{#crossLink "BitmapCache"}}{{/crossLink}} 6219 * @property _cacheScale 6220 * @protected 6221 * @type {Number} 6222 * @default 1 6223 * @deprecated 6224 **/ 6225 6226 /** 6227 * Moved to {{#crossLink "BitmapCache"}}{{/crossLink}} 6228 * @property _cacheDataURLID 6229 * @protected 6230 * @type {Number} 6231 * @default 0 6232 * @deprecated 6233 */ 6234 6235 /** 6236 * Moved to {{#crossLink "BitmapCache"}}{{/crossLink}} 6237 * @property _cacheDataURL 6238 * @protected 6239 * @type {String} 6240 * @default null 6241 * @deprecated 6242 */ 6243 6244 /** 6245 * @property _props 6246 * @protected 6247 * @type {DisplayObject} 6248 * @default null 6249 **/ 6250 this._props = new createjs.DisplayProps(); 6251 6252 /** 6253 * @property _rectangle 6254 * @protected 6255 * @type {Rectangle} 6256 * @default null 6257 **/ 6258 this._rectangle = new createjs.Rectangle(); 6259 6260 /** 6261 * @property _bounds 6262 * @protected 6263 * @type {Rectangle} 6264 * @default null 6265 **/ 6266 this._bounds = null; 6267 6268 /** 6269 * Where StageGL should look for required display properties, matters only for leaf display objects. Containers 6270 * or cached objects won't use this property, it's for native display of terminal elements. 6271 * @property _webGLRenderStyle 6272 * @protected 6273 * @type {number} 6274 * @default 0 6275 */ 6276 this._webGLRenderStyle = DisplayObject._StageGL_NONE; 6277 } 6278 var p = createjs.extend(DisplayObject, createjs.EventDispatcher); 6279 6280// static properties: 6281 /** 6282 * Listing of mouse event names. Used in _hasMouseEventListener. 6283 * @property _MOUSE_EVENTS 6284 * @protected 6285 * @static 6286 * @type {Array} 6287 **/ 6288 DisplayObject._MOUSE_EVENTS = ["click","dblclick","mousedown","mouseout","mouseover","pressmove","pressup","rollout","rollover"]; 6289 6290 /**
6291 * Suppresses errors generated when using features like hitTest, mouse events, and {{#crossLink "getObjectsUnderPoint"}}{{/crossLink}} 6292 * with cross domain content. 6293 * @property suppressCrossDomainErrors 6294 * @static 6295 * @type {Boolean} 6296 * @default false 6297 **/ 6298 DisplayObject.suppressCrossDomainErrors = false; 6299 6300 /** 6301 * @property _snapToPixelEnabled 6302 * @protected 6303 * @static 6304 * @type {Boolean} 6305 * @default false 6306 **/ 6307 DisplayObject._snapToPixelEnabled = false; // stage.snapToPixelEnabled is temporarily copied here during a draw to provide global access. 6308 6309 /** 6310 * Enum like property for determining StageGL render lookup, i.e. where to expect properties. 6311 * @property _StageGL_NONE 6312 * @protected 6313 * @static 6314 * @type {number} 6315 */ 6316 DisplayObject._StageGL_NONE = 0; 6317 6318 /** 6319 * Enum like property for determining StageGL render lookup, i.e. where to expect properties. 6320 * @property _StageGL_SPRITE 6321 * @protected 6322 * @static 6323 * @type {number} 6324 */ 6325 DisplayObject._StageGL_SPRITE = 1; 6326 6327 /** 6328 * Enum like property for determining StageGL render lookup, i.e. where to expect properties. 6329 * @property _StageGL_BITMAP 6330 * @protected 6331 * @static 6332 * @type {number} 6333 */ 6334 DisplayObject._StageGL_BITMAP = 2; 6335 6336 /** 6337 * @property _hitTestCanvas 6338 * @type {HTMLCanvasElement | Object} 6339 * @static 6340 * @protected 6341 **/ 6342 /** 6343 * @property _hitTestContext 6344 * @type {CanvasRenderingContext2D} 6345 * @static 6346 * @protected 6347 **/ 6348 var canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); // prevent errors on load in browsers without canvas. 6349 if (canvas.getContext) { 6350 DisplayObject._hitTestCanvas = canvas; 6351 DisplayObject._hitTestContext = canvas.getContext("2d"); 6352 canvas.width = canvas.height = 1; 6353 } 6354 6355// events: 6356 /** 6357 * Dispatched when the user presses their left mouse button over the display object. See the 6358 * {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. 6359 * @event mousedown 6360 * @since 0.6.0 6361 */ 6362 6363 /** 6364 * Dispatched when the user presses their left mouse button and then releases it while over the display object. 6365 * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. 6366 * @event click 6367 * @since 0.6.0 6368 */ 6369 6370 /** 6371 * Dispatched when the user double clicks their left mouse button over this display object. 6372 * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. 6373 * @event dblclick 6374 * @since 0.6.0 6375 */ 6376 6377 /** 6378 * Dispatched when the user's mouse enters this display object. This event must be enabled using 6379 * {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. See also {{#crossLink "DisplayObject/rollover:event"}}{{/crossLink}}. 6380 * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. 6381 * @event mouseover 6382 * @since 0.6.0 6383 */ 6384 6385 /** 6386 * Dispatched when the user's mouse leaves this display object. This event must be enabled using 6387 * {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. See also {{#crossLink "DisplayObject/rollout:event"}}{{/crossLink}}. 6388 * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. 6389 * @event mouseout 6390 * @since 0.6.0 6391 */ 6392 6393 /** 6394 * This event is similar to {{#crossLink "DisplayObject/mouseover:event"}}{{/crossLink}}, with the following 6395 * differences: it does not bubble, and it considers {{#crossLink "Container"}}{{/crossLink}} instances as an 6396 * aggregate of their content. 6397 * 6398 * For example, myContainer contains two overlapping children: shapeA and shapeB. The user moves their mouse over 6399 * shapeA and then directly on to shapeB. With a listener for {{#crossLink "mouseover:event"}}{{/crossLink}} on 6400 * myContainer, two events would be received, each targeting a child element:<OL> 6401 * <LI>when the mouse enters shapeA (target=shapeA)</LI> 6402 * <LI>when the mouse enters shapeB (target=shapeB)</LI> 6403 * </OL> 6404 * However, with a listener for "rollover" instead, only a single event is received when the mouse first enters 6405 * the aggregate myContainer content (target=myContainer). 6406 * 6407 * This event must be enabled using {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. 6408 * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. 6409 * @event rollover 6410 * @since 0.7.0 6411 */ 6412 6413 /** 6414 * This event is similar to {{#crossLink "DisplayObject/mouseout:event"}}{{/crossLink}}, with the following 6415 * differences: it does not bubble, and it considers {{#crossLink "Container"}}{{/crossLink}} instances as an 6416 * aggregate of their content. 6417 * 6418 * For example, myContainer contains two overlapping children: shapeA and shapeB. The user moves their mouse over 6419 * shapeA, then directly on to shapeB, then off both. With a listener for {{#crossLink "mouseout:event"}}{{/crossLink}} 6420 * on myContainer, two events would be received, each targeting a child element:<OL> 6421 * <LI>when the mouse leaves shapeA (target=shapeA)</LI> 6422 * <LI>when the mouse leaves shapeB (target=shapeB)</LI> 6423 * </OL> 6424 * However, with a listener for "rollout" instead, only a single event is received when the mouse leaves 6425 * the aggregate myContainer content (target=myContainer). 6426 * 6427 * This event must be enabled using {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. 6428 * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. 6429 * @event rollout 6430 * @since 0.7.0 6431 */ 6432 6433 /** 6434 * After a {{#crossLink "DisplayObject/mousedown:event"}}{{/crossLink}} occurs on a display object, a pressmove 6435 * event will be generated on that object whenever the mouse moves until the mouse press is released. This can be 6436 * useful for dragging and similar operations. 6437 *
6438 * **Please note** that if the initial mouse target from a `mousedown` event is removed from the stage after being pressed 6439 * (e.g. during a `pressmove` event), a `pressmove` event is still generated. However since it is no longer in the 6440 * display list, the event can not bubble. This means that previous ancestors (parent containers) will not receive 6441 * the event, and therefore can not re-dispatch it. If you intend to listen for `{{#crossLink "DisplayObject/pressup:event"}}{{/crossLink}}` 6442 * or `pressmove` on a dynamic object (such as a {{#crossLink "MovieClip"}}{{/crossLink}} or {{#crossLink "Container"}}{{/crossLink}}), 6443 * then ensure you set {{#crossLink "Container/mouseChildren:property"}}{{/crossLink}} to `false`. 6444 * @event pressmove 6445 * @since 0.7.0 6446 */ 6447 6448 /** 6449 * After a {{#crossLink "DisplayObject/mousedown:event"}}{{/crossLink}} occurs on a display object, a pressup event 6450 * will be generated on that object when that mouse press is released. This can be useful for dragging and similar 6451 * operations. 6452 * 6453 * **Please note** that if the initial mouse target from a `mousedown` event is removed from the stage after being pressed 6454 * (e.g. during a `pressmove` event), a `pressup` event is still generated. However since it is no longer in the 6455 * display list, the event can not bubble. This means that previous ancestors (parent containers) will not receive 6456 * the event, and therefore can not re-dispatch it. If you intend to listen for `{{#crossLink "DisplayObject/pressmove:event"}}{{/crossLink}}` 6457 * or `pressup` on a dynamic object (such as a {{#crossLink "MovieClip"}}{{/crossLink}} or {{#crossLink "Container"}}{{/crossLink}}), 6458 * then ensure you set {{#crossLink "Container/mouseChildren:property"}}{{/crossLink}} to `false`. 6459 * @event pressup 6460 * @since 0.7.0 6461 */ 6462 6463 /** 6464 * Dispatched when the display object is added to a parent container. 6465 * @event added 6466 */ 6467 6468 /** 6469 * Dispatched when the display object is removed from its parent container. 6470 * @event removed 6471 */ 6472 6473 /** 6474 * Dispatched on each display object on a stage whenever the stage updates. This occurs immediately before the 6475 * rendering (draw) pass. When {{#crossLink "Stage/update"}}{{/crossLink}} is called, first all display objects on 6476 * the stage dispatch the tick event, then all of the display objects are drawn to stage. Children will have their 6477 * {{#crossLink "tick:event"}}{{/crossLink}} event dispatched in order of their depth prior to the event being 6478 * dispatched on their parent. 6479 * @event tick 6480 * @param {Object} target The object that dispatched the event. 6481 * @param {String} type The event type. 6482 * @param {Array} params An array containing any arguments that were passed to the Stage.update() method. For 6483 * example if you called stage.update("hello"), then the params would be ["hello"]. 6484 * @since 0.6.0 6485 */ 6486 6487 6488// getter / setters: 6489 /** 6490 * Use the {{#crossLink "DisplayObject/stage:property"}}{{/crossLink}} property instead. 6491 * @method _getStage 6492 * @protected 6493 * @return {Stage} 6494 **/ 6495 p._getStage = function() { 6496 // uses dynamic access to avoid circular dependencies; 6497 var o = this, _Stage = createjs["Stage"]; 6498 while (o.parent) { o = o.parent; } 6499 if (o instanceof _Stage) { return o; } 6500 return null; 6501 }; 6502 // DisplayObject.getStage is @deprecated. Remove for 1.1+ 6503 p.getStage = createjs.deprecate(p._getStage, "DisplayObject.getStage"); 6504 6505 /** 6506 * Returns the Stage instance that this display object will be rendered on, or null if it has not been added to one. 6507 * @property stage 6508 * @type {Stage} 6509 * @readonly 6510 **/ 6511 6512 /** 6513 * Returns an ID number that uniquely identifies the current cache for this display object. This can be used to 6514 * determine if the cache has changed since a previous check. 6515 * Moved to {{#crossLink "BitmapCache"}}{{/crossLink}} 6516 * @property cacheID 6517 * @deprecated 6518 * @type {Number} 6519 * @default 0 6520 */ 6521 6522 /** 6523 * Set both the {{#crossLink "DisplayObject/scaleX:property"}}{{/crossLink}} and the {{#crossLink "DisplayObject/scaleY"}}{{/crossLink}} 6524 * property to the same value. Note that when you get the value, if the `scaleX` and `scaleY` are different values, 6525 * it will return only the `scaleX`. 6526 * @property scaleX 6527 * @type {Number} 6528 * @default 1 6529 */ 6530 try { 6531 Object.defineProperties(p, { 6532 stage: { get: p._getStage }, 6533 cacheID: { 6534 get: function(){ return this.bitmapCache && this.bitmapCache.cac
6534heID }, 6535 set: function(a){ this.bitmapCache && (this.bitmapCache.cacheID = a) } 6536 }, 6537 scale: { 6538 get: function() { return this.scaleX; }, 6539 set: function(scale) { this.scaleX = this.scaleY = scale; }, 6540 } 6541 }); 6542 } catch (e) {} 6543 6544 6545// public methods: 6546 /** 6547 * Returns true or false indicating whether the display object would be visible if drawn to a canvas. 6548 * This does not account for whether it would be visible within the boundaries of the stage. 6549 * 6550 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 6551 * @method isVisible 6552 * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas 6553 **/ 6554 p.isVisible = function() { 6555 return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0); 6556 }; 6557 6558 /** 6559 * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. 6560 * Returns <code>true</code> if the draw was handled (useful for overriding functionality). 6561 * 6562 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 6563 * @method draw 6564 * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. 6565 * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. For example, 6566 * used for drawing the cache (to prevent it from simply drawing an existing cache back into itself). 6567 * @return {Boolean} 6568 **/ 6569 p.draw = function(ctx, ignoreCache) { 6570 var cache = this.bitmapCache; 6571 if(cache && !ignoreCache) { 6572 return cache.draw(ctx); 6573 } 6574 return false; 6575 }; 6576 6577 /** 6578 * Applies this display object's transformation, alpha, globalCompositeOperation, clipping path (mask), and shadow 6579 * to the specified context. This is typically called prior to {{#crossLink "DisplayObject/draw"}}{{/crossLink}}. 6580 * @method updateContext 6581 * @param {CanvasRenderingContext2D} ctx The canvas 2D to update. 6582 **/ 6583 p.updateContext = function(ctx) { 6584 var o=this, mask=o.mask, mtx= o._props.matrix; 6585 6586 if (mask && mask.graphics && !mask.graphics.isEmpty()) { 6587 mask.getMatrix(mtx); 6588 ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty); 6589 6590 mask.graphics.drawAsPath(ctx); 6591 ctx.clip(); 6592 6593 mtx.invert(); 6594 ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty); 6595 } 6596 6597 this.getMatrix(mtx); 6598 var tx = mtx.tx, ty = mtx.ty; 6599 if (DisplayObject._snapToPixelEnabled && o.snapToPixel) { 6600 tx = tx + (tx < 0 ? -0.5 : 0.5) | 0; 6601 ty = ty + (ty < 0 ? -0.5 : 0.5) | 0; 6602 } 6603 ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, tx, ty); 6604 ctx.globalAlpha *= o.alpha; 6605 if (o.compositeOperation) { ctx.globalCompositeOperation = o.compositeOperation; } 6606 if (o.shadow) { this._applyShadow(ctx, o.shadow); } 6607 }; 6608 6609 /** 6610 * Draws the display object into a new element, which is then used for subsequent draws. Intended for complex content 6611 * that does not change frequently (ex. a Container with many children that do not move, or a complex vector Shape), 6612 * this can provide for much faster rendering because the content does not need to be re-rendered each tick. The 6613 * cached display object can be moved, rotated, faded, etc freely, however if its content changes, you must manually 6614 * update the cache by calling <code>updateCache()</code> again. You must specify the cached area via the x, y, w, 6615 * and h parameters. This defines the rectangle that will be rendered and cached using this display object's coordinates. 6616 * 6617 * <h4>Example</h4> 6618 * For example if you defined a Shape that drew a circle at 0, 0 with a radius of 25: 6619 * 6620 * var shape = new createjs.Shape(); 6621 * shape.graphics.beginFill("#ff0000").drawCircle(0, 0, 25); 6622 * shape.cache(-25, -25, 50, 50); 6623 * 6624 * Note that filters need to be defined <em>before</em> the cache is applied or you will have to call updateCache after 6625 * application. Check out the {{#crossLink "Filter"}}{{/crossLink}} class for more information. Some filters 6626 * (ex. BlurFilter) may not work as expected in conjunction with the scale param. 6627 * 6628 * Usually, the resulting cacheCanvas will have the dimensions width * scale, height * scale, however some filters (ex. BlurFilter) 6629 * will add padding to the canvas dimensions. 6630 * 6631 * In previous versions caching was handled on DisplayObject but has since been moved to {{#crossLink "BitmapCache"}}{{/crossLink}}. 6632 * This allows for easier interaction and alternate cache methods like WebGL with {{#crossLink "StageGL"}}{{/crossLink}}. 6633 * For more information on the options object, see the BitmapCache {{#crossLink "BitmapCache/define"}}{{/crossLink}}. 6634 * 6635 * @method cache 6636 * @param {Number} x The x coordinate origin for the cache region. 6637 * @param {Number} y The y coordinate origin for the cache region. 6638 * @param {Number} width The width of the cache region. 6639 * @param {Number} height The height of the cache region. 6640 * @param {Number} [scale=1] The scale at which the cache will be created. For example, if you cache a vector shape using 6641 * myShape.cache(0,0,100,100,2) then the resulting cacheCanvas will be 200x200 px. This lets you scale and rotate 6642 * cached elements with greater fidelity. Default is 1. 6643 * @param {Object} [options=undefined] Specify additional parameters for the cache logic 6644 **/ 6645 p.cache = function(x, y, width, height, scale, options) { 6646 if(!this.bitmapCache){ 6647 this.bitmapCache = new createjs.BitmapCache(); 6648 } 6649 this.bitmapCache.define(this, x, y, width, height, scale, options); 6650 }; 6651 6652 /** 6653 * Redraws the display object to its cache. Calling updateCache without an active cache will throw an error. 6654 * If compositeOperation is null the current cache will be cleared prior to drawing. Otherwise the display object 6655 * will be drawn over the existing cache using the specified compositeOperation. 6656 * 6657 * <h4>Example</h4> 6658 * Clear the current graphics of a cached shape, draw some new instructions, and then update the cache. The new line 6659 * will be drawn on top of the old one. 6660 * 6661 * // Not shown: Creating the shape, and caching it. 6662 * shapeInstance.clear(); 6663 * shapeInstance.setStrokeStyle(3).beginStroke("#ff0000").moveTo(100, 100).lineTo(200,200); 6664 * shapeInstance.updateCache(); 6665 * 6666 * In previous versions caching was handled on DisplayObject but has since been moved to {{#crossLink "BitmapCache"}}{{/crossLink}}. 6667 * This allows for easier interaction and alternate cache methods like WebGL and {{#crossLink "StageGL"}}{{/crossLink}}. 6668 * 6669 * @method updateCache 6670 * @param {String} compositeOperation The compositeOperation to use, or null to clear the cache and redraw it. 6671 * <a href="https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-globalcompositeoperation"> 6672 * whatwg spec on compositing</a>. 6673 **/ 6674 p.updateCache = function(compositeOperation) { 6675 if(!this.bitmapCache) { 6676 throw "cache() must be called before updateCache()"; 6677 } 6678 this.bitmapCache.update(compositeOperation); 6679 }; 6680 6681 /** 6682 * Clears the current cache. See {{#crossLink "DisplayObject/cache"}}{{/crossLink}} for more information. 6683 * @method uncache 6684 **/ 6685 p.uncache = function() { 6686 if(this.bitmapCache) { 6687 this.bitmapCache.release(); 6688 this.bitmapCache = undefined; 6689 } 6690 }; 6691 6692 /** 6693 * Returns a data URL for the cache, or null if this display object is not cached. 6694 * Only generated if the cache has changed, otherwise returns last result. 6695 * @method getCacheDataURL 6696 * @return {String} The image data url for the cache. 6697 **/ 6698 p.getCacheDataURL = function() { 6699 return this.bitmapCache?this.bitmapCache.getDataURL():null; 6700 }; 6701 6702 /** 6703 * Transforms the specified x and y position from the coordinate space of the display object 6704 * to the global (stage) coordinate space. For example, this could be used to position an HTML label 6705 * over a specific point on a nested display object. Returns a Point instance with x and y properties 6706 * correlating to the transformed coordinates on the stage. 6707 * 6708 * <h4>Example</h4> 6709 * 6710 * displayObject.x = 300; 6711 * displayObject.y = 200; 6712 * stage.addChild(displayObject); 6713 * var point = displayObject.localToGlobal(100, 100); 6714 * // Results in x=400, y=300 6715 * 6716 * @method localToGlobal 6717 * @param {Number} x The x position in the source display object to transform. 6718 * @param {Number} y The y position in the source display object to transform. 6719 * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. 6720 * @return {Point} A Point instance with x and y properties correlating to the transformed coordinates 6721 * on the stage. 6722 **/ 6723 p.localToGlobal = function(x, y, pt) {
6724 return this.getConcatenatedMatrix(this._props.matrix).transformPoint(x,y, pt||new createjs.Point()); 6725 }; 6726 6727 /** 6728 * Transforms the specified x and y position from the global (stage) coordinate space to the 6729 * coordinate space of the display object. For example, this could be used to determine 6730 * the current mouse position within the display object. Returns a Point instance with x and y properties 6731 * correlating to the transformed position in the display object's coordinate space. 6732 * 6733 * <h4>Example</h4> 6734 * 6735 * displayObject.x = 300; 6736 * displayObject.y = 200; 6737 * stage.addChild(displayObject); 6738 * var point = displayObject.globalToLocal(100, 100); 6739 * // Results in x=-200, y=-100 6740 * 6741 * @method globalToLocal 6742 * @param {Number} x The x position on the stage to transform. 6743 * @param {Number} y The y position on the stage to transform. 6744 * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. 6745 * @return {Point} A Point instance with x and y properties correlating to the transformed position in the 6746 * display object's coordinate space. 6747 **/ 6748 p.globalToLocal = function(x, y, pt) { 6749 return this.getConcatenatedMatrix(this._props.matrix).invert().transformPoint(x,y, pt||new createjs.Point()); 6750 }; 6751 6752 /** 6753 * Transforms the specified x and y position from the coordinate space of this display object to the coordinate 6754 * space of the target display object. Returns a Point instance with x and y properties correlating to the 6755 * transformed position in the target's coordinate space. Effectively the same as using the following code with 6756 * {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}} and {{#crossLink "DisplayObject/globalToLocal"}}{{/crossLink}}. 6757 * 6758 * var pt = this.localToGlobal(x, y); 6759 * pt = target.globalToLocal(pt.x, pt.y); 6760 * 6761 * @method localToLocal 6762 * @param {Number} x The x position in the source display object to transform. 6763 * @param {Number} y The y position on the source display object to transform. 6764 * @param {DisplayObject} target The target display object to which the coordinates will be transformed. 6765 * @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned. 6766 * @return {Point} Returns a Point instance with x and y properties correlating to the transformed position 6767 * in the target's coordinate space. 6768 **/ 6769 p.localToLocal = function(x, y, target, pt) { 6770 pt = this.localToGlobal(x, y, pt); 6771 return target.globalToLocal(pt.x, pt.y, pt); 6772 }; 6773 6774 /** 6775 * Shortcut method to quickly set the transform properties on the display object. All parameters are optional. 6776 * Omitted parameters will have the default value set. 6777 * 6778 * <h4>Example</h4> 6779 * 6780 * displayObject.setTransform(100, 100, 2, 2); 6781 * 6782 * @method setTransform 6783 * @param {Number} [x=0] The horizontal translation (x position) in pixels 6784 * @param {Number} [y=0] The vertical translation (y position) in pixels 6785 * @param {Number} [scaleX=1] The horizontal scale, as a percentage of 1 6786 * @param {Number} [scaleY=1] the vertical scale, as a percentage of 1 6787 * @param {Number} [rotation=0] The rotation, in degrees 6788 * @param {Number} [skewX=0] The horizontal skew factor 6789 * @param {Number} [skewY=0] The vertical skew factor 6790 * @param {Number} [regX=0] The horizontal registration point in pixels 6791 * @param {Number} [regY=0] The vertical registration point in pixels 6792 * @return {DisplayObject} Returns this instance. Useful for chaining commands. 6793 * @chainable 6794 */ 6795 p.setTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) { 6796 this.x = x || 0; 6797 this.y = y || 0; 6798 this.scaleX = scaleX == null ? 1 : scaleX; 6799 this.scaleY = scaleY == null ? 1 : scaleY; 6800 this.rotation = rotation || 0; 6801 this.skewX = skewX || 0; 6802 this.skewY = skewY || 0; 6803 this.regX = regX || 0; 6804 this.regY = regY || 0; 6805 return this; 6806 }; 6807 6808 /** 6809 * Returns a matrix based on this object's current transform. 6810 * @method getMatrix 6811 * @param {Matrix2D} matrix Optional. A Matrix2D object to populate with the calculated values. If null, a new 6812 * Matrix object is returned. 6813 * @return {Matrix2D} A matrix representing this display object's transform. 6814 **/ 6815 p.getMatrix = function(matrix) { 6816 var o = this, mtx = matrix&&matrix.identity() || new createjs.Matrix2D(); 6817 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); 6818 }; 6819 6820 /**
6821 * Generates a Matrix2D object representing the combined transform of the display object and all of its 6822 * parent Containers up to the highest level ancestor (usually the {{#crossLink "Stage"}}{{/crossLink}}). This can 6823 * be used to transform positions between coordinate spaces, such as with {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}} 6824 * and {{#crossLink "DisplayObject/globalToLocal"}}{{/crossLink}}. 6825 * @method getConcatenatedMatrix 6826 * @param {Matrix2D} [matrix] A {{#crossLink "Matrix2D"}}{{/crossLink}} object to populate with the calculated values. 6827 * If null, a new Matrix2D object is returned. 6828 * @return {Matrix2D} The combined matrix. 6829 **/ 6830 p.getConcatenatedMatrix = function(matrix) { 6831 var o = this, mtx = this.getMatrix(matrix); 6832 while (o = o.parent) { 6833 mtx.prependMatrix(o.getMatrix(o._props.matrix)); 6834 } 6835 return mtx; 6836 }; 6837 6838 /** 6839 * Generates a DisplayProps object representing the combined display properties of the object and all of its 6840 * parent Containers up to the highest level ancestor (usually the {{#crossLink "Stage"}}{{/crossLink}}). 6841 * @method getConcatenatedDisplayProps 6842 * @param {DisplayProps} [props] A {{#crossLink "DisplayProps"}}{{/crossLink}} object to populate with the calculated values. 6843 * If null, a new DisplayProps object is returned. 6844 * @return {DisplayProps} The combined display properties. 6845 **/ 6846 p.getConcatenatedDisplayProps = function(props) { 6847 props = props ? props.identity() : new createjs.DisplayProps(); 6848 var o = this, mtx = o.getMatrix(props.matrix); 6849 do { 6850 props.prepend(o.visible, o.alpha, o.shadow, o.compositeOperation); 6851 6852 // 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. 6853 // this could be simplified (ie. just done as part of the prepend above) if we switched to using a pool. 6854 if (o != this) { mtx.prependMatrix(o.getMatrix(o._props.matrix)); } 6855 } while (o = o.parent); 6856 return props; 6857 }; 6858 6859 /** 6860 * Tests whether the display object intersects the specified point in local coordinates (ie. draws a pixel with alpha > 0 at 6861 * the specified position). This ignores the alpha, shadow, hitArea, mask, and compositeOperation of the display object. 6862 * 6863 * <h4>Example</h4> 6864 * 6865 * stage.addEventListener("stagemousedown", handleMouseDown); 6866 * function handleMouseDown(event) { 6867 * var hit = myShape.hitTest(event.stageX, event.stageY); 6868 * } 6869 * 6870 * Please note that shape-to-shape collision is not currently supported by EaselJS. 6871 * @method hitTest 6872 * @param {Number} x The x position to check in the display object's local coordinates. 6873 * @param {Number} y The y position to check in the display object's local coordinates. 6874 * @return {Boolean} A Boolean indicating whether a visible portion of the DisplayObject intersect the specified 6875 * local Point. 6876 */ 6877 p.hitTest = function(x, y) { 6878 var ctx = DisplayObject._hitTestContext; 6879 ctx.setTransform(1, 0, 0, 1, -x, -y); 6880 this.draw(ctx); 6881 6882 var hit = this._testHit(ctx); 6883 ctx.setTransform(1, 0, 0, 1, 0, 0); 6884 ctx.clearRect(0, 0, 2, 2); 6885 return hit; 6886 }; 6887 6888 /** 6889 * Provides a chainable shortcut method for setting a number of properties on the instance. 6890 * 6891 * <h4>Example</h4> 6892 * 6893 * var myGraphics = new createjs.Graphics().beginFill("#ff0000").drawCircle(0, 0, 25); 6894 * var shape = stage.addChild(new Shape()).set({graphics:myGraphics, x:100, y:100, alpha:0.5}); 6895 * 6896 * @method set 6897 * @param {Object}
6897 props A generic object containing properties to copy to the DisplayObject instance. 6898 * @return {DisplayObject} Returns the instance the method is called on (useful for chaining calls.) 6899 * @chainable 6900 */ 6901 p.set = function(props) { 6902 for (var n in props) { this[n] = props[n]; } 6903 return this; 6904 }; 6905 6906 /** 6907 * Returns a rectangle representing this object's bounds in its local coordinate system (ie. with no transformation). 6908 * Objects that have been cached will return the bounds of the cache. 6909 * 6910 * Not all display objects can calculate their own bounds (ex. Shape). For these objects, you can use 6911 * {{#crossLink "DisplayObject/setBounds"}}{{/crossLink}} so that they are included when calculating Container 6912 * bounds. 6913 * 6914 * <table> 6915 * <tr><td><b>All</b></td><td> 6916 * All display objects support setting bounds manually using setBounds(). Likewise, display objects that 6917 * have been cached using cache() will return the bounds of their cache. Manual and cache bounds will override 6918 * the automatic calculations listed below. 6919 * </td></tr> 6920 * <tr><td><b>Bitmap</b></td><td> 6921 * Returns the width and height of the sourceRect (if specified) or image, extending from (x=0,y=0). 6922 * </td></tr> 6923 * <tr><td><b>Sprite</b></td><td> 6924 * Returns the bounds of the current frame. May have non-zero x/y if a frame registration point was specified 6925 * in the spritesheet data. See also {{#crossLink "SpriteSheet/getFrameBounds"}}{{/crossLink}} 6926 * </td></tr> 6927 * <tr><td><b>Container</b></td><td> 6928 * Returns the aggregate (combined) bounds of all children that return a non-null value from getBounds(). 6929 * </td></tr> 6930 * <tr><td><b>Shape</b></td><td> 6931 * Does not currently support automatic bounds calculations. Use setBounds() to manually define bounds. 6932 * </td></tr> 6933 * <tr><td><b>Text</b></td><td> 6934 * Returns approximate bounds. Horizontal values (x/width) are quite accurate, but vertical values (y/height) are 6935 * not, especially when using textBaseline values other than "top". 6936 * </td></tr> 6937 * <tr><td><b>BitmapText</b></td><td> 6938 * Returns approximate bounds. Values will be more accurate if spritesheet frame registration points are close 6939 * to (x=0,y=0). 6940 * </td></tr> 6941 * </table> 6942 * 6943 * Bounds can be expensive to calculate for some objects (ex. text, or containers with many children), and 6944 * are recalculated each time you call getBounds(). You can prevent recalculation on static objects by setting the 6945 * bounds explicitly: 6946 * 6947 * var bounds = obj.getBounds(); 6948 * obj.setBounds(bounds.x, bounds.y, bounds.width, bounds.height); 6949 * // getBounds will now use the set values, instead of recalculating 6950 * 6951 * To reduce memory impact, the returned Rectangle instance may be reused internally; clone the instance or copy its 6952 * values if you need to retain it. 6953 * 6954 * var myBounds = obj.getBounds().clone(); 6955 * // OR: 6956 * myRect.copy(obj.getBounds()); 6957 * 6958 * @method getBounds 6959 * @return {Rectangle} A Rectangle instance representing the bounds, or null if bounds are not available for this 6960 * object. 6961 **/ 6962 p.getBounds = function() { 6963 if (this._bounds) { return this._rectangle.copy(this._bounds); } 6964 var cacheCanvas = this.cacheCanvas; 6965 if (cacheCanvas) { 6966 var scale = this._cacheScale; 6967 return this._rectangle.setValues(this._cacheOffsetX, this._cacheOffsetY, cacheCanvas.width/scale, cacheCanvas.height/scale); 6968 } 6969 return null; 6970 }; 6971 6972 /** 6973 * Returns a rectangle representing this object's bounds in its parent's coordinate system (ie. with transformations applied). 6974 * Objects that have been cached will return the transformed bounds of the cache. 6975 * 6976 * Not all display objects can calculate their own bounds (ex. Shape). For these objects, you can use 6977 * {{#crossLink "DisplayObject/setBounds"}}{{/crossLink}} so that they are included when calculating Container 6978 * bounds. 6979 * 6980 * To reduce memory impact, the returned Rectangle instance may be reused internally; clone the instance or copy its 6981 * values if you need to retain it. 6982 * 6983 * Container instances calculate aggregate bounds for all children that return bounds via getBounds. 6984 * @method getTransformedBounds 6985 * @return {Rectangle} A Rectangle instance representing the bounds, or null if bounds are not available for this object. 6986 **/ 6987 p.getTransformedBounds = function() { 6988 return this._getBounds(); 6989 }; 6990 6991 /** 6992 * Allows you to manually specify the bounds of an object that either cannot calculate their own bounds (ex. Shape & 6993 * Text) for future reference, or so the object can be included in Container bounds. Manually set bounds will always 6994 * override calculated bounds. 6995 * 6996 * The bounds should be specified in the object's local (untransformed) coordinates. For example, a Shape instance
6997 * with a 25px radius circle centered at 0,0 would have bounds of (-25, -25, 50, 50). 6998 * @method setBounds 6999 * @param {Number} x The x origin of the bounds. Pass null to remove the manual bounds. 7000 * @param {Number} y The y origin of the bounds. 7001 * @param {Number} width The width of the bounds. 7002 * @param {Number} height The height of the bounds. 7003 **/ 7004 p.setBounds = function(x, y, width, height) { 7005 if (x == null) { this._bounds = x; return; } 7006 this._bounds = (this._bounds || new createjs.Rectangle()).setValues(x, y, width, height); 7007 }; 7008 7009 /** 7010 * Returns a clone of this DisplayObject. Some properties that are specific to this instance's current context are 7011 * reverted to their defaults (for example .parent). Caches are not maintained across clones, and some elements 7012 * are copied by reference (masks, individual filter instances, hit area) 7013 * @method clone 7014 * @return {DisplayObject} A clone of the current DisplayObject instance. 7015 **/ 7016 p.clone = function() { 7017 return this._cloneProps(new DisplayObject()); 7018 }; 7019 7020 /** 7021 * Returns a string representation of this object. 7022 * @method toString 7023 * @return {String} a string representation of the instance. 7024 **/ 7025 p.toString = function() { 7026 return "[DisplayObject (name="+ this.name +")]"; 7027 }; 7028 7029 7030// private methods: 7031 /** 7032 * Called before the object gets drawn and is a chance to ensure the display state of the object is correct. 7033 * Mostly used by {{#crossLink "MovieClip"}}{{/crossLink}} and {{#crossLink "BitmapText"}}{{/crossLink}} to 7034 * correct their internal state and children prior to being drawn. 7035 * 7036 * Is manually called via draw in a {{#crossLink "Stage"}}{{/crossLink}} but is automatically called when 7037 * present in a {{#crossLink "StageGL"}}{{/crossLink}} instance. 7038 * 7039 * @method _updateState 7040 * @default null 7041 */ 7042 p._updateState = null; 7043 7044 // separated so it can be used more easily in subclasses: 7045 /** 7046 * @method _cloneProps 7047 * @param {DisplayObject} o The DisplayObject instance which will have properties from the current DisplayObject 7048 * instance copied into. 7049 * @return {DisplayObject} o 7050 * @protected 7051 **/ 7052 p._cloneProps = function(o) { 7053 o.alpha = this.alpha; 7054 o.mouseEnabled = this.mouseEnabled; 7055 o.tickEnabled = this.tickEnabled; 7056 o.name = this.name; 7057 o.regX = this.regX; 7058 o.regY = this.regY; 7059 o.rotation = this.rotation; 7060 o.scaleX = this.scaleX; 7061 o.scaleY = this.scaleY; 7062 o.shadow = this.shadow; 7063 o.skewX = this.skewX; 7064 o.skewY = this.skewY; 7065 o.visible = this.visible; 7066 o.x = this.x; 7067 o.y = this.y; 7068 o.compositeOperation = this.compositeOperation; 7069 o.snapToPixel = this.snapToPixel; 7070 o.filters = this.filters==null?null:this.filters.slice(0); 7071 o.mask = this.mask; 7072 o.hitArea = this.hitArea; 7073 o.cursor = this.cursor; 7074 o._bounds = this._bounds; 7075 return o; 7076 }; 7077 7078 /** 7079 * @method _applyShadow 7080 * @protected 7081 * @param {CanvasRenderingContext2D} ctx 7082 * @param {Shadow} shadow 7083 **/ 7084 p._applyShadow = function(ctx, shadow) { 7085 shadow = shadow || Shadow.identity; 7086 ctx.shadowColor = shadow.color; 7087 ctx.shadowOffsetX = shadow.offsetX; 7088 ctx.shadowOffsetY = shadow.offsetY; 7089 ctx.shadowBlur = shadow.blur; 7090 }; 7091 7092 /** 7093 * @method _tick 7094 * @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. 7095 * @protected 7096 **/ 7097 p._tick = function(evtObj) { 7098 // because tick can be really performance sensitive, check for listeners before calling dispatchEvent. 7099 var ls = this._listeners; 7100 if (ls && ls["tick"]) { 7101 // reset & reuse the event object to avoid construction / GC costs: 7102 evtObj.target = null; 7103 evtObj.propagationStopped = evtObj.immediatePropagationStopped = false;
7104 this.dispatchEvent(evtObj); 7105 } 7106 }; 7107 7108 /** 7109 * @method _testHit 7110 * @protected 7111 * @param {CanvasRenderingContext2D} ctx 7112 * @return {Boolean} 7113 **/ 7114 p._testHit = function(ctx) { 7115 try { 7116 var hit = ctx.getImageData(0, 0, 1, 1).data[3] > 1; 7117 } catch (e) { 7118 if (!DisplayObject.suppressCrossDomainErrors) { 7119 throw "An error has occurred. This is most likely due to security restrictions on reading canvas pixel data with local or cross-domain images."; 7120 } 7121 } 7122 return hit; 7123 }; 7124 7125 /** 7126 * @method _getBounds 7127 * @param {Matrix2D} matrix 7128 * @param {Boolean} ignoreTransform If true, does not apply this object's transform. 7129 * @return {Rectangle} 7130 * @protected 7131 **/ 7132 p._getBounds = function(matrix, ignoreTransform){ 7133 return this._transformBounds(this.getBounds(), matrix, ignoreTransform); 7134 }; 7135 7136 /** 7137 * @method _transformBounds 7138 * @param {Rectangle} bounds 7139 * @param {Matrix2D} matrix 7140 * @param {Boolean} ignoreTransform 7141 * @return {Rectangle} 7142 * @protected 7143 **/ 7144 p._transformBounds = function(bounds, matrix, ignoreTransform) { 7145 if (!bounds) { return bounds; } 7146 var x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height, mtx = this._props.matrix; 7147 mtx = ignoreTransform ? mtx.identity() : this.getMatrix(mtx); 7148 7149 if (x || y) { mtx.appendTransform(0,0,1,1,0,0,0,-x,-y); } // TODO: simplify this. 7150 if (matrix) { mtx.prependMatrix(matrix); } 7151 7152 var x_a = width*mtx.a, x_b = width*mtx.b; 7153 var y_c = height*mtx.c, y_d = height*mtx.d; 7154 var tx = mtx.tx, ty = mtx.ty; 7155 7156 var minX = tx, maxX = tx, minY = ty, maxY = ty; 7157 7158 if ((x = x_a + tx) < minX) { minX = x; } else if (x > maxX) { maxX = x; } 7159 if ((x = x_a + y_c + tx) < minX) { minX = x; } else if (x > maxX) { maxX = x; } 7160 if ((x = y_c + tx) < minX) { minX = x; } else if (x > maxX) { maxX = x; } 7161 7162 if ((y = x_b + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; } 7163 if ((y = x_b + y_d + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; } 7164 if ((y = y_d + ty) < minY) { minY = y; } else if (y > maxY) { maxY = y; } 7165 7166 return bounds.setValues(minX, minY, maxX-minX, maxY-minY); 7167 }; 7168 7169 /** 7170 * Indicates whether the display object has any mouse event listeners or a cursor. 7171 * @method _isMouseOpaque 7172 * @return {Boolean} 7173 * @protected 7174 **/ 7175 p._hasMouseEventListener = function() { 7176 var evts = DisplayObject._MOUSE_EVENTS; 7177 for (var i= 0, l=evts.length; i<l; i++) { 7178 if (this.hasEventListener(evts[i])) { return true; } 7179 } 7180 return !!this.cursor; 7181 }; 7182 7183 createjs.DisplayObject = createjs.promote(DisplayObject, "EventDispatcher"); 7184}()); 7185 7186//############################################################################## 7187// Container.js 7188//############################################################################## 7189 7190this.createjs = this.createjs||{}; 7191 7192(function() { 7193 "use strict"; 7194 7195 7196// constructor: 7197/** 7198 * A Container is a nestable display list that allows you to work with compound dis
7198play elements. For example you could 7199 * group arm, leg, torso and head {{#crossLink "Bitmap"}}{{/crossLink}} instances together into a Person Container, and 7200 * transform them as a group, while still being able to move the individual parts relative to each other. Children of 7201 * containers have their <code>transform</code> and <code>alpha</code> properties concatenated with their parent 7202 * Container. 7203 * 7204 * For example, a {{#crossLink "Shape"}}{{/crossLink}} with x=100 and alpha=0.5, placed in a Container with <code>x=50</code> 7205 * and <code>alpha=0.7</code> will be rendered to the canvas at <code>x=150</code> and <code>alpha=0.35</code>. 7206 * Containers have some overhead, so you generally shouldn't create a Container to hold a single child. 7207 * 7208 * <h4>Example</h4> 7209 * 7210 * var container = new createjs.Container(); 7211 * container.addChild(bitmapInstance, shapeInstance); 7212 * container.x = 100; 7213 * 7214 * @class Container 7215 * @extends DisplayObject 7216 * @constructor 7217 **/ 7218 function Container() { 7219 this.DisplayObject_constructor(); 7220 7221 // public properties: 7222 /** 7223 * The array of children in the display list. You should usually use the child management methods such as 7224 * {{#crossLink "Container/addChild"}}{{/crossLink}}, {{#crossLink "Container/removeChild"}}{{/crossLink}}, 7225 * {{#crossLink "Container/swapChildren"}}{{/crossLink}}, etc, rather than accessing this directly, but it is 7226 * included for advanced uses. 7227 * @property children 7228 * @type Array 7229 * @default null 7230 **/ 7231 this.children = []; 7232 7233 /** 7234 * Indicates whether the children of this container are independently enabled for mouse/pointer interaction. 7235 * If false, the children will be aggregated under the container - for example, a click on a child shape would 7236 * trigger a click event on the container. 7237 * @property mouseChildren 7238 * @type Boolean 7239 * @default true 7240 **/ 7241 this.mouseChildren = true; 7242 7243 /** 7244 * If false, the tick will not be propagated to children of this Container. This can provide some performance benefits. 7245 * In addition to preventing the "tick" event from being dispatched, it will also prevent tick related updates 7246 * on some display objects (ex. Sprite & MovieClip frame advancing, DOMElement visibility handling). 7247 * @property tickChildren 7248 * @type Boolean 7249 * @default true 7250 **/ 7251 this.tickChildren = true; 7252 } 7253 var p = createjs.extend(Container, createjs.DisplayObject); 7254 7255 7256// getter / setters: 7257 /** 7258 * Use the {{#crossLink "Container/numChildren:property"}}{{/crossLink}} property instead. 7259 * @method _getNumChildren 7260 * @protected 7261 * @return {Number} 7262 **/ 7263 p._getNumChildren = function() { 7264 return this.children.length; 7265 }; 7266 // Container.getNumChildren is @deprecated. Remove for 1.1+ 7267 p.getNumChildren = createjs.deprecate(p._getNumChildren, "Container.getNumChildren"); 7268 7269 /** 7270 * Returns the number of children in the container. 7271 * @property numChildren 7272 * @type {Number} 7273 * @readonly 7274 **/ 7275 try { 7276 Object.defineProperties(p, { 7277 numChildren: { get: p._getNumChildren } 7278 }); 7279 } catch (e) {} 7280 7281 7282// public methods: 7283 /** 7284 * Constructor alias for backwards compatibility. This method will be removed in future versions. 7285 * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}. 7286 * @method initialize 7287 * @deprecated in favour of `createjs.promote()` 7288 **/ 7289 p.initialize = Container; // TODO: deprecated. 7290 7291 /** 7292 * Returns true or false indicating whether the display object would be visible if drawn to a canvas. 7293 * This does not account for whether it would be visible within the boundaries of the stage. 7294 * 7295 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 7296 * @method isVisible 7297 * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas 7298 **/ 7299 p.isVisible = function() { 7300 var hasContent = this.cacheCanvas || this.children.length; 7301 return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent); 7302 }; 7303 7304 /** 7305 * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. 7306 * Returns true if the draw was handled (useful for overriding functionality). 7307 * 7308 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 7309 * @method draw 7310 * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. 7311 * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. 7312 * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back 7313 * into itself). 7314 **/ 7315 p.draw = function(ctx, ignoreCache) { 7316 if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } 7317 7318 // this ensures we don't have issues with display list changes that occur during a draw: 7319 var list = this.children.slice(); 7320 for (var i=0,l=list.length; i<l; i++) { 7321 var child = list[i]; 7322 if (!child.isVisible()) { continue; } 7323 7324 // draw the child: 7325 ctx.save(); 7326 child.updateContext(ctx); 7327 child.draw(ctx);
7328 ctx.restore(); 7329 } 7330 return true; 7331 }; 7332 7333 /** 7334 * Adds a child to the top of the display list. 7335 * 7336 * <h4>Example</h4> 7337 * 7338 * container.addChild(bitmapInstance); 7339 * 7340 * You can also add multiple children at once: 7341 * 7342 * container.addChild(bitmapInstance, shapeInstance, textInstance); 7343 * 7344 * @method addChild 7345 * @param {DisplayObject} child The display object to add. 7346 * @return {DisplayObject} The child that was added, or the last child if multiple children were added. 7347 **/ 7348 p.addChild = function(child) { 7349 if (child == null) { return child; } 7350 var l = arguments.length; 7351 if (l > 1) { 7352 for (var i=0; i<l; i++) { this.addChild(arguments[i]); } 7353 return arguments[l-1]; 7354 } 7355 // Note: a lot of duplication with addChildAt, but push is WAY faster than splice. 7356 var par=child.parent, silent = par === this; 7357 par&&par._removeChildAt(createjs.indexOf(par.children, child), silent); 7358 child.parent = this; 7359 this.children.push(child); 7360 if (!silent) { child.dispatchEvent("added"); } 7361 return child; 7362 }; 7363 7364 /** 7365 * Adds a child to the display list at the specified index, bumping children at equal or greater indexes up one, and 7366 * setting its parent to this Container. 7367 * 7368 * <h4>Example</h4> 7369 * 7370 * addChildAt(child1, index); 7371 * 7372 * You can also add multiple children, such as: 7373 * 7374 * addChildAt(child1, child2, ..., index); 7375 * 7376 * The index must be between 0 and numChildren. For example, to add myShape under otherShape in the display list, 7377 * you could use: 7378 * 7379 * container.addChildAt(myShape, container.getChildIndex(otherShape)); 7380 * 7381 * This would also bump otherShape's index up by one. Fails silently if the index is out of range. 7382 * 7383 * @method addChildAt 7384 * @param {DisplayObject} child The display object to add. 7385 * @param {Number} index The index to add the child at. 7386 * @return {DisplayObject} Returns the last child that was added, or the last child if multiple children were added. 7387 **/ 7388 p.addChildAt = function(child, index) { 7389 var l = arguments.length; 7390 var indx = arguments[l-1]; // can't use the same name as the index param or it replaces arguments[1] 7391 if (indx < 0 || indx > this.children.length) { return arguments[l-2]; } 7392 if (l > 2) { 7393 for (var i=0; i<l-1; i++) { this.addChildAt(arguments[i], indx+i); } 7394 return arguments[l-2]; 7395 } 7396 var par=child.parent, silent = par === this; 7397 par&&par._removeChildAt(createjs.indexOf(par.children, child), silent); 7398 child.parent = this; 7399 this.children.splice(index, 0, child); 7400 if (!silent) { child.dispatchEvent("added"); } 7401 return child; 7402 }; 7403 7404 /** 7405 * Removes the specified child from the display list. Note that it is faster to use removeChildAt() if the index is 7406 * already known. 7407 * 7408 * <h4>Example</h4> 7409 * 7410 * container.removeChild(child); 7411 * 7412 * You can also remove multiple children: 7413 * 7414 * removeChild(child1, child2, ...); 7415 * 7416 * Returns true if the child (or children) was removed, or false if it was not in the display list. 7417 * @method removeChild 7418 * @param {DisplayObject} child The child to remove. 7419 * @return {Boolean} true if the child (or children) was removed, or false if it was not in the display list. 7420 **/ 7421 p.removeChild = function(child) { 7422 var l = arguments.length; 7423 if (l > 1) { 7424 var good = true; 7425 for (var i=0; i<l; i++) { good = good && this.removeChild(arguments[i]); } 7426 return good; 7427 } 7428 return this._removeChildAt(createjs.indexOf(this.children, child)); 7429 }; 7430 7431 /** 7432 * Removes the child at the specified index from the display list, and sets its parent to null. 7433 * 7434 * <h4>Example</h4> 7435 * 7436 * container.removeChildAt(2); 7437 * 7438 * You can also remove multiple children: 7439 * 7440 * container.removeChild(2, 7, ...) 7441 * 7442 * Returns true if the child (or children) was removed, or false if any index was out of range. 7443 * @method removeChildAt 7444 * @param {Number} index The index of the child to remove. 7445 * @return {Boolean} true if the child (or children) was removed, or false if any index was out of range. 7446 **/ 7447 p.removeChildAt = function(index) { 7448 var l = arguments.length; 7449 if (l > 1) { 7450 var a = []; 7451 for (var i=0; i<l; i++) { a[i] = arguments[i]; }
7452 a.sort(function(a, b) { return b-a; }); 7453 var good = true; 7454 for (var i=0; i<l; i++) { good = good && this._removeChildAt(a[i]); } 7455 return good; 7456 } 7457 return this._removeChildAt(index); 7458 }; 7459 7460 /** 7461 * Removes all children from the display list. 7462 * 7463 * <h4>Example</h4> 7464 * 7465 * container.removeAllChildren(); 7466 * 7467 * @method removeAllChildren 7468 **/ 7469 p.removeAllChildren = function() { 7470 var kids = this.children; 7471 while (kids.length) { this._removeChildAt(0); } 7472 }; 7473 7474 /** 7475 * Returns the child at the specified index. 7476 * 7477 * <h4>Example</h4> 7478 * 7479 * container.getChildAt(2); 7480 * 7481 * @method getChildAt 7482 * @param {Number} index The index of the child to return. 7483 * @return {DisplayObject} The child at the specified index. Returns null if there is no child at the index. 7484 **/ 7485 p.getChildAt = function(index) { 7486 return this.children[index]; 7487 }; 7488 7489 /** 7490 * Returns the child with the specified name. 7491 * @method getChildByName 7492 * @param {String} name The name of the child to return. 7493 * @return {DisplayObject} The child with the specified name. 7494 **/ 7495 p.getChildByName = function(name) { 7496 var kids = this.children; 7497 for (var i=0,l=kids.length;i<l;i++) { 7498 if(kids[i].name == name) { return kids[i]; } 7499 } 7500 return null; 7501 }; 7502 7503 /** 7504 * Performs an array sort operation on the child list. 7505 * 7506 * <h4>Example: Display children with a higher y in front.</h4> 7507 * 7508 * var sortFunction = function(obj1, obj2, options) { 7509 * if (obj1.y > obj2.y) { return 1; } 7510 * if (obj1.y < obj2.y) { return -1; } 7511 * return 0; 7512 * } 7513 * container.sortChildren(sortFunction); 7514 * 7515 * @method sortChildren 7516 * @param {Function} sortFunction the function to use to sort the child list. See JavaScript's <code>Array.sort</code> 7517 * documentation for details. 7518 **/ 7519 p.sortChildren = function(sortFunction) { 7520 this.children.sort(sortFunction); 7521 }; 7522 7523 /** 7524 * Returns the index of the specified child in the display list, or -1 if it is not in the display list. 7525 * 7526 * <h4>Example</h4> 7527 * 7528 * var index = container.getChildIndex(child); 7529 * 7530 * @method getChildIndex 7531 * @param {DisplayObject} child The child to return the index of. 7532 * @return {Number} The index of the specified child. -1 if the child is not found. 7533 **/ 7534 p.getChildIndex = function(child) { 7535 return createjs.indexOf(this.children, child); 7536 }; 7537 7538 /** 7539 * Swaps the children at the specified indexes. Fails silently if either index is out of range. 7540 * @method swapChildrenAt 7541 * @param {Number} index1 7542 * @param {Number} index2 7543 **/ 7544 p.swapChildrenAt = function(index1, index2) { 7545 var kids = this.children; 7546 var o1 = kids[index1]; 7547 var o2 = kids[index2]; 7548 if (!o1 || !o2) { return; } 7549 kids[index1] = o2; 7550 kids[index2] = o1; 7551 }; 7552 7553 /** 7554 * Swaps the specified children's depth in the display list. Fails silently if either child is not a child of this 7555 * Container. 7556 * @method swapChildren 7557 * @param {DisplayObject} child1 7558 * @param {DisplayObject} child2 7559 **/ 7560 p.swapChildren = function(child1, child2) { 7561 var kids = this.children; 7562 var index1,index2; 7563 for (var i=0,l=kids.length;i<l;i++) { 7564 if (kids[i] == child1) { index1 = i; } 7565 if (kids[i] == child2) { index2 = i; } 7566 if (index1 != null && index2 != null) { break; } 7567 } 7568 if (i==l) { return; } // TODO: throw error? 7569 kids[index1] = child2; 7570 kids[index2] = child1; 7571 }; 7572 7573 /** 7574 * 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. 7575 * @param {DisplayObject} child 7576 * @param {Number} index 7577 * @method setChildIndex 7578 **/ 7579 p.setChildIndex = function(child, index) { 7580 var kids = this.children, l=kids.length; 7581 if (child.parent != this || index < 0 || index >= l) { return; } 7582 for (var i=0;i<l;i++) { 7583 if (kids[i] == child) { break; } 7584 } 7585 if (i==l || i == index) { return; } 7586 kids.splice(i,1); 7587 kids.splice(index,0,child); 7588 }; 7589 7590 /** 7591 * Returns true if the specified display object either is this container or is a descendent (child, grandchild, etc) 7592 * of this container. 7593 * @method contains 7594 * @param {DisplayObject} child The DisplayObject to be checked. 7595 * @return {Boolean} true if the specified display object either is this container or is a descendent. 7596 **/ 7597 p.contains = function(child) { 7598 while (child) { 7599 if (child == this) { return true; } 7600 child = child.parent; 7601 } 7602 return false;
7603 }; 7604 7605 /** 7606 * Tests whether the display object intersects the specified local point (ie. draws a pixel with alpha > 0 at the 7607 * specified position). This ignores the alpha, shadow and compositeOperation of the display object, and all 7608 * transform properties including regX/Y. 7609 * @method hitTest 7610 * @param {Number} x The x position to check in the display object's local coordinates. 7611 * @param {Number} y The y position to check in the display object's local coordinates. 7612 * @return {Boolean} A Boolean indicating whether there is a visible section of a DisplayObject that overlaps the specified 7613 * coordinates. 7614 **/ 7615 p.hitTest = function(x, y) { 7616 // TODO: optimize to use the fast cache check where possible. 7617 return (this.getObjectUnderPoint(x, y) != null); 7618 }; 7619 7620 /** 7621 * Returns an array of all display objects under the specified coordinates that are in this container's display 7622 * list. This routine ignores any display objects with {{#crossLink "DisplayObject/mouseEnabled:property"}}{{/crossLink}} 7623 * set to `false`. The array will be sorted in order of visual depth, with the top-most display object at index 0. 7624 * This uses shape based hit detection, and can be an expensive operation to run, so it is best to use it carefully. 7625 * For example, if testing for objects under the mouse, test on tick (instead of on {{#crossLink "DisplayObject/mousemove:event"}}{{/crossLink}}), 7626 * and only if the mouse's position has changed. 7627 * 7628 * <ul> 7629 * <li>By default (mode=0) this method evaluates all display objects.</li> 7630 * <li>By setting the `mode` parameter to `1`, the {{#crossLink "DisplayObject/mouseEnabled:property"}}{{/crossLink}} 7631 * and {{#crossLink "mouseChildren:property"}}{{/crossLink}} properties will be respected.</li> 7632 * <li>Setting the `mode` to `2` additionally excludes display objects that do not have active mouse event 7633 * listeners or a {{#crossLink "DisplayObject:cursor:property"}}{{/crossLink}} property. That is, only objects 7634 * that would normally intercept mouse interaction will be included. This can significantly improve performance 7635 * in some cases by reducing the number of display objects that need to be tested.</li> 7636 * </li> 7637 * 7638 * This method accounts for both {{#crossLink "DisplayObject/hitArea:property"}}{{/crossLink}} and {{#crossLink "DisplayObject/mask:property"}}{{/crossLink}}. 7639 * @method getObjectsUnderPoint 7640 * @param {Number} x The x position in the container to test. 7641 * @param {Number} y The y position in the container to test. 7642 * @param {Number} [mode=0] The mode to use to determine which display objects to include. 0-all, 1-respect mouseEnabled/mouseChildren, 2-only mouse opaque objects. 7643 * @return {Array} An Array of DisplayObjects under the specified coordinates. 7644 **/ 7645 p.getObjectsUnderPoint = function(x, y, mode) { 7646 var arr = []; 7647 var pt = this.localToGlobal(x, y); 7648 this._getObjectsUnderPoint(pt.x, pt.y, arr, mode>0, mode==1); 7649 return arr; 7650 }; 7651 7652 /** 7653 * Similar to {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}}, but returns only the top-most display 7654 * object. This runs significantly faster than <code>getObjectsUnderPoint()</code>, but is still potentially an expensive 7655 * operation. See {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}} for more information. 7656 * @method getObjectUnderPoint 7657 * @param {Number} x The x position in the container to test. 7658 * @param {Number} y The y position in the container to test. 7659 * @param {Number} mode The mode to use to determine which display objects to include. 0-all, 1-respect mouseEnabled/mouseChildren, 2-only mouse opaque objects. 7660 * @return {DisplayObject} The top-most display object under the specified coordinates. 7661 **/ 7662 p.getObjectUnderPoint = function(x, y, mode) { 7663 var pt = this.localToGlobal(x, y); 7664 return this._getObjectsUnderPoint(pt.x, pt.y, null, mode>0, mode==1); 7665 }; 7666 7667 /** 7668 * Docced in superclass. 7669 */ 7670 p.getBounds = function() { 7671 return this._getBounds(null, true); 7672 }; 7673 7674 7675 /** 7676 * Docced in superclass. 7677 */ 7678 p.getTransformedBounds = function() { 7679 return this._getBounds(); 7680 }; 7681 7682 /** 7683 * Returns a clone of this Container. Some properties that are specific to this instance's current context are 7684 * reverted to their defaults (for example .parent). 7685 * @method clone 7686 * @param {Boolean} [recursive=false] If true, all of the descendants of this container will be cloned recursively. If false, the 7687 * properties of the container will be cloned, but the new instance will not have any children. 7688 * @return {Container} A clone of the current Container instance. 7689 **/ 7690 p.clone = function(recursive) { 7691 var o = this._cloneProps(new Container()); 7692 if (recursive) { this._cloneChildren(o); } 7693 return o; 7694 }; 7695 7696 /** 7697 * Returns a string representation of this object. 7698 * @method toString 7699 * @return {String} a string representation of the instance. 7700 **/ 7701 p.toString = function() { 7702 return "[Container (name="+ this.name +")]"; 7703 }; 7704 7705 7706// private methods: 7707 /** 7708 * @method _tick 7709 * @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. 7710 * @protected 7711 **/ 7712 p._tick = function(evtObj) { 7713 if (this.tickChildren) { 7714 for (var i=this.children.length-1; i>=0; i--) { 7715 var child = this.children[i]; 7716 if (child.tickEnabled && child._tick) { child._tick(evtObj); } 7717 } 7718 } 7719 this.DisplayObject__tick(evtObj); 7720 }; 7721 7722 /** 7723 * Recursively clones all children of this container, and adds them to the target container. 7724 * @method cloneChildren 7725 * @protected 7726 * @param {Container} o The target container. 7727 **/ 7728 p._cloneChildren = function(o) { 7729 if (o.children.length) { o.removeAllChildren(); } 7730 var arr = o.children; 7731 for (var i=0, l=this.children.length; i<l; i++) { 7732 var clone = this.children[i].clone(true); 7733 clone.parent = o; 7734 arr.push(clone); 7735 } 7736 }; 7737 7738 /** 7739 * Removes the child at the specified index from the display list, and sets its parent to null. 7740 * Used by `removeChildAt`, `addChild`, and `addChildAt`. 7741 * @method removeChildAt 7742 * @protected 7743 * @param {Number} index The index of the child to remove. 7744 * @param {Boolean} [silent] Prevents dispatch of `removed` event if true. 7745 * @return {Boolean} true if the child (or children) was removed, or false if any index was out of range. 7746 **/ 7747 p._removeChildAt = function(index, silent) { 7748 if (index < 0 || index > this.children.length-1) { return false; } 7749 var child = this.children[index]; 7750 if (child) { child.parent = null; } 7751 this.children.splice(index, 1); 7752 if (!silent) { child.dispatchEvent("removed"); } 7753 return true; 7754 }; 7755 7756 /** 7757 * @method _getObjectsUnderPoint 7758 * @param {Number} x 7759 * @param {Number} y 7760 * @param {Array} arr 7761 * @param {Boolean} mouse If true, it will respect mouse interaction properties like mouseEnabled, mouseChildren, and active listeners. 7762 * @param {Boolean} activeListener If true, there is an active mouse event listener on a parent object. 7763 * @param {Number} currentDepth Indicates the current depth of the search. 7764 * @return {DisplayObject} 7765 * @protected 7766 **/ 7767 p._getObjectsUnderPoint = function(x, y, arr, mouse, activeListener, currentDepth) { 7768 currentDepth = currentDepth || 0; 7769 if (!currentDepth && !this._testMask(this, x, y)) { return null; } 7770 var mtx, ctx = createjs.DisplayObject._hitTestContext; 7771 activeListener = activeListener || (mouse&&this._hasMouseEventListener()); 7772 7773 // draw children one at a time, and check if we get a hit: 7774 var children = this.children, l = children.length; 7775 for (var i=l-1; i>=0; i--) { 7776 var child = children[i]; 7777 var hitArea = child.hitArea; 7778 if (!child.visible || (!hitArea && !child.isVisible()) || (mouse && !child.mouseEnabled)) { continue; } 7779 if (!hitArea && !this._testMask(child, x, y)) { continue; } 7780 7781 // if a child container has a hitArea then we only need to check its hitAre2a, so we can treat it as a normal DO: 7782 if (!hitArea && child instanceof Container) { 7783 var result = child._getObjectsUnderPoint(x, y, arr, mouse, activeListener, currentDepth+1); 7784 if (!arr && result) { return (mouse && !this.mouseChildren) ? this
7784: result; } 7785 } else { 7786 if (mouse && !activeListener && !child._hasMouseEventListener()) { continue; } 7787 7788 // TODO: can we pass displayProps forward, to avoid having to calculate this backwards every time? It's kind of a mixed bag. When we're only hunting for DOs with event listeners, it may not make sense. 7789 var props = child.getConcatenatedDisplayProps(child._props); 7790 mtx = props.matrix; 7791 7792 if (hitArea) { 7793 mtx.appendMatrix(hitArea.getMatrix(hitArea._props.matrix)); 7794 props.alpha = hitArea.alpha; 7795 } 7796 7797 ctx.globalAlpha = props.alpha; 7798 ctx.setTransform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx-x, mtx.ty-y); 7799 (hitArea||child).draw(ctx); 7800 if (!this._testHit(ctx)) { continue; } 7801 ctx.setTransform(1, 0, 0, 1, 0, 0); 7802 ctx.clearRect(0, 0, 2, 2); 7803 if (arr) { arr.push(child); } 7804 else { return (mouse && !this.mouseChildren) ? this : child; } 7805 } 7806 } 7807 return null; 7808 }; 7809 7810 /** 7811 * @method _testMask 7812 * @param {DisplayObject} target 7813 * @param {Number} x 7814 * @param {Number} y 7815 * @return {Boolean} Indicates whether the x/y is within the masked region. 7816 * @protected 7817 **/ 7818 p._testMask = function(target, x, y) { 7819 var mask = target.mask; 7820 if (!mask || !mask.graphics || mask.graphics.isEmpty()) { return true; } 7821 7822 var mtx = this._props.matrix, parent = target.parent; 7823 mtx = parent ? parent.getConcatenatedMatrix(mtx) : mtx.identity();
7824 mtx = mask.getMatrix(mask._props.matrix).prependMatrix(mtx); 7825 7826 var ctx = createjs.DisplayObject._hitTestContext; 7827 ctx.setTransform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx-x, mtx.ty-y); 7828 7829 // draw the mask as a solid fill: 7830 mask.graphics.drawAsPath(ctx); 7831 ctx.fillStyle = "#000"; 7832 ctx.fill(); 7833 7834 if (!this._testHit(ctx)) { return false; } 7835 ctx.setTransform(1, 0, 0, 1, 0, 0); 7836 ctx.clearRect(0, 0, 2, 2); 7837 7838 return true; 7839 }; 7840 7841 /** 7842 * @method _getBounds 7843 * @param {Matrix2D} matrix 7844 * @param {Boolean} ignoreTransform If true, does not apply this object's transform. 7845 * @return {Rectangle} 7846 * @protected 7847 **/ 7848 p._getBounds = function(matrix, ignoreTransform) { 7849 var bounds = this.DisplayObject_getBounds(); 7850 if (bounds) { return this._transformBounds(bounds, matrix, ignoreTransform); } 7851 7852 var mtx = this._props.matrix; 7853 mtx = ignoreTransform ? mtx.identity() : this.getMatrix(mtx); 7854 if (matrix) { mtx.prependMatrix(matrix); } 7855 7856 var l = this.children.length, rect=null; 7857 for (var i=0; i<l; i++) { 7858 var child = this.children[i]; 7859 if (!child.visible || !(bounds = child._getBounds(mtx))) { continue; } 7860 if (rect) { rect.extend(bounds.x, bounds.y, bounds.width, bounds.height); } 7861 else { rect = bounds.clone(); } 7862 } 7863 return rect; 7864 }; 7865 7866 7867 createjs.Container = createjs.promote(Container, "DisplayObject"); 7868}()); 7869 7870//############################################################################## 7871// Stage.js 7872//############################################################################## 7873 7874this.createjs = this.createjs||{}; 7875 7876(function() { 7877 "use strict"; 7878 7879 7880// constructor: 7881 /** 7882 * A stage is the root level {{#crossLink "Container"}}{{/crossLink}} for a display list. Each time its {{#crossLink "Stage/tick"}}{{/crossLink}} 7883 * method is called, it will render its display list to its target canvas. 7884 * 7885 * <h4>Example</h4> 7886 * This example creates a stage, adds a child to it, then uses {{#crossLink "Ticker"}}{{/crossLink}} to update the child 7887 * and redraw the stage using {{#crossLink "Stage/update"}}{{/crossLink}}. 7888 * 7889 * var stage = new createjs.Stage("canvasElementId"); 7890 * var image = new createjs.Bitmap("imagePath.png"); 7891 * stage.addChild(image); 7892 * createjs.Ticker.addEventListener("tick", handleTick); 7893 * function handleTick(event) { 7894 * image.x += 10; 7895 * stage.update(); 7896 * } 7897 * 7898 * @class Stage 7899 * @extends Container 7900 * @constructor 7901 * @param {HTMLCanvasElement | String | Object} canvas A canvas object that the Stage will render to, or the string id 7902 * of a canvas object in the current document. 7903 **/ 7904 function Stage(canvas) {
7905 this.Container_constructor(); 7906 7907 7908 // public properties: 7909 /** 7910 * Indicates whether the stage should automatically clear the canvas before each render. You can set this to <code>false</code> 7911 * to manually control clearing (for generative art, or when pointing multiple stages at the same canvas for 7912 * example). 7913 * 7914 * <h4>Example</h4> 7915 * 7916 * var stage = new createjs.Stage("canvasId"); 7917 * stage.autoClear = false; 7918 * 7919 * @property autoClear 7920 * @type Boolean 7921 * @default true 7922 **/ 7923 this.autoClear = true; 7924 7925 /** 7926 * The canvas the stage will render to. Multiple stages can share a single canvas, but you must disable autoClear for all but the 7927 * first stage that will be ticked (or they will clear each other's render). 7928 * 7929 * When changing the canvas property you must disable the events on the old canvas, and enable events on the 7930 * new canvas or mouse events will not work as expected. For example: 7931 * 7932 * myStage.enableDOMEvents(false); 7933 * myStage.canvas = anotherCanvas; 7934 * myStage.enableDOMEvents(true); 7935 * 7936 * @property canvas 7937 * @type HTMLCanvasElement | Object 7938 **/ 7939 this.canvas = (typeof canvas == "string") ? document.getElementById(canvas) : canvas; 7940 7941 /** 7942 * The current mouse X position on the canvas. If the mouse leaves the canvas, this will indicate the most recent 7943 * position over the canvas, and mouseInBounds will be set to false. 7944 * @property mouseX 7945 * @type Number 7946 * @readonly 7947 **/ 7948 this.mouseX = 0; 7949 7950 /** 7951 * The current mouse Y position on the canvas. If the mouse leaves the canvas, this will indicate the most recent 7952 * position over the canvas, and mouseInBounds will be set to false. 7953 * @property mouseY 7954 * @type Number 7955 * @readonly 7956 **/ 7957 this.mouseY = 0; 7958 7959 /** 7960 * Specifies the area of the stage to affect when calling update. This can be use to selectively 7961 * re-draw specific regions of the canvas. If null, the whole canvas area is drawn. 7962 * @property drawRect 7963 * @type {Rectangle} 7964 */ 7965 this.drawRect = null; 7966 7967 /** 7968 * Indicates whether display objects should be rendered on whole pixels. You can set the 7969 * {{#crossLink "DisplayObject/snapToPixel"}}{{/crossLink}} property of 7970 * display objects to false to enable/disable this behaviour on a per instance basis. 7971 * @property snapToPixelEnabled 7972 * @type Boolean 7973 * @default false 7974 **/ 7975 this.snapToPixelEnabled = false; 7976 7977 /** 7978 * Indicates whether the mouse is currently within the bounds of the canvas. 7979 * @property mouseInBounds 7980 * @type Boolean 7981 * @default false 7982 **/ 7983 this.mouseInBounds = false; 7984 7985 /** 7986 * If true, tick callbacks will be called on all display objects on the stage prior to rendering to the canvas. 7987 * @property tickOnUpdate 7988 * @type Boolean 7989 * @default true 7990 **/ 7991 this.tickOnUpdate = true; 7992 7993 /** 7994 * If true, mouse move events will continue to be called when the mouse leaves the target canvas. See 7995 * {{#crossLink "Stage/mouseInBounds:property"}}{{/crossLink}}, and {{#crossLink "MouseEvent"}}{{/crossLink}} 7996 * x/y/rawX/rawY. 7997 * @property mouseMoveOutside 7998 * @type Boolean 7999 * @default false 8000 **/ 8001 this.mouseMoveOutside = false;
8002 8003 8004 /** 8005 * Prevents selection of other elements in the html page if the user clicks and drags, or double clicks on the canvas. 8006 * This works by calling `preventDefault()` on any mousedown events (or touch equivalent) originating on the canvas. 8007 * @property preventSelection 8008 * @type Boolean 8009 * @default true 8010 **/ 8011 this.preventSelection = true; 8012 8013 /** 8014 * The hitArea property is not supported for Stage. 8015 * @property hitArea 8016 * @type {DisplayObject} 8017 * @default null 8018 */ 8019 8020 8021 // private properties: 8022 /** 8023 * Holds objects with data for each active pointer id. Each object has the following properties: 8024 * x, y, event, target, overTarget, overX, overY, inBounds, posEvtObj (native event that last updated position) 8025 * @property _pointerData 8026 * @type {Object} 8027 * @private 8028 */ 8029 this._pointerData = {}; 8030 8031 /** 8032 * Number of active pointers. 8033 * @property _pointerCount 8034 * @type {Object} 8035 * @private 8036 */ 8037 this._pointerCount = 0; 8038 8039 /** 8040 * The ID of the primary pointer. 8041 * @property _primaryPointerID 8042 * @type {Object} 8043 * @private 8044 */ 8045 this._primaryPointerID = null; 8046 8047 /** 8048 * @property _mouseOverIntervalID 8049 * @protected 8050 * @type Number 8051 **/ 8052 this._mouseOverIntervalID = null; 8053 8054 /** 8055 * @property _nextStage 8056 * @protected 8057 * @type Stage 8058 **/ 8059 this._nextStage = null; 8060 8061 /** 8062 * @property _prevStage 8063 * @protected 8064 * @type Stage 8065 **/ 8066 this._prevStage = null; 8067 8068 8069 // initialize: 8070 this.enableDOMEvents(true); 8071 } 8072 var p = createjs.extend(Stage, createjs.Container); 8073 8074// events: 8075 /** 8076 * Dispatched when the user moves the mouse over the canvas. 8077 * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. 8078 * @event stagemousemove 8079 * @since 0.6.0 8080 */ 8081 8082 /** 8083 * Dispatched when the user presses their left mouse button on the canvas. See the {{#crossLink "MouseEvent"}}{{/crossLink}} 8084 * class for a listing of event properties. 8085 * @event stagemousedown 8086 * @since 0.6.0 8087 */ 8088 8089 /** 8090 * Dispatched when the user the user presses somewhere on the stage, then releases the mouse button anywhere that the page can detect it (this varies slightly between browsers). 8091 * You can use {{#crossLink "Stage/mouseInBounds:property"}}{{/crossLink}} to check whether the mouse is currently within the stage bounds. 8092 * See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties. 8093 * @event stagemouseup 8094 * @since 0.6.0 8095 */ 8096 8097 /** 8098 * Dispatched when the mouse moves from within the canvas area (mouseInBounds == true) to outside it (mouseInBounds == false). 8099 * This is currently only dispatched for mouse input (not touch). See the {{#crossLink "MouseEvent"}}{{/crossLink}} 8100 * class for a listing of event properties. 8101 * @event mouseleave 8102 * @since 0.7.0 8103 */ 8104 8105 /** 8106 * Dispatched when the mouse moves into the canvas area (mouseInBounds == false) from outside it (mouseInBounds == true). 8107 * This is currently only dispatched for mouse input (not touch). See the {{#crossLink "MouseEvent"}}{{/crossLink}} 8108 * class for a listing of event properties. 8109 * @event mouseenter 8110 * @since 0.7.0 8111 */ 8112 8113 /** 8114 * Dispatched each update immediately before the tick event is propagated through the display list. 8115 * You can call preventDefault on the event object to cancel propagating the tick event. 8116 * @event tickstart 8117 * @since 0.7.0 8118 */ 8119 8120 /** 8121 * Dispatched each update immediately after the tick event is propagated through the display list. Does not fire if 8122 * tickOnUpdate is false. Precedes the "drawstart" event. 8123 * @event tickend 8124 * @since 0.7.0 8125 */ 8126 8127 /** 8128 * Dispatched each update immediately before the canvas is cleared and the display list is drawn to it. 8129 * You can call preventDefault on the event object to cancel the draw. 8130 * @event drawstart 8131 * @since 0.7.0 8132 */ 8133 8134 /**
8135 * Dispatched each update immediately after the display list is drawn to the canvas and the canvas context is restored. 8136 * @event drawend 8137 * @since 0.7.0 8138 */ 8139 8140 8141// getter / setters: 8142 /** 8143 * Specifies a target stage that will have mouse / touch interactions relayed to it after this stage handles them. 8144 * This can be useful in cases where you have multiple layered canvases and want user interactions 8145 * events to pass through. For example, this would relay mouse events from topStage to bottomStage: 8146 * 8147 * topStage.nextStage = bottomStage; 8148 * 8149 * To disable relaying, set nextStage to null. 8150 * 8151 * MouseOver, MouseOut, RollOver, and RollOut interactions are also passed through using the mouse over settings 8152 * of the top-most stage, but are only processed if the target stage has mouse over interactions enabled. 8153 * Considerations when using roll over in relay targets:<OL> 8154 * <LI> The top-most (first) stage must have mouse over interactions enabled (via enableMouseOver)</LI> 8155 * <LI> All stages that wish to participate in mouse over interaction must enable them via enableMouseOver</LI> 8156 * <LI> All relay targets will share the frequency value of the top-most stage</LI> 8157 * </OL> 8158 * To illustrate, in this example the targetStage would process mouse over interactions at 10hz (despite passing 8159 * 30 as it's desired frequency): 8160 * topStage.nextStage = targetStage; 8161 * topStage.enableMouseOver(10); 8162 * targetStage.enableMouseOver(30); 8163 * 8164 * If the target stage's canvas is completely covered by this stage's canvas, you may also want to disable its 8165 * DOM events using: 8166 * 8167 * targetStage.enableDOMEvents(false); 8168 * 8169 * @property nextStage 8170 * @type {Stage} 8171 **/ 8172 p._get_nextStage = function() { 8173 return this._nextStage; 8174 }; 8175 p._set_nextStage = function(value) { 8176 if (this._nextStage) { this._nextStage._prevStage = null; } 8177 if (value) { value._prevStage = this; } 8178 this._nextStage = value; 8179 }; 8180 8181 try { 8182 Object.defineProperties(p, { 8183 nextStage: { get: p._get_nextStage, set: p._set_nextStage } 8184 }); 8185 } catch (e) {} // TODO: use Log 8186 8187 8188// public methods: 8189 /** 8190 * Each time the update method is called, the stage will call {{#crossLink "Stage/tick"}}{{/crossLink}} 8191 * unless {{#crossLink "Stage/tickOnUpdate:property"}}{{/crossLink}} is set to false, 8192 * and then render the display list to the canvas. 8193 * 8194 * @method update 8195 * @param {Object} [props] Props object to pass to `tick()`. Should usually be a {{#crossLink "Ticker"}}{{/crossLink}} event object, or similar object with a delta property. 8196 **/ 8197 p.update = function(props) { 8198 if (!this.canvas) { return; } 8199 if (this.tickOnUpdate) { this.tick(props); } 8200 if (this.dispatchEvent("drawstart", false, true) === false) { return; } 8201 createjs.DisplayObject._snapToPixelEnabled = this.snapToPixelEnabled; 8202 var r = this.drawRect, ctx = this.canvas.getContext("2d"); 8203 ctx.setTransform(1, 0, 0, 1, 0, 0); 8204 if (this.autoClear) { 8205 if (r) { ctx.clearRect(r.x, r.y, r.width, r.height); } 8206 else { ctx.clearRect(0, 0, this.canvas.width+1, this.canvas.height+1); } 8207 } 8208 ctx.save(); 8209 if (this.drawRect) { 8210 ctx.beginPath(); 8211 ctx.rect(r.x, r.y, r.width, r.height); 8212 ctx.clip(); 8213 } 8214 this.updateContext(ctx); 8215 this.draw(ctx, false); 8216 ctx.restore(); 8217 this.dispatchEvent("drawend"); 8218 }; 8219 8220 /** 8221 * Propagates a tick event through the display list. This is automatically called by {{#crossLink "Stage/update"}}{{/crossLink}} 8222 * unless {{#crossLink "Stage/tickOnUpdate:property"}}{{/crossLink}} is set to false. 8223 * 8224 * If a props object is passed to `tick()`, then all of its properties will be copied to the event object that is 8225 * propagated to listeners. 8226 * 8227 * Some time-based features in EaselJS (for example {{#crossLink "Sprite/framerate"}}{{/crossLink}} require that 8228 * a {{#crossLink "Ticker/tick:event"}}{{/crossLink}} event object (or equivalent object with a delta property) be 8229 * passed as the `props` parameter to `tick()`. For example: 8230 * 8231 * Ticker.on("tick", handleTick); 8232 * function handleTick(evtObj) { 8233 * // clone the event object from Ticker, and add some custom data to it: 8234 * var evt = evtObj.clone().set({greeting:"hello", name:"world"}); 8235 *
8236 * // pass it to stage.update(): 8237 * myStage.update(evt); // subsequently calls tick() with the same param 8238 * } 8239 * 8240 * // ... 8241 * myDisplayObject.on("tick", handleDisplayObjectTick); 8242 * function handleDisplayObjectTick(evt) { 8243 * console.log(evt.delta); // the delta property from the Ticker tick event object 8244 * console.log(evt.greeting, evt.name); // custom data: "hello world" 8245 * } 8246 * 8247 * @method tick 8248 * @param {Object} [props] An object with properties that should be copied to the event object. Should usually be a Ticker event object, or similar object with a delta property. 8249 **/ 8250 p.tick = function(props) { 8251 if (!this.tickEnabled || this.dispatchEvent("tickstart", false, true) === false) { return; } 8252 var evtObj = new createjs.Event("tick"); 8253 if (props) { 8254 for (var n in props) { 8255 if (props.hasOwnProperty(n)) { evtObj[n] = props[n]; } 8256 } 8257 } 8258 this._tick(evtObj); 8259 this.dispatchEvent("tickend"); 8260 }; 8261 8262 /** 8263 * Default event handler that calls the Stage {{#crossLink "Stage/update"}}{{/crossLink}} method when a {{#crossLink "DisplayObject/tick:event"}}{{/crossLink}} 8264 * event is received. This allows you to register a Stage instance as a event listener on {{#crossLink "Ticker"}}{{/crossLink}} 8265 * directly, using: 8266 * 8267 * Ticker.addEventListener("tick", myStage); 8268 * 8269 * Note that if you subscribe to ticks using this pattern, then the tick event object will be passed through to 8270 * display object tick handlers, instead of <code>delta</code> and <code>paused</code> parameters. 8271 * @property handleEvent 8272 * @type Function 8273 **/ 8274 p.handleEvent = function(evt) { 8275 if (evt.type == "tick") { this.update(evt); } 8276 }; 8277 8278 /** 8279 * Clears the target canvas. Useful if {{#crossLink "Stage/autoClear:property"}}{{/crossLink}} is set to `false`. 8280 * @method clear 8281 **/ 8282 p.clear = function() { 8283 if (!this.canvas) { return; } 8284 var ctx = this.canvas.getContext("2d"); 8285 ctx.setTransform(1, 0, 0, 1, 0, 0); 8286 ctx.clearRect(0, 0, this.canvas.width+1, this.canvas.height+1); 8287 }; 8288 8289 /** 8290 * Returns a data url that contains a Base64-encoded image of the contents of the stage. The returned data url can 8291 * be specified as the src value of an image element. 8292 * @method toDataURL 8293 * @param {String} [backgroundColor] The background color to be used for the generated image. Any valid CSS color 8294 * value is allowed. The default value is a transparent background. 8295 * @param {String} [mimeType="image/png"] The MIME type of the image format to be create. The default is "image/png". If an unknown MIME type 8296 * is passed in, or if the browser does not support the specified MIME type, the default value will be used. 8297 * @return {String} a Base64 encoded image. 8298 **/ 8299 p.toDataURL = function(backgroundColor, mimeType) { 8300 var data, ctx = this.canvas.getContext('2d'), w = this.canvas.width, h = this.canvas.height; 8301 8302 if (backgroundColor) { 8303 data = ctx.getImageData(0, 0, w, h); 8304 var compositeOperation = ctx.globalCompositeOperation; 8305 ctx.globalCompositeOperation = "destination-over"; 8306 8307 ctx.fillStyle = backgroundColor; 8308 ctx.fillRect(0, 0, w, h); 8309 } 8310 8311 var dataURL = this.canvas.toDataURL(mimeType||"image/png"); 8312 8313 if(backgroundColor) { 8314 ctx.putImageData(data, 0, 0); 8315 ctx.globalCompositeOperation = compositeOperation; 8316 } 8317 8318 return dataURL; 8319 }; 8320 8321 /** 8322 * Enables or disables (by passing a frequency of 0) mouse over ({{#crossLink "DisplayObject/mouseover:event"}}{{/crossLink}} 8323 * and {{#crossLink "DisplayObject/mouseout:event"}}{{/crossLink}}) and roll over events ({{#crossLink "DisplayObject/rollover:event"}}{{/crossLink}} 8324 * and {{#crossLink "DisplayObject/rollout:event"}}{{/crossLink}}) for this stage's display list. These events can 8325 * be expensive to generate, so they are disabled by default. The frequency of the events can be controlled 8326 * independently of mouse move events via the optional `frequency` parameter. 8327 * 8328 * <h4>Example</h4> 8329 * 8330 * var stage = new createjs.Stage("canvasId"); 8331 * stage.enableMouseOver(10); // 10 updates per second 8332 * 8333 * @method enableMouseOver 8334 * @param {Number} [frequency=20] Optional param specifying the maximum number of times per second to broadcast 8335 * mouse over/out events. Set to 0 to disable mouse over events completely. Maximum is 50. A lower frequency is less 8336 * responsive, but uses less CPU. 8337 **/ 8338 p.enableMouseOver = function(frequency) { 8339 if (this._mouseOverIntervalID) { 8340 clearInterval(this._mouseOverIntervalID); 8341 this._mouseOverIntervalID = null; 8342 if (frequency == 0) { 8343 this._testMouseOver(true); 8344 } 8345 } 8346 if (frequency == null) { frequency = 20; } 8347 else if (frequency <= 0) { return; } 8348 var o = this; 8349 this._mouseOverIntervalID = setInterval(function(){ o._testMouseOver(); }, 1000/Math.min(50,frequency)); 8350 }; 8351 8352 /** 8353 * Enables or disables the event listeners that stage adds to DOM elements (window, document and canvas). It is good 8354 * practice to disable events when disposing of a Stage instance, otherwise the stage will continue to receive 8355 * events from the page. 8356 * 8357 * When changing the canvas property you must disable the events on the old canvas, and enable events on the 8358 * new canvas or mouse events will not work as expected. For example: 8359 * 8360 * myStage.enableDOMEvents(false); 8361 * myStage.canvas = anotherCanvas; 8362 * myStage.enableDOMEvents(true); 8363 * 8364 * @method enableDOMEvents 8365 * @param {Boolean} [enable=true] Indicates whether to enable or disable the events. Default is true. 8366 **/ 8367 p.enableDOMEvents = function(enable) { 8368 if (enable == null) { enable = true; } 8369 var n, o, ls = this._eventListeners; 8370 if (!enable && ls) { 8371 for (n in ls) { 8372 o = ls[n]; 8373 o.t.removeEventListener(n, o.f, false); 8374 } 8375 this._eventListeners = null; 8376 } else if (enable && !ls && this.canvas) { 8377 var t = window.addEventListener ? window : document; 8378 var _this = this; 8379 ls = this._eventListeners = {};
8380 ls["mouseup"] = {t:t, f:function(e) { _this._handleMouseUp(e)} }; 8381 ls["mousemove"] = {t:t, f:function(e) { _this._handleMouseMove(e)} }; 8382 ls["dblclick"] = {t:this.canvas, f:function(e) { _this._handleDoubleClick(e)} }; 8383 ls["mousedown"] = {t:this.canvas, f:function(e) { _this._handleMouseDown(e)} }; 8384 8385 for (n in ls) { 8386 o = ls[n]; 8387 o.t.addEventListener(n, o.f, false); 8388 } 8389 } 8390 }; 8391 8392 /** 8393 * Stage instances cannot be cloned. 8394 * @method clone 8395 **/ 8396 p.clone = function() { 8397 throw("Stage cannot be cloned."); 8398 }; 8399 8400 /** 8401 * Returns a string representation of this object. 8402 * @method toString 8403 * @return {String} a string representation of the instance. 8404 **/ 8405 p.toString = function() { 8406 return "[Stage (name="+ this.name +")]"; 8407 }; 8408 8409 8410// private methods: 8411 /** 8412 * @method _getElementRect 8413 * @protected 8414 * @param {HTMLElement} e 8415 **/ 8416 p._getElementRect = function(e) { 8417 var bounds; 8418 try { bounds = e.getBoundingClientRect(); } // this can fail on disconnected DOM elements in IE9 8419 catch (err) { bounds = {top: e.offsetTop, left: e.offsetLeft, width:e.offsetWidth, height:e.offsetHeight}; } 8420 8421 var offX = (window.pageXOffset || document.scrollLeft || 0) - (document.clientLeft || document.body.clientLeft || 0); 8422 var offY = (window.pageYOffset || document.scrollTop || 0) - (document.clientTop || document.body.clientTop || 0); 8423 8424 var styles = window.getComputedStyle ? getComputedStyle(e,null) : e.currentStyle; // IE <9 compatibility. 8425 var padL = parseInt(styles.paddingLeft)+parseInt(styles.borderLeftWidth); 8426 var padT = parseInt(styles.paddingTop)+parseInt(styles.borderTopWidth); 8427 var padR = parseInt(styles.paddingRight)+parseInt(styles.borderRightWidth); 8428 var padB = parseInt(styles.paddingBottom)+parseInt(styles.borderBottomWidth); 8429 8430 // note: in some browsers bounds properties are read only. 8431 return { 8432 left: bounds.left+offX+padL, 8433 right: bounds.right+offX-padR, 8434 top: bounds.top+offY+padT, 8435 bottom: bounds.bottom+offY-padB 8436 } 8437 }; 8438 8439 /** 8440 * @method _getPointerData 8441 * @protected 8442 * @param {Number} id 8443 **/ 8444 p._getPointerData = function(id) { 8445 var data = this._pointerData[id]; 8446 if (!data) { data = this._pointerData[id] = {x:0,y:0}; } 8447 return data; 8448 }; 8449 8450 /** 8451 * @method _handleMouseMove 8452 * @protected 8453 * @param {MouseEvent} e 8454 **/ 8455 p._handleMouseMove = function(e) { 8456 if(!e){ e = window.event; } 8457 this._handlePointerMove(-1, e, e.pageX, e.pageY); 8458 }; 8459 8460 /** 8461 * @method _handlePointerMove 8462 * @protected 8463 * @param {Number} id 8464 * @param {Event} e 8465 * @param {Number} pageX 8466 * @param {Number} pageY 8467 * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage. 8468 **/ 8469 p._handlePointerMove = function(id, e, pageX, pageY, owner) { 8470 if (this._prevStage && owner === undefined) { return; } // redundant listener. 8471 if (!this.canvas) { return; } 8472 var nextStage=this._nextStage, o=this._getPointerData(id); 8473 8474 var inBounds = o.inBounds; 8475 this._updatePointerPosition(id, e, pageX, pageY); 8476 if (inBounds || o.inBounds || this.mouseMoveOutside) { 8477 if (id === -1 && o.inBounds == !inBounds) { 8478 this._dispatchMouseEvent(this, (inBounds ? "mouseleave" : "mouseenter"), false, id, o, e); 8479 } 8480 8481 this._dispatchMouseEvent(this, "stagemousemove", false, id, o, e); 8482 this._dispatchMouseEvent(o.target, "pressmove", true, id, o, e); 8483 } 8484 8485 nextStage&&nextStage._handlePointerMove(id, e, pageX, pageY, null); 8486 }; 8487 8488 /** 8489 * @method _updatePointerPosition 8490 * @protected 8491 * @param {Number} id 8492 * @param {Event} e 8493 * @param {Number} pageX 8494 * @param {Number} pageY 8495 **/ 8496 p._updatePointerPosition = function(id, e, pageX, pageY) { 8497 var rect = this._getElementRect(this.canvas); 8498 pageX -= rect.left; 8499 pageY -= rect.top; 8500 8501 var w = this.canvas.width; 8502 var h = this.canvas.height; 8503 pageX /= (rect.right-rect.left)/w; 8504 pageY /= (rect.bottom-rect.top)/h; 8505 var o = this._getPointerData(id); 8506 if (o.inBounds = (pageX >= 0 && pageY >= 0 && pageX <= w-1 && pageY <= h-1)) { 8507 o.x = pageX; 8508 o.y = pageY; 8509 } else if (this.mouseMoveOutside) { 8510 o.x = pageX < 0 ? 0 : (pageX > w-1 ? w-1 : pageX); 8511 o.y = pageY < 0 ? 0 : (pageY > h-1 ? h-1 : pageY); 8512 } 8513 8514 o.posEvtObj = e; 8515 o.rawX = pageX; 8516 o.rawY = pageY; 8517 8518 if (id === this._primaryPointerID || id === -1) { 8519 this.mouseX = o.x; 8520 this.mouseY = o.y; 8521 this.mouseInBounds = o.inBounds; 8522 } 8523 }; 8524 8525 /** 8526 * @method _handleMouseUp 8527 * @protected 8528 * @param {MouseEvent} e 8529 **/ 8530 p._handleMouseUp = function(e) { 8531 this._handlePointerUp(-1, e, false); 8532 }; 8533 8534 /** 8535 * @method _handlePointerUp 8536 * @protected 8537 * @param {Number} id 8538 * @param {Event} e 8539 * @param {Boolean} clear 8540 * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage. 8541 **/ 8542 p._handlePointerUp = function(id, e, clear, owner) { 8543 var nextStage = this._nextStage, o = this._getPointerData(id); 8544 if (this._prevStage && owner === undefined) { return; } // redundant listener. 8545 8546 var target=null, oTarget = o.target; 8547 if (!owner && (oTarget || nextStage)) { target = this._getObjectsUnderPoint(o.x, o.y, null, true); } 8548 8549 if (o.down) { this._dispatchMouseEvent(this, "stagemouseup", false, id, o, e, target); o.down = false; } 8550 8551 if (target == oTarget) { this._dispatchMouseEvent(oTarget, "click", true, id, o, e); } 8552 this._dispatchMouseEvent(oTarget, "pressup", true, id, o, e); 8553 8554 if (clear) { 8555 if (id==this._primaryPointerID) { this._primaryPointerID = null; } 8556 delete(this._pointerData[id]); 8557 } else { o.target = null; } 8558 8559 nextStage&&nextStage._handlePointerUp(id, e, clear, owner || target && this); 8560 }; 8561 8562 /** 8563 * @method _handleMouseDown 8564 * @protected 8565 * @param {MouseEvent} e 8566 **/ 8567 p._handleMouseDown = function(e) { 8568 this._handlePointerDown(-1, e, e.pageX, e.pageY); 8569 }; 8570 8571 /** 8572 * @method _handlePointerDown 8573 * @protected 8574 * @param {Number} id 8575 * @param {Event} e 8576 * @param {Number} pageX 8577 * @param {Number} pageY 8578 * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage. 8579 **/ 8580 p._handlePointerDown = function(id, e, pageX, pageY, owner) { 8581 if (this.preventSelection) { e.preventDefault(); } 8582 if (this._primaryPointerID == null || id === -1) { this._primaryPointerID = id; } // mouse always takes over. 8583 8584 if (pageY != null) { this._updatePointerPosition(id, e, pageX, pageY); } 8585 var target = null, nextStage = this._nextStage, o = this._getPointerData(id); 8586 if (!owner) { target = o.target = this._getObjectsUnderPoint(o.x, o.y, null, true); } 8587 8588 if (o.inBounds) { this._dispatchMouseEvent(this, "stagemousedown", false, id, o, e, target); o.down = true; } 8589 this._dispatchMouseEvent(target, "mousedown", true, id, o, e); 8590 8591 nextStage&&nextStage._handlePointerDown(id, e, pageX, pageY, owner || target && this); 8592 }; 8593 8594 /** 8595 * @method _testMouseOver 8596 * @param {Boolean} clear If true, clears the mouseover / rollover (ie. no target) 8597 * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage. 8598 * @param {Stage} eventTarget The stage that the cursor is actively over. 8599 * @protected 8600 **/ 8601 p._testMouseOver = function(clear, owner, eventTarget) { 8602 if (this._prevStage && owner === undefined) { return; } // redundant listener. 8603 8604 var nextStage = this._nextStage; 8605 if (!this._mouseOverIntervalID) { 8606 // not enabled for mouseover, but should still relay the event. 8607 nextStage&&nextStage._testMouseOver(clear, owner, eventTarget); 8608 return; 8609 } 8610 var o = this._getPointerData(-1); 8611 // only update if the mouse position has changed. This provides a lot of optimization, but has some trade-offs. 8612 if (!o || (!clear && this.mouseX == this._mouseOverX && this.mouseY == this._mouseOverY && this.mouseInBounds)) { return; } 8613 8614 var e = o.posEvtObj; 8615 var isEventTarget = eventTarget || e&&(e.target == this.canvas); 8616 var target=null, common = -1, cursor="", t, i, l; 8617 8618 if (!owner && (clear || this.mouseInBounds && isEventTarget)) { 8619 target = this._getObjectsUnderPoint(this.mouseX, this.mouseY, null, true); 8620 this._mouseOverX = this.mouseX; 8621 this._mouseOverY = this.mouseY; 8622 } 8623 8624 var oldList = this._mouseOverTarget||[]; 8625 var oldTarget = oldList[oldList.length-1]; 8626 var list = this._mouseOverTarget = []; 8627 8628 // generate ancestor list and check for cursor: 8629 t = target; 8630 while (t) { 8631 list.unshift(t);
8632 if (!cursor) { cursor = t.cursor; } 8633 t = t.parent; 8634 } 8635 this.canvas.style.cursor = cursor; 8636 if (!owner && eventTarget) { eventTarget.canvas.style.cursor = cursor; } 8637 8638 // find common ancestor: 8639 for (i=0,l=list.length; i<l; i++) { 8640 if (list[i] != oldList[i]) { break; } 8641 common = i; 8642 } 8643 8644 if (oldTarget != target) { 8645 this._dispatchMouseEvent(oldTarget, "mouseout", true, -1, o, e, target); 8646 } 8647 8648 for (i=oldList.length-1; i>common; i--) { 8649 this._dispatchMouseEvent(oldList[i], "rollout", false, -1, o, e, target); 8650 } 8651 8652 for (i=list.length-1; i>common; i--) { 8653 this._dispatchMouseEvent(list[i], "rollover", false, -1, o, e, oldTarget); 8654 } 8655 8656 if (oldTarget != target) { 8657 this._dispatchMouseEvent(target, "mouseover", true, -1, o, e, oldTarget); 8658 } 8659 8660 nextStage&&nextStage._testMouseOver(clear, owner || target && this, eventTarget || isEventTarget && this); 8661 }; 8662 8663 /** 8664 * @method _handleDoubleClick 8665 * @protected 8666 * @param {MouseEvent} e 8667 * @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage. 8668 **/ 8669 p._handleDoubleClick = function(e, owner) { 8670 var target=null, nextStage=this._nextStage, o=this._getPointerData(-1); 8671 if (!owner) { 8672 target = this._getObjectsUnderPoint(o.x, o.y, null, true); 8673 this._dispatchMouseEvent(target, "dblclick", true, -1, o, e); 8674 } 8675 nextStage&&nextStage._handleDoubleClick(e, owner || target && this); 8676 }; 8677 8678 /** 8679 * @method _dispatchMouseEvent 8680 * @protected 8681 * @param {DisplayObject} target 8682 * @param {String} type 8683 * @param {Boolean} bubbles 8684 * @param {Number} pointerId 8685 * @param {Object} o 8686 * @param {MouseEvent} [nativeEvent] 8687 * @param {DisplayObject} [relatedTarget] 8688 **/ 8689 p._dispatchMouseEvent = function(target, type, bubbles, pointerId, o, nativeEvent, relatedTarget) { 8690 // TODO: might be worth either reusing MouseEvent instances, or adding a willTrigger method to avoid GC. 8691 if (!target || (!bubbles && !target.hasEventListener(type))) { return; } 8692 /* 8693 // TODO: account for stage transformations? 8694 this._mtx = this.getConcatenatedMatrix(this._mtx).invert(); 8695 var pt = this._mtx.transformPoint(o.x, o.y); 8696 var evt = new createjs.MouseEvent(type, bubbles, false, pt.x, pt.y, nativeEvent, pointerId, pointerId==this._primaryPointerID || pointerId==-1, o.rawX, o.rawY); 8697 */ 8698 var evt = new createjs.MouseEvent(type, bubbles, false, o.x, o.y, nativeEvent, pointerId, pointerId === this._primaryPointerID || pointerId === -1, o.rawX, o.rawY, relatedTarget); 8699 target.dispatchEvent(evt); 8700 }; 8701 8702 8703 createjs.Stage = createjs.promote(Stage, "Container"); 8704}()); 8705 8706//############################################################################## 8707// StageGL.js 8708//############################################################################## 8709 8710this.createjs = this.createjs||{}; 8711 8712/* 8713 * README IF EDITING: 8714 * Terminology for developers: 8715 * 8716 * Vertex: a point that help defines a shape, 3 per triangle. Usually has an x,y,z but can have more/less info. 8717 * Vertex Property: a piece of information attached to the vertex like a vector3 containing x,y,z 8718 * Index/Indices: used in groups of 3 to define a triangle, points to vertices by their index in an array (some render 8719 * modes do not use these) 8720 * Card: a group of 2 triangles used to display a rectangular image 8721 * U/V: common names for the [0-1] texture co-ordinates on an image 8722 * Batch: a single call to the renderer, best done as little as possible so multiple cards are put into a single batch 8723 * Buffer: WebGL array data
8724 * Program/Shader: For every vertex we run the Vertex shader. The results are used per pixel by the Fragment shader. When 8725 * combined and paired these are a shader "program" 8726 * Texture: WebGL representation of image data and associated extra information 8727 * Slot: A space on the GPU into which textures can be loaded for use in a batch, using "ActiveTexture" switches texture slot. 8728 */ 8729 8730(function () { 8731 "use strict"; 8732 8733 /** 8734 * A StageGL instance is the root level {{#crossLink "Container"}}{{/crossLink}} for an WebGL-optimized display list, 8735 * which is used in place of the usual {{#crossLink "Stage"}}{{/crossLink}}. This class should behave identically to 8736 * a {{#crossLink "Stage"}}{{/crossLink}} except for WebGL-specific functionality. 8737 * 8738 * Each time the {{#crossLink "Stage/tick"}}{{/crossLink}} method is called, the display list is rendered to the 8739 * target <canvas/> instance, ignoring non-WebGL-compatible display objects. On devices and browsers that don't 8740 * support WebGL, content will automatically be rendered to canvas 2D context instead. 8741 * 8742 * <h4>Limitations</h4> 8743 * - {{#crossLink "Shape"}}{{/crossLink}}, {{#crossLink "Shadow"}}{{/crossLink}}, and {{#crossLink "Text"}}{{/crossLink}} 8744 * are not rendered when added to the display list. 8745 * - To display something StageGL cannot render, {{#crossLink "displayObject/cache"}}{{/crossLink}} the object. 8746 * Caches can be rendered regardless of source. 8747 * - Images are wrapped as a webGL "Texture". Each graphics card has a limit to its concurrent Textures, too many 8748 * Textures will noticeably slow performance. 8749 * - Each cache counts as an individual Texture. As such {{#crossLink "SpriteSheet"}}{{/crossLink}} and 8750 * {{#crossLink "SpriteSheetBuilder"}}{{/crossLink}} are recommended practices to help keep texture counts low. 8751 * - To use any image node (DOM Image/Canvas Element) between multiple StageGL instances it must be a 8752 * {{#crossLink "Bitmap/clone"}}{{/crossLink}}, otherwise the GPU texture loading and tracking will get confused. 8753 * - to avoid an up/down scaled render you must call {{#crossLink "StageGL/updateViewport"}}{{/crossLink}} if you 8754 * resize your canvas after making a StageGL instance, this will properly size the WebGL context stored in memory. 8755 * - Best performance in demanding scenarios will come from manual management of texture memory, but it is handled 8756 * automatically by default. See {{#crossLink "StageGL/releaseTexture"}}{{/crossLink}} for details. 8757 * 8758 * <h4>Example</h4> 8759 * This example creates a StageGL instance, adds a child to it, then uses the EaselJS {{#crossLink "Ticker"}}{{/crossLink}} 8760 * to update the child and redraw the stage. 8761 * 8762 * var stage = new createjs.StageGL("canvasElementId"); 8763 * 8764 * var image = new createjs.Bitmap("imagePath.png"); 8765 * stage.addChild(image); 8766 * 8767 * createjs.Ticker.on("tick", handleTick); 8768 * 8769 * function handleTick(event) { 8770 * image.x += 10; 8771 * stage.update(); 8772 * } 8773 * 8774 * <h4>Notes</h4> 8775 * - StageGL is not currently included in the minified version of EaselJS. 8776 * - {{#crossLink "SpriteContainer"}}{{/crossLink}} (the previous approach to WebGL with EaselJS) has been deprecated. 8777 * - Earlier versions of WebGL support in EaselJS (SpriteStage and SpriteContainer) had hard limitations on images 8778 * per container, which have been solved. 8779 * 8780 * @class StageGL 8781 * @extends Stage 8782 * @constructor 8783 * @param {HTMLCanvasElement | String | Object} canvas A canvas object that StageGL will render to, or the string id 8784 * of a canvas object in the current DOM. 8785 * @param {Object} options All the option parameters in a reference object, some are not supported by some browsers. 8786 * @param {Boolean} [options.preserveBuffer=false] If `true`, the canvas is NOT auto-cleared by WebGL (the spec 8787 * discourages setting this to `true`). This is useful if you want persistent draw effects. 8788 * @param {Boolean} [options.antialias=false] Specifies whether or not the browser's WebGL implementation should try
8789 * to perform anti-aliasing. This will also enable linear pixel sampling on power-of-two textures (smoother images). 8790 * @param {Boolean} [options.transparent=false] If `true`, the canvas is transparent. This is <strong>very</strong> 8791 * expensive, and should be used with caution. 8792 * @param {Boolean} [options.premultiply=false] Alters color handling. If `true`, this assumes the shader must 8793 * account for pre-multiplied alpha. This can help avoid visual halo effects with some assets, but may also cause 8794 * problems with other assets. 8795 * @param {Integer} [options.autoPurge=1200] How often the system should automatically dump unused textures with 8796 * `purgeTextures(autoPurge)` every `autoPurge/2` draws. See {{#crossLink "StageGL/purgeTextures"}}{{/crossLink}} for more 8797 * information. 8798 */ 8799 function StageGL(canvas, options) { 8800 this.Stage_constructor(canvas); 8801 8802 if (options !== undefined) { 8803 if (typeof options !== "object"){ throw("Invalid options object"); } 8804 var premultiply = options.premultiply; 8805 var transparent = options.transparent; 8806 var antialias = options.antialias; 8807 var preserveBuffer = options.preserveBuffer; 8808 var autoPurge = options.autoPurge; 8809 } 8810 8811// public properties: 8812 /** 8813 * Console log potential issues and problems. This is designed to have <em>minimal</em> performance impact, so 8814 * if extensive debugging information is required, this may be inadequate. See {{#crossLink "WebGLInspector"}}{{/crossLink}} 8815 * @property vocalDebug 8816 * @type {Boolean} 8817 * @default false 8818 */ 8819 this.vocalDebug = false; 8820 8821// private properties: 8822 /** 8823 * Specifies whether or not the canvas is auto-cleared by WebGL. The WebGL spec discourages `true`. 8824 * If true, the canvas is NOT auto-cleared by WebGL. Used when the canvas context is created and requires 8825 * context re-creation to update. 8826 * @property _preserveBuffer 8827 * @protected 8828 * @type {Boolean} 8829 * @default false 8830 */ 8831 this._preserveBuffer = preserveBuffer||false; 8832 8833 /** 8834 * Specifies whether or not the browser's WebGL implementation should try to perform anti-aliasing. 8835 * @property _antialias 8836 * @protected 8837 * @type {Boolean} 8838 * @default false 8839 */ 8840 this._antialias = antialias||false; 8841 8842 /** 8843 * Specifies whether or not the browser's WebGL implementation should be transparent. 8844 * @property _transparent 8845 * @protected 8846 * @type {Boolean} 8847 * @default false 8848 */ 8849 this._transparent = transparent||false; 8850 8851 /** 8852 * Specifies whether or not StageGL is handling colours as premultiplied alpha. 8853 * @property _premultiply 8854 * @protected 8855 * @type {Boolean} 8856 * @default false 8857 */ 8858 this._premultiply = premultiply||false; 8859 8860 /** 8861 * Internal value of {{#crossLink "StageGL/autoPurge"}}{{/crossLink}} 8862 * @property _autoPurge 8863 * @protected 8864 * @type {Integer} 8865 * @default null 8866 */ 8867 this._autoPurge = undefined; 8868 this.autoPurge = autoPurge; //getter/setter handles setting the real value and validating 8869 8870 /** 8871 * The width in px of the drawing surface saved in memory. 8872 * @property _viewportWidth 8873 * @protected 8874 * @type {Number} 8875 * @default 0 8876 */ 8877 this._viewportWidth = 0; 8878 8879 /** 8880 * The height in px of the drawing surface saved in memory. 8881 * @property _viewportHeight 8882 * @protected 8883 * @type {Number} 8884 * @default 0 8885 */ 8886 this._viewportHeight = 0; 8887 8888 /** 8889 * A 2D projection matrix used to convert WebGL's viewspace into canvas co-ordinates. Regular canvas display 8890 * uses Top-Left values of [0,0] where WebGL uses a Center [0,0] Top-Right [1,1] (euclidean) system. 8891 * @property _projectionMatrix 8892 * @protected 8893 * @type {Float32Array} 8894 * @default null 8895 */ 8896 this._projectionMatrix = null; 8897 8898 /** 8899 * The current WebGL canvas context. Often shorthanded to just "gl" in many parts of the code. 8900 * @property _webGLContext 8901 * @protected 8902 * @type {WebGLRenderingContext} 8903 * @default null 8904 */ 8905 this._webGLContext = null; 8906 8907 /** 8908 * The color to use when the WebGL canvas has been cleared. May appear as a background color. Defaults to grey. 8909 * @property _clearColor 8910 * @protected 8911 * @type {Object} 8912 * @default {r: 0.50, g: 0.50, b: 0.50, a: 0.00} 8913 */ 8914 this._clearColor = {r: 0.50, g: 0.50, b: 0.50, a: 0.00}; 8915 8916 /** 8917 * The maximum number of cards (aka a single sprite) that can be drawn in one draw call. Use getter/setters to 8918 * modify otherwise internal buffers may be incorrect sizes. 8919 * @property _maxCardsPerBatch 8920 * @protected 8921 * @type {Number} 8922 * @default StageGL.DEFAULT_MAX_BATCH_SIZE (10000) 8923 */ 8924 this._maxCardsPerBatch = StageGL.DEFAULT_MAX_BATCH_SIZE; //TODO: write getter/setters for this 8925 8926 /** 8927 * The shader program used to draw the current batch. 8928 * @property _activeShader 8929 * @protected 8930 * @type {WebGLProgram} 8931 * @default null 8932 */ 8933 this._activeShader = null; 8934 8935 /** 8936 * The vertex position data for the current draw call. 8937 * @property _vertices 8938 * @protected 8939 * @type {Float32Array} 8940 * @default null 8941 */ 8942 this._vertices = null; 8943 8944 /** 8945 * The WebGL buffer attached to {{#crossLink "StageGL/_vertices:property"}}{{/crossLink}}. 8946 * @property _vertexPositionBuffer 8947 * @protected 8948 * @type {WebGLBuffer} 8949 * @default null 8950 */ 8951 this._vertexPositionBuffer = null; 8952 8953 /** 8954 * The vertex U/V data for the current draw call. 8955 * @property _uvs 8956 * @protected 8957 * @type {Float32Array} 8958 * @default null 8959 */ 8960 this._uvs = null; 8961 8962 /** 8963 * The WebGL buffer attached to {{#crossLink "StageGL/_uvs:property"}}{{/crossLink}}. 8964 * @property _uvPositionBuffer 8965 * @protected 8966 * @type {WebGLBuffer} 8967 * @default null 8968 */ 8969 this._uvPositionBuffer = null; 8970 8971 /** 8972 * The vertex indices data for the current draw call. 8973 * @property _indices 8974 * @protected 8975 * @type {Float32Array} 8976 * @default null 8977 */ 8978 this._indices = null; 8979 8980 /** 8981 * The WebGL buffer attached to {{#crossLink "StageGL/_indices:property"}}{{/crossLink}}. 8982 * @property _textureIndexBuffer 8983 * @protected 8984 * @type {WebGLBuffer} 8985 * @default null 8986 */ 8987 this._textureIndexBuffer = null; 8988 8989 /** 8990 * The vertices data for the current draw call. 8991 * @property _alphas 8992 * @protected 8993 * @type {Float32Array} 8994 * @default null 8995 */ 8996 this._alphas = null; 8997 8998 /** 8999 * The WebGL buffer attached to {{#crossLink "StageGL/_alphas:property"}}{{/crossLink}}. 9000 * @property _alphaBuffer 9001 * @protected 9002 * @type {WebGLBuffer} 9003 * @default null 9004 */ 9005 this._alphaBuffer = null; 9006 9007 /** 9008 * An index based lookup of every WebGL Texture currently in use. 9009 * @property _drawTexture 9010 * @protected 9011 * @type {Array} 9012 */ 9013 this._textureDictionary = []; 9014 9015 /** 9016 * A string based lookup hash of which index a texture is stored at in the dictionary. The lookup string is 9017 * often the src url. 9018 * @property _textureIDs 9019 * @protected 9020 * @type {Object} 9021 */ 9022 this._textureIDs = {}; 9023 9024 /** 9025 * An array of all the textures currently loaded into the GPU. The index in the array matches the GPU index. 9026 * @property _batchTextures 9027 * @protected 9028 * @type {Array} 9029 */ 9030 this._batchTextures = []; 9031 9032 /** 9033 * An array of all the simple filler textures used to prevent issues with missing textures in a batch. 9034 * @property _baseTextures 9035 * @protected 9036 * @type {Array} 9037 */ 9038 this._baseTextures = []; 9039 9040 /** 9041 * The number of concurrent textures the GPU can handle. This value is dynamically set from WebGL during initialization 9042 * via `gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)`. The WebGL spec states that the lowest guaranteed value is 8, 9043 * but it could be higher. Do not set this value higher than the value returned by the GPU. Setting it lower will 9044 * probably reduce performance, but may be advisable to reserve slots for custom filter work. 9045 * NOTE: Can also act as a length for {{#crossLink "StageGL/_batchTextures:property"}}. 9046 * @property _batchTextureCount 9047 * @protected 9048 * @type {Number} 9049 * @default 8 9050 */ 9051 this._batchTextureCount = 8; 9052 9053 /** 9054 * The location at which the last texture was inserted into a GPU slot in {{#crossLink "StageGL/_batchTextures:property"}}{{/crossLink}}.
9055 * Manual control of this variable can yield improvements in performance by intelligently replacing textures 9056 * inside a batch to reduce texture re-load. It is impossible to write automated general use code, as it requires 9057 * display list look ahead inspection and/or render foreknowledge. 9058 * @property _lastTextureInsert 9059 * @protected 9060 * @type {Number} 9061 * @default -1 9062 */ 9063 this._lastTextureInsert = -1; 9064 9065 /** 9066 * The current batch being drawn, A batch consists of a call to `drawElements` on the GPU. Many of these calls 9067 * can occur per draw. 9068 * @property _batchId 9069 * @protected 9070 * @type {Number} 9071 * @default 0 9072 */ 9073 this._batchID = 0; 9074 9075 /** 9076 * The current draw being performed, may contain multiple batches. Comparing to {{#crossLink "StageGL/_batchID:property"}}{{/crossLink}} 9077 * can reveal batching efficiency. 9078 * @property _drawID 9079 * @protected 9080 * @type {Number} 9081 * @default 0 9082 */ 9083 this._drawID = 0; 9084 9085 /** 9086 * Used to prevent textures in certain GPU slots from being replaced by an insert. 9087 * @property _slotBlackList 9088 * @protected 9089 * @type {Array} 9090 */ 9091 this._slotBlacklist = []; 9092 9093 /** 9094 * Used to prevent nested draw calls from accidentally overwriting drawing information by tracking depth. 9095 * @property _isDrawing 9096 * @protected 9097 * @type {Number} 9098 * @default 0 9099 */ 9100 this._isDrawing = 0; 9101 9102 /** 9103 * Used to ensure every canvas used as a texture source has a unique ID. 9104 * @property _lastTrackedCanvas 9105 * @protected 9106 * @type {Number} 9107 * @default 0 9108 */ 9109 this._lastTrackedCanvas = 0; 9110 9111 /** 9112 * Controls whether final rendering output of a {{#crossLink "cacheDraw"}}{{/crossLink}} is the canvas or a render 9113 * texture. See the {{#crossLink "cache"}}{{/crossLink}} function modifications for full implications and discussion. 9114 * @property isCacheControlled 9115 * @protected 9116 * @type {Boolean} 9117 * @default false 9118 * @todo LM: is this supposed to be _isCacheControlled since its private? 9119 */ 9120 this.isCacheControlled = false; 9121 9122 /** 9123 * Used to counter-position the object being cached so it aligns with the cache surface. Additionally ensures 9124 * that all rendering starts with a top level container. 9125 * @property _cacheContainer 9126 * @protected 9127 * @type {Container} 9128 * @default An instance of an EaselJS Container. 9129 */ 9130 this._cacheContainer = new createjs.Container(); 9131 9132 // and begin 9133 this._initializeWebGL(); 9134 } 9135 var p = createjs.extend(StageGL, createjs.Stage); 9136 9137// static methods: 9138 /** 9139 * Calculate the U/V co-ordinate based info for sprite frames. Instead of pixel count it uses a 0-1 space. Also includes 9140 * the ability to get info back for a specific frame, or only calculate that one frame. 9141 * 9142 * //generate UV rects for all entries 9143 * StageGL.buildUVRects( spriteSheetA ); 9144 * //generate all, fetch the first 9145 * var firstFrame = StageGL.buildUVRects( spriteSheetB, 0 ); 9146 * //generate the rect for just a single frame for performance's sake 9147 * var newFrame = StageGL.buildUVRects( dynamicSpriteSheet, newFrameIndex, true ); 9148 * 9149 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 9150 * @method buildUVRects 9151 * @param {SpriteSheet} spritesheet The spritesheet to find the frames on 9152 * @param {int} [target=-1] The index of the frame to return 9153 * @param {Boolean} [onlyTarget=false] Whether "target" is the only frame that gets calculated 9154 * @static 9155 * @return {Object} the target frame if supplied and present or a generic frame {t, l, b, r} 9156 */ 9157 StageGL.buildUVRects = function (spritesheet, target, onlyTarget) { 9158 if (!spritesheet || !spritesheet._frames) { return null; } 9159 if (target === undefined) { target = -1; } 9160 if (onlyTarget === undefined) { onlyTarget = false; } 9161 9162 var start = (target != -1 && onlyTarget)?(target):(0); 9163 var end = (target != -1 && onlyTarget)?(target+1):(spritesheet._frames.length); 9164 for (var i=start; i<end; i++) { 9165 var f = spritesheet._frames[i]; 9166 if (f.uvRect || f.image.width <= 0 || f.image.height <= 0) { continue; } 9167 9168 var r = f.rect; 9169 f.uvRect = { 9170 t: r.y / f.image.height, 9171 l: r.x / f.image.width, 9172 b: (r.y + r.height) / f.image.height, 9173 r: (r.x + r.width) / f.image.width 9174 }; 9175 } 9176 9177 return spritesheet._frames[(target != -1) ? target : 0].uvRect || {t:0, l:0, b:1, r:1}; 9178 }; 9179 9180 /** 9181 * Test a context to see if it has WebGL enabled on it. 9182 * @method isWebGLActive 9183 * @param {CanvasContext} ctx The context to test 9184 * @static 9185 * @return {Boolean} Whether WebGL is enabled 9186 */ 9187 StageGL.isWebGLActive = function (ctx) { 9188 return ctx && 9189 ctx instanceof WebGLRenderingContext && 9190 typeof WebGLRenderingContext !== 'undefined'; 9191 }; 9192 9193// static properties: 9194 /** 9195 * The number of properties defined per vertex (x, y, textureU, textureV, textureIndex, alpha) 9196 * @property VERTEX_PROPERTY_COUNT 9197 * @static 9198 * @final 9199 * @type {Number} 9200 * @default 6 9201 * @readonly 9202 */ 9203 StageGL.VERTEX_PROPERTY_COUNT = 6; 9204 9205 /** 9206 * The number of triangle indices it takes to form a Card. 3 per triangle, 2 triangles. 9207 * @property INDICIES_PER_CARD 9208 * @static 9209 * @final 9210 * @type {Number} 9211 * @default 6 9212 * @readonly 9213 */ 9214 StageGL.INDICIES_PER_CARD = 6; 9215 9216 /** 9217 * The default value for the maximum number of cards we want to process in a batch. See 9218 * {{#crossLink "StageGL/WEBGL_MAX_INDEX_NUM:property"}}{{/crossLink}} for a hard limit. 9219 * @property DEFAULT_MAX_BATCH_SIZE 9220 * @static 9221 * @final 9222 * @type {Number} 9223 * @default 10000 9224 * @readonly 9225 */ 9226 StageGL.DEFAULT_MAX_BATCH_SIZE = 10000; 9227 9228 /** 9229 * The maximum size WebGL allows for element index numbers. Uses a 16 bit unsigned integer. It takes 6 indices to 9230 * make a unique card.
9231 * @property WEBGL_MAX_INDEX_NUM 9232 * @static 9233 * @final 9234 * @type {Number} 9235 * @default 65536 9236 * @readonly 9237 */ 9238 StageGL.WEBGL_MAX_INDEX_NUM = Math.pow(2, 16); 9239 9240 /** 9241 * Default U/V rect for dealing with full coverage from an image source. 9242 * @property UV_RECT 9243 * @static 9244 * @final 9245 * @type {Object} 9246 * @default {t:0, l:0, b:1, r:1} 9247 * @readonly 9248 */ 9249 StageGL.UV_RECT = {t:0, l:0, b:1, r:1}; 9250 9251 try { 9252 /** 9253 * Vertex positions for a card that covers the entire render. Used with render targets primarily. 9254 * @property COVER_VERT 9255 * @static 9256 * @final 9257 * @type {Float32Array} 9258 * @readonly 9259 */ 9260 StageGL.COVER_VERT = new Float32Array([ 9261 -1, 1, //TL 9262 1, 1, //TR 9263 -1, -1, //BL 9264 1, 1, //TR 9265 1, -1, //BR 9266 -1, -1 //BL 9267 ]); 9268 9269 /** 9270 * U/V for {{#crossLink "StageGL/COVER_VERT:property"}}{{/crossLink}}. 9271 * @property COVER_UV 9272 * @static 9273 * @final 9274 * @type {Float32Array} 9275 * @readonly 9276 */ 9277 StageGL.COVER_UV = new Float32Array([ 9278 0, 0, //TL 9279 1, 0, //TR 9280 0, 1, //BL 9281 1, 0, //TR 9282 1, 1, //BR 9283 0, 1 //BL 9284 ]); 9285 9286 /** 9287 * Flipped U/V for {{#crossLink "StageGL:COVER_VERT:property"}}{{/crossLink}}. 9288 * @property COVER_UV_FLIP 9289 * @static 9290 * @final 9291 * @type {Float32Array} 9292 * @readonly 9293 */ 9294 StageGL.COVER_UV_FLIP = new Float32Array([ 9295 0, 1, //TL 9296 1, 1, //TR 9297 0, 0, //BL 9298 1, 1, //TR 9299 1, 0, //BR 9300 0, 0 //BL 9301 ]); 9302 } catch(e) { /* Breaking in older browsers, but those browsers wont run StageGL so no recovery or warning needed */ } 9303 9304 /** 9305 * Portion of the shader that contains the "varying" properties required in both vertex and fragment shaders. The 9306 * regular shader is designed to render all expected objects. Shader code may contain templates that are replaced 9307 * pre-compile. 9308 * @property REGULAR_VARYING_HEADER 9309 * @static 9310 * @final 9311 * @type {String} 9312 * @readonly 9313 */ 9314 StageGL.REGULAR_VARYING_HEADER = ( 9315 "precision mediump float;" + 9316 "varying vec2 vTextureCoord;" + 9317 "varying lowp float indexPicker;" + 9318 "varying lowp float alphaValue;" 9319 ); 9320 9321 /** 9322 * Actual full header for the vertex shader. Includes the varying header. The regular shader is designed to render 9323 * all expected objects. Shader code may contain templates that are replaced pre-compile. 9324 * @property REGULAR_VERTEX_HEADER 9325 * @static 9326 * @final 9327 * @type {String} 9328 * @readonly 9329 */ 9330 StageGL.REGULAR_VERTEX_HEADER = ( 9331 StageGL.REGULAR_VARYING_HEADER + 9332 "attribute vec2 vertexPosition;" + 9333 "attribute vec2 uvPosition;" + 9334 "attribute lowp float textureIndex;" + 9335 "attribute lowp float objectAlpha;" + 9336 "uniform mat4 pMatrix;" 9337 ); 9338 9339 /** 9340 * Actual full header for the fragment shader. Includes the varying header. The regular shader is designed to render 9341 * all expected objects. Shader code may contain templates that are replaced pre-compile. 9342 * @property REGULAR_FRAGMENT_HEADER 9343 * @static 9344 * @final 9345 * @type {String} 9346 * @readonly 9347 */ 9348 StageGL.REGULAR_FRAGMENT_HEADER = ( 9349 StageGL.REGULAR_VARYING_HEADER + 9350 "uniform sampler2D uSampler[{{count}}];" 9351 ); 9352 9353 /** 9354 * Body of the vertex shader. The regular shader is designed to render all expected objects. Shader code may contain 9355 * templates that are replaced pre-compile. 9356 * @property REGULAR_VERTEX_BODY 9357 * @static 9358 * @final 9359 * @type {String} 9360 * @readonly 9361 */ 9362 StageGL.REGULAR_VERTEX_BODY = ( 9363 "void main(void) {" + 9364 //DHG TODO: This doesn't work. Must be something wrong with the hand built matrix see js... bypass for now 9365 //vertexPosition, round if flag 9366 //"gl_Position = pMatrix * vec4(vertexPosition.x, vertexPosition.y, 0.0, 1.0);" + 9367 "gl_Position = vec4("+ 9368 "(vertexPosition.x * pMatrix[0][0]) + pMatrix[3][0]," + 9369 "(vertexPosition.y * pMatrix[1][1]) + pMatrix[3][1]," + 9370 "pMatrix[3][2]," + 9371 "1.0" + 9372 ");" + 9373 "alphaValue = objectAlpha;" + 9374 "indexPicker = textureIndex;" + 9375 "vTextureCoord = uvPosition;" + 9376 "}" 9377 ); 9378 9379 /** 9380 * Body of the fragment shader. The regular shader is designed to render all expected objects. Shader code may 9381 * contain templates that are replaced pre-compile. 9382 * @property REGULAR_FRAGMENT_BODY 9383 * @static 9384 * @final 9385 * @type {String} 9386 * @readonly 9387 */ 9388 StageGL.REGULAR_FRAGMENT_BODY = ( 9389 "void main(void) {" + 9390 "vec4 color = vec4(1.0, 0.0, 0.0, 1.0);" + 9391 9392 "if (indexPicker <= 0.5) {" + 9393 "color = texture2D(uSampler[0], vTextureCoord);" + 9394 "{{alternates}}" + 9395 "}" + 9396 9397 "{{fragColor}}" + 9398 "}" 9399 ); 9400 StageGL.REGULAR_FRAG_COLOR_NORMAL = ( 9401 "gl_FragColor = vec4(color.rgb, color.a * alphaValue);" 9402 ); 9403 StageGL.REGULAR_FRAG_COLOR_PREMULTIPLY = ( 9404 "if(color.a > 0.0035) {" + // 1/255 = 0.0039, so ignore any value below 1 because it's probably noise
9405 "gl_FragColor = vec4(color.rgb/color.a, color.a * alphaValue);" + 9406 "} else {" + 9407 "gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);" + 9408 "}" 9409 ); 9410 9411 //TODO: DHG: a real particle shader 9412 /** 9413 * @property PARTICLE_VERTEX_BODY 9414 * @todo 9415 * @final 9416 * @static 9417 * @type {String} 9418 * @readonly 9419 */ 9420 StageGL.PARTICLE_VERTEX_BODY = ( 9421 StageGL.REGULAR_VERTEX_BODY 9422 ); 9423 /** 9424 * @property PARTICLE_FRAGMENT_BODY 9425 * @todo 9426 * @final 9427 * @static 9428 * @type {String} 9429 * @readonly 9430 */ 9431 StageGL.PARTICLE_FRAGMENT_BODY = ( 9432 StageGL.REGULAR_FRAGMENT_BODY 9433 ); 9434 9435 /** 9436 * Portion of the shader that contains the "varying" properties required in both vertex and fragment shaders. The 9437 * cover shader is designed to be a simple vertex/uv only texture render that covers the render surface. Shader 9438 * code may contain templates that are replaced pre-compile. 9439 * @property COVER_VARYING_HEADER 9440 * @static 9441 * @final 9442 * @type {String} 9443 * @readonly 9444 */ 9445 StageGL.COVER_VARYING_HEADER = ( 9446 "precision mediump float;" + 9447 9448 "varying highp vec2 vRenderCoord;" + 9449 "varying highp vec2 vTextureCoord;" 9450 ); 9451 9452 /** 9453 * Actual full header for the vertex shader. Includes the varying header. The cover shader is designed to be a 9454 * simple vertex/uv only texture render that covers the render surface. Shader code may contain templates that are 9455 * replaced pre-compile. 9456 * @property COVER_VERTEX_HEADER 9457 * @static 9458 * @final 9459 * @type {String} 9460 * @readonly 9461 */ 9462 StageGL.COVER_VERTEX_HEADER = ( 9463 StageGL.COVER_VARYING_HEADER + 9464 "attribute vec2 vertexPosition;" + 9465 "attribute vec2 uvPosition;" + 9466 "uniform float uUpright;" 9467 ); 9468 9469 /** 9470 * Actual full header for the fragment shader. Includes the varying header. The cover shader is designed to be a 9471 * simple vertex/uv only texture render that covers the render surface. Shader code may contain templates that are 9472 * replaced pre-compile. 9473 * @property COVER_FRAGMENT_HEADER 9474 * @static 9475 * @final 9476 * @type {String} 9477 * @readonly 9478 */ 9479 StageGL.COVER_FRAGMENT_HEADER = ( 9480 StageGL.COVER_VARYING_HEADER + 9481 "uniform sampler2D uSampler;" 9482 ); 9483 9484 /** 9485 * Body of the vertex shader. The cover shader is designed to be a simple vertex/uv only texture render that covers 9486 * the render surface. Shader code may contain templates that are replaced pre-compile. 9487 * @property COVER_VERTEX_BODY 9488 * @static 9489 * @final 9490 * @type {String} 9491 * @readonly 9492 */ 9493 StageGL.COVER_VERTEX_BODY = ( 9494 "void main(void) {" + 9495 "gl_Position = vec4(vertexPosition.x, vertexPosition.y, 0.0, 1.0);" + 9496 "vRenderCoord = uvPosition;" + 9497 "vTextureCoord = vec2(uvPosition.x, abs(uUpright - uvPosition.y));" + 9498 "}" 9499 ); 9500 9501 /** 9502 * Body of the fragment shader. The cover shader is designed to be a simple vertex/uv only texture render that 9503 * covers the render surface. Shader code may contain templates that are replaced pre-compile. 9504 * @property COVER_FRAGMENT_BODY 9505 * @static 9506 * @final 9507 * @type {String} 9508 * @readonly 9509 */ 9510 StageGL.COVER_FRAGMENT_BODY = ( 9511 "void main(void) {" + 9512 "vec4 color = texture2D(uSampler, vRenderCoord);" + 9513 "gl_FragColor = color;" + 9514 "}" 9515 ); 9516 9517// events: 9518 /** 9519 * Dispatched each update immediately before the canvas is cleared and the display list is drawn to it. You can call 9520 * {{#crossLink "Event/preventDefault"}}{{/crossLink}} on the event to cancel the draw. 9521 * @event drawstart 9522 */ 9523 9524 /** 9525 * Dispatched each update immediately after the display list is drawn to the canvas and the canvas context is restored. 9526 * @event drawend 9527 */ 9528 9529// getter / setters: 9530 p._get_isWebGL = function () { 9531 return !!this._webGLContext; 9532 }; 9533 9534 p._set_autoPurge = function (value) { 9535 value = isNaN(value)?1200:value; 9536 if (value != -1) { 9537 value = value<10?10:value; 9538 } 9539 this._autoPurge = value; 9540 }; 9541 p._get_autoPurge = function () { 9542 return Number(this._autoPurge); 9543 }; 9544 9545 try { 9546 Object.defineProperties(p, { 9547 /** 9548 * Indicates whether WebGL is being used for rendering. For example, this would be `false` if WebGL is not 9549 * supported in the browser. 9550 * @property isWebGL 9551 * @type {Boolean} 9552 * @readonly 9553 */
9554 isWebGL: { get: p._get_isWebGL }, 9555 9556 /** 9557 * Specifies whether or not StageGL is automatically purging unused textures. Higher numbers purge less 9558 * often. Values below 10 are upgraded to 10, and -1 disables this feature. 9559 * @property autoPurge 9560 * @protected 9561 * @type {Integer} 9562 * @default 1000 9563 */ 9564 autoPurge: { get: p._get_autoPurge, set: p._set_autoPurge } 9565 }); 9566 } catch (e) {} // TODO: use Log 9567 9568 9569// constructor methods: 9570 /** 9571 * Create and properly initialize the WebGL instance. 9572 * @method _initializeWebGL 9573 * @protected 9574 * @return {WebGLRenderingContext} 9575 */ 9576 p._initializeWebGL = function () { 9577 if (this.canvas) { 9578 if (!this._webGLContext || this._webGLContext.canvas !== this.canvas) { 9579 // A context hasn't been defined yet, 9580 // OR the defined context belongs to a different canvas, so reinitialize. 9581 9582 // defaults and options 9583 var options = { 9584 depth: false, // Disable the depth buffer as it isn't used. 9585 alpha: this._transparent, // Make the canvas background transparent. 9586 stencil: true, 9587 antialias: this._antialias, 9588 premultipliedAlpha: this._premultiply, // Assume the drawing buffer contains colors with premultiplied alpha. 9589 preserveDrawingBuffer: this._preserveBuffer 9590 }; 9591 9592 var gl = this._webGLContext = this._fetchWebGLContext(this.canvas, options); 9593 if (!gl) { return null; } 9594 9595 this.updateSimultaneousTextureCount(gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)); 9596 this._maxTextureSlots = gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS); 9597 this._createBuffers(gl); 9598 this._initTextures(gl); 9599 9600 gl.disable(gl.DEPTH_TEST); 9601 gl.enable(gl.BLEND); 9602 gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); 9603 gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, this._premultiply); 9604 //gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE); 9605 9606 this._webGLContext.clearColor(this._clearColor.r, this._clearColor.g, this._clearColor.b, this._clearColor.a); 9607 this.updateViewport(this._viewportWidth || this.canvas.width, this._viewportHeight || this.canvas.height); 9608 } 9609 } else { 9610 this._webGLContext = null; 9611 } 9612 return this._webGLContext; 9613 }; 9614 9615// public methods: 9616 /** 9617 * Docced in superclass 9618 */ 9619 p.update = function (props) { 9620 if (!this.canvas) { return; } 9621 if (this.tickOnUpdate) { this.tick(props); } 9622 this.dispatchEvent("drawstart"); 9623 if (this.autoClear) { this.clear(); } 9624 9625 if (this._webGLContext) { 9626 // Use WebGL. 9627 this._batchDraw(this, this._webGLContext); 9628 if (this._autoPurge != -1 && !(this._drawID%((this._autoPurge/2)|0))) { 9629 this.purgeTextures(this._autoPurge); 9630 } 9631 } else { 9632 // Use 2D. 9633 var ctx = this.canvas.getContext("2d"); 9634 ctx.save(); 9635 this.updateContext(ctx); 9636 this.draw(ctx, false); 9637 ctx.restore(); 9638 } 9639 this.dispatchEvent("drawend"); 9640 }; 9641 9642 /** 9643 * Docced in superclass 9644 */ 9645 p.clear = function () { 9646 if (!this.canvas) { return; } 9647 if (StageGL.isWebGLActive(this._webGLContext)) { 9648 var gl = this._webGLContext; 9649 var cc = this._clearColor; 9650 var adjust = this._transparent ? cc.a : 1.0; 9651 // Use WebGL settings; adjust for pre multiplied alpha appropriate to scenario 9652 this._webGLContext.clearColor(cc.r * adjust, cc.g * adjust, cc.b * adjust, adjust); 9653 gl.clear(gl.COLOR_BUFFER_BIT); 9654 this._webGLContext.clearColor(cc.r, cc.g, cc.b, cc.a); 9655 } else { 9656 // Use 2D. 9657 this.Stage_clear(); 9658 } 9659 }; 9660 9661 /** 9662 * Draws the stage into the supplied context if possible. Many WebGL properties only exist on their context. As such 9663 * you cannot share contexts among many StageGLs and each context requires a unique StageGL instance. Contexts that 9664 * don't match the context managed by this StageGL will be treated as a 2D context. 9665 * 9666 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 9667 * @method draw 9668 * @param {CanvasRenderingContext2D | WebGLRenderingContext} context The context object to draw into. 9669 * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. For 9670 * example, used for drawing the cache (to prevent it from simply drawing an existing cache back into itself). 9671 * @return {Boolean} If the draw was handled by this function 9672 */ 9673 p.draw = function (context, ignoreCache) { 9674 if (context === this._webGLContext && StageGL.isWebGLActive(this._webGLContext)) { 9675 var gl = this._webGLContext; 9676 this._batchDraw(this, gl, ignoreCache); 9677 return true; 9678 } else { 9679 return this.Stage_draw(context, ignoreCache); 9680 } 9681 }; 9682 9683 /** 9684 * Draws the target into the correct context, be it a canvas or Render Texture using WebGL. 9685 * 9686 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 9687 * @method cacheDraw 9688 * @param {DisplayObject} target The object we're drawing into cache. 9689 * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back into itself). 9690 * @param {Array} filters The filters we're drawing into cache. 9691 * @param {BitmapCache} manager The BitmapCache instance looking after the cache 9692 * @return {Boolean} If the draw was handled by this function 9693 */ 9694 p.cacheDraw = function (target, filters, manager) { 9695 if (StageGL.isWebGLActive(this._webGLContext)) { 9696 var gl = this._webGLContext; 9697 this._cacheDraw(gl, target, filters, manager); 9698 return true; 9699 } else { 9700 return false;
9701 } 9702 }; 9703 9704 /** 9705 * Blocks, or frees a texture "slot" on the GPU. Can be useful if you are overflowing textures. When overflowing 9706 * textures they are re-uploaded to the GPU every time they're encountered, this can be expensive with large textures. 9707 * By blocking the slot you reduce available slots, potentially increasing draw calls, but mostly you prevent a 9708 * texture being re-uploaded if it would have moved slots due to overflow. 9709 * 9710 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 9711 * For example, block the slot a background image is stored in so there is less re-loading of that image. 9712 * @method protectTextureSlot 9713 * @param {Number} id The slot to be affected 9714 * @param {Boolean} [lock=false] Whether this slot is the one being locked. 9715 */ 9716 p.protectTextureSlot = function (id, lock) { 9717 if (id > this._maxTextureSlots || id < 0) { 9718 throw "Slot outside of acceptable range"; 9719 } 9720 this._slotBlacklist[id] = !!lock; 9721 }; 9722 9723 /** 9724 * Render textures can't draw into themselves so any item being used for renderTextures needs two to alternate between. 9725 * This function creates, gets, and toggles the render surface between the two. 9726 * 9727 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 9728 * @method getTargetRenderTexture 9729 * @param {DisplayObject} target The object associated with the render textures, usually a cached object. 9730 * @param {Number} w The width to create the texture at. 9731 * @param {Number} h The height to create the texture at. 9732 * @return {Objet} 9733 * @todo fill in return type 9734 */ 9735 p.getTargetRenderTexture = function (target, w, h) { 9736 var result, toggle = false; 9737 var gl = this._webGLContext; 9738 if (target.__lastRT !== undefined && target.__lastRT === target.__rtA) { toggle = true; } 9739 if (!toggle) { 9740 if (target.__rtA === undefined) { 9741 target.__rtA = this.getRenderBufferTexture(w, h); 9742 } else { 9743 if (w != target.__rtA._width || h != target.__rtA._height) { 9744 this.resizeTexture(target.__rtA, w, h); 9745 } 9746 this.setTextureParams(gl); 9747 } 9748 result = target.__rtA; 9749 } else { 9750 if (target.__rtB === undefined) { 9751 target.__rtB = this.getRenderBufferTexture(w, h); 9752 } else { 9753 if (w != target.__rtB._width || h != target.__rtB._height) { 9754 this.resizeTexture(target.__rtB, w, h); 9755 } 9756 this.setTextureParams(gl); 9757 } 9758 result = target.__rtB; 9759 } 9760 if (!result) { 9761 throw "Problems creating render textures, known causes include using too much VRAM by not releasing WebGL texture instances"; 9762 } 9763 target.__lastRT = result; 9764 return result; 9765 }; 9766 9767 /** 9768 * For every image encountered StageGL registers and tracks it automatically. This tracking can cause memory leaks 9769 * if not purged. StageGL, by default, automatically purges them. This does have a cost and may unfortunately find 9770 * false positives. This function is for manual management of this memory instead of the automatic system controlled 9771 * by the {{#crossLink "StageGL/autoPurge:property"}}{{/crossLink}} property. 9772 * 9773 * This function will recursively remove all textures found on the object, its children, cache, etc. It will uncache 9774 * objects and remove any texture it finds REGARDLESS of whether it is currently in use elsewhere. It is up to the 9775 * developer to ensure that a texture in use is not removed. 9776 * 9777 * Textures in use, or to be used again shortly, should not be removed. This is simply for performance reasons. 9778 * Removing a texture in use will cause the texture to have to be re-uploaded slowing rendering. 9779 * @method releaseTexture 9780 * @param {DisplayObject | Texture | Image | Canvas} item An object that used the texture to be discarded. 9781 */ 9782 p.releaseTexture = function (item) { 9783 var i, l; 9784 if (!item) { return; } 9785 9786 // this is a container object 9787 if (item.children) { 9788 for (i = 0, l = item.children.length; i < l; i++) { 9789 this.releaseTexture(item.children[i]); 9790 } 9791 } 9792 9793 // this has a cache canvas 9794 if (item.cacheCanvas) { 9795 item.uncache(); 9796 } 9797 9798 var foundImage = undefined; 9799 if (item._storeID !== undefined) { 9800 // this is a texture itself 9801 if (item === this._textureDictionary[item._storeID]) { 9802 this._killTextureObject(item); 9803 item._storeID = undefined; 9804 return; 9805 } 9806 9807 // this is an image or canvas 9808 foundImage = item; 9809 } else if (item._webGLRenderStyle === 2) { 9810 // this is a Bitmap class 9811 foundImage = item.image; 9812 } else if (item._webGLRenderStyle === 1) { 9813 // this is a SpriteSheet, we can't tell which image we used from the list easily so remove them all! 9814 for (i = 0, l = item.spriteSheet._images.length; i < l; i++) { 9815 this.releaseTexture(item.spriteSheet._images[i]); 9816 } 9817 return; 9818 } 9819 9820 // did we find anything 9821 if (foundImage === undefined) { 9822 if (this.vocalDebug) { 9823 console.log("No associated texture found on release"); 9824 } 9825 return; 9826 } 9827 9828 // remove it 9829 this._killTextureObject(this._textureDictionary[foundImage._storeID]); 9830 foundImage._storeID = undefined; 9831 }; 9832 9833 /** 9834 * Similar to {{#crossLink "releaseTexture"}}{{/crossLink}}, but this function differs by searching for textures to 9835 * release. It works by assuming that it can purge any texture which was last used more than "count" draw calls ago. 9836 * Because this process is unaware of the objects and whether they may be used on your stage, false positives can 9837 * occur. It is recommended to manually manage your memory with {{#crossLink "StageGL/releaseTexture"}}{{/crossLink}}, 9838 * however, there are many use cases where this is simpler and error-free. This process is also run by default under 9839 * the hood to prevent leaks. To disable it see the {{#crossLink "StageGL/autoPurge:property"}}{{/crossLink}} property. 9840 * @method purgeTextures 9841 * @param {Number} [count=100] How many renders ago the texture was last used 9842 */ 9843 p.purgeTextures = function (count) { 9844 if (count == undefined){ count = 100; } 9845 9846 var dict = this._textureDictionary; 9847 var l = dict.length; 9848 for (var i= 0; i<l; i++) { 9849 var item = dict[i]; 9850 if (!item) { continue; } 9851 if (item._drawID + count <= this._drawID) { // use draw not batch as draw is more indicative of time 9852 this._killTextureObject(item); 9853 } 9854 } 9855 }; 9856 9857 /** 9858 * Try to set the max textures the system can handle. It should default to the hardware maximum, and lower values 9859 * may limit performance. Some devices have been known to mis-report their max textures, or you may
9859need a standard 9860 * baseline cross devices for testing. Barring the previous suggestions, there is little need to call this function 9861 * as the library will automatically try to find the best value. 9862 * 9863 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 9864 * @method updateSimultaneousTextureCount 9865 * @param {Number} [count=1] The number of textures intended for simultaneous loading. 9866 */ 9867 p.updateSimultaneousTextureCount = function (count) { 9868 // TODO: DHG: make sure API works in all instances, may be some issues with buffers etc I haven't foreseen 9869 var gl = this._webGLContext; 9870 var success = false; 9871 9872 if (count < 1 || isNaN(count)) { count = 1; } 9873 this._batchTextureCount = count; 9874 9875 while (!success) { 9876 try { 9877 this._activeShader = this._fetchShaderProgram(gl); 9878 success = true; 9879 } catch(e) { 9880 if (this._batchTextureCount == 1) { 9881 throw "Cannot compile shader " + e; 9882 } 9883 9884 this._batchTextureCount -= 4; 9885 if (this._batchTextureCount < 1) { this._batchTextureCount = 1; } 9886 9887 if (this.vocalDebug) { 9888 console.log("Reducing desired texture count due to errors: " + this._batchTextureCount); 9889 } 9890 } 9891 } 9892 }; 9893 9894 /** 9895 * Update the WebGL viewport. Note that this does <strong>not</strong> update the canvas element's width/height, but 9896 * the render surface's instead. This is necessary after manually resizing the canvas element on the DOM to avoid a 9897 * up/down scaled render. 9898 * @method updateViewport 9899 * @param {Integer} width The width of the render surface in pixels. 9900 * @param {Integer} height The height of the render surface in pixels. 9901 */ 9902 p.updateViewport = function (width, height) { 9903 this._viewportWidth = width|0; 9904 this._viewportHeight = height|0; 9905 var gl = this._webGLContext; 9906 9907 if (gl) { 9908 gl.viewport(0, 0, this._viewportWidth, this._viewportHeight); 9909 9910 // WebGL works with a -1,1 space on its screen. It also follows Y-Up 9911 // we need to flip the y, scale and then translate the co-ordinates to match this 9912 // additionally we offset into they Y so the polygons are inside the camera's "clipping" plane 9913 this._projectionMatrix = new Float32Array([ 9914 2 / this._viewportWidth, 0, 0, 0, 9915 0, -2 / this._viewportHeight, 1, 0, 9916 0, 0, 1, 0, 9917 -1, 1, 0.1, 0 9918 ]); 9919 // create the flipped version for use with render texture flipping 9920 // DHG: this would be a slice/clone but some platforms don't offer them for Float32Array 9921 this._projectionMatrixFlip = new Float32Array([0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]); 9922 this._projectionMatrixFlip.set(this._projectionMatrix); 9923 this._projectionMatrixFlip[5] *= -1; 9924 this._projectionMatrixFlip[13] *= -1; 9925 } 9926 }; 9927 9928 /** 9929 * Fetches the shader compiled and set up to work with the provided filter/object. The shader is compiled on first 9930 * use and returned on subsequent calls. 9931 * @method getFilterShader 9932 * @param {Filter|Object} filter The object which will provide the information needed to construct the filter shader. 9933 * @return {WebGLProgram} 9934 */ 9935 p.getFilterShader = function (filter) { 9936 if (!filter) { filter = this; } 9937 9938 var gl = this._webGLContext; 9939 var targetShader = this._activeShader; 9940 9941 if (filter._builtShader) { 9942 targetShader = filter._builtShader; 9943 if (filter.shaderParamSetup) { 9944 gl.useProgram(targetShader); 9945 filter.shaderParamSetup(gl, this, targetShader); 9946 } 9947 } else { 9948 try { 9949 targetShader = this._fetchShaderProgram( 9950 gl, "filter", 9951 filter.VTX_SHADER_BODY, filter.FRAG_SHADER_BODY, 9952 filter.shaderParamSetup && filter.shaderParamSetup.bind(filter) 9953 ); 9954 filter._builtShader = targetShader; 9955 targetShader._name = filter.toString(); 9956 } catch (e) { 9957 console && console.log("SHADER SWITCH FAILURE", e); 9958 } 9959 } 9960 return targetShader; 9961 }; 9962 9963 /** 9964 * Returns a base texture that has no image or data loaded. Not intended for loading images. It may return `null` 9965 * in some error cases, and trying to use a "null" texture can cause renders to fail. 9966 * @method getBaseTexture 9967 * @param {uint} [w=1] The width of the texture in pixels, defaults to 1 9968 * @param {uint} [h=1] The height of the texture in pixels, defaults to 1 9969 */ 9970 p.getBaseTexture = function (w, h) { 9971 var width = Math.ceil(w > 0 ? w : 1) || 1;
9972 var height = Math.ceil(h > 0 ? h : 1) || 1; 9973 9974 var gl = this._webGLContext; 9975 var texture = gl.createTexture(); 9976 this.resizeTexture(texture, width, height); 9977 this.setTextureParams(gl, false); 9978 9979 return texture; 9980 }; 9981 9982 /** 9983 * Resizes a supplied texture element. May generate invalid textures in some error cases such as; when the texture 9984 * is too large, when an out of texture memory error occurs, or other error scenarios. Trying to use an invalid texture 9985 * can cause renders to hard stop on some devices. Check the WebGL bound texture after running this function. 9986 * 9987 * NOTE: The supplied texture must have been made with the WebGL "texImage2D" function, all default APIs in StageGL 9988 * use this, so this note only matters for library developers and plugins. 9989 * 9990 * @protected 9991 * @method resizeTexture 9992 * @param {WebGLTexture} texture The GL Texture to be modified. 9993 * @param {uint} [width=1] The width of the texture in pixels, defaults to 1 9994 * @param {uint} [height=1] The height of the texture in pixels, defaults to 1 9995 */ 9996 p.resizeTexture = function (texture, width,height) { 9997 var gl = this._webGLContext; 9998 gl.bindTexture(gl.TEXTURE_2D, texture); 9999 gl.texImage2D( 10000 gl.TEXTURE_2D, // target 10001 0, // level of detail 10002 gl.RGBA, // internal format 10003 width, height, 0, // width, height, border (only for array/null sourced textures) 10004 gl.RGBA, // format (match internal format) 10005 gl.UNSIGNED_BYTE, // type of texture(pixel color depth) 10006 null // image data, we can do null because we're doing array data 10007 ); 10008 texture.width = width; 10009 texture.height = height; 10010 }; 10011 10012 /** 10013 * Returns a base texture (see {{#crossLink "StageGL/getBaseTexture"}}{{/crossLink}}) for details. Also includes an 10014 * attached and linked render buffer in `texture._frameBuffer`. RenderTextures can be thought of as an internal 10015 * canvas on the GPU that can be drawn to. 10016 * @method getRenderBufferTexture 10017 * @param {Number} w The width of the texture in pixels. 10018 * @param {Number} h The height of the texture in pixels. 10019 * @return {Texture} the basic texture instance with a render buffer property. 10020 */ 10021 p.getRenderBufferTexture = function (w, h) { 10022 var gl = this._webGLContext; 10023 10024 // get the texture 10025 var renderTexture = this.getBaseTexture(w, h); 10026 if (!renderTexture) { return null; } 10027 10028 // get the frame buffer 10029 var frameBuffer = gl.createFramebuffer(); 10030 if (!frameBuffer) { return null; } 10031 10032 // set its width and height for spoofing as an image 10033 renderTexture.width = w; 10034 renderTexture.height = h; 10035 10036 // attach frame buffer to texture and provide cross links to look up each other 10037 gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer); 10038 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, renderTexture, 0); 10039 frameBuffer._renderTexture = renderTexture; 10040 renderTexture._frameBuffer = frameBuffer; 10041 10042 // these keep track of themselves simply to reduce complexity of some lookup code 10043 renderTexture._storeID = this._textureDictionary.length; 10044 this._textureDictionary[renderTexture._storeID] = renderTexture; 10045 10046 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 10047 return renderTexture; 10048 }; 10049 10050 /** 10051 * Common utility function used to apply the correct texture processing parameters for the bound texture. 10052 * @method setTextureParams 10053 * @param {WebGLRenderingContext} gl The canvas WebGL context object to draw into. 10054 * @param {Boolean} [isPOT=false] Marks whether the texture is "Power of Two", this may allow better quality AA. 10055 */ 10056 p.setTextureParams = function (gl, isPOT) { 10057 if (isPOT && this._antialias) { 10058 //non POT linear works in some devices, but performance is NOT good, investigate 10059 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 10060 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 10061 } else { 10062 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 10063 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 10064 } 10065 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 10066 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 10067 }; 10068 10069 /** 10070 * Changes the webGL clear, aka "background" color to the provided value. A transparent clear is recommended, as 10071 * non-transparent colours may create undesired boxes around some visuals. 10072 * 10073 * The clear color will also be used for filters and other "render textures". The stage background will ignore the 10074 * transparency value and display a solid color normally. For the stage to re
10074cognize and use transparency it must be 10075 * created with the transparent flag set to `true` (see {{#crossLink "StageGL/constructor"}}{{/crossLink}})). 10076 * 10077 * Using "transparent white" to demonstrate, the valid data formats are as follows: 10078 * <ul> 10079 * <li>"#FFF"</li> 10080 * <li>"#FFFFFF"</li> 10081 * <li>"#FFFFFF00"</li> 10082 * <li>"rgba(255,255,255,0.0)"</li> 10083 * </ul> 10084 * @method setClearColor 10085 * @param {String|int} [color=0x00000000] The new color to use as the background 10086 */ 10087 p.setClearColor = function (color) { 10088 var r, g, b, a, output; 10089 10090 if (typeof color == "string") { 10091 if (color.indexOf("#") == 0) { 10092 if (color.length == 4) { 10093 color = "#" + color.charAt(1)+color.charAt(1) + color.charAt(2)+color.charAt(2) + color.charAt(3)+color.charAt(3) 10094 } 10095 r = Number("0x"+color.slice(1, 3))/255; 10096 g = Number("0x"+color.slice(3, 5))/255; 10097 b = Number("0x"+color.slice(5, 7))/255; 10098 a = Number("0x"+color.slice(7, 9))/255; 10099 } else if (color.indexOf("rgba(") == 0) { 10100 output = color.slice(5, -1).split(","); 10101 r = Number(output[0])/255; 10102 g = Number(output[1])/255; 10103 b = Number(output[2])/255; 10104 a = Number(output[3]); 10105 } 10106 } else { // >>> is an unsigned shift which is what we want as 0x80000000 and up are negative values 10107 r = ((color & 0xFF000000) >>> 24)/255; 10108 g = ((color & 0x00FF0000) >>> 16)/255; 10109 b = ((color & 0x0000FF00) >>> 8)/255; 10110 a = (color & 0x000000FF)/255; 10111 } 10112 10113 this._clearColor.r = r || 0; 10114 this._clearColor.g = g || 0; 10115 this._clearColor.b = b || 0; 10116 this._clearColor.a = a || 0; 10117 10118 if (!this._webGLContext) { return; } 10119 this._webGLContext.clearColor(this._clearColor.r, this._clearColor.g, this._clearColor.b, this._clearColor.a); 10120 }; 10121 10122 /** 10123 * docced in subclass 10124 */ 10125 p.toString = function () { 10126 return "[StageGL (name="+ this.name +")]"; 10127 }; 10128 10129// private methods: 10130 /** 10131 * Sets up and returns the WebGL context for the canvas. May return undefined in error scenarios. These can include 10132 * situations where the canvas element already has a context, 2D or GL. 10133 * @param {Canvas} canvas The DOM canvas element to attach to 10134 * @param {Object} options The options to be handed into the WebGL object, see WebGL spec 10135 * @method _fetchWebGLContext 10136 * @protected 10137 * @return {WebGLRenderingContext} The WebGL context, may return undefined in error scenarios 10138 */ 10139 p._fetchWebGLContext = function (canvas, options) { 10140 var gl; 10141 10142 try { 10143 gl = canvas.getContext("webgl", options) || canvas.getContext("experimental-webgl", options); 10144 } catch (e) { 10145 // don't do anything in catch, null check will handle it 10146 } 10147 10148 if (!gl) { 10149 var msg = "Could not initialize WebGL"; 10150 console.error?console.error(msg):console.log(msg); 10151 } else { 10152 gl.viewportWidth = canvas.width; 10153 gl.viewportHeight = canvas.height; 10154 } 10155 10156 return gl; 10157 }; 10158 10159 /** 10160 * Create the completed Shader Program from the vertex and fragment shaders. Allows building of custom shaders for 10161 * filters. Once compiled, shaders are saved so. If the Shader code requires dynamic alterations re-run this function 10162 * to generate a new shader. 10163 * @method _fetchShaderProgram 10164 * @param {WebGLRenderingContext} gl The canvas WebGL context object to draw into. 10165 * @param {String} [shaderName="regular"] Working values: "regular", "override", and "filter". Which type of shader to build. 10166 * Filter and override both accept the custom params. Regular and override have all features. Filter is a special case reduced feature shader meant to be over-ridden. 10167 * @param {String} [customVTX] Extra vertex shader information to replace a regular draw, see 10168 * {{#crossLink "StageGL/COVER_VERTEX_BODY"}}{{/crossLink}} for default and {{#crossLink "Filter"}}{{/crossLink}} for examples. 10169 * @param {String} [customFRAG] Extra fragment shader information to replace a regular draw, see 10170 * {{#crossLink "StageGL/COVER_FRAGMENT_BODY"}}{{/crossLink}} for default and {{#crossLink "Filter"}}{{/crossLink}} for examples. 10171 * @param {Function} [shaderParamSetup] Function to run so custom shader parameters can get applied for the render. 10172 * @protected 10173 * @return {WebGLProgram} The compiled and linked shader 10174 */ 10175 p._fetchShaderProgram = function (gl, shaderName, customVTX, customFRAG, shaderParamSetup) { 10176 gl.useProgram(null); // safety to avoid collisions 10177 10178 // build the correct shader string out of the right headers and bodies 10179 var targetFrag, targetVtx; 10180 switch (shaderName) { 10181 case "filter": 10182 targetVtx = StageGL.COVER_VERTEX_HEADER + (customVTX || StageGL.COVER_VERTEX_BODY); 10183 targetFrag = StageGL.COVER_FRAGMENT_HEADER + (customFRAG || StageGL.COVER_FRAGMENT_BODY); 10184 break; 10185 case "particle": //TODO 10186 targetVtx = StageGL.REGULAR_VERTEX_HEADER + StageGL.PARTICLE_VERTEX_BODY; 10187 targetFrag = StageGL.REGULAR_FRAGMENT_HEADER + StageGL.PARTICLE_FRAGMENT_BODY; 10188 break; 10189 case "override": 10190 targetVtx = StageGL.REGULAR_VERTEX_HEADER + (customVTX || StageGL.REGULAR_VERTEX_BODY); 10191 targetFrag = StageGL.REGULAR_FRAGMENT_HEADER + (customFRAG || StageGL.REGULAR_FRAGMENT_BODY); 10192 break; 10193 case "regular": 10194 default: 10195 targetVtx = StageGL.REGULAR_VERTEX_HEADER + StageGL.REGULAR_VERTEX_BODY; 10196 targetFrag = StageGL.REGULAR_FRAGMENT_HEADER + StageGL.REGULAR_FRAGMENT_BODY; 10197 break; 10198 } 10199 10200 // create the separate vars 10201 var vertexShader = this._createShader(gl, gl.VERTEX_SHADER, targetVtx); 10202 var fragmentShader = this._createShader(gl, gl.FRAGMENT_SHADER, targetFrag); 10203 10204 // link them together 10205 var shaderProgram = gl.createProgram(); 10206 gl.attachShader(shaderProgram, vertexShader); 10207 gl.attachShader(shaderProgram, fragmentShader); 10208 gl.linkProgram(shaderProgram); 10209 shaderProgram._type = shaderName; 10210 10211 // check compile status 10212 if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { 10213 gl.useProgram(this._activeShader); 10214 throw gl.getProgramInfoLog(shaderProgram); 10215 } 10216 10217 // set up the parameters on the shader 10218 gl.useProgram(shaderProgram); 10219 switch (shaderName) { 10220 case "filter": 10221 // get the places in memory the shader is stored so we can feed information into them
10222 // then save it off on the shader because it's so tied to the shader itself 10223 shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "vertexPosition"); 10224 gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); 10225 10226 shaderProgram.uvPositionAttribute = gl.getAttribLocation(shaderProgram, "uvPosition"); 10227 gl.enableVertexAttribArray(shaderProgram.uvPositionAttribute); 10228 10229 shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); 10230 gl.uniform1i(shaderProgram.samplerUniform, 0); 10231 10232 shaderProgram.uprightUniform = gl.getUniformLocation(shaderProgram, "uUpright"); 10233 gl.uniform1f(shaderProgram.uprightUniform, 0); 10234 10235 // if there's some custom attributes be sure to hook them up 10236 if (shaderParamSetup) { 10237 shaderParamSetup(gl, this, shaderProgram); 10238 } 10239 break; 10240 case "override": 10241 case "particle": 10242 case "regular": 10243 default: 10244 // get the places in memory the shader is stored so we can feed information into them 10245 // then save it off on the shader because it's so tied to the shader itself 10246 shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "vertexPosition"); 10247 gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); 10248 10249 shaderProgram.uvPositionAttribute = gl.getAttribLocation(shaderProgram, "uvPosition"); 10250 gl.enableVertexAttribArray(shaderProgram.uvPositionAttribute); 10251 10252 shaderProgram.textureIndexAttribute = gl.getAttribLocation(shaderProgram, "textureIndex"); 10253 gl.enableVertexAttribArray(shaderProgram.textureIndexAttribute); 10254 10255 shaderProgram.alphaAttribute = gl.getAttribLocation(shaderProgram, "objectAlpha"); 10256 gl.enableVertexAttribArray(shaderProgram.alphaAttribute); 10257 10258 var samplers = []; 10259 for (var i = 0; i < this._batchTextureCount; i++) { 10260 samplers[i] = i; 10261 } 10262 10263 shaderProgram.samplerData = samplers; 10264 shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler"); 10265 gl.uniform1iv(shaderProgram.samplerUniform, samplers); 10266 10267 shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "pMatrix"); 10268 break; 10269 } 10270 10271 gl.useProgram(this._activeShader); 10272 return shaderProgram; 10273 }; 10274 10275 /** 10276 * Creates a shader from the specified string replacing templates. Template items are defined via `{{` `key` `}}``. 10277 * @method _createShader 10278 * @param {WebGLRenderingContext} gl The canvas WebGL context object to draw into. 10279 * @param {Number} type The type of shader to create. gl.VERTEX_SHADER | gl.FRAGMENT_SHADER 10280 * @param {String} str The definition for the shader. 10281 * @return {WebGLShader} 10282 * @protected 10283 */ 10284 p._createShader = function (gl, type, str) { 10285 // inject the static number 10286 str = str.replace(/{{count}}/g, this._batchTextureCount); 10287 10288 // resolve issue with no dynamic samplers by creating correct samplers in if else chain 10289 // TODO: WebGL 2.0 does not need this support 10290 var insert = ""; 10291 for (var i = 1; i<this._batchTextureCount; i++) { 10292 insert += "} else if (indexPicker <= "+ i +".5) { color = texture2D(uSampler["+ i +"], vTextureCoord);"; 10293 } 10294 str = str.replace(/{{alternates}}/g, insert); 10295 str = str.replace(/{{fragColor}}/g, this._premultiply ? StageGL.REGULAR_FRAG_COLOR_PREMULTIPLY : StageGL.REGULAR_FRAG_COLOR_NORMAL); 10296 10297 // actually compile the shader 10298 var shader = gl.createShader(type); 10299 gl.shaderSource(shader, str); 10300 gl.compileShader(shader); 10301 10302 // check compile status 10303 if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { 10304 throw gl.getShaderInfoLog(shader); 10305 } 10306 10307 return shader; 10308 }; 10309 10310 /** 10311 * Sets up the necessary vertex property buffers, including position and U/V.
10312 * @method _createBuffers 10313 * @param {WebGLRenderingContext} gl 10314 * @protected 10315 */ 10316 p._createBuffers = function (gl) { 10317 var groupCount = this._maxCardsPerBatch * StageGL.INDICIES_PER_CARD; 10318 var groupSize, i, l; 10319 10320 // INFO: 10321 // all buffers are created using this pattern 10322 // create a WebGL buffer 10323 // attach it to context 10324 // figure out how many parts it has to an entry 10325 // fill it with empty data to reserve the memory 10326 // attach the empty data to the GPU 10327 // track the sizes on the buffer object 10328 10329 // INFO: 10330 // a single buffer may be optimal in some situations and would be approached like this, 10331 // currently not implemented due to lack of need and potential complications with drawCover 10332 10333 // var vertexBuffer = this._vertexBuffer = gl.createBuffer(); 10334 // gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); 10335 // groupSize = 2 + 2 + 1 + 1; //x/y, u/v, index, alpha 10336 // var vertexData = this._vertexData = new Float32Array(groupCount * groupSize); 10337 // for (i=0; i<vertexData.length; i+=groupSize) { 10338 // vertexData[i+0] = vertexData[i+1] = 0; 10339 // vertexData[i+2] = vertexData[i+3] = 0.5; 10340 // vertexData[i+4] = 0; 10341 // vertexData[i+5] = 1; 10342 // } 10343 // vertexBuffer.itemSize = groupSize; 10344 // vertexBuffer.numItems = groupCount; 10345 // TODO bechmark and test using unified buffer 10346 10347 // the actual position information 10348 var vertexPositionBuffer = this._vertexPositionBuffer = gl.createBuffer(); 10349 gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer); 10350 groupSize = 2; 10351 var vertices = this._vertices = new Float32Array(groupCount * groupSize); 10352 for (i=0, l=vertices.length; i<l; i+=groupSize) { vertices[i] = vertices[i+1] = 0; } 10353 gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.DYNAMIC_DRAW); 10354 vertexPositionBuffer.itemSize = groupSize; 10355 vertexPositionBuffer.numItems = groupCount; 10356 10357 // where on the texture it gets its information 10358 var uvPositionBuffer = this._uvPositionBuffer = gl.createBuffer(); 10359 gl.bindBuffer(gl.ARRAY_BUFFER, uvPositionBuffer); 10360 groupSize = 2; 10361 var uvs = this._uvs = new Float32Array(groupCount * groupSize); 10362 for (i=0, l=uvs.length; i<l; i+=groupSize) { uvs[i] = uvs[i+1] = 0; } 10363 gl.bufferData(gl.ARRAY_BUFFER, uvs, gl.DYNAMIC_DRAW); 10364 uvPositionBuffer.itemSize = groupSize; 10365 uvPositionBuffer.numItems = groupCount; 10366 10367 // what texture it should use 10368 var textureIndexBuffer = this._textureIndexBuffer = gl.createBuffer(); 10369 gl.bindBuffer(gl.ARRAY_BUFFER, textureIndexBuffer); 10370 groupSize = 1; 10371 var indices = this._indices = new Float32Array(groupCount * groupSize); 10372 for (i=0, l=indices.length; i<l; i++) { indices[i] = 0; } 10373 gl.bufferData(gl.ARRAY_BUFFER, indices, gl.DYNAMIC_DRAW); 10374 textureIndexBuffer.itemSize = groupSize; 10375 textureIndexBuffer.numItems = groupCount; 10376 10377 // what alpha it should have 10378 var alphaBuffer = this._alphaBuffer = gl.createBuffer(); 10379 gl.bindBuffer(gl.ARRAY_BUFFER, alphaBuffer); 10380 groupSize = 1; 10381 var alphas = this._alphas = new Float32Array(groupCount * groupSize); 10382 for (i=0, l=alphas.length; i<l;
10382 i++) { alphas[i] = 1; } 10383 gl.bufferData(gl.ARRAY_BUFFER, alphas, gl.DYNAMIC_DRAW); 10384 alphaBuffer.itemSize = groupSize; 10385 alphaBuffer.numItems = groupCount; 10386 }; 10387 10388 /** 10389 * Do all the setup steps for textures in the system. 10390 * @method _initTextures 10391 * @protected 10392 */ 10393 p._initTextures = function () { 10394 //TODO: DHG: add a cleanup routine in here in case this happens mid stream 10395 10396 // reset counters 10397 this._lastTextureInsert = -1; 10398 10399 // clear containers 10400 this._textureDictionary = []; 10401 this._textureIDs = {}; 10402 this._baseTextures = []; 10403 this._batchTextures = []; 10404 10405 // fill in blanks as it helps the renderer be stable while textures are loading and reduces need for safety code 10406 for (var i=0; i<this._batchTextureCount;i++) { 10407 var tex = this.getBaseTexture(); 10408 this._baseTextures[i] = this._batchTextures[i] = tex; 10409 if (!tex) { 10410 throw "Problems creating basic textures, known causes include using too much VRAM by not releasing WebGL texture instances"; 10411 } 10412 } 10413 }; 10414 10415 /** 10416 * Load a specific texture, accounting for potential delay, as it might not be preloaded. 10417 * @method _loadTextureImage 10418 * @param {WebGLRenderingContext} gl 10419 * @param {Image} image Actual image to be loaded 10420 * @return {WebGLTexture} The resulting Texture object 10421 * @protected 10422 */ 10423 p._loadTextureImage = function (gl, image) { 10424 var src = image.src; 10425 10426 if (!src) { 10427 // one time canvas property setup 10428 image._isCanvas = true; 10429 src = image.src = "canvas_" + this._lastTrackedCanvas++; 10430 } 10431 10432 // put the texture into our storage system 10433 var storeID = this._textureIDs[src]; 10434 if (storeID === undefined) { 10435 storeID = this._textureIDs[src] = this._textureDictionary.length; 10436 } 10437 if (this._textureDictionary[storeID] === undefined) { 10438 this._textureDictionary[storeID] = this.getBaseTexture(); 10439 } 10440 10441 var texture = this._textureDictionary[storeID]; 10442 10443 if (texture) { 10444 // get texture params all set up 10445 texture._batchID = this._batchID; 10446 texture._storeID = storeID; 10447 texture._imageData = image; 10448 this._insertTextureInBatch(gl, texture); 10449 10450 // get the data into the texture or wait for it to load 10451 image._storeID = storeID; 10452 if (image.complete || image.naturalWidth || image._isCanvas) { // is it already loaded 10453 this._updateTextureImageData(gl, image); 10454 } else { 10455 image.addEventListener("load", this._updateTextureImageData.bind(this, gl, image)); 10456 } 10457 } else { 10458 // we really really should have a texture, try to recover the error by using a saved empty texture so we don't crash 10459 var msg = "Problem creating desired texture, known causes include using too much VRAM by not releasing WebGL texture instances"; 10460 (console.error && console.error(msg)) || console.log(msg); 10461 10462 texture = this._baseTextures[0]; 10463 texture._batchID = this._batchID; 10464 texture._storeID = -1; 10465 texture._imageData = texture; 10466 this._insertTextureInBatch(gl, texture); 10467 } 10468 10469 return texture; 10470 }; 10471 10472 /** 10473 * Necessary to upload the actual image data to the GPU. Without this the texture will be blank. Called automatically 10474 * in most cases due to loading and caching APIs. Flagging an image source with `_invalid = true` will trigger this 10475 * next time the image is rendered. 10476 * @param {WebGLRenderingContext} gl 10477 * @param {Image | Canvas} image The image data to be uploaded 10478 * @protected 10479 */ 10480 p._updateTextureImageData = function (gl, image) { 10481 // the bitwise & is intentional, cheap exponent 2 check 10482 var isNPOT = (image.width & image.width-1) || (image.height & image.height-1); 10483 var texture = this._textureDictionary[image._storeID]; 10484 10485 gl.activeTexture(gl.TEXTURE0 + texture._activeIndex); 10486 gl.bindTexture(gl.TEXTURE_2D, texture); 10487 10488 texture.isPOT = !isNPOT;
10489 this.setTextureParams(gl, texture.isPOT); 10490 10491 try { 10492 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); 10493 } catch(e) { 10494 var errString = "\nAn error has occurred. This is most likely due to security restrictions on WebGL images with local or cross-domain origins"; 10495 if(console.error) { 10496 //TODO: LM: I recommend putting this into a log function internally, since you do it so often, and each is implemented differently. 10497 console.error(errString); 10498 console.error(e); 10499 } else if (console) { 10500 console.log(errString); 10501 console.log(e); 10502 } 10503 } 10504 10505 image._invalid = false; 10506 10507 texture._w = image.width; 10508 texture._h = image.height; 10509 10510 if (this.vocalDebug) { 10511 if (isNPOT) { 10512 console.warn("NPOT(Non Power of Two) Texture: "+ image.src); 10513 } 10514 if (image.width > gl.MAX_TEXTURE_SIZE || image.height > gl.MAX_TEXTURE_SIZE){ 10515 console && console.error("Oversized Texture: "+ image.width+"x"+image.height +" vs "+ gl.MAX_TEXTURE_SIZE +"max"); 10516 } 10517 } 10518 }; 10519 10520 /** 10521 * Adds the texture to a spot in the current batch, forcing a draw if no spots are free. 10522 * @method _insertTextureInBatch 10523 * @param {WebGLRenderingContext} gl The canvas WebGL context object to draw into. 10524 * @param {WebGLTexture} texture The texture to be inserted. 10525 * @protected 10526 */ 10527 p._insertTextureInBatch = function (gl, texture) { 10528 // if it wasn't used last batch 10529 if (this._batchTextures[texture._activeIndex] !== texture) { 10530 // we've got to find it a a spot. 10531 var found = -1; 10532 var start = (this._lastTextureInsert+1) % this._batchTextureCount; 10533 var look = start; 10534 do { 10535 if (this._batchTextures[look]._batchID != this._batchID && !this._slotBlacklist[look]) { 10536 found = look; 10537 break; 10538 } 10539 look = (look+1) % this._batchTextureCount; 10540 } while (look !== start); 10541 10542 // we couldn't find anywhere for it go, meaning we're maxed out 10543 if (found === -1) { 10544 this.batchReason = "textureOverflow"; 10545 this._drawBuffers(gl); // <------------------------------------------------------------------------ 10546 this.batchCardCount = 0; 10547 found = start; 10548 } 10549 10550 // lets put it into that spot 10551 this._batchTextures[found] = texture; 10552 texture._activeIndex = found; 10553 var image = texture._imageData; 10554 if (image && image._invalid && texture._drawID !== undefined) { 10555 this._updateTextureImageData(gl, image); 10556 } else { 10557 gl.activeTexture(gl.TEXTURE0 + found); 10558 gl.bindTexture(gl.TEXTURE_2D, texture); 10559 this.setTextureParams(gl); 10560 } 10561 this._lastTextureInsert = found; 10562 } else { 10563 var image = texture._imageData; 10564 if (texture._storeID != undefined && image && image._invalid) { 10565 this._updateTextureImageData(gl, image); 10566 } 10567 } 10568 10569 texture._drawID = this._drawID; 10570 texture._batchID = this._batchID; 10571 }; 10572 10573 /** 10574 * Remove and clean the texture, expects a texture and is inflexible. Mostly for internal use, recommended to call 10575 * {{#crossLink "StageGL/releaseTexture"}}{{/crossLink}} instead as it will call this with the correct texture object(s). 10576 * Note: Testing shows this may not happen immediately, have to wait frames for WebGL to have actually adjust memory. 10577 * @method _killTextureObject 10578 * @param {Texture} tex The texture to be cleaned out 10579 * @protected 10580 */ 10581 p._killTextureObject = function (tex) { 10582 if (!tex) { return; } 10583 var gl = this._webGLContext; 10584 10585 // remove linkage 10586 if (tex._storeID !== undefined && tex._storeID >= 0) { 10587 this._textureDictionary[tex._storeID] = undefined; 10588 for (var n in this._textureIDs) { 10589 if (this._textureIDs[n] == tex._storeID) { delete this._textureIDs[n]; } 10590 } 10591 if(tex._imageData) { tex._imageData._storeID = undefined; } 10592 tex._imageData = tex._storeID = undefined; 10593 } 10594 10595 // make sure to drop it out of an active slot 10596 if (tex._activeIndex !== undefined && this._batchTextures[tex._activeIndex] === tex) { 10597 this._batchTextures[tex._activeIndex] = this._baseTextures[tex._activeIndex]; 10598 } 10599 10600 // remove buffers if present 10601 try { 10602 if (tex._frameBuffer) { gl.deleteFramebuffer(tex._frameBuffer); } 10603 tex._frameBuffer = undefined; 10604 } catch(e) { 10605 /* suppress delete errors because it's already gone or didn't need deleting probably */ 10606 if (this.vocalDebug) { console.log(e); } 10607 } 10608 10609 // remove entry 10610 try { 10611 gl.deleteTexture(tex); 10612 } catch(e) { 10613 /* suppress delete errors because it's already gone or didn't need deleting probably */ 10614 if (this.vocalDebug) { console.log(e); } 10615 } 10616 }; 10617 10618 /** 10619 * Store or restore current batch textures into a backup array 10620 * @method _backupBatchTextures 10621 * @param {Boolean} restore Perform a restore instead of a store. 10622 * @param {Array} [target=this._backupTextures] Where to perform the backup, defaults to internal backup. 10623 * @protected 10624 */ 10625 p._backupBatchTextures = function (restore, target) { 10626 var gl = this._webGLContext; 10627 10628 if (!this._backupTextures) { this._backupTextures = []; } 10629 if (target === undefined) { target = this._backupTextures; } 10630 10631 for (var i=0; i<this._batchTextureCount; i++) { 10632 gl.activeTexture(gl.TEXTURE0 + i); 10633 if (restore) { 10634 this._batchTextures[i] = target[i]; 10635 } else { 10636 target[i] = this._batchTextures[i]; 10637 this._batchTextures[i] = this._baseTextures[i]; 10638 } 10639 gl.bindTexture(gl.TEXTURE_2D, this._batchTextures[i]);
10640 this.setTextureParams(gl, this._batchTextures[i].isPOT); 10641 } 10642 10643 if (restore && target === this._backupTextures) { this._backupTextures = []; } 10644 }; 10645 10646 /** 10647 * Begin the drawing process for a regular render. 10648 * @method _batchDraw 10649 * @param {WebGLRenderingContext} gl The canvas WebGL context object to draw into. 10650 * @param {Stage || Container} sceneGraph {{#crossLink "Container"}}{{/crossLink}} object with all that needs to rendered, preferably a Stage. 10651 * @param {Boolean} ignoreCache 10652 * @protected 10653 */ 10654 p._batchDraw = function (sceneGraph, gl, ignoreCache) { 10655 if (this._isDrawing > 0) { 10656 this._drawBuffers(gl); 10657 } 10658 this._isDrawing++; 10659 this._drawID++; 10660 10661 this.batchCardCount = 0; 10662 this.depth = 0; 10663 10664 this._appendToBatchGroup(sceneGraph, gl, new createjs.Matrix2D(), this.alpha, ignoreCache); 10665 10666 this.batchReason = "drawFinish"; 10667 this._drawBuffers(gl); // <-------------------------------------------------------- 10668 this._isDrawing--; 10669 }; 10670 10671 /** 10672 * Perform the drawing process to fill a specific cache texture, including applying filters. 10673 * @method _cacheDraw 10674 * @param {DisplayObject} target The object we're drawing into the cache. For example, used for drawing the cache 10675 * (to prevent it from simply drawing an existing cache back into itself). 10676 * @param {Array} filters The filters we're drawing into cache. 10677 * @param {BitmapCache} manager The BitmapCache instance looking after the cache 10678 * @protected 10679 */ 10680 p._cacheDraw = function (gl, target, filters, manager) { 10681 /* 10682 Implicitly there are 4 modes to this function: filtered-sameContext, filtered-uniqueContext, sameContext, uniqueContext. 10683 Each situation must be handled slightly differently as 'sameContext' or 'uniqueContext' define how the output works, 10684 one drawing directly into the main context and the other drawing into a stored renderTexture respectively. 10685 When the draw is a 'filtered' draw, the filters are applied sequentially and will draw into saved textures repeatedly. 10686 Once the final filter is done the final output is treated depending upon whether it is a same or unique context. 10687 The internal complexity comes from reducing over-draw, shared code, and issues like textures needing to be flipped 10688 sometimes when written to render textures. 10689 */ 10690 var renderTexture; 10691 var shaderBackup = this._activeShader; 10692 var blackListBackup = this._slotBlacklist; 10693 var lastTextureSlot = this._maxTextureSlots-1; 10694 var wBackup = this._viewportWidth, hBackup = this._viewportHeight; 10695 10696 // protect the last slot so that we have somewhere to bind the renderTextures so it doesn't get upset 10697 this.protectTextureSlot(lastTextureSlot, true); 10698 10699 // create offset container for drawing item 10700 var mtx = target.getMatrix(); 10701 mtx = mtx.clone(); 10702 mtx.scale(1/manager.scale, 1/manager.scale); 10703 mtx = mtx.invert(); 10704 mtx.translate(-manager.offX/manager.scale*target.scaleX, -manager.offY/manager.scale*target.scaleY); 10705 var container = this._cacheContainer; 10706 container.children = [target]; 10707 container.transformMatrix = mtx; 10708 10709 this._backupBatchTextures(false); 10710 10711 if (filters && filters.length) { 10712 this._drawFilters(target, filters, manager); 10713 } else { 10714 // is this for another stage or mine? 10715 if (this.isCacheControlled) { 10716 // draw item to canvas I -> C 10717 gl.clear(gl.COLOR_BUFFER_BIT); 10718 this._batchDraw(container, gl, true); 10719 } else { 10720 gl.activeTexture(gl.TEXTURE0 + lastTextureSlot); 10721 target.cacheCanvas = this.getTargetRenderTexture(target, manager._drawWidth, manager._drawHeight); 10722 renderTexture = target.cacheCanvas; 10723 10724 // draw item to render texture I -> T 10725 gl.bindFramebuffer(gl.FRAMEBUFFER, renderTexture._frameBuffer); 10726 this.updateViewport(manager._drawWidth, manager._drawHeight); 10727 this._projectionMatrix = this._projectionMatrixFlip; 10728 gl.clear(gl.COLOR_BUFFER_BIT); 10729 this._batchDraw(container, gl, true); 10730 10731 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 10732 this.updateViewport(wBackup, hBackup); 10733 } 10734 } 10735 10736 this._backupBatchTextures(true); 10737 10738 this.protectTextureSlot(lastTextureSlot, false); 10739 this._activeShader = shaderBackup; 10740 this._slotBlacklist = blackListBackup; 10741 }; 10742 10743 /** 10744 * Sub portion of _cacheDraw, split off for readability. Do not call independently. 10745 * @method _drawFilters 10746 * @param {DisplayObject} target The object we're drawing with a filter. 10747 * @param {Array} filters The filters we're drawing into cache. 10748 * @param {BitmapCache} manager The BitmapCache instance looking after the cache 10749 */ 10750 p._drawFilters = function (target, filters, manager) { 10751 var gl = this._webGLContext; 10752 var renderTexture; 10753 var lastTextureSlot = this._maxTextureSlots-1; 10754 var wBackup = this._viewportWidth, hBackup = this._viewportHe
10754ight; 10755 10756 var container = this._cacheContainer; 10757 var filterCount = filters.length; 10758 10759 // we don't know which texture slot we're dealing with previously and we need one out of the way 10760 // once we're using that slot activate it so when we make and bind our RenderTexture it's safe there 10761 gl.activeTexture(gl.TEXTURE0 + lastTextureSlot); 10762 renderTexture = this.getTargetRenderTexture(target, manager._drawWidth, manager._drawHeight); 10763 10764 // draw item to render texture I -> T 10765 gl.bindFramebuffer(gl.FRAMEBUFFER, renderTexture._frameBuffer); 10766 this.updateViewport(manager._drawWidth, manager._drawHeight); 10767 gl.clear(gl.COLOR_BUFFER_BIT); 10768 this._batchDraw(container, gl, true); 10769 10770 // bind the result texture to slot 0 as all filters and cover draws assume original content is in slot 0 10771 gl.activeTexture(gl.TEXTURE0); 10772 gl.bindTexture(gl.TEXTURE_2D, renderTexture); 10773 this.setTextureParams(gl); 10774 10775 var flipY = false; 10776 var i = 0, filter = filters[i]; 10777 do { // this is safe because we wouldn't be in apply filters without a filter count of at least 1 10778 10779 // swap to correct shader 10780 this._activeShader = this.getFilterShader(filter); 10781 if (!this._activeShader) { continue; } 10782 10783 // now the old result is stored in slot 0, make a new render texture 10784 gl.activeTexture(gl.TEXTURE0 + lastTextureSlot); 10785 renderTexture = this.getTargetRenderTexture(target, manager._drawWidth, manager._drawHeight); 10786 gl.bindFramebuffer(gl.FRAMEBUFFER, renderTexture._frameBuffer); 10787 10788 // draw result to render texture R -> T 10789 gl.viewport(0, 0, manager._drawWidth, manager._drawHeight); 10790 gl.clear(gl.COLOR_BUFFER_BIT); 10791 this._drawCover(gl, flipY); 10792 10793 // bind the result texture to slot 0 as all filters and cover draws assume original content is in slot 0 10794 gl.activeTexture(gl.TEXTURE0); 10795 gl.bindTexture(gl.TEXTURE_2D, renderTexture); 10796 this.setTextureParams(gl); 10797 10798 // use flipping to keep things upright, things already cancel out on a single filter 10799 // this needs to be here as multiPass is not accurate to _this_ frame until after shader acquisition 10800 if (filterCount > 1 || filters[0]._multiPass) { 10801 flipY = !flipY; 10802 } 10803 10804 // work through the multipass if it's there, otherwise move on 10805 filter = filter._multiPass !== null ? filter._multiPass : filters[++i]; 10806 } while (filter); 10807 10808 // is this for another stage or mine 10809 if (this.isCacheControlled) { 10810 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 10811 this.updateViewport(wBackup, hBackup); 10812 10813 // draw result to canvas R -> C 10814 this._activeShader = this.getFilterShader(this); 10815 gl.clear(gl.COLOR_BUFFER_BIT); 10816 this._drawCover(gl, flipY); 10817 } else { 10818 //TODO: DHG: this is less than ideal. A flipped initial render for this circumstance might help. Adjust the perspective matrix? 10819 if (flipY) { 10820 gl.activeTexture(gl.TEXTURE0 + lastTextureSlot); 10821 renderTexture = this.getTargetRenderTexture(target, manager._drawWidth, manager._drawHeight); 10822 gl.bindFramebuffer(gl.FRAMEBUFFER, renderTexture._frameBuffer); 10823 10824 this._activeShader = this.getFilterShader(this); 10825 gl.viewport(0, 0, manager._drawWidth, manager._drawHeight); 10826 gl.clear(gl.COLOR_BUFFER_BIT); 10827 this._drawCover(gl, !flipY); 10828 } 10829 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 10830 this.updateViewport(wBackup, hBackup); 10831 10832 // make sure the last texture is the active thing to draw 10833 target.cacheCanvas = renderTexture; 10834 } 10835 }; 10836 10837 /** 10838 * Add all the contents of a container to the pending buffers, called recursively on each container. This may 10839 * trigger a draw if a buffer runs out of space. This is the main workforce of the render loop. 10840 * @method _appendToBatchGroup 10841 * @param {Container} container The {{#crossLink "Container"}}{{/crossLink}} that contains everything to be drawn. 10842 * @param {WebGLRenderingContext} gl The canvas WebGL context object to draw into. 10843 * @param {Matrix2D} concatMtx The effective (concatenated) transformation matrix when beginning this container 10844 * @param {Number} concatAlpha The effective (concatenated) alpha when beginning this container 10845 * @param {Boolean} ignoreCache Don't use an element's cache during this draw 10846 * @protected 10847 */ 10848 p._appendToBatchGroup = function (container, gl, concatMtx, concatAlpha, ignoreCache) { 10849 // sort out shared properties 10850 if (!container._glMtx) { container._glMtx = new createjs.Matrix2D(); } 10851 var cMtx = container._glMtx; 10852 cMtx.copy(concatMtx); 10853 if (container.transformMatrix) { 10854 cMtx.appendMatrix(container.transformMatrix); 10855 } else { 10856 cMtx.appendTransform( 10857 container.x, container.y, 10858 container.scaleX, container.scaleY,
10859 container.rotation, container.skewX, container.skewY, 10860 container.regX, container.regY 10861 ); 10862 } 10863 10864 // sub components of figuring out the position an object holds 10865 var subL, subT, subR, subB; 10866 10867 // actually apply its data to the buffers 10868 var l = container.children.length; 10869 for (var i = 0; i < l; i++) { 10870 var item = container.children[i]; 10871 10872 if (!(item.visible && concatAlpha)) { continue; } 10873 if (!item.cacheCanvas || ignoreCache) { 10874 if (item._updateState){ 10875 item._updateState(); 10876 } 10877 if (item.children) { 10878 this._appendToBatchGroup(item, gl, cMtx, item.alpha * concatAlpha); 10879 continue; 10880 } 10881 } 10882 10883 // check for overflowing batch, if yes then force a render 10884 // TODO: DHG: consider making this polygon count dependant for things like vector draws 10885 if (this.batchCardCount+1 > this._maxCardsPerBatch) { 10886 this.batchReason = "vertexOverflow"; 10887 this._drawBuffers(gl); // <------------------------------------------------------------ 10888 this.batchCardCount = 0; 10889 } 10890 10891 // keep track of concatenated position 10892 if (!item._glMtx) { item._glMtx = new createjs.Matrix2D(); } 10893 var iMtx = item._glMtx; 10894 iMtx.copy(cMtx); 10895 if (item.transformMatrix) { 10896 iMtx.appendMatrix(item.transformMatrix); 10897 } else { 10898 iMtx.appendTransform( 10899 item.x, item.y, 10900 item.scaleX, item.scaleY, 10901 item.rotation, item.skewX, item.skewY, 10902 item.regX, item.regY 10903 ); 10904 } 10905 10906 var uvRect, texIndex, image, frame, texture, src; 10907 var useCache = item.cacheCanvas && !ignoreCache; 10908 10909 if (item._webGLRenderStyle === 2 || useCache) { // BITMAP / Cached Canvas 10910 image = (ignoreCache?false:item.cacheCanvas) || item.image; 10911 } else if (item._webGLRenderStyle === 1) { // SPRITE 10912 frame = item.spriteSheet.getFrame(item.currentFrame); //TODO: Faster way? 10913 if (frame === null) { continue; } 10914 image = frame.image; 10915 } else { // MISC (DOM objects render themselves later) 10916 continue; 10917 } 10918 10919 var uvs = this._uvs; 10920 var vertices = this._vertices; 10921 var texI = this._indices; 10922 var alphas = this._alphas; 10923 10924 // calculate texture 10925 if (!image) { continue; } 10926 if (image._storeID === undefined) { 10927 // this texture is new to us so load it and add it to the batch 10928 texture = this._loadTextureImage(gl, image); 10929 this._insertTextureInBatch(gl, texture); 10930 } else { 10931 // fetch the texture (render textures know how to look themselves up to simplify this logic) 10932 texture = this._textureDictionary[image._storeID]; 10933 if (!texture){ 10934 if (this.vocalDebug){ console.log("Texture should not be looked up while not being stored."); } 10935 continue; 10936 } 10937 10938 // put it in the batch if needed 10939 if (texture._batchID !== this._batchID) { 10940 this._insertTextureInBatch(gl, texture); 10941 } 10942 } 10943 texIndex = texture._activeIndex; 10944 10945 if (item._webGLRenderStyle === 2 || useCache) { // BITMAP / Cached Canvas 10946 if (!useCache && item.sourceRect) { 10947 // calculate uvs 10948 if (!item._uvRect) { item._uvRect = {}; } 10949 src = item.sourceRect; 10950 uvRect = item._uvRect; 10951 uvRect.t = (src.y)/image.height; 10952 uvRect.l = (src.x)/image.width; 10953 uvRect.b = (src.y + src.height)/image.height; 10954 uvRect.r = (src.x + src.width)/image.width; 10955 10956 // calculate vertices 10957 subL = 0; subT = 0; 10958 subR = src.width+subL; subB = src.height+subT; 10959 } else { 10960 // calculate uvs 10961 uvRect = StageGL.UV_RECT; 10962 // calculate vertices 10963 if (useCache) { 10964 src = item.bitmapCache; 10965 subL = src.x+(src._filterOffX/src.scale); subT = src.y+(src._filterOffY/src.scale); 10966 subR = (src._drawWidth/src.scale)+subL; subB = (src._drawHeight/src.scale)+subT; 10967 } else { 10968 subL = 0; subT = 0; 10969 subR = image.width+subL; subB = image.height+subT; 10970 } 10971 } 10972 } else if (item._webGLRenderStyle === 1) { // SPRITE 10973 var rect = frame.rect; 10974 10975 // calculate uvs 10976 uvRect = frame.uvRect; 10977 if (!uvRect) { 10978 uvRect = StageGL.buildUVRects(item.spriteSheet, item.currentFrame, false); 10979 } 10980 10981 // calculate vertices 10982 subL = -frame.regX; subT = -frame.regY; 10983 subR = rect.width-frame.regX; subB = rect.height-frame.regY; 10984 } 10985 10986 // These must be calculated here else a forced draw might happen after they're set 10987 var offV1 = this.batchCardCount*StageGL.INDICIES_PER_CARD; // offset for 1 component vectors 10988 var offV2 = offV1*2; // offset for 2 component vectors 10989 10990 //DHG: See Matrix2D.transformPoint for why this math specifically 10991 // apply vertices 10992 vertices[offV2] = subL *iMtx.a + subT *iMtx.c +iMtx.tx; vertices[offV2+1] = subL *iMtx.b + subT *iMtx.d +iMtx.ty; 10993 vertices[offV2+2] = subL *iMtx.a + subB *iMtx.c +iMtx.tx; vertices[offV2+3] = subL *iMtx.b + subB *iMtx.d +iMtx.ty; 10994 vertices[offV2+4] = subR *iMtx.a + subT *iMtx.c +iMtx.tx; vertices[offV2+5] = subR *iMtx.b + subT *iMtx.d +iMtx.ty; 10995 vertices[offV2+6] = vertices[offV2+2]; vertices[offV2+7] = vertices[offV2+3]; 10996 vertices[offV2+8] = vertices[offV2+4]; vertices[offV2+9] = vertices[offV2+5]; 10997 vertices[offV2+10] = subR *iMtx.a + subB *iMtx.c +iMtx.tx; vertices[offV2+11] = subR *iMtx.b + subB *iMtx.d +iMtx.ty; 10998 10999 // apply uvs 11000 uvs[offV2] = uvRect.l; uvs[offV2+1] = uvRect.t; 11001 uvs[offV2+2] = uvRect.l; uvs[offV2+3] = uvRect.b; 11002 uvs[offV2+4] = uvRect.r; uvs[offV2+5] = uvRect.t; 11003 uvs[offV2+6] = uvRect.l; uvs[offV2+7] = uvRect.b; 11004 uvs[offV2+8] = uvRect.r; uvs[offV2+9] = uvRect.t; 11005 uvs[offV2+10] = uvRect.r; uvs[offV2+11] = uvRect.b; 11006 11007 // apply texture 11008 texI[offV1] = texI[offV1+1] = texI[offV1+2] = texI[offV1+3] = texI[offV1+4] = texI[offV1+5] = texIndex; 11009 11010 // apply alpha 11011 alphas[offV1] = alphas[offV1+1] = alphas[offV1+2] = alphas[offV1+3] = alphas[offV1+4] = alphas[offV1+5] = item.alpha * concatAlpha; 11012 11013 this.batchCardCount++; 11014 } 11015 }; 11016 11017 /** 11018 * Draws all the currently defined cards in the buffer to the render surface. 11019 * @method _drawBuffers 11020 * @param {WebGLRenderingContext} gl The canvas WebGL context object to draw into. 11021 * @protected 11022 */ 11023 p._drawBuffers = function (gl) { 11024 if (this.batchCardCount <= 0) { return; } // prevents error logs on stages filled with un-renederable content. 11025 11026 if (this.vocalDebug) { 11027 console.log("Draw["+ this._drawID +":"+ this._batchID +"] : "+ this.batchReason); 11028 } 11029 var shaderProgram = this._activeShader; 11030 var vertexPositionBuffer = this._vertexPositionBuffer; 11031 var textureIndexBuffer = this._textureIndexBuffer; 11032 var uvPositionBuffer = this._uvPositionBuffer; 11033 var alphaBuffer = this._alphaBuffer; 11034 11035 gl.useProgram(shaderProgram); 11036 11037 gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer); 11038 gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, vertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0); 11039 gl.bufferSubData(gl.ARRAY_BUFFER, 0, this._vertices); 11040 11041 gl.bindBuffer(gl.ARRAY_BUFFER, textureIndexBuffer); 11042 gl.vertexAttribPointer(shaderProgram.textureIndexAttribute, textureIndexBuffer.itemSize, gl.FLOAT, false, 0, 0); 11043 gl.bufferSubData(gl.ARRAY_BUFFER, 0, this._indices); 11044 11045 gl.bindBuffer(gl.ARRAY_BUFFER, uvPositionBuffer); 11046 gl.vertexAttribPointer(shaderProgram.uvPositionAttribute, uvPositionBuffer.itemSize, gl.FLOAT, false, 0, 0); 11047 gl.bufferSubData(gl.ARRAY_BUFFER, 0, this._uvs); 11048 11049 gl.bindBuffer(gl.ARRAY_BUFFER, alphaBuffer); 11050 gl.vertexAttribPointer(shaderProgram.alphaAttribute, alphaBuffer.itemSize, gl.FLOAT, false, 0, 0); 11051 gl.bufferSubData(gl.ARRAY_BUFFER, 0, this._alphas); 11052 11053 gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, gl.FALSE, this._projectionMatrix); 11054 11055 for (var i = 0; i < this._batchTextureCount; i++) { 11056 var texture = this._batchTextures[i]; 11057 gl.activeTexture(gl.TEXTURE0 + i); 11058 gl.bindTexture(gl.TEXTURE_2D, texture);
11059 this.setTextureParams(gl, texture.isPOT); 11060 } 11061 11062 gl.drawArrays(gl.TRIANGLES, 0, this.batchCardCount*StageGL.INDICIES_PER_CARD); 11063 this._batchID++; 11064 }; 11065 11066 /** 11067 * Draws a card that covers the entire render surface. Mainly used for filters. 11068 * @method _drawBuffers 11069 * @param {WebGLRenderingContext} gl The canvas WebGL context object to draw into. 11070 * @param {Boolean} flipY Covers are used for things like RenderTextures and because of 3D vs Canvas space this can 11071 * end up meaning the `y` space sometimes requires flipping in the render. 11072 * @protected 11073 */ 11074 p._drawCover = function (gl, flipY) { 11075 if (this._isDrawing > 0) { 11076 this._drawBuffers(gl); 11077 } 11078 11079 if (this.vocalDebug) { 11080 console.log("Draw["+ this._drawID +":"+ this._batchID +"] : "+ "Cover"); 11081 } 11082 var shaderProgram = this._activeShader; 11083 var vertexPositionBuffer = this._vertexPositionBuffer; 11084 var uvPositionBuffer = this._uvPositionBuffer; 11085 11086 gl.clear(gl.COLOR_BUFFER_BIT); 11087 gl.useProgram(shaderProgram); 11088 11089 gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer); 11090 gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, vertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0); 11091 gl.bufferSubData(gl.ARRAY_BUFFER, 0, StageGL.COVER_VERT); 11092 gl.bindBuffer(gl.ARRAY_BUFFER, uvPositionBuffer); 11093 gl.vertexAttribPointer(shaderProgram.uvPositionAttribute, uvPositionBuffer.itemSize, gl.FLOAT, false, 0, 0); 11094 gl.bufferSubData(gl.ARRAY_BUFFER, 0, flipY?StageGL.COVER_UV_FLIP:StageGL.COVER_UV); 11095 11096 gl.uniform1i(shaderProgram.samplerUniform, 0); 11097 gl.uniform1f(shaderProgram.uprightUniform, flipY?0:1); 11098 11099 gl.drawArrays(gl.TRIANGLES, 0, StageGL.INDICIES_PER_CARD); 11100 }; 11101 11102 createjs.StageGL = createjs.promote(StageGL, "Stage"); 11103}()); 11104 11105//############################################################################## 11106// Bitmap.js 11107//############################################################################## 11108 11109this.createjs = this.createjs||{}; 11110 11111(function() { 11112 11113 /** 11114 * A Bitmap represents an Image, Canvas, or Video in the display list. A Bitmap can be instantiated using an existing 11115 * HTML element, or a string. 11116 * 11117 * <h4>Example</h4> 11118 * 11119 * var bitmap = new createjs.Bitmap("imagePath.jpg"); 11120 * 11121 * <strong>Notes:</strong> 11122 * <ol> 11123 * <li>When using a video source that may loop or seek, use a {{#crossLink "VideoBuffer"}}{{/crossLink}} object to 11124 * prevent blinking / flashing. 11125 * <li>When a string path or image tag that is not yet loaded is used, the stage may need to be redrawn before it 11126 * will be displayed.</li> 11127 * <li>Bitmaps with an SVG source currently will not respect an alpha value other than 0 or 1. To get around this, 11128 * the Bitmap can be cached.</li> 11129 * <li>Bitmaps with an SVG source will taint the canvas with cross-origin data, which prevents interactivity. This 11130 * happens in all browsers except recent Firefox builds.</li> 11131 * <li>Images loaded cross-origin will throw cross-origin security errors when interacted with using a mouse, using 11132 * methods such as `getObjectUnderPoint`, or using filters, or caching. You can get around this by setting 11133 * `crossOrigin` flags on your images before passing them to EaselJS, eg: `img.crossOrigin="Anonymous";`</li> 11134 * </ol> 11135 * 11136 * @class Bitmap 11137 * @extends DisplayObject 11138 * @constructor 11139 * @param {CanvasImageSource | String | Object} imageOrUri The source image to display. This can be a CanvasImageSource 11140 * (image, video, canvas), an object with a `getImage` method that returns a CanvasImageSource, or a string URL to an image. 11141 * If the latter, a new Image instance with the URL as its src will be used. 11142 **/ 11143 function Bitmap(imageOrUri) { 11144 this.DisplayObject_constructor(); 11145 11146 11147 // public properties: 11148 /** 11149 * The source image to display. This can be a CanvasImageSource 11150 * (image, video, canvas), an object with a `getImage` method that returns a CanvasImageSource, or a string URL to an image. 11151 * If the latter, a new Image instance with the URL as its src will be used. 11152 * @property image 11153 * @type CanvasImageSource | Object 11154 **/ 11155 if (typeof imageOrUri == "string") { 11156 this.image = document.createElement("img"); 11157 this.image.src = imageOrUri; 11158 } else { 11159 this.image = imageOrUri; 11160 } 11161 11162 /** 11163 * Specifies an area of the source image to draw. If omitted, the whole image will be drawn. 11164 * Notes: 11165 * <ul> 11166 * <li>that video sources must have a width / height set to work correctly with `sourceRect`</li> 11167 * <li>Cached objects will ignore the `sourceRect` property</li> 11168 * </ul> 11169 * @property sourceRect 11170 * @type Rectangle 11171 * @default null 11172 */ 11173 this.sourceRect = null; 11174 11175 // private properties: 11176 /** 11177 * Docced in superclass. 11178 */ 11179 this._webGLRenderStyle = createjs.DisplayObject._StageGL_BITMAP; 11180 } 11181 var p = createjs.extend(Bitmap, createjs.DisplayObject); 11182 11183 11184// public methods: 11185 /** 11186 * Constructor alias for backwards compatibility. This method will be removed in future versions. 11187 * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}. 11188 * @method initialize
11189 * @deprecated in favour of `createjs.promote()` 11190 **/ 11191 p.initialize = Bitmap; // TODO: deprecated. 11192 11193 /** 11194 * Returns true or false indicating whether the display object would be visible if drawn to a canvas. 11195 * This does not account for whether it would be visible within the boundaries of the stage. 11196 * 11197 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 11198 * @method isVisible 11199 * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas 11200 **/ 11201 p.isVisible = function() { 11202 var image = this.image; 11203 var hasContent = this.cacheCanvas || (image && (image.naturalWidth || image.getContext || image.readyState >= 2)); 11204 return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent); 11205 }; 11206 11207 /** 11208 * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. 11209 * Returns true if the draw was handled (useful for overriding functionality). 11210 * 11211 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 11212 * @method draw 11213 * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. 11214 * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. 11215 * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back 11216 * into itself). 11217 * @return {Boolean} 11218 **/ 11219 p.draw = function(ctx, ignoreCache) { 11220 if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } 11221 var img = this.image, rect = this.sourceRect; 11222 if (img.getImage) { img = img.getImage(); } 11223 if (!img) { return true; } 11224 if (rect) { 11225 // some browsers choke on out of bound values, so we'll fix them: 11226 var x1 = rect.x, y1 = rect.y, x2 = x1 + rect.width, y2 =
11226y1 + rect.height, x = 0, y = 0, w = img.width, h = img.height; 11227 if (x1 < 0) { x -= x1; x1 = 0; } 11228 if (x2 > w) { x2 = w; } 11229 if (y1 < 0) { y -= y1; y1 = 0; } 11230 if (y2 > h) { y2 = h; } 11231 ctx.drawImage(img, x1, y1, x2-x1, y2-y1, x, y, x2-x1, y2-y1); 11232 } else { 11233 ctx.drawImage(img, 0, 0); 11234 } 11235 return true; 11236 }; 11237 11238 //Note, the doc sections below document using the specified APIs (from DisplayObject) from 11239 //Bitmap. This is why they have no method implementations. 11240 11241 /** 11242 * Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances. 11243 * You should <b>not</b> cache Bitmap instances as it can degrade performance. 11244 * 11245 * <strong>However: If you want to use a filter on a Bitmap, you <em>MUST</em> cache it, or it will not work.</strong> 11246 * To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}} 11247 * method. 11248 * @method cache 11249 **/ 11250 11251 /** 11252 * Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances. 11253 * You should <b>not</b> cache Bitmap instances as it can degrade performance. 11254 * 11255 * <strong>However: If you want to use a filter on a Bitmap, you <em>MUST</em> cache it, or it will not work.</strong> 11256 * To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}} 11257 * method. 11258 * @method updateCache 11259 **/ 11260 11261 /** 11262 * Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances. 11263 * You should <b>not</b> cache Bitmap instances as it can degrade performance. 11264 * 11265 * <strong>However: If you want to use a filter on a Bitmap, you <em>MUST</em> cache it, or it will not work.</strong> 11266 * To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}} 11267 * method. 11268 * @method uncache 11269 **/ 11270 11271 /** 11272 * Docced in superclass. 11273 */ 11274 p.getBounds = function() { 11275 var rect = this.DisplayObject_getBounds(); 11276 if (rect) { return rect; } 11277 var image = this.image, o = this.sourceRect || image; 11278 var hasContent = (image && (image.naturalWidth || image.getContext || image.readyState >= 2)); 11279 return hasContent ? this._rectangle.setValues(0, 0, o.width, o.height) : null; 11280 }; 11281 11282 /** 11283 * Returns a clone of the Bitmap instance. 11284 * @method clone 11285 * @param {Boolean} node Whether the underlying dom element should be cloned as well. 11286 * @return {Bitmap} a clone of the Bitmap instance. 11287 **/ 11288 p.clone = function(node) { 11289 var image = this.image; 11290 if(image && node){ image = image.cloneNode(); } 11291 var o = new Bitmap(image); 11292 if (this.sourceRect) { o.sourceRect = this.sourceRect.clone(); } 11293 this._cloneProps(o); 11294 return o; 11295 }; 11296 11297 /** 11298 * Returns a string representation of this object. 11299 * @method toString 11300 * @return {String} a string representation of the instance. 11301 **/ 11302 p.toString = function() { 11303 return "[Bitmap (name="+ this.name +")]"; 11304 }; 11305 11306 11307 createjs.Bitmap = createjs.promote(Bitmap, "DisplayObject"); 11308}()); 11309 11310//############################################################################## 11311// Sprite.js 11312//############################################################################## 11313 11314this.createjs = this.createjs||{}; 11315 11316(function() { 11317 "use strict"; 11318 11319 11320// constructor: 11321 /** 11322 * Displays a frame or sequence of frames (ie. an animation) from a SpriteSheet instance. A sprite sheet is a series of 11323 * images (usually animation frames) combined into a single image. For example, an animation consisting of 8 100x100 11324 * images could be combined into a 400x200 sprite sheet (4 frames across by 2 high). You can display individual frames, 11325 * play frames as an animation, and even sequence animations together. 11326 * 11327 * See the {{#crossLink "SpriteSheet"}}{{/crossLink}} class for more information on setting up frames and animations. 11328 * 11329 * <h4>Example</h4> 11330 * 11331 * var instance = new createjs.Sprite(spriteSheet); 11332 * instance.gotoAndStop("frameName"); 11333 * 11334 * Until {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} or {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}} is called, 11335 * only the first defined frame defined in the sprite sheet will be displayed. 11336 * 11337 * @class Sprite
11338 * @extends DisplayObject 11339 * @constructor 11340 * @param {SpriteSheet} spriteSheet The SpriteSheet instance to play back. This includes the source image(s), frame 11341 * dimensions, and frame data. See {{#crossLink "SpriteSheet"}}{{/crossLink}} for more information. 11342 * @param {String|Number} [frameOrAnimation] The frame number or animation to play initially. 11343 **/ 11344 function Sprite(spriteSheet, frameOrAnimation) { 11345 this.DisplayObject_constructor(); 11346 11347 11348 // public properties: 11349 /** 11350 * The frame index that will be drawn when draw is called. Note that with some {{#crossLink "SpriteSheet"}}{{/crossLink}} 11351 * definitions, this will advance non-sequentially. This will always be an integer value. 11352 * @property currentFrame 11353 * @type {Number} 11354 * @default 0 11355 * @readonly 11356 **/ 11357 this.currentFrame = 0; 11358 11359 /** 11360 * Returns the name of the currently playing animation. 11361 * @property currentAnimation 11362 * @type {String} 11363 * @final 11364 * @readonly 11365 **/ 11366 this.currentAnimation = null; 11367 11368 /** 11369 * Prevents the animation from advancing each tick automatically. For example, you could create a sprite 11370 * sheet of icons, set paused to true, and display the appropriate icon by setting <code>currentFrame</code>. 11371 * @property paused 11372 * @type {Boolean} 11373 * @default false 11374 **/ 11375 this.paused = true; 11376 11377 /** 11378 * The SpriteSheet instance to play back. This includes the source image, frame dimensions, and frame 11379 * data. See {{#crossLink "SpriteSheet"}}{{/crossLink}} for more information. 11380 * @property spriteSheet 11381 * @type {SpriteSheet} 11382 * @readonly 11383 **/ 11384 this.spriteSheet = spriteSheet; 11385 11386 /** 11387 * Specifies the current frame index within the currently playing animation. When playing normally, this will increase 11388 * from 0 to n-1, where n is the number of frames in the current animation. 11389 * 11390 * This could be a non-integer value if 11391 * using time-based playback (see {{#crossLink "Sprite/framerate"}}{{/crossLink}}, or if the animation's speed is 11392 * not an integer. 11393 * @property currentAnimationFrame 11394 * @type {Number} 11395 * @default 0 11396 **/ 11397 this.currentAnimationFrame = 0; 11398 11399 /** 11400 * By default Sprite instances advance one frame per tick. Specifying a framerate for the Sprite (or its related 11401 * SpriteSheet) will cause it to advance based on elapsed time between ticks as appropriate to maintain the target 11402 * framerate. 11403 * 11404 * For example, if a Sprite with a framerate of 10 is placed on a Stage being updated at 40fps, then the Sprite will 11405 * advance roughly one frame every 4 ticks. This will not be exact, because the time between each tick will 11406 * vary slightly between frames. 11407 * 11408 * This feature is dependent on the tick event object (or an object with an appropriate "delta" property) being 11409 * passed into {{#crossLink "Stage/update"}}{{/crossLink}}. 11410 * @property framerate 11411 * @type {Number} 11412 * @default 0 11413 **/ 11414 this.framerate = 0; 11415 11416 11417 // private properties: 11418 /** 11419 * Current animation object. 11420 * @property _animation 11421 * @protected 11422 * @type {Object} 11423 * @default null 11424 **/ 11425 this._animation = null; 11426 11427 /** 11428 * Current frame index. 11429 * @property _currentFrame 11430 * @protected 11431 * @type {Number} 11432 * @default null 11433 **/ 11434 this._currentFrame = null; 11435 11436 /** 11437 * Skips the next auto advance. Used by gotoAndPlay to avoid immediately jumping to the next frame 11438 * @property _skipAdvance 11439 * @protected 11440 * @type {Boolean} 11441 * @default false 11442 **/ 11443 this._skipAdvance = false; 11444 11445 /** 11446 * Docced in superclass. 11447 */ 11448 this._webGLRenderStyle = createjs.DisplayObject._StageGL_SPRITE; 11449 11450 if (frameOrAnimation != null) { this.gotoAndPlay(frameOrAnimation); } 11451 } 11452 var p = createjs.extend(Sprite, createjs.DisplayObject); 11453 11454 /** 11455 * Constructor alias for backwards compatibility. This method will be removed in future versions. 11456 * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}. 11457 * @method initialize
11458 * @deprecated in favour of `createjs.promote()` 11459 **/ 11460 p.initialize = Sprite; // TODO: Deprecated. This is for backwards support of Flash/Animate spritesheet export. 11461 11462 11463// events: 11464 /** 11465 * Dispatched when an animation reaches its ends. 11466 * @event animationend 11467 * @param {Object} target The object that dispatched the event. 11468 * @param {String} type The event type. 11469 * @param {String} name The name of the animation that just ended. 11470 * @param {String} next The name of the next animation that will be played, or null. This will be the same as name if the animation is looping. 11471 * @since 0.6.0 11472 */ 11473 11474 /** 11475 * Dispatched any time the current frame changes. For example, this could be due to automatic advancement on a tick, 11476 * or calling gotoAndPlay() or gotoAndStop(). 11477 * @event change 11478 * @param {Object} target The object that dispatched the event. 11479 * @param {String} type The event type. 11480 */ 11481 11482 11483// public methods: 11484 /** 11485 * Returns true or false indicating whether the display object would be visible if drawn to a canvas. 11486 * This does not account for whether it would be visible within the boundaries of the stage. 11487 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 11488 * @method isVisible 11489 * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas 11490 **/ 11491 p.isVisible = function() { 11492 var hasContent = this.cacheCanvas || this.spriteSheet.complete; 11493 return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent); 11494 }; 11495 11496 /** 11497 * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. 11498 * Returns true if the draw was handled (useful for overriding functionality). 11499 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 11500 * @method draw 11501 * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. 11502 * @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache. 11503 * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back 11504 * into itself). 11505 **/ 11506 p.draw = function(ctx, ignoreCache) { 11507 if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } 11508 this._normalizeFrame(); 11509 var o = this.spriteSheet.getFrame(this._currentFrame|0); 11510 if (!o) { return false; } 11511 var rect = o.rect; 11512 if (rect.width && rect.height) { ctx.drawImage(o.image, rect.x, rect.y, rect.width, rect.height, -o.regX, -o.regY, rect.width, rect.height); } 11513 return true; 11514 }; 11515 11516 //Note, the doc sections below document using the specified APIs (from DisplayObject) from 11517 //Bitmap. This is why they have no method implementations. 11518 11519 /** 11520 * Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances. 11521 * You should not cache Sprite instances as it can degrade performance. 11522 * @method cache 11523 **/ 11524 11525 /** 11526 * Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances. 11527 * You should not cache Sprite instances as it can degrade performance. 11528 * @method updateCache 11529 **/ 11530 11531 /** 11532 * Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances. 11533 * You should not cache Sprite instances as it can degrade performance. 11534 * @method uncache 11535 **/ 11536 11537 /** 11538 * Play (unpause) the current animation. The Sprite will be paused if either {{#crossLink "Sprite/stop"}}{{/crossLink}} 11539 * or {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} is called. Single frame animations will remain 11540 * unchanged. 11541 * @method play 11542 **/ 11543 p.play = function() { 11544 this.paused = false; 11545 }; 11546 11547 /** 11548 * Stop playing a running animation. The Sprite will be playing if {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}} 11549 * is called. Note that calling {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}} or {{#crossLink "Sprite/play"}}{{/crossLink}} 11550 * will resume playback. 11551 * @method stop 11552 **/ 11553 p.stop = function() { 11554 this.paused = true; 11555 }; 11556 11557 /**
11558 * Sets paused to false and plays the specified animation name, named frame, or frame number. 11559 * @method gotoAndPlay 11560 * @param {String|Number} frameOrAnimation The frame number or animation name that the playhead should move to 11561 * and begin playing. 11562 **/ 11563 p.gotoAndPlay = function(frameOrAnimation) { 11564 this.paused = false; 11565 this._skipAdvance = true; 11566 this._goto(frameOrAnimation); 11567 }; 11568 11569 /** 11570 * Sets paused to true and seeks to the specified animation name, named frame, or frame number. 11571 * @method gotoAndStop 11572 * @param {String|Number} frameOrAnimation The frame number or animation name that the playhead should move to 11573 * and stop. 11574 **/ 11575 p.gotoAndStop = function(frameOrAnimation) { 11576 this.paused = true; 11577 this._goto(frameOrAnimation); 11578 }; 11579 11580 /** 11581 * Advances the playhead. This occurs automatically each tick by default. 11582 * @param [time] {Number} The amount of time in ms to advance by. Only applicable if framerate is set on the Sprite 11583 * or its SpriteSheet. 11584 * @method advance 11585 */ 11586 p.advance = function(time) { 11587 var fps = this.framerate || this.spriteSheet.framerate; 11588 var t = (fps && time != null) ? time/(1000/fps) : 1; 11589 this._normalizeFrame(t); 11590 }; 11591 11592 /** 11593 * Returns a {{#crossLink "Rectangle"}}{{/crossLink}} instance defining the bounds of the current frame relative to 11594 * the origin. For example, a 90 x 70 frame with <code>regX=50</code> and <code>regY=40</code> would return a 11595 * rectangle with [x=-50, y=-40, width=90, height=70]. This ignores transformations on the display object. 11596 * 11597 * Also see the SpriteSheet {{#crossLink "SpriteSheet/getFrameBounds"}}{{/crossLink}} method. 11598 * @method getBounds 11599 * @return {Rectangle} A Rectangle instance. Returns null if the frame does not exist, or the image is not fully 11600 * loaded. 11601 **/ 11602 p.getBounds = function() { 11603 // TODO: should this normalizeFrame? 11604 return this.DisplayObject_getBounds() || this.spriteSheet.getFrameBounds(this.currentFrame, this._rectangle); 11605 }; 11606 11607 /** 11608 * Returns a clone of the Sprite instance. Note that the same SpriteSheet is shared between cloned 11609 * instances. 11610 * @method clone 11611 * @return {Sprite} a clone of the Sprite instance. 11612 **/ 11613 p.clone = function() { 11614 return this._cloneProps(new Sprite(this.spriteSheet)); 11615 }; 11616 11617 /** 11618 * Returns a string representation of this object. 11619 * @method toString 11620 * @return {String} a string representation of the instance. 11621 **/ 11622 p.toString = function() { 11623 return "[Sprite (name="+ this.name +")]"; 11624 }; 11625 11626// private methods: 11627 /** 11628 * @method _cloneProps 11629 * @param {Sprite} o 11630 * @return {Sprite} o 11631 * @protected 11632 **/ 11633 p._cloneProps = function(o) { 11634 this.DisplayObject__cloneProps(o); 11635 o.currentFrame = this.currentFrame; 11636 o.currentAnimation = this.currentAnimation; 11637 o.paused = this.paused; 11638 o.currentAnimationFrame = this.currentAnimationFrame; 11639 o.framerate = this.framerate; 11640 11641 o._animation = this._animation; 11642 o._currentFrame = this._currentFrame; 11643 o._skipAdvance = this._skipAdvance; 11644 return o; 11645 }; 11646 11647 /** 11648 * Advances the <code>currentFrame</code> if paused is not true. This is called automatically when the {{#crossLink "Stage"}}{{/crossLink}} 11649 * ticks. 11650 * @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. 11651 * @protected 11652 * @method _tick 11653 **/ 11654 p._tick = function(evtObj) { 11655 if (!this.paused) { 11656 if (!this._skipAdvance) { this.advance(evtObj&&evtObj.delta); } 11657 this._skipAdvance = false; 11658 } 11659 this.DisplayObject__tick(evtObj); 11660 }; 11661 11662 11663 /** 11664 * Normalizes the current frame, advancing animations and dispatching callbacks as appropriate. 11665 * @protected 11666 * @method _normalizeFrame 11667 **/ 11668 p._normalizeFrame = function(frameDelta) { 11669 frameDelta = frameDelta || 0; 11670 var animation = this._animation; 11671 var paused = this.paused; 11672 var frame = this._currentFrame; 11673 var l; 11674 11675 if (animation) { 11676 var speed = animation.speed || 1; 11677 var animFrame = this.currentAnimationFrame; 11678 l = animation.frames.length; 11679 if (animFrame + frameDelta * speed >= l) { 11680 var next = animation.next; 11681 if (this._dispatchAnimationEnd(animation, frame, paused, next, l - 1)) { 11682 // something changed in the event stack, so we shouldn't make any more changes here. 11683 return; 11684 } else if (next) { 11685 // sequence. Automatically calls _normalizeFrame again with the remaining frames. 11686 return this._goto(next, frameDelta - (l - animFrame) / speed); 11687 } else { 11688 // end. 11689 this.paused = true; 11690 animFrame = animation.frames.length - 1; 11691 } 11692 } else { 11693 animFrame += frameDelta * speed; 11694 } 11695 this.currentAnimationFrame = animFrame; 11696 this._currentFrame = animation.frames[animFrame | 0] 11697 } else { 11698 frame = (this._currentFrame += frameDelta); 11699 l = this.spriteSheet.getNumFrames(); 11700 if (frame >= l && l > 0) { 11701 if (!this._dispatchAnimationEnd(animation, frame, paused, l - 1)) { 11702 // looped. 11703 if ((this._currentFrame -= l) >= l) { return this._normalizeFrame(); } 11704 } 11705 } 11706 } 11707 frame = this._currentFrame | 0; 11708 if (this.currentFrame != frame) { 11709 this.currentFrame = frame; 11710 this.dispatchEvent("change"); 11711 } 11712 }; 11713 11714 /**
11715 * Dispatches the "animationend" event. Returns true if a handler changed the animation (ex. calling {{#crossLink "Sprite/stop"}}{{/crossLink}}, 11716 * {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}}, etc.) 11717 * @property _dispatchAnimationEnd 11718 * @private 11719 * @type {Function} 11720 **/ 11721 p._dispatchAnimationEnd = function(animation, frame, paused, next, end) { 11722 var name = animation ? animation.name : null; 11723 if (this.hasEventListener("animationend")) { 11724 var evt = new createjs.Event("animationend"); 11725 evt.name = name; 11726 evt.next = next; 11727 this.dispatchEvent(evt); 11728 } 11729 // did the animation get changed in the event stack?: 11730 var changed = (this._animation != animation || this._currentFrame != frame); 11731 // if the animation hasn't changed, but the sprite was paused, then we want to stick to the last frame: 11732 if (!changed && !paused && this.paused) { this.currentAnimationFrame = end; changed = true; } 11733 return changed; 11734 }; 11735 11736 /** 11737 * Moves the playhead to the specified frame number or animation. 11738 * @method _goto 11739 * @param {String|Number} frameOrAnimation The frame number or animation that the playhead should move to. 11740 * @param {Boolean} [frame] The frame of the animation to go to. Defaults to 0. 11741 * @protected 11742 **/ 11743 p._goto = function(frameOrAnimation, frame) { 11744 this.currentAnimationFrame = 0; 11745 if (isNaN(frameOrAnimation)) { 11746 var data = this.spriteSheet.getAnimation(frameOrAnimation); 11747 if (data) { 11748 this._animation = data; 11749 this.currentAnimation = frameOrAnimation; 11750 this._normalizeFrame(frame); 11751 } 11752 } else { 11753 this.currentAnimation = this._animation = null; 11754 this._currentFrame = frameOrAnimation; 11755 this._normalizeFrame(); 11756 } 11757 }; 11758 11759 11760 createjs.Sprite = createjs.promote(Sprite, "DisplayObject"); 11761}()); 11762 11763//############################################################################## 11764// Shape.js 11765//############################################################################## 11766 11767this.createjs = this.createjs||{}; 11768 11769(function() { 11770 "use strict"; 11771 11772 11773// constructor: 11774 /** 11775 * A Shape allows you to display vector art in the display list. It composites a {{#crossLink "Graphics"}}{{/crossLink}} 11776 * instance which exposes all of the vector drawing methods. The Graphics instance can be shared between multiple Shape 11777 * instances to display the same vector graphics with different positions or transforms. 11778 * 11779 * If the vector art will not 11780 * change between draws, you may want to use the {{#crossLink "DisplayObject/cache"}}{{/crossLink}} method to reduce the 11781 * rendering cost. 11782 * 11783 * <h4>Example</h4> 11784 * 11785 * var graphics = new createjs.Graphics().beginFill("#ff0000").drawRect(0, 0, 100, 100);
11786 * var shape = new createjs.Shape(graphics); 11787 * 11788 * //Alternatively use can also use the graphics property of the Shape class to renderer the same as above. 11789 * var shape = new createjs.Shape(); 11790 * shape.graphics.beginFill("#ff0000").drawRect(0, 0, 100, 100); 11791 * 11792 * @class Shape 11793 * @extends DisplayObject 11794 * @constructor 11795 * @param {Graphics} graphics Optional. The graphics instance to display. If null, a new Graphics instance will be created. 11796 **/ 11797 function Shape(graphics) { 11798 this.DisplayObject_constructor(); 11799 11800 11801 // public properties: 11802 /** 11803 * The graphics instance to display. 11804 * @property graphics 11805 * @type Graphics 11806 **/ 11807 this.graphics = graphics ? graphics : new createjs.Graphics(); 11808 } 11809 var p = createjs.extend(Shape, createjs.DisplayObject); 11810 11811 // TODO: deprecated 11812 // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. 11813 11814 11815// public methods: 11816 /** 11817 * Returns true or false indicating whether the Shape would be visible if drawn to a canvas. 11818 * This does not account for whether it would be visible within the boundaries of the stage. 11819 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 11820 * @method isVisible 11821 * @return {Boolean} Boolean indicating whether the Shape would be visible if drawn to a canvas 11822 **/ 11823 p.isVisible = function() { 11824 var hasContent = this.cacheCanvas || (this.graphics && !this.graphics.isEmpty()); 11825 return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent); 11826 }; 11827 11828 /** 11829 * Draws the Shape into the specified context ignoring its visible, alpha, shadow, and transform. Returns true if 11830 * the draw was handled (useful for overriding functionality). 11831 * 11832 * <i>NOTE: This method is mainly for internal use, though it may be useful for advanced uses.</i> 11833 * @method draw 11834 * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. 11835 * @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. For example, 11836 * used for drawing the cache (to prevent it from simply drawing an existing cache back into itself). 11837 * @return {Boolean} 11838 **/ 11839 p.draw = function(ctx, ignoreCache) { 11840 if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } 11841 this.graphics.draw(ctx, this); 11842 return true; 11843 }; 11844 11845 /** 11846 * Returns a clone of this Shape. Some properties that are specific to this instance's current context are reverted to 11847 * their defaults (for example .parent). 11848 * @method clone 11849 * @param {Boolean} recursive If true, this Shape's {{#crossLink "Graphics"}}{{/crossLink}} instance will also be 11850 * cloned. If false, the Graphics instance will be shared with the new Shape. 11851 **/ 11852 p.clone = function(recursive) { 11853 var g = (recursive && this.graphics) ? this.graphics.clone() : this.graphics; 11854 return this._cloneProps(new Shape(g)); 11855 }; 11856 11857 /** 11858 * Returns a string representation of this object. 11859 * @method toString 11860 * @return {String} a string representation of the instance. 11861 **/ 11862 p.toString = function() { 11863 return "[Shape (name="+ this.name +")]"; 11864 }; 11865 11866 11867 createjs.Shape = createjs.promote(Shape, "DisplayObject"); 11868}()); 11869 11870//############################################################################## 11871// Text.js 11872//############################################################################## 11873 11874this.createjs = this.createjs||{}; 11875 11876(function() { 11877 "use strict"; 11878 11879 11880// constructor: 11881 /** 11882 * Display one or more lines of dynamic text (not user editable) in the display list. Line wrapping support (using the 11883 * lineWidth) is very basic, wrapping on spaces and tabs only. Note that as an alternative to Text, you can position HTML 11884 * text above or below the canvas relative to items in the display list using the {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}} 11885 * method, or using {{#crossLink "DOMElement"}}{{/crossLink}}. 11886 * 11887 * <b>Please note that Text does not support HTML text, and can only display one font style at a time.</b> To use 11888 * multiple font styles, you will need to create multiple text instances, and position them manually. 11889 * 11890 * <h4>Example</h4> 11891 * 11892 * var text = new createjs.Text("Hello World", "20px Arial", "#ff7700"); 11893 * text.x = 100; 11894 * text.textBaseline = "alphabetic"; 11895 * 11896 * CreateJS Text supports web fonts (the same rules as Canvas). The font must be loaded and supported by the browser 11897 * before it can be displayed. 11898 * 11899 * <strong>Note:</strong> Text can be expensive to generate, so cache instances where possible. Be aware that not all 11900 * browsers will render Text exactly the same. 11901 * @class Text
11902 * @extends DisplayObject 11903 * @constructor 11904 * @param {String} [text] The text to display. 11905 * @param {String} [font] The font style to use. Any valid value for the CSS font attribute is acceptable (ex. "bold 11906 * 36px Arial"). 11907 * @param {String} [color] The color to draw the text in. Any valid value for the CSS color attribute is acceptable (ex. 11908 * "#F00", "red", or "#FF0000"). 11909 **/ 11910 function Text(text, font, color) { 11911 this.DisplayObject_constructor(); 11912 11913 11914 // public properties: 11915 /** 11916 * The text to display. 11917 * @property text 11918 * @type String 11919 **/ 11920 this.text = text; 11921 11922 /** 11923 * The font style to use. Any valid value for the CSS font attribute is acceptable (ex. "bold 36px Arial"). 11924 * @property font 11925 * @type String 11926 **/ 11927 this.font = font; 11928 11929 /** 11930 * The color to draw the text in. Any valid value for the CSS color attribute is acceptable (ex. "#F00"). Default is "#000". 11931 * It will also accept valid canvas fillStyle values. 11932 * @property color
11933 * @type String 11934 **/ 11935 this.color = color; 11936 11937 /** 11938 * The horizontal text alignment. Any of "start", "end", "left", "right", and "center". For detailed 11939 * information view the 11940 * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles"> 11941 * whatwg spec</a>. Default is "left". 11942 * @property textAlign 11943 * @type String 11944 **/ 11945 this.textAlign = "left"; 11946 11947 /** 11948 * The vertical alignment point on the font. Any of "top", "hanging", "middle", "alphabetic", "ideographic", or 11949 * "bottom". For detailed information view the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles"> 11950 * whatwg spec</a>. Default is "top". 11951 * @property textBaseline 11952 * @type String 11953 */ 11954 this.textBaseline = "top"; 11955 11956 /** 11957 * The maximum width to draw the text. If maxWidth is specified (not null), the text will be condensed or 11958 * shrunk to make it fit in this width. For detailed information view the 11959 * <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles"> 11960 * whatwg spec</a>. 11961 * @property maxWidth 11962 * @type Number 11963 */ 11964 this.maxWidth = null; 11965 11966 /** 11967 * If greater than 0, the text will be drawn as a stroke (outline) of the specified width. 11968 * @property outline 11969 * @type Number 11970 **/ 11971 this.outline = 0; 11972 11973 /** 11974 * Indicates the line height (vertical distance between baselines) for multi-line text. If null or 0, 11975 * the value of getMeasuredLineHeight is used. 11976 * @property lineHeight 11977 * @type Number 11978 **/ 11979 this.lineHeight = 0; 11980 11981 /** 11982 * Indicates the maximum width for a line of text before it is wrapped to multiple lines. If null, 11983 * the text will not be wrapped. 11984 * @property lineWidth 11985 * @type Number 11986 **/ 11987 this.lineWidth = null; 11988 } 11989 var p = createjs.extend(Text, createjs.DisplayObject); 11990 11991 // TODO: deprecated 11992 // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. 11993 11994 11995// static properties: 11996 /** 11997 * @property _workingContext 11998 * @type CanvasRenderingContext2D 11999 * @private 12000 **/ 12001 var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")); 12002 if (canvas.getContext) { Text._workingContext = canvas.getContext("2d"); canvas.width = canvas.height = 1; } 12003 12004 12005// constants: 12006 /** 12007 * Lookup table for the ratio to offset bounds x calculations based on the textAlign property. 12008 * @property H_OFFSETS 12009 * @type Object 12010 * @protected 12011 * @static 12012 **/ 12013 Text.H_OFFSETS = {start: 0, left: 0, center: -0.5, end: -1, right: -1}; 12014 12015 /** 12016 * Lookup table for the ratio to offset bounds y calculations based on the textBaseline property. 12017 * @property H_OFFSETS 12018 * @type Object 12019 * @protected 12020 * @static 12021 **/ 12022 Text.V_OFFSETS = {top: 0, hanging: -0.01, middle: -0.4, alphabetic: -0.8, ideographic: -0.85, bottom: -1}; 12023 12024 12025// public methods: 12026 /** 12027 * Returns true or false indicating whether the display object would be visible if drawn to a canvas. 12028 * This does not account for whether it would be visible within the boundaries of the stage. 12029 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 12030 * @method isVisible 12031 * @return {Boolean} Whether the display object would be visible if drawn to a canvas 12032 **/ 12033 p.isVisible = function() { 12034 var hasContent = this.cacheCanvas || (this.text != null && this.text !== ""); 12035 return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent); 12036 }; 12037 12038 /** 12039 * Draws the Text into the specified context ignoring its visible, alpha, shadow, and transform. 12040 * Returns true if the draw was handled (useful for overriding functionality). 12041 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 12042 * @method draw 12043 * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. 12044 * @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache. 12045 * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back 12046 * into itself). 12047 **/ 12048 p.draw = function(ctx, ignoreCache) { 12049 if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } 12050 12051 var col = this.color || "#000"; 12052 if (this.outline) { ctx.strokeStyle = col; ctx.lineWidth = this.outline*1; } 12053 else { ctx.fillStyle = col; } 12054 12055 this._drawText(this._prepContext(ctx)); 12056 return true; 12057 }; 12058 12059 /** 12060 * Returns the measured, untransformed width of the text without wrapping. Use getBounds for a more robust value. 12061 * @method getMeasuredWidth 12062 * @return {Number} The measured, untransformed width of the text. 12063 **/ 12064 p.getMeasuredWidth = function() { 12065 return this._getMeasuredWidth(this.text); 12066 }; 12067 12068 /** 12069 * Returns an approximate line height of the text, ignoring the lineHeight property. This is based on the measured 12070 * width of a "M" character multiplied by 1.2, which provides an approximate line height for most fonts. 12071 * @method getMeasuredLineHeight 12072 * @return {Number} an approximate line height of the text, ignoring the lineHeight property. This is 12073 * based on the measured width of a "M" character multiplied by 1.2, which approximates em for most fonts. 12074 **/ 12075 p.getMeasuredLineHeight = function() { 12076 return this._getMeasuredWidth("M")*1.2; 12077 }; 12078 12079 /** 12080 * Returns the approximate height of multi-line text by multiplying the number of lines against either the 12081 * <code>lineHeight</code> (if specified) or {{#crossLink "Text/getMeasuredLineHeight"}}{{/crossLink}}. Note that 12082 * this operation requires the text flowing logic to run, which has an associated CPU cost. 12083 * @method getMeasuredHeight 12084 * @return {Number} The approximate height of the untransformed multi-line text. 12085 **/ 12086 p.getMeasuredHeight = function() { 12087 return this._drawText(null,{}).height; 12088 }; 12089 12090 /** 12091 * Docced in superclass. 12092 */ 12093 p.getBounds = function() { 12094 var rect = this.DisplayObject_getBounds(); 12095 if (rect) { return rect; } 12096 if (this.text == null || this.text === "") { return null; } 12097 var o = this._drawText(null, {}); 12098 var w = (this.maxWidth && this.maxWidth < o.width) ? this.maxWidth : o.width; 12099 var x = w * Text.H_OFFSETS[this.textAlign||"left"]; 12100 var lineHeight = this.lineHeight||this.getMeasuredLineHeight(); 12101 var y = lineHeight * Text.V_OFFSETS[this.textBaseline||"top"]; 12102 return this._rectangle.setValues(x, y, w, o.height); 12103 }; 12104 12105 /** 12106 * Returns an object with width, height, and lines properties. The width and height are the visual width and height 12107 * of the drawn text. The lines property contains an array of str
12107ings, one for 12108 * each line of text that will be drawn, accounting for line breaks and wrapping. These strings have trailing 12109 * whitespace removed. 12110 * @method getMetrics 12111 * @return {Object} An object with width, height, and lines properties. 12112 **/ 12113 p.getMetrics = function() { 12114 var o = {lines:[]}; 12115 o.lineHeight = this.lineHeight || this.getMeasuredLineHeight(); 12116 o.vOffset = o.lineHeight * Text.V_OFFSETS[this.textBaseline||"top"]; 12117 return this._drawText(null, o, o.lines); 12118 }; 12119 12120 /** 12121 * Returns a clone of the Text instance. 12122 * @method clone 12123 * @return {Text} a clone of the Text instance. 12124 **/ 12125 p.clone = function() { 12126 return this._cloneProps(new Text(this.text, this.font, this.color)); 12127 }; 12128 12129 /** 12130 * Returns a string representation of this object. 12131 * @method toString 12132 * @return {String} a string representation of the instance. 12133 **/ 12134 p.toString = function() { 12135 return "[Text (text="+ (this.text.length > 20 ? this.text.substr(0, 17)+"..." : this.text) +")]"; 12136 }; 12137 12138 12139// private methods: 12140 /** 12141 * @method _cloneProps 12142 * @param {Text} o 12143 * @protected 12144 * @return {Text} o 12145 **/ 12146 p._cloneProps = function(o) { 12147 this.DisplayObject__cloneProps(o); 12148 o.textAlign = this.textAlign; 12149 o.textBaseline = this.textBaseline; 12150 o.maxWidth = this.maxWidth; 12151 o.outline = this.outline; 12152 o.lineHeight = this.lineHeight; 12153 o.lineWidth = this.lineWidth; 12154 return o; 12155 }; 12156 12157 /** 12158 * @method _getWorkingContext 12159 * @param {CanvasRenderingContext2D} ctx 12160 * @return {CanvasRenderingContext2D} 12161 * @protected 12162 **/ 12163 p._prepContext = function(ctx) { 12164 ctx.font = this.font||"10px sans-serif"; 12165 ctx.textAlign = this.textAlign||"left"; 12166 ctx.textBaseline = this.textBaseline||"top"; 12167 ctx.lineJoin = "miter"; 12168 ctx.miterLimit = 2.5; 12169 return ctx; 12170 }; 12171 12172 /** 12173 * Draws multiline text. 12174 * @method _drawText 12175 * @param {CanvasRenderingContext2D} ctx 12176 * @param {Object} o 12177 * @param {Array} lines 12178 * @return {Object} 12179 * @protected 12180 **/ 12181 p._drawText = function(ctx, o, lines) { 12182 var paint = !!ctx; 12183 if (!paint) { 12184 ctx = Text._workingContext; 12185 ctx.save(); 12186 this._prepContext(ctx); 12187 } 12188 var lineHeight = this.lineHeight||this.getMeasuredLineHeight(); 12189 12190 var maxW = 0, count = 0; 12191 var hardLines = String(this.text).split(/(?:\r\n|\r|\n)/); 12192 for (var i=0, l=hardLines.length; i<l; i++) { 12193 var str = hardLines[i]; 12194 var w = null; 12195 12196 if (this.lineWidth != null && (w = ctx.measureText(str).width) > this.lineWidth) { 12197 // text wrapping: 12198 var words = str.split(/(\s)/); 12199 str = words[0]; 12200 w = ctx.measureText(str).width; 12201 12202 for (var j=1, jl=words.length; j<jl; j+=2) { 12203 // Line needs to wrap: 12204 var wordW = ctx.measureText(words[j] + words[j+1]).width; 12205 if (w + wordW > this.lineWidth) { 12206 if (paint) { this._drawTextLine(ctx, str, count*lineHeight); } 12207 if (lines) { lines.push(str); } 12208 if (w > maxW) { maxW = w; } 12209 str = words[j+1]; 12210 w = ctx.measureText(str).width; 12211 count++; 12212 } else { 12213 str += words[j] + words[j+1]; 12214 w += wordW; 12215 } 12216 } 12217 } 12218 12219 if (paint) { this._drawTextLine(ctx, str, count*lineHeight); } 12220 if (lines) { lines.push(str); } 12221 if (o && w == null) { w = ctx.measureText(str).width; } 12222 if (w > maxW) { maxW = w; } 12223 count++; 12224 } 12225 12226 if (o) { 12227 o.width = maxW; 12228 o.height = count*lineHeight; 12229 } 12230 if (!paint) { ctx.restore(); } 12231 return o; 12232 }; 12233 12234 /** 12235 * @method _drawTextLine 12236 * @param {CanvasRenderingContext2D} ctx 12237 * @param {String} text 12238 * @param {Number} y 12239 * @protected 12240 **/ 12241 p._drawTextLine = function(ctx, text, y) { 12242 // Chrome 17 will fail to draw the text if the last param is included but null, so we feed it a large value instead: 12243 if (this.outline) { ctx.strokeText(text, 0, y, this.maxWidth||0xFFFF); } 12244 else { ctx.fillText(text, 0, y, this.maxWidth||0xFFFF); } 12245 }; 12246 12247 12248 /** 12249 * @method _getMeasuredWidth 12250 * @param {String} text 12251 * @protected 12252 **/ 12253 p._getMeasuredWidth = function(text) { 12254 var ctx = Text._workingContext; 12255 ctx.save(); 12256 var w = this._prepContext(ctx).measureText(text).width;
12257 ctx.restore(); 12258 return w; 12259 }; 12260 12261 12262 createjs.Text = createjs.promote(Text, "DisplayObject"); 12263}()); 12264 12265//############################################################################## 12266// BitmapText.js 12267//############################################################################## 12268 12269this.createjs = this.createjs || {}; 12270 12271(function () { 12272 "use strict"; 12273 12274 12275// constructor: 12276 /** 12277 * Displays text using bitmap glyphs defined in a sprite sheet. Multi-line text is supported using new line characters, 12278 * but automatic wrapping is not supported. See the {{#crossLink "BitmapText/spriteSheet:property"}}{{/crossLink}} 12279 * property for more information on defining glyphs. 12280 * 12281 * <strong>Important:</strong> While BitmapText extends Container, it is not designed to be used as one. 12282 * As such, methods like addChild and removeChild are disabled. 12283 * 12284 * 12285 * @class BitmapText 12286 * @extends DisplayObject 12287 * @param {String} [text=""] The text to display. 12288 * @param {SpriteSheet} [spriteSheet=null] The spritesheet that defines the character glyphs. 12289 * @constructor 12290 **/ 12291 function BitmapText(text, spriteSheet) {
12292 this.Container_constructor(); 12293 12294 12295 // public properties: 12296 /** 12297 * The text to display. 12298 * @property text 12299 * @type String 12300 * @default "" 12301 **/ 12302 this.text = text||""; 12303 12304 /** 12305 * A SpriteSheet instance that defines the glyphs for this bitmap text. Each glyph/character 12306 * should have a single frame animation defined in the sprite sheet named the same as 12307 * corresponding character. For example, the following animation definition: 12308 * 12309 * "A": {frames: [0]} 12310 * 12311 * would indicate that the frame at index 0 of the spritesheet should be drawn for the "A" character. The short form 12312 * is also acceptable: 12313 * 12314 * "A": 0 12315 * 12316 * Note that if a character in the text is not found in the sprite sheet, it will also 12317 * try to use the alternate case (upper or lower). 12318 * 12319 * See SpriteSheet for more information on defining sprite sheet data. 12320 * @property spriteSheet 12321 * @type SpriteSheet 12322 * @default null 12323 **/ 12324 this.spriteSheet = spriteSheet; 12325 12326 /** 12327 * The height of each line of text. If 0, then it will use a line height calculated 12328 * by checking for the height of the "1", "T", or "L" character (in that order). If 12329 * those characters are not defined, it will use the height of the first frame of the 12330 * sprite sheet. 12331 * @property lineHeight 12332 * @type Number 12333 * @default 0 12334 **/ 12335 this.lineHeight = 0; 12336 12337 /** 12338 * This spacing (in pixels) will be added after each character in the output. 12339 * @property letterSpacing 12340 * @type Number 12341 * @default 0 12342 **/ 12343 this.letterSpacing = 0; 12344 12345 /** 12346 * If a space character is not defined in the sprite sheet, then empty pixels equal to 12347 * spaceWidth will be inserted instead. If 0, then it will use a value calculated 12348 * by checking for the width of the "1", "l", "E", or "A" character (in that order). If 12349 * those characters are not defined, it will use the width of the first frame of the 12350 * sprite sheet.
12351 * @property spaceWidth 12352 * @type Number 12353 * @default 0 12354 **/ 12355 this.spaceWidth = 0; 12356 12357 12358 // private properties: 12359 /** 12360 * @property _oldProps 12361 * @type Object 12362 * @protected 12363 **/ 12364 this._oldProps = {text:0,spriteSheet:0,lineHeight:0,letterSpacing:0,spaceWidth:0}; 12365 12366 /** 12367 * Used to track the object which this class attached listeners to, helps optimize listener attachment. 12368 * @property _oldStage 12369 * @type Stage 12370 * @protected 12371 */ 12372 this._oldStage = null; 12373 /** 12374 * The event listener proxy triggered drawing draw for special circumstances. 12375 * @property _drawAction 12376 * @type function 12377 * @protected 12378 */ 12379 this._drawAction = null; 12380 } 12381 var p = createjs.extend(BitmapText, createjs.Container); 12382 12383// static properties: 12384 /** 12385 * BitmapText uses Sprite instances to draw text. To reduce the creation and destruction of instances (and thus garbage collection), it maintains 12386 * an internal object pool of sprite instances to reuse. Increasing this value can cause more sprites to be 12387 * retained, slightly increasing memory use, but reducing instantiation. 12388 * @property maxPoolSize 12389 * @type Number 12390 * @static 12391 * @default 100 12392 **/ 12393 BitmapText.maxPoolSize = 100; 12394 12395 /** 12396 * Sprite object pool. 12397 * @type {Array} 12398 * @static 12399 * @private 12400 */ 12401 BitmapText._spritePool = []; 12402 12403 12404// public methods: 12405 /** 12406 * Docced in superclass. 12407 **/ 12408 p.draw = function(ctx, ignoreCache) { 12409 if (this.DisplayObject_draw(ctx, ignoreCache)) { return; } 12410 this._updateState(); 12411 this.Container_draw(ctx, ignoreCache); 12412 }; 12413 12414 /** 12415 * Docced in superclass. 12416 **/ 12417 p.getBounds = function() { 12418 this._updateText(); 12419 return this.Container_getBounds(); 12420 }; 12421 12422 /** 12423 * Returns true or false indicating whether the display object would be visible if drawn to a canvas. 12424 * This does not account for whether it would be visible within the boundaries of the stage. 12425 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 12426 * @method isVisible 12427 * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas 12428 **/ 12429 p.isVisible = function() { 12430 var hasContent = this.cacheCanvas || (this.spriteSheet && this.spriteSheet.complete && this.text); 12431 return !!(this.visible && this.alpha > 0 && this.scaleX !== 0 && this.scaleY !== 0 && hasContent); 12432 }; 12433 12434 p.clone = function() { 12435 return this._cloneProps(new BitmapText(this.text, this.spriteSheet)); 12436 }; 12437 12438 /** 12439 * <strong>Disabled in BitmapText.</strong> 12440 * @method addChild 12441 **/ 12442 /** 12443 * <strong>Disabled in BitmapText.</strong> 12444 * @method addChildAt 12445 **/ 12446 /** 12447 * <strong>Disabled in BitmapText.</strong> 12448 * @method removeChild 12449 **/ 12450 /** 12451 * <strong>Disabled in BitmapText.</strong> 12452 * @method removeChildAt 12453 **/ 12454 /** 12455 * <strong>Disabled in BitmapText.</strong> 12456 * @method removeAllChildren 12457 **/ 12458 p.addChild = p.addChildAt = p.removeChild = p.removeChildAt = p.removeAllChildren = function() {}; 12459 12460 12461// private methods: 12462 /** 12463 * Docced in superclass. 12464 **/ 12465 p._updateState = function() { 12466 this._updateText(); 12467 }; 12468 12469 /** 12470 * @method _cloneProps 12471 * @param {BitmapText} o 12472 * @return {BitmapText} o 12473 * @protected 12474 **/ 12475 p._cloneProps = function(o) { 12476 this.Container__cloneProps(o); 12477 o.lineHeight = this.lineHeight; 12478 o.letterSpacing = this.letterSpacing; 12479 o.spaceWidth = this.spaceWidth; 12480 return o; 12481 }; 12482 12483 /** 12484 * @method _getFrameIndex 12485 * @param {String} character 12486 * @param {SpriteSheet} spriteSheet 12487 * @return {Number} 12488 * @protected 12489 **/ 12490 p._getFrameIndex = function(character, spriteSheet) { 12491 var c, o = spriteSheet.getAnimation(character); 12492 if (!o) { 12493 (character != (c = character.toUpperCase())) || (character != (c = character.toLowerCase())) || (c=null); 12494 if (c) { o = spriteSheet.getAnimation(c); } 12495 } 12496 return o && o.frames[0]; 12497 }; 12498 12499 /** 12500 * @method _getFrame 12501 * @param {String} character 12502 * @param {SpriteSheet} spriteSheet 12503 * @return {Object} 12504 * @protected 12505 **/
12506 p._getFrame = function(character, spriteSheet) { 12507 var index = this._getFrameIndex(character, spriteSheet); 12508 return index == null ? index : spriteSheet.getFrame(index); 12509 }; 12510 12511 /** 12512 * @method _getLineHeight 12513 * @param {SpriteSheet} ss 12514 * @return {Number} 12515 * @protected 12516 **/ 12517 p._getLineHeight = function(ss) { 12518 var frame = this._getFrame("1",ss) || this._getFrame("T",ss) || this._getFrame("L",ss) || ss.getFrame(0); 12519 return frame ? frame.rect.height : 1; 12520 }; 12521 12522 /** 12523 * @method _getSpaceWidth 12524 * @param {SpriteSheet} ss 12525 * @return {Number} 12526 * @protected 12527 **/ 12528 p._getSpaceWidth = function(ss) { 12529 var frame = this._getFrame("1",ss) || this._getFrame("l",ss) || this._getFrame("e",ss) || this._getFrame("a",ss) || ss.getFrame(0); 12530 return frame ? frame.rect.width : 1; 12531 }; 12532 12533 /** 12534 * @method _updateText 12535 * @protected 12536 **/ 12537 p._updateText = function() { 12538 var x=0, y=0, o=this._oldProps, change=false, spaceW=this.spaceWidth, lineH=this.lineHeight, ss=this.spriteSheet; 12539 var pool=BitmapText._spritePool, kids=this.children, childIndex=0, numKids=kids.length, sprite; 12540 12541 for (var n in o) { 12542 if (o[n] != this[n]) { 12543 o[n] = this[n]; 12544 change = true; 12545 } 12546 } 12547 if (!change) { return; } 12548 12549 var hasSpace = !!this._getFrame(" ", ss); 12550 if (!hasSpace && !spaceW) { spaceW = this._getSpaceWidth(ss); } 12551 if (!lineH) { lineH = this._getLineHeight(ss); } 12552 12553 for(var i=0, l=this.text.length; i<l; i++) { 12554 var character = this.text.charAt(i); 12555 if (character == " " && !hasSpace) { 12556 x += spaceW; 12557 continue; 12558 } else if (character=="\n" || character=="\r") { 12559 if (character=="\r" && this.text.charAt(i+1) == "\n") { i++; } // crlf 12560 x = 0; 12561 y += lineH; 12562 continue; 12563 } 12564 12565 var index = this._getFrameIndex(character, ss); 12566 if (index == null) { continue; } 12567 12568 if (childIndex < numKids) { 12569 sprite = kids[childIndex]; 12570 } else { 12571 kids.push(sprite = pool.length ? pool.pop() : new createjs.Sprite()); 12572 sprite.parent = this; 12573 numKids++; 12574 } 12575 sprite.spriteSheet = ss; 12576 sprite.gotoAndStop(index); 12577 sprite.x = x; 12578 sprite.y = y; 12579 childIndex++; 12580 12581 x += sprite.getBounds().width + this.letterSpacing; 12582 } 12583 while (numKids > childIndex) { 12584 // faster than removeChild. 12585 pool.push(sprite = kids.pop()); 12586 sprite.parent = null; 12587 numKids--; 12588 } 12589 if (pool.length > BitmapText.maxPoolSize) { pool.length = BitmapText.maxPoolSize; } 12590 }; 12591 12592 12593 createjs.BitmapText = createjs.promote(BitmapText, "Container"); 12594}()); 12595 12596//############################################################################## 12597// MovieClip.js 12598//############################################################################## 12599 12600this.createjs = this.createjs||{}; 12601 12602(function() { 12603 "use strict"; 12604 12605 12606// constructor: 12607 /** 12608 * The MovieClip class associates a TweenJS Timeline with an EaselJS {{#crossLink "Container"}}{{/crossLink}}. It allows 12609 * you to create objects which encapsulate timeline animations, state changes, and synched actions. The MovieClip 12610 * class has been included in the EaselJS minified file since 0.7.0. 12611 * 12612 * Currently MovieClip only works properly if it is tick based (as opposed to time based) though some concessions have 12613 * been made to support time-based timelines in the future. 12614 * 12615 * <h4>Example</h4> 12616 * This example animates two shapes back and forth. The grey shape starts on the left, but we jump to a mid-point in 12617 * the animation using {{#crossLink "MovieClip/gotoAndPlay"}}{{/crossLink}}. 12618 * 12619 * var stage = new createjs.Stage("canvas"); 12620 * createjs.Ticker.addEventListener("tick", stage); 12621 * 12622 * var mc = new createjs.MovieClip({loop:-1, labels:{myLabel:20}}); 12623 * stage.addChild(mc); 12624 * 12625 * var child1 = new createjs.Shape( 12626 * new createjs.Graphics().beginFill("#999999") 12627 * .drawCircle(30,30,30)); 12628 * var child2 = new createjs.Shape( 12629 * new createjs.Graphics().beginFill("#5a9cfb") 12630 * .drawCircle(30,30,30)); 12631 * 12632 * mc.timeline.addTween( 12633 * createjs.Tween.get(child1) 12634 * .to({x:0}).to({x:60}, 50).to({x:0}, 50)); 12635 * mc.timeline.addTween( 12636 * createjs.Tween.get(child2) 12637 * .to({x:60}).to({x:0}, 50).to({x:60}, 50)); 12638 * 12639 * mc.gotoAndPlay("start"); 12640 * 12641 * It is recommended to use <code>tween.to()</code> to animate and set properties (use no duration to have it set 12642 * immediately), and the <code>tween.wait()</code> method to create delays between animations. Note that using the 12643 * <code>tween.set()</code> method to affect properties will likely not provide the desired result. 12644 * 12645 * @class MovieClip 12646 * @main MovieClip 12647 * @param {Object} [props] The configuration properties to apply to this instance (ex. `{mode:MovieClip.SYNCHED}`). 12648 * Supported props for the MovieClip are listed below. These props are set on the corresponding instance properties except where 12649 * specified.<UL> 12650 * <LI>
12650 `mode`</LI> 12651 * <LI> `startPosition`</LI> 12652 * <LI> `frameBounds`</LI> 12653 * </UL> 12654 * 12655 * This object will also be passed into the Timeline instance associated with this MovieClip. See the documentation 12656 * for Timeline for a list of supported props (ex. `paused`, `labels`, `loop`, `reversed`, etc.) 12657 * @extends Container 12658 * @constructor 12659 **/ 12660 function MovieClip(props) { 12661 this.Container_constructor(); 12662 !MovieClip.inited&&MovieClip.init(); // static init 12663 12664 var mode, startPosition, loop, labels; 12665 12666 // handle old params (mode, startPosition, loop, labels): 12667 // TODO: deprecated param handling: 12668 if (props instanceof String || arguments.length > 1) { 12669 mode = props; 12670 startPosition = arguments[1]; 12671 loop = arguments[2]; 12672 labels = arguments[3]; 12673 if (loop == null) { loop = -1; } 12674 props = null; 12675 } else if (props) { 12676 mode = props.mode; 12677 startPosition = props.startPosition; 12678 loop = props.loop; 12679 labels = props.labels; 12680 } 12681 if (!props) { props = {labels:labels}; } 12682 12683 12684 // public properties: 12685 /** 12686 * Controls how this MovieClip advances its time. Must be one of 0 (INDEPENDENT), 1 (SINGLE_FRAME), or 2 (SYNCHED). 12687 * See each constant for a description of the behaviour. 12688 * @property mode
12689 * @type String 12690 * @default null 12691 **/ 12692 this.mode = mode||MovieClip.INDEPENDENT; 12693 12694 /** 12695 * Specifies what the first frame to play in this movieclip, or the only frame to display if mode is SINGLE_FRAME. 12696 * @property startPosition 12697 * @type Number 12698 * @default 0 12699 */ 12700 this.startPosition = startPosition||0; 12701 12702 /** 12703 * Specifies how many times this MovieClip should loop. A value of -1 indicates it should loop indefinitely. A value of 12704 * 1 would cause it to loop once (ie. play a total of twice). 12705 * @property loop 12706 * @type Number 12707 * @default -1 12708 */ 12709 this.loop = loop === true ? -1 : (loop || 0); 12710 12711 /** 12712 * The current frame of the movieclip. 12713 * @property currentFrame 12714 * @type Number 12715 * @default 0 12716 * @readonly 12717 */ 12718 this.currentFrame = 0; 12719 12720 /** 12721 * If true, the MovieClip's position will not advance when ticked. 12722 * @property paused 12723 * @type Boolean 12724 * @default false 12725 */ 12726 this.paused = props.paused||false; 12727 12728 /** 12729 * If true, actions in this MovieClip's tweens will be run when the playhead advances. 12730 * @property actionsEnabled 12731 * @type Boolean 12732 * @default true 12733 */ 12734 this.actionsEnabled = true; 12735 12736 /** 12737 * If true, the MovieClip will automatically be reset to its first frame whenever the timeline adds 12738 * it back onto the display list. This only applies to MovieClip instances with mode=INDEPENDENT. 12739 * <br><br> 12740 * For example, if you had a character animation with a "body" child MovieClip instance 12741 * with different costumes on each frame, you could set body.autoReset = false, so that 12742 * you can manually change the frame it is on, without worrying that it will be reset 12743 * automatically. 12744 * @property autoReset 12745 * @type Boolean 12746 * @default true 12747 */ 12748 this.autoReset = true; 12749 12750 /** 12751 * An array of bounds for each frame in the MovieClip. This is mainly intended for tool output. 12752 * @property frameBounds 12753 * @type Array 12754 * @default null 12755 */ 12756 this.frameBounds = this.frameBounds||props.frameBounds; // frameBounds are set on the prototype in Animate. 12757 12758 /** 12759 * By default MovieClip instances advance one frame per tick. Specifying a framerate for the MovieClip 12760 * will cause it to advance based on elapsed time between ticks as appropriate to maintain the target 12761 * framerate. 12762 * 12763 * For example, if a MovieClip with a framerate of 10 is placed on a Stage being updated at 40fps, then the MovieClip will 12764 * advance roughly one frame every 4 ticks. This will not be exact, because the time between each tick will 12765 * vary slightly between frames. 12766 * 12767 * This feature is dependent on the tick event object (or an object with an appropriate "delta" property) being 12768 * passed into {{#crossLink "Stage/update"}}{{/crossLink}}. 12769 * @property framerate 12770 * @type {Number} 12771 * @default null 12772 **/ 12773 this.framerate = null; 12774 12775 // set up the needed props for Timeline: 12776 props.useTicks = props.paused = true; 12777 12778 /** 12779 * The TweenJS Timeline that is associated with this MovieClip. This is created automatically when the MovieClip 12780 * instance is initialized. Animations are created by adding <a href="http://tweenjs.com">TweenJS</a> Tween 12781 * instances to the timeline. 12782 * 12783 * <h4>Example</h4> 12784 * 12785 * var tween = createjs.Tween.get(target).to({x:0}).to({x:100}, 30); 12786 * var mc = new createjs.MovieClip(); 12787 * mc.timeline.addTween(tween); 12788 * 12789 * Elements can be added and removed from the timeline by toggling an "_off" property 12790 * using the <code>tweenInstance.to()</code> method. Note that using <code>Tween.set</code> is not recommended to 12791 * create MovieClip animations. The following example will toggle the target off on frame 0, and then back on for 12792 * frame 1. You can use the "visible" property to achieve the same effect. 12793 * 12794 * var tween = createjs.Tween.get(target).to({_off:false}) 12795 * .wait(1).to({_off:true}) 12796 * .wait(1).to({_off:false}); 12797 * 12798 * @property timeline 12799 * @type Timeline 12800 * @default null 12801 */ 12802 this.timeline = new createjs.Timeline(props); 12803 12804 12805 // private properties: 12806 /** 12807 * @property _synchOffset 12808 * @type Number 12809 * @default 0 12810 * @private 12811 */ 12812 this._synchOffset = 0; 12813 12814 /** 12815 * @property _rawPosition 12816 * @type Number 12817 * @default -1 12818 * @private 12819 */ 12820 this._rawPosition = -1; // TODO: evaluate using a ._reset Boolean prop instead of -1. 12821 12822 /** 12823 * @property _bound_resolveState 12824 * @type Function 12825 * @private 12826 */ 12827 this._bound_resolveState = this._resolveState.bind(this); 12828 12829 12830 /** 12831 * The time remaining from the previous tick, only applicable when .framerate is set. 12832 * @property _t 12833 * @type Number 12834 * @private 12835 */ 12836 this._t = 0; 12837 12838 /** 12839 * List of display objects that are actively being managed by the MovieClip. 12840 * @property _managed 12841 * @type Object 12842 * @private 12843 */ 12844 this._managed = {}; 12845 } 12846 var p = createjs.extend(MovieClip, createjs.Container); 12847 12848 12849// constants: 12850 /** 12851 * The MovieClip will advance independently of its parent, even if its parent is paused. 12852 * This is the default mode. 12853 * @property INDEPENDENT 12854 * @static
12855 * @type String 12856 * @default "independent" 12857 * @readonly 12858 **/ 12859 MovieClip.INDEPENDENT = "independent"; 12860 12861 /** 12862 * The MovieClip will only display a single frame (as determined by the startPosition property). 12863 * @property SINGLE_FRAME 12864 * @static 12865 * @type String 12866 * @default "single" 12867 * @readonly 12868 **/ 12869 MovieClip.SINGLE_FRAME = "single"; 12870 12871 /** 12872 * The MovieClip will be advanced only when its parent advances and will be synched to the position of 12873 * the parent MovieClip. 12874 * @property SYNCHED 12875 * @static 12876 * @type String 12877 * @default "synched" 12878 * @readonly 12879 **/ 12880 MovieClip.SYNCHED = "synched"; 12881 12882 12883// static properties: 12884 MovieClip.inited = false; 12885 12886 12887// static methods: 12888 MovieClip.init = function() { 12889 if (MovieClip.inited) { return; } 12890 // plugins introduce some overhead to Tween, so we only install this if an MC is instantiated. 12891 MovieClipPlugin.install(); 12892 MovieClip.inited = true; 12893 }; 12894 12895 12896// getter / setters: 12897 /** 12898 * Use the {{#crossLink "MovieClip/labels:property"}}{{/crossLink}} property instead. 12899 * @method _getLabels 12900 * @protected 12901 * @return {Array} 12902 **/ 12903 p._getLabels = function() { 12904 return this.timeline.getLabels(); 12905 }; 12906 // MovieClip.getLabels is @deprecated. Remove for 1.1+ 12907 p.getLabels = createjs.deprecate(p._getLabels, "MovieClip.getLabels"); 12908 12909 /** 12910 * Use the {{#crossLink "MovieClip/currentLabel:property"}}{{/crossLink}} property instead. 12911 * @method _getCurrentLabel 12912 * @protected 12913 * @return {String} 12914 **/ 12915 p._getCurrentLabel = function() { 12916 return this.timeline.currentLabel; 12917 }; 12918 // MovieClip.getCurrentLabel is @deprecated. Remove for 1.1+ 12919 p.getCurrentLabel = createjs.deprecate(p._getCurrentLabel, "MovieClip.getCurrentLabel"); 12920 12921 /** 12922 * Use the {{#crossLink "MovieClip/duration:property"}}{{/crossLink}} property instead. 12923 * @method _getDuration 12924 * @protected 12925 * @return {Number} 12926 **/ 12927 p._getDuration = function() { 12928 return this.timeline.duration; 12929 }; 12930 // MovieClip.getDuration is @deprecated. Remove for 1.1+ 12931 p.getDuration = createjs.deprecate(p._getDuration, "MovieClip.getDuration"); 12932 12933 /** 12934 * Returns an array of objects with label and position (aka frame) properties, sorted by position. 12935 * @property labels 12936 * @type {Array} 12937 * @readonly 12938 **/ 12939 12940 /** 12941 * Returns the name of the label on or immediately before the current frame. 12942 * @property currentLabel 12943 * @type {String} 12944 * @readonly 12945 **/ 12946 12947 /** 12948 * Returns the duration of this MovieClip in seconds or ticks. 12949 * @property totalFrames 12950 * @type {Number} 12951 * @readonly 12952 **/ 12953 12954 /** 12955 * Returns the duration of this MovieClip in seconds or ticks. 12956 * @property duration 12957 * @type {Number} 12958 * @readonly 12959 **/ 12960 try { 12961 Object.defineProperties(p, { 12962 labels: { get: p._getLabels }, 12963 currentLabel: { get: p._getCurrentLabel }, 12964 totalFrames: { get: p._getDuration }, 12965 duration: { get: p._getDuration } 12966 // TODO: can we just proxy .currentFrame to tl.position as well? Ditto for .loop (or just remove entirely). 12967 }); 12968 } catch (e) {} 12969 12970 12971// public methods: 12972 /** 12973 * Constructor alias for backwards compatibility. This method will be removed in future versions. 12974 * Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}. 12975 * @method initialize 12976 * @deprecated in favour of `createjs.promote()` 12977 **/ 12978 p.initialize = MovieClip; // TODO: Deprecated. This is for backwards support of Adobe Flash/Animate 12979 12980 /** 12981 * Returns true or false indicating whether the display object would be visible if drawn to a canvas. 12982 * This does not account for whether it would be visible within the boundaries of the stage. 12983 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 12984 * @method isVisible 12985 * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas 12986 **/ 12987 p.isVisible = function() { 12988 // children are placed in draw, so we can't determine if we have content. 12989 return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0); 12990 }; 12991 12992 /** 12993 * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. 12994 * Returns true if the draw was handled (useful for overriding functionality). 12995 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 12996 * @method draw 12997 * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. 12998 * @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache. 12999 * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back 13000 * into itself). 13001 **/ 13002 p.draw = function(ctx, ignoreCache) { 13003 // draw to cache first: 13004 if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; } 13005 this._updateState(); 13006 this.Container_draw(ctx, ignoreCache); 13007 return true; 13008 }; 13009 13010 /**
13011 * Sets paused to false. 13012 * @method play 13013 **/ 13014 p.play = function() { 13015 this.paused = false; 13016 }; 13017 13018 /** 13019 * Sets paused to true. 13020 * @method stop 13021 **/ 13022 p.stop = function() { 13023 this.paused = true; 13024 }; 13025 13026 /** 13027 * Advances this movie clip to the specified position or label and sets paused to false. 13028 * @method gotoAndPlay 13029 * @param {String|Number} positionOrLabel The animation name or frame number to go to. 13030 **/ 13031 p.gotoAndPlay = function(positionOrLabel) { 13032 this.paused = false; 13033 this._goto(positionOrLabel); 13034 }; 13035 13036 /** 13037 * Advances this movie clip to the specified position or label and sets paused to true. 13038 * @method gotoAndStop 13039 * @param {String|Number} positionOrLabel The animation or frame name to go to. 13040 **/ 13041 p.gotoAndStop = function(positionOrLabel) { 13042 this.paused = true; 13043 this._goto(positionOrLabel); 13044 }; 13045 13046 /** 13047 * Advances the playhead. This occurs automatically each tick by default. 13048 * @param [time] {Number} The amount of time in ms to advance by. Only applicable if framerate is set. 13049 * @method advance 13050 */ 13051 p.advance = function(time) { 13052 var independent = MovieClip.INDEPENDENT; 13053 if (this.mode !== independent) { return; } // update happens in draw for synched clips 13054 13055 // if this MC doesn't have a framerate, hunt ancestors for one: 13056 var o=this, fps = o.framerate; 13057 while ((o = o.parent) && fps === null) { if (o.mode === independent) { fps = o._framerate; } } 13058 this._framerate = fps; 13059 13060 if (this.paused) { return; } 13061 13062 // calculate how many frames to advance: 13063 var t = (fps !== null && fps !== -1 && time !== null) ? time/(1000/fps) + this._t : 1; 13064 var frames = t|0; 13065 this._t = t-frames; // leftover time, save to add to next advance. 13066 13067 while (frames--) { this._updateTimeline(this._rawPosition+1, false); } 13068 }; 13069 13070 /** 13071 * MovieClip instances cannot be cloned. 13072 * @method clone 13073 **/ 13074 p.clone = function() { 13075 // TODO: add support for this? Need to clone the Timeline & retarget tweens - pretty complex. 13076 throw("MovieClip cannot be cloned."); 13077 }; 13078 13079 /** 13080 * Returns a string representation of this object. 13081 * @method toString 13082 * @return {String} a string representation of the instance. 13083 **/ 13084 p.toString = function() { 13085 return "[MovieClip (name="+ this.name +")]"; 13086 }; 13087 13088 13089// private methods: 13090 /** 13091 * Docced in superclass. 13092 **/ 13093 p._updateState = function() { 13094 if (this._rawPosition === -1 || this.mode !== MovieClip.INDEPENDENT) { this._updateTimeline(-1); } 13095 }; 13096 13097 /** 13098 * @method _tick 13099 * @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. 13100 * function. 13101 * @protected 13102 **/ 13103 p._tick = function(evtObj) { 13104 this.advance(evtObj&&evtObj.delta); 13105 this.Container__tick(evtObj); 13106 }; 13107 13108 /** 13109 * @method _goto 13110 * @param {String|Number} positionOrLabel The animation name or frame number to go to. 13111 * @protected 13112 **/ 13113 p._goto = function(positionOrLabel) { 13114 var pos = this.timeline.resolve(positionOrLabel); 13115 if (pos == null) { return; } 13116 this._t = 0; 13117 this._updateTimeline(pos, true); 13118 }; 13119 13120 /** 13121 * @method _reset 13122 * @private 13123 **/ 13124 p._reset = function() { 13125 this._rawPosition = -1; 13126 this._t = this.currentFrame = 0; 13127 this.paused = false; 13128 }; 13129 13130 /** 13131 * @method _updateTimeline 13132 * @param {Boolean} jump Indicates whether this update is due to jumping (via gotoAndXX) to a new position. 13133 * @protected 13134 **/ 13135 p._updateTimeline = function(rawPosition, jump) { 13136 var synced = this.mode !== MovieClip.INDEPENDENT, tl = this.timeline; 13137 if (synced) { rawPosition = this.startPosition + (this.mode===MovieClip.SINGLE_FRAME?0:this._synchOffset); } 13138 if (rawPosition < 0) { rawPosition = 0; } 13139 if (this._rawPosition === rawPosition && !synced) { return; } 13140 this._rawPosition = rawPosition; 13141 13142 // update timeline position, ignoring actions if this is a graphic. 13143 tl.loop = this.loop; // TODO: should we maintain this on MovieClip, or just have it on timeline? 13144 tl.setPosition(rawPosition, synced || !this.actionsEnabled, jump, this._bound_resolveState); 13145 }; 13146 13147 /**
13148 * Renders position 0 without running actions or updating _rawPosition. 13149 * Primarily used by Animate CC to build out the first frame in the constructor of MC symbols. 13150 * NOTE: not tested when run after the MC advances past the first frame. 13151 * @method _renderFirstFrame 13152 * @protected 13153 **/ 13154 p._renderFirstFrame = function() { 13155 var tl = this.timeline, pos = tl.rawPosition; 13156 tl.setPosition(0, true, true, this._bound_resolveState); 13157 tl.rawPosition = pos; 13158 }; 13159 13160 /** 13161 * Runs via a callback after timeline property updates and before actions. 13162 * @method _resolveState 13163 * @protected 13164 **/ 13165 p._resolveState = function() { 13166 var tl = this.timeline; 13167 this.currentFrame = tl.position; 13168 13169 for (var n in this._managed) { this._managed[n] = 1; } 13170 13171 var tweens = tl.tweens; 13172 for (var i=0, l=tweens.length; i<l; i++) { 13173 var tween = tweens[i], target = tween.target; 13174 if (target === this || tween.passive) { continue; } // TODO: this assumes the actions tween from Animate has `this` as the target. There's likely a better approach. 13175 var offset = tween._stepPosition; 13176 13177 if (target instanceof createjs.DisplayObject) { 13178 // motion tween. 13179 this._addManagedChild(target, offset); 13180 } else { 13181 // state tween. 13182 this._setState(target.state, offset); 13183 } 13184 } 13185 13186 var kids = this.children; 13187 for (i=kids.length-1; i>=0; i--) { 13188 var id = kids[i].id; 13189 if (this._managed[id] === 1) { 13190 this.removeChildAt(i); 13191 delete(this._managed[id]); 13192 } 13193 } 13194 }; 13195 13196 /** 13197 * @method _setState 13198 * @param {Array} state 13199 * @param {Number} offset 13200 * @protected 13201 **/ 13202 p._setState = function(state, offset) { 13203 if (!state) { return; } 13204 for (var i=state.length-1;i>=0;i--) { 13205 var o = state[i]; 13206 var target = o.t; 13207 var props = o.p; 13208 for (var n in props) { target[n] = props[n]; } 13209 this._addManagedChild(target, offset); 13210 } 13211 }; 13212 13213 /** 13214 * Adds a child to the timeline, and sets it up as a managed child. 13215 * @method _addManagedChild 13216 * @param {MovieClip} child The child MovieClip to manage 13217 * @param {Number} offset 13218 * @private 13219 **/ 13220 p._addManagedChild = function(child, offset) { 13221 if (child._off) { return; } 13222 this.addChildAt(child,0); 13223 13224 if (child instanceof MovieClip) { 13225 child._synchOffset = offset; 13226 // TODO: this does not precisely match Adobe Flash/Animate, which loses track of the clip if it is renamed or removed from the timeline, which causes it to reset. 13227 // TODO: should also reset when MovieClip loops, though that will be a bit tricky to detect. 13228 if (child.mode === MovieClip.INDEPENDENT && child.autoReset && (!this._managed[child.id])) { child._reset(); } 13229 } 13230 this._managed[child.id] = 2; 13231 }; 13232 13233 /** 13234 * @method _getBounds 13235 * @param {Matrix2D} matrix 13236 * @param {Boolean} ignoreTransform 13237 * @return {Rectangle} 13238 * @protected 13239 **/ 13240 p._getBounds = function(matrix, ignoreTransform) { 13241 var bounds = this.DisplayObject_getBounds(); 13242 if (!bounds) { 13243 if (this.frameBounds) { bounds = this._rectangle.copy(this.frameBounds[this.currentFrame]); } 13244 } 13245 if (bounds) { return this._transformBounds(bounds, matrix, ignoreTransform); } 13246 return this.Container__getBounds(matrix, ignoreTransform); 13247 }; 13248 13249 13250 createjs.MovieClip = createjs.promote(MovieClip, "Container"); 13251 13252 13253 13254// MovieClipPlugin for TweenJS: 13255 /** 13256 * This plugin works with <a href="http://tweenjs.com" target="_blank">TweenJS</a> to prevent the startPosition 13257 * property from tweening. 13258 * @private 13259 * @class MovieClipPlugin 13260 * @constructor 13261 **/ 13262 function MovieClipPlugin() { 13263 throw("MovieClipPlugin cannot be instantiated.") 13264 } 13265 13266 /** 13267 * @property priority 13268 * @type {Number} 13269 * @static 13270 * @readonly 13271 **/ 13272 MovieClipPlugin.priority = 100;
13272 // very high priority, should run first 13273 13274 /** 13275 * @property ID 13276 * @type {String} 13277 * @static 13278 * @readonly 13279 **/ 13280 MovieClipPlugin.ID = "MovieClip"; 13281 13282 /** 13283 * @method install 13284 * @static 13285 **/ 13286 MovieClipPlugin.install = function() { 13287 createjs.Tween._installPlugin(MovieClipPlugin); 13288 }; 13289 13290 /** 13291 * @method init 13292 * @param {Tween} tween 13293 * @param {String} prop 13294 * @param {*} value 13295 * @static 13296 **/ 13297 MovieClipPlugin.init = function(tween, prop, value) { 13298 if (prop === "startPosition" && tween.target instanceof MovieClip) { tween._addPlugin(MovieClipPlugin); } 13299 }; 13300 13301 /** 13302 * @method step 13303 * @param {Tween} tween 13304 * @param {TweenStep} step 13305 * @param {Object} props 13306 * @static 13307 **/ 13308 MovieClipPlugin.step = function(tween, step, props) {}; 13309 13310 /** 13311 * @method change 13312 * @param {Tween} tween 13313 * @param {TweenStep} step 13314 * @param {*} value 13315 * @param {Number} ratio 13316 * @param {Object} end 13317 * @return {*} 13318 * @static 13319 */ 13320 MovieClipPlugin.change = function(tween, step, prop, value, ratio, end) { 13321 if (prop === "startPosition") { return (ratio === 1 ? step.props[prop] : step.prev.props[prop]); } 13322 }; 13323 13324}()); 13325 13326//############################################################################## 13327// SpriteSheetUtils.js 13328//############################################################################## 13329 13330this.createjs = this.createjs||{}; 13331 13332(function() { 13333 "use strict"; 13334 13335 13336// constructor: 13337 /** 13338 * The SpriteSheetUtils class is a collection of static methods for working with {{#crossLink "SpriteSheet"}}{{/crossLink}}s. 13339 * A sprite sheet is a series of images (usually animation frames) combined into a single image on a regular grid. For 13340 * example, an animation consisting of 8 100x100 images could be combined into a 400x200 sprite sheet (4 frames across 13341 * by 2 high). The SpriteSheetUtils class uses a static interface and should not be instantiated. 13342 * @class SpriteSheetUtils 13343 * @static 13344 **/ 13345 function SpriteSheetUtils() { 13346 throw "SpriteSheetUtils cannot be instantiated"; 13347 } 13348 13349 13350// private static properties: 13351 /** 13352 * @property _workingCanvas 13353 * @static 13354 * @type HTMLCanvasElement | Object 13355 * @protected 13356 */ 13357 /** 13358 * @property _workingContext 13359 * @static 13360 * @type CanvasRenderingContext2D 13361 * @protected 13362 */ 13363 var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas")); 13364 if (canvas.getContext) { 13365 SpriteSheetUtils._workingCanvas = canvas; 13366 SpriteSheetUtils._workingContext = canvas.getContext("2d"); 13367 canvas.width = canvas.height = 1; 13368 } 13369 13370 13371// public static methods: 13372 /** 13373 * Returns a single frame of the specified sprite sheet as a new PNG image. An example of when this may be useful is 13374 * to use a spritesheet frame as the source for a bitmap fill. 13375 * 13376 * <strong>WARNING:</strong> In almost all cases it is better to display a single frame using a {{#crossLink "Sprite"}}{{/crossLink}} 13377 * with a {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} call than it is to slice out a frame using this 13378 * method and display it with a Bitmap instance. You can also crop an image using the {{#crossLink "Bitmap/sourceRect"}}{{/crossLink}} 13379 * property of {{#crossLink "Bitmap"}}{{/crossLink}}. 13380 * 13381 * The extractFrame method may cause cross-domain warnings since it accesses pixels directly on the canvas. 13382 * @method extractFrame 13383 * @static 13384 * @param {SpriteSheet} spriteSheet The SpriteSheet instance to extract a frame from. 13385 * @param {Number|String} frameOrAnimation The frame number or animation name to extract. If an animation 13386 * name is specified, only the first frame of the animation will be extracted. 13387 * @return {HTMLImageElement} a single frame of the specified sprite sheet as a new PNG image. 13388 */ 13389 SpriteSheetUtils.extractFrame = function(spriteSheet, frameOrAnimation) { 13390 if (isNaN(frameOrAnimation)) { 13391 frameOrAnimation = spriteSheet.getAnimation(frameOrAnimation).frames[0]; 13392 } 13393 var data = spriteSheet.getFrame(frameOrAnimation); 13394 if (!data) { return null; } 13395 var r = data.rect; 13396 var canvas = SpriteSheetUtils._workingCanvas; 13397 canvas.width = r.width; 13398 canvas.height = r.height; 13399 SpriteSheetUtils._workingContext.drawImage(data.image, r.x, r.y, r.width, r.height, 0, 0, r.width, r.height); 13400 var img = document.createElement("img"); 13401 img.src = canvas.toDataURL("image/png"); 13402 return img; 13403 }; 13404 13405 // SpriteSheetUtils.addFlippedFrames is @deprecated. Remove for 1.1+ 13406 SpriteSheetUtils.addFlippedFrames = createjs.deprecate(null, "SpriteSheetUtils.addFlippedFrames"); 13407 13408 // SpriteSheetUtils.addFlippedFrames is @deprecated. Remove for 1.1+ 13409 SpriteSheetUtils.mergeAlpha = createjs.deprecate(null, "SpriteSheetUtils.mergeAlpha"); 13410 13411 13412// private static methods: 13413 SpriteSheetUtils._flip = function(spriteSheet, count, h, v) { 13414 var imgs = spriteSheet._images; 13415 var canvas = SpriteSheetUtils._workingCanvas; 13416 var ctx = SpriteSheetUtils._workingContext; 13417 var il = imgs.length/count; 13418 for (var i=0;i<il;i++) { 13419 var src = imgs[i]; 13420 src.__tmp = i; // a bit hacky, but faster than doing indexOf below. 13421 ctx.setTransform(1,0,0,1,0,0); 13422 ctx.clearRect(0,0,canvas.width+1,canvas.height+1); 13423 canvas.width = src.width; 13424 canvas.height = src.height; 13425 ctx.setTransform(h?-1:1, 0, 0, v?-1:1, h?src.width:0, v?src.height:0); 13426 ctx.drawImage(src,0,0); 13427 var img = document.createElement("img"); 13428 img.src = canvas.toDataURL("image/png"); 13429 // work around a strange bug in Safari:
13430 img.width = (src.width||src.naturalWidth); 13431 img.height = (src.height||src.naturalHeight); 13432 imgs.push(img); 13433 } 13434 13435 var frames = spriteSheet._frames; 13436 var fl = frames.length/count; 13437 for (i=0;i<fl;i++) { 13438 src = frames[i]; 13439 var rect = src.rect.clone(); 13440 img = imgs[src.image.__tmp+il*count]; 13441 13442 var frame = {image:img,rect:rect,regX:src.regX,regY:src.regY}; 13443 if (h) { 13444 rect.x = (img.width||img.naturalWidth)-rect.x-rect.width; // update rect 13445 frame.regX = rect.width-src.regX; // update registration point 13446 } 13447 if (v) { 13448 rect.y = (img.height||img.naturalHeight)-rect.y-rect.height; // update rect 13449 frame.regY = rect.height-src.regY; // update registration point 13450 } 13451 frames.push(frame); 13452 } 13453 13454 var sfx = "_"+(h?"h":"")+(v?"v":""); 13455 var names = spriteSheet._animations; 13456 var data = spriteSheet._data; 13457 var al = names.length/count; 13458 for (i=0;i<al;i++) { 13459 var name = names[i]; 13460 src = data[name]; 13461 var anim = {name:name+sfx,speed:src.speed,next:src.next,frames:[]}; 13462 if (src.next) { anim.next += sfx; } 13463 frames = src.frames; 13464 for (var j=0,l=frames.length;j<l;j++) { 13465 anim.frames.push(frames[j]+fl*count); 13466 } 13467 data[anim.name] = anim; 13468 names.push(anim.name); 13469 } 13470 }; 13471 13472 13473 createjs.SpriteSheetUtils = SpriteSheetUtils; 13474}()); 13475 13476//############################################################################## 13477// SpriteSheetBuilder.js 13478//############################################################################## 13479 13480this.createjs = this.createjs||{}; 13481 13482(function() { 13483 "use strict"; 13484 13485 13486// constructor: 13487 /** 13488 * The SpriteSheetBuilder allows you to generate {{#crossLink "SpriteSheet"}}{{/crossLink}} instances at run time 13489 * from any display object. This can allow you to maintain your assets as vector graphics (for low file size), and 13490 * render them at run time as SpriteSheets for better performance. 13491 * 13492 * SpriteSheets can be built either synchronously, or asynchronously, so that large SpriteSheets can be generated 13493 * without locking the UI. 13494 * 13495 * Note that the "images" used in the generated SpriteSheet are actually canvas elements, and that they will be 13496 * sized to the nearest power of 2 up to the value of {{#crossLink "SpriteSheetBuilder/maxWidth:property"}}{{/crossLink}} 13497 * or {{#crossLink "SpriteSheetBuilder/maxHeight:property"}}{{/crossLink}}. 13498 * @class SpriteSheetBuilder 13499 * @param {Number} [framerate=0] The {{#crossLink "SpriteSheet/framerate:property"}}{{/crossLink}} of 13500 * {{#crossLink "SpriteSheet"}}{{/crossLink}} instances that are created. 13501 * @extends EventDispatcher 13502 * @constructor 13503 **/ 13504 function SpriteSheetBuilder(framerate) { 13505 this.EventDispatcher_constructor(); 13506 13507 // public properties: 13508 /** 13509 * The maximum width for the images (not individual frames) in the generated SpriteSheet. It is recommended to 13510 * use a power of 2 for this value (ex. 1024, 2048, 4096). If the frames cannot all fit within the max 13511 * dimensions, then additional images will be created as needed. 13512 * @property maxWidth 13513 * @type Number 13514 * @default 2048 13515 */ 13516 this.maxWidth = 2048; 13517 13518 /** 13519 * The maximum height for the images (not individual frames) in the generated SpriteSheet. It is recommended to 13520 * use a power of 2 for this value (ex. 1024, 2048, 4096). If the frames cannot all fit within the max 13521 * dimensions, then additional images will be created as needed. 13522 * @property maxHeight 13523 * @type Number 13524 * @default 2048 13525 **/ 13526 this.maxHeight = 2048; 13527 13528 /** 13529 * The SpriteSheet that was generated. This will be null before a build is completed successfully. 13530 * @property spriteSheet 13531 * @type SpriteSheet 13532 **/ 13533 this.spriteSheet = null; 13534 13535 /** 13536 * The scale to apply when drawing all frames to the SpriteSheet. This is multiplied against any scale specified 13537 * in the addFrame call. This can be used, for example, to generate a SpriteSheet at run time that is tailored 13538 * to the a specific device resolution (ex. tablet vs mobile). 13539 * @property scale 13540 * @type Number 13541 * @default 1 13542 **/ 13543 this.scale = 1; 13544 13545 /** 13546 * The padding to use between frames. This is helpful to preserve antialiasing on drawn vector content. 13547 * @property padding 13548 * @type Number 13549 * @default 1 13550 **/ 13551 this.padding = 1; 13552 13553 /** 13554 * A number from 0.01 to 0.99 that indicates what percentage of time the builder can use. This can be 13555 * thought of as the number of seconds per second the builder will use. For example, with a timeSlice value of 0.3, 13556 * the builder will run 20 times per second, using approximately 15ms per build (30% of available time, or 0.3s per second). 13557 * Defaults to 0.3. 13558 * @property timeSlice 13559 * @type Number 13560 * @default 0.3 13561 **/ 13562 this.timeSlice = 0.3; 13563 13564 /** 13565 * A value between 0 and 1 that indicates the progress of a build, or -1 if a build has not 13566 * been initiated. 13567 * @property progress 13568 * @type Number 13569 * @default -1 13570 * @readonly 13571 */ 13572 this.progress = -1; 13573 13574 /** 13575 * A {{#crossLink "SpriteSheet/framerate:property"}}{{/crossLink}}
13575 value that will be passed to new {{#crossLink "SpriteSheet"}}{{/crossLink}} instances that are 13576 * created. If no framerate is specified (or it is 0), then SpriteSheets will use the {{#crossLink "Ticker"}}{{/crossLink}} 13577 * framerate. 13578 * @property framerate 13579 * @type Number 13580 * @default 0 13581 */ 13582 this.framerate = framerate || 0; 13583 13584 13585 // private properties: 13586 /** 13587 * @property _frames 13588 * @protected 13589 * @type Array 13590 **/ 13591 this._frames = []; 13592 13593 /** 13594 * @property _animations 13595 * @protected 13596 * @type Array 13597 **/ 13598 this._animations = {}; 13599 13600 /** 13601 * @property _data 13602 * @protected 13603 * @type Array 13604 **/ 13605 this._data = null; 13606 13607 /** 13608 * @property _nextFrameIndex 13609 * @protected 13610 * @type Number 13611 **/ 13612 this._nextFrameIndex = 0; 13613 13614 /** 13615 * @property _index 13616 * @protected 13617 * @type Number 13618 **/ 13619 this._index = 0; 13620 13621 /** 13622 * @property _timerID 13623 * @protected 13624 * @type Number 13625 **/ 13626 this._timerID = null; 13627 13628 /** 13629 * @property _scale 13630 * @protected 13631 * @type Number 13632 **/ 13633 this._scale = 1; 13634 } 13635 var p = createjs.extend(SpriteSheetBuilder, createjs.EventDispatcher); 13636 13637// constants: 13638 SpriteSheetBuilder.ERR_DIMENSIONS = "frame dimensions exceed max spritesheet dimensions"; 13639 SpriteSheetBuilder.ERR_RUNNING = "a build is already running"; 13640 13641// events: 13642 /** 13643 * Dispatched when a build completes. 13644 * @event complete 13645 * @param {Object} target The object that dispatched the event. 13646 * @param {String} type The event type. 13647 * @since 0.6.0 13648 */ 13649 13650 /** 13651 * Dispatched when an asynchronous build has progress. 13652 * @event progress 13653 * @param {Object} target The object that dispatched the event. 13654 * @param {String} type The event type. 13655 * @param {Number} progress The current progress value (0-1). 13656 * @since 0.6.0 13657 */ 13658 13659 13660// public methods: 13661 /** 13662 * Adds a frame to the {{#crossLink "SpriteSheet"}}{{/crossLink}}. Note that the frame will not be drawn until you 13663 * call {{#crossLink "SpriteSheetBuilder/build"}}{{/crossLink}} method. The optional setup params allow you to have 13664 * a function run immediately before the draw occurs. For example, this allows you to add a single source multiple 13665 * times, but manipulate it or its children to change it to generate different frames. 13666 * 13667 * Note that the source's transformations (x, y, scale, rotate, alpha) will be ignored, except for regX/Y. To apply 13668 * transforms to a source object and have them captured in the SpriteSheet, simply place it into a {{#crossLink "Container"}}{{/crossLink}} 13669 * and pass in the Container as the source. 13670 * @method addFrame 13671 * @param {DisplayObject} source The source {{#crossLink "DisplayObject"}}{{/crossLink}} to draw as the frame. 13672 * @param {Rectangle} [sourceRect] A {{#crossLink "Rectangle"}}{{/crossLink}} defining the portion of the 13673 * source to draw to the frame. If not specified, it will look for a `getBounds` method, bounds property, or 13674 * `nominalBounds` property on the source to use. If one is not found, the frame will be skipped. 13675 * @param {Number} [scale=1] Optional. The scale to draw this frame at. Default is 1. 13676 * @param {Function} [setupFunction] A function to call immediately before drawing this frame. It will be called with two parameters: the source, and setupData. 13677 * @param {Object} [setupData] Arbitrary setup data to pass to setupFunction as the second parameter. 13678 * @return {Number} The index of the frame that was just added, or null if a sourceRect could not be determined. 13679 **/ 13680 p.addFrame = function(source, sourceRect, scale, setupFunction, setupData) { 13681 if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; } 13682 var rect = sourceRect||source.bounds||source.nominalBounds; 13683 if (!rect&&source.getBounds) { rect = source.getBounds(); } 13684 if (!rect) { return null; } 13685 scale = scale||1; 13686 return this._frames.push({source:source, sourceRect:rect, scale:scale, funct:setupFunction, data:setupData, index:this._frames.length, height:rect.height*scale})-1; 13687 }; 13688 13689 /** 13690 * Adds an animation that will be included in the created {{#crossLink "SpriteSheet"}}{{/crossLink}}. 13691 * @method addAnimation 13692 * @param {String} name The name for the animation. 13693 * @param {Array} frames An array of frame indexes that comprise the animation. Ex. [3,6,5] would describe an animation 13694 * that played frame indexes 3, 6, and 5 in that order. 13695 * @param {String} [next] Specifies the name of the animation to continue to after this animation ends. You can 13696 * also pass false to have the animation stop when it ends. By default it will loop to the start of the same animation. 13697 * @param {Number} [speed] Specifies a frame advance speed for this animation. For example, a value of 0.5 would 13698 * cause the animation to advance every second tick. Note that earlier versions used `frequency` instead, which had 13699 * the opposite effect. 13700 **/ 13701 p.addAnimation = function(name, frames, next, speed) { 13702 if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; } 13703 this._animations[name] = {frames:frames, next:next, speed:speed}; 13704 }; 13705 13706 /** 13707 * This will take a {{#crossLink "MovieClip"}}{{/crossLink}} instance, and add its frames and labels to this 13708 * builder. Labels will be added as an animation running from the label index to the next label. For example, if 13709 * there is a label named "foo" at frame 0 and a label named "bar" at frame 10, in a MovieClip with 15 frames, it 13710 * will add an animation named "foo" that runs from frame index 0 to 9, and an animation named "bar" that runs from 13711 * frame index 10 to 14. 13712 * 13713 * Note that this will iterate through the full MovieClip with {{#crossLink "MovieClip/actionsEnabled:property"}}{{/crossLink}} 13714 * set to `false`, ending on the last frame. 13715 * @method addMovieClip 13716 * @param {MovieClip} source The source MovieClip instance to add to the SpriteSheet. 13717 * @param {Rectangle} [sourceRect] A {{#crossLink "Rectangle"}}{{/crossLink}} defining the portion of the source to 13718 * draw to the frame. If not specified, it will look for a {{#crossLink "DisplayObject/getBounds"}}{{/crossLink}} 13719 * method, `frameBounds` Array, `bounds` property, or `nominalBounds` property on the source to use. If one is not 13720 * found, the MovieClip will be skipped. 13721 * @param {Number}
13721 [scale=1] The scale to draw the movie clip at. 13722 * @param {Function} [setupFunction] A function to call immediately before drawing each frame. It will be called 13723 * with three parameters: the source, setupData, and the frame index. 13724 * @param {Object} [setupData] Arbitrary setup data to pass to setupFunction as the second parameter. 13725 * @param {Function} [labelFunction] This method will be called for each MovieClip label that is added with four 13726 * parameters: the label name, the source MovieClip instance, the starting frame index (in the movieclip timeline) 13727 * and the end index. It must return a new name for the label/animation, or `false` to exclude the label. 13728 **/ 13729 p.addMovieClip = function(source, sourceRect, scale, setupFunction, setupData, labelFunction) { 13730 if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; } 13731 var rects = source.frameBounds; 13732 var rect = sourceRect||source.bounds||source.nominalBounds; 13733 if (!rect&&source.getBounds) { rect = source.getBounds(); } 13734 if (!rect && !rects) { return; } 13735 13736 var i, l, baseFrameIndex = this._frames.length; 13737 var duration = source.timeline.duration; 13738 for (i=0; i<duration; i++) { 13739 var r = (rects&&rects[i]) ? rects[i] : rect; 13740 this.addFrame(source, r, scale, this._setupMovieClipFrame, {i:i, f:setupFunction, d:setupData}); 13741 } 13742 var labels = source.timeline._labels; 13743 var lbls = []; 13744 for (var n in labels) { 13745 lbls.push({index:labels[n], label:n}); 13746 } 13747 if (lbls.length) { 13748 lbls.sort(function(a,b){ return a.index-b.index; }); 13749 for (i=0,l=lbls.length; i<l; i++) { 13750 var label = lbls[i].label; 13751 var start = baseFrameIndex+lbls[i].index; 13752 var end = baseFrameIndex+((i == l-1) ? duration : lbls[i+1].index); 13753 var frames = []; 13754 for (var j=start; j<end; j++) { frames.push(j); } 13755 if (labelFunction) { 13756 label = labelFunction(label, source, start, end); 13757 if (!label) { continue; } 13758 } 13759 this.addAnimation(label, frames, true); // for now, this loops all animations. 13760 } 13761 } 13762 }; 13763 13764 /** 13765 * Builds a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance based on the current frames. 13766 * @method build 13767 * @return {SpriteSheet} The created SpriteSheet instance, or null if a build is already running or an error 13768 * occurred. 13769 **/ 13770 p.build = function() { 13771 if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; } 13772 this._startBuild(); 13773 while (this._drawNext()) {} 13774 this._endBuild(); 13775 return this.spriteSheet; 13776 }; 13777 13778 /** 13779 * Asynchronously builds a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance based on the current frames. It will 13780 * run 20 times per second, using an amount of time defined by `timeSlice`. When it is complete it will call the 13781 * specified callback. 13782 * @method buildAsync 13783 * @param {Number} [timeSlice] Sets the timeSlice property on this instance. 13784 **/ 13785 p.buildAsync = function(timeSlice) { 13786 if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; } 13787 this.timeSlice = timeSlice; 13788 this._startBuild(); 13789 var _this = this; 13790 this._timerID = setTimeout(function() { _this._run(); }, 50-Math.max(0.01, Math.min(0.99, this.timeSlice||0.3))*50); 13791 }; 13792 13793 /** 13794 * Stops the current asynchronous build. 13795 * @method stopAsync 13796 **/ 13797 p.stopAsync = function() { 13798 clearTimeout(this._timerID); 13799 this._data = null; 13800 }; 13801 13802 /** 13803 * SpriteSheetBuilder instances cannot be cloned. 13804 * @method clone 13805 **/ 13806 p.clone = function() { 13807 throw("SpriteSheetBuilder cannot be cloned."); 13808 }; 13809 13810 /** 13811 * Returns a string representation of this object. 13812 * @method toString 13813 * @return {String} a string representation of the instance. 13814 **/ 13815 p.toString = function() { 13816 return "[SpriteSheetBuilder]"; 13817 }; 13818 13819 13820// private methods: 13821 /** 13822 * @method _startBuild 13823 * @protected 13824 **/ 13825 p._startBuild = function() { 13826 var pad = this.padding||0; 13827 this.progress = 0; 13828 this.spriteSheet = null; 13829 this._index = 0; 13830 this._scale = this.scale; 13831 var dataFrames = []; 13832 this._data = { 13833 images: [], 13834 frames: dataFrames, 13835 framerate: this.framerate, 13836 animations: this._animations // TODO: should we "clone" _animations in case someone adds more animations after a build? 13837 }; 13838 13839 var frames = this._frames.slice(); 13840 frames.sort(function(a,b) { return (a.height<=b.height) ? -1 : 1; }); 13841 13842 if (frames[frames.length-1].height+pad*2 > this.maxHeight) { throw SpriteSheetBuilder.ERR_DIMENSIONS; } 13843 var y=0, x=0; 13844 var img = 0; 13845 while (frames.length) { 13846 var o = this._fillRow(frames, y, img, dataFrames, pad); 13847 if (o.w > x) { x = o.w; } 13848 y += o.h; 13849 if (!o.h || !frames.length) { 13850 var canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); 13851 canvas.width = this._getSize(x,this.maxWidth); 13852 canvas.height = this._getSize(y,this.maxHeight); 13853 this._data.images[img] = canvas; 13854 if (!o.h) { 13855 x=y=0; 13856 img++; 13857 } 13858 } 13859 } 13860 }; 13861 13862 /** 13863 * @method _setupMovieClipFrame 13864 * @protected 13865 * @return {Number} The width & height of the row. 13866 **/ 13867 p._setupMovieClipFrame = function(source, data) { 13868 var ae = source.actionsEnabled; 13869 source.actionsEnabled = false;
13870 source.gotoAndStop(data.i); 13871 source.actionsEnabled = ae; 13872 data.f&&data.f(source, data.d, data.i); 13873 }; 13874 13875 /** 13876 * @method _getSize 13877 * @protected 13878 * @return {Number} The width & height of the row. 13879 **/ 13880 p._getSize = function(size,max) { 13881 var pow = 4; 13882 while (Math.pow(2,++pow) < size){} 13883 return Math.min(max,Math.pow(2,pow)); 13884 }; 13885 13886 /** 13887 * @method _fillRow 13888 * @param {Array} frames 13889 * @param {Number} y 13890 * @param {HTMLImageElement} img 13891 * @param {Object} dataFrames 13892 * @param {Number} pad 13893 * @protected 13894 * @return {Number} The width & height of the row. 13895 **/ 13896 p._fillRow = function(frames, y, img, dataFrames, pad) { 13897 var w = this.maxWidth; 13898 var maxH = this.maxHeight; 13899 y += pad; 13900 var h = maxH-y; 13901 var x = pad; 13902 var height = 0; 13903 for (var i=frames.length-1; i>=0; i--) { 13904 var frame = frames[i]; 13905 var sc = this._scale*frame.scale; 13906 var rect = frame.sourceRect; 13907 var source = frame.source; 13908 var rx = Math.floor(sc*rect.x-pad); 13909 var ry = Math.floor(sc*rect.y-pad); 13910 var rh = Math.ceil(sc*rect.height+pad*2); 13911 var rw = Math.ceil(sc*rect.width+pad*2); 13912 if (rw > w) { throw SpriteSheetBuilder.ERR_DIMENSIONS; } 13913 if (rh > h || x+rw > w) { continue; } 13914 frame.img = img; 13915 frame.rect = new createjs.Rectangle(x,y,rw,rh); 13916 height = height || rh; 13917 frames.splice(i,1); 13918 dataFrames[frame.index] = [x,y,rw,rh,img,Math.round(-rx+sc*source.regX-pad),Math.round(-ry+sc*source.regY-pad)]; 13919 x += rw; 13920 } 13921 return {w:x, h:height}; 13922 }; 13923 13924 /** 13925 * @method _endBuild 13926 * @protected 13927 **/ 13928 p._endBuild = function() { 13929 this.spriteSheet = new createjs.SpriteSheet(this._data); 13930 this._data = null; 13931 this.progress = 1; 13932 this.dispatchEvent("complete"); 13933 }; 13934 13935 /** 13936 * @method _run 13937 * @protected 13938 **/ 13939 p._run = function() { 13940 var ts = Math.max(0.01, Math.min(0.99, this.timeSlice||0.3))*50; 13941 var t = (new Date()).getTime()+ts; 13942 var complete = false; 13943 while (t > (new Date()).getTime()) { 13944 if (!this._drawNext()) { complete = true; break; } 13945 } 13946 if (complete) { 13947 this._endBuild(); 13948 } else { 13949 var _this = this; 13950 this._timerID = setTimeout(function() { _this._run(); }, 50-ts); 13951 } 13952 var p = this.progress = this._index/this._frames.length; 13953 if (this.hasEventListener("progress")) { 13954 var evt = new createjs.Event("progress"); 13955 evt.progress = p; 13956 this.dispatchEvent(evt); 13957 } 13958 }; 13959 13960 /** 13961 * @method _drawNext 13962 * @protected 13963 * @return Boolean Returns false if this is the last draw. 13964 **/ 13965 p._drawNext = function() { 13966 var frame = this._frames[this._index]; 13967 var sc = frame.scale*this._scale; 13968 var rect = frame.rect; 13969 var sourceRect = frame.sourceRect; 13970 var canvas = this._data.images[frame.img]; 13971 var ctx = canvas.getContext("2d"); 13972 frame.funct&&frame.funct(frame.source, frame.data); 13973 ctx.save(); 13974 ctx.beginPath(); 13975 ctx.rect(rect.x, rect.y, rect.width, rect.height); 13976 ctx.clip(); 13977 ctx.translate(Math.ceil(rect.x-sourceRect.x*sc), Math.ceil(rect.y-sourceRect.y*sc)); 13978 ctx.scale(sc,sc); 13979 frame.source.draw(ctx); // display object will draw itself. 13980 ctx.restore(); 13981 return (++this._index) < this._frames.length; 13982 }; 13983 13984 13985 createjs.SpriteSheetBuilder = createjs.promote(SpriteSheetBuilder, "EventDispatcher"); 13986}()); 13987 13988//############################################################################## 13989// DOMElement.js 13990//############################################################################## 13991 13992this.createjs = this.createjs||{}; 13993 13994(function() { 13995 "use strict"; 13996 13997 13998// constructor: 13999 /** 14000 * <b>This class is still experimental, and more advanced use is likely to be buggy. Please report bugs.</b> 14001 * 14002 * A DOMElement allows you to associate a HTMLElement with the display list. It will be transformed 14003 * within the DOM as though it is child of the {{#crossLink "Container"}}{{/crossLink}} it is added to. However, it is 14004 * not rendered to canvas, and as such will retain whatever z-index it has relative to the canvas (ie. it will be 14005 * drawn in front of or behind the canvas). 14006 * 14007 * The position of a DOMElement is relative to their parent node in the DOM. It is recommended that 14008 * the DOM Object be added to a div that also contains the canvas so that they share the same position 14009 * on the page. 14010 * 14011 * DOMElement is useful for positioning HTML elements over top of c
14011anvas content, and for elements 14012 * that you want to display outside the bounds of the canvas. For example, a tooltip with rich HTML 14013 * content. 14014 * 14015 * <h4>Mouse Interaction</h4> 14016 * 14017 * DOMElement instances are not full EaselJS display objects, and do not participate in EaselJS mouse 14018 * events or support methods like hitTest. To get mouse events from a DOMElement, you must instead add handlers to 14019 * the htmlElement (note, this does not support EventDispatcher) 14020 * 14021 * var domElement = new createjs.DOMElement(htmlElement); 14022 * domElement.htmlElement.onclick = function() { 14023 * console.log("clicked"); 14024 * } 14025 * 14026 * <strong>Important:</strong> This class needs to be notified it is about to be drawn, this will happen automatically 14027 * if you call stage.update, calling stage.draw or disabling tickEnabled will miss important steps and it will render 14028 * stale information. 14029 * 14030 * @class DOMElement 14031 * @extends DisplayObject 14032 * @constructor 14033 * @param {HTMLElement} htmlElement A reference or id for the DOM element to manage. 14034 */ 14035 function DOMElement(htmlElement) { 14036 this.DisplayObject_constructor(); 14037 14038 if (typeof(htmlElement)=="string") { htmlElement = document.getElementById(htmlElement); } 14039 this.mouseEnabled = false; 14040 14041 var style = htmlElement.style; 14042 style.position = "absolute"; 14043 style.transformOrigin = style.WebkitTransformOrigin = style.msTransformOrigin = style.MozTransformOrigin = style.OTransformOrigin = "0% 0%"; 14044 14045 14046 // public properties: 14047 /** 14048 * The DOM object to manage. 14049 * @property htmlElement 14050 * @type HTMLElement 14051 */ 14052 this.htmlElement = htmlElement; 14053 14054 14055 // private properties: 14056 /** 14057 * @property _oldMtx 14058 * @type Matrix2D 14059 * @protected 14060 */ 14061 this._oldProps = null; 14062 14063 /** 14064 * Used to track the object which this class attached listeners to, helps optimize listener attachment. 14065 * @property _oldStage 14066 * @type Stage 14067 * @protected 14068 */ 14069 this._oldStage = null; 14070 /** 14071 * The event listener proxy triggered drawing draw for special circumstances. 14072 * @property _drawAction 14073 * @type function 14074 * @protected 14075 */ 14076 this._drawAction = null; 14077 } 14078 var p = createjs.extend(DOMElement, createjs.DisplayObject); 14079 14080 // TODO: deprecated 14081 // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. 14082 14083 14084// public methods: 14085 /** 14086 * Returns true or false indicating whether the display object would be visible if drawn to a canvas. 14087 * This does not account for whether it would be visible within the boundaries of the stage. 14088 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 14089 * @method isVisible 14090 * @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas 14091 */ 14092 p.isVisible = function() { 14093 return this.htmlElement != null; 14094 }; 14095 14096 /** 14097 * Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform. 14098 * Returns true if the draw was handled (useful for overriding functionality). 14099 * NOTE: This method is mainly for internal use, though it may be useful for advanced uses. 14100 * @method draw 14101 * @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into. 14102 * @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache. 14103 * For example, used for drawing the cache (to prevent it from simply drawing an existing cache back 14104 * into itself). 14105 * @return {Boolean} 14106 */ 14107 p.draw = function(ctx, ignoreCache) { 14108 // this relies on the _tick method because draw isn't called if the parent is not visible. 14109 // the actual update happens in _handleDrawEnd 14110 return true; 14111 }; 14112 14113 /** 14114 * Not applicable to DOMElement. 14115 * @method cache 14116 */ 14117 p.cache = function() {}; 14118 14119 /** 14120 * Not applicable to DOMElement. 14121 * @method uncache 14122 */ 14123 p.uncache = function() {}; 14124 14125 /** 14126 * Not applicable to DOMElement. 14127 * @method updateCache 14128 */ 14129 p.updateCache = function() {}; 14130 14131 /** 14132 * Not applicable to DOMElement. 14133 * @method hitTest 14134 */ 14135 p.hitTest = function() {}; 14136 14137 /** 14138 * Not applicable to DOMElement. 14139 * @method localToGlobal 14140 */ 14141 p.localToGlobal = function() {}; 14142 14143 /** 14144 * Not applicable to DOMElement. 14145 * @method globalToLocal 14146 */ 14147 p.globalToLocal = function() {}; 14148 14149 /** 14150 * Not applicable to DOMElement. 14151 * @method localToLocal 14152 */ 14153 p.localToLocal = function() {}; 14154 14155 /** 14156 * DOMElement cannot be cloned. Throws an error. 14157 * @method clone 14158 */ 14159 p.clone = function() { 14160 throw("DOMElement cannot be cloned.") 14161 }; 14162 14163 /** 14164 * Returns a string representation of this object. 14165 * @method toString 14166 * @return {String} a string representation of the instance. 14167 */ 14168 p.toString = function() { 14169 return "[DOMElement (name="+ this.name +")]"; 14170 }; 14171 14172 /** 14173 * Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances 14174 * are not full EaselJS display objects and do not participate in EaselJS mouse events. 14175 * @event click 14176 */ 14177 14178 /** 14179 * Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances 14180 * are not full EaselJS display objects and do not participate in EaselJS mouse events. 14181 * @event dblClick 14182 */ 14183 14184 /** 14185 * Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances 14186 * are not full EaselJS display objects and do not participate in EaselJS mouse events. 14187 * @event mousedown 14188 */ 14189 14190 /** 14191 * The HTMLElement can listen for the mouseover event, not the DOMElement instance. 14192 * Since DOMElement instances are not full EaselJS display objects and do not participate in EaselJS mouse events. 14193 * @event mouseover 14194 */ 14195 14196 /** 14197 * Not applicable to DOMElement. 14198 * @event tick 14199 */ 14200 14201 14202// private methods: 14203 /** 14204 * @method _tick 14205 * @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. 14206 * function. 14207 * @protected 14208 */ 14209 p._tick = function(evtObj) { 14210 var stage = this.stage; 14211 if(stage && stage !== this._oldStage) { 14212 this._drawAction && stage.off("drawend", this._drawAction); 14213 this._drawAction = stage.on("drawend", this._handleDrawEnd, this); 14214 this._oldStage = stage; 14215 } 14216 this.DisplayObject__tick(evtObj); 14217 }; 14218 14219 /** 14220 * @method _handleDrawEnd 14221 * @param {Event} evt 14222 * @protected 14223 */ 14224 p._handleDrawEnd = function(evt) { 14225 var o = this.htmlElement; 14226 if (!o) { return; } 14227 var style = o.style; 14228 14229 var props = this.getConcatenatedDisplayProps(this._props), mtx = props.matrix; 14230 14231 var visibility = props.visible ? "visible" : "hidden"; 14232 if (visibility != style.visibility) { style.visibility = visibility; } 14233 if (!props.visible) { return; } 14234 14235 var oldProps = this._oldProps, oldMtx = oldProps&&oldProps.matrix; 14236 var n = 10000; // precision 14237 14238 if (!oldMtx || !oldMtx.equals(mtx)) {
14239 var str = "matrix(" + (mtx.a*n|0)/n +","+ (mtx.b*n|0)/n +","+ (mtx.c*n|0)/n +","+ (mtx.d*n|0)/n +","+ (mtx.tx+0.5|0); 14240 style.transform = style.WebkitTransform = style.OTransform = style.msTransform = str +","+ (mtx.ty+0.5|0) +")"; 14241 style.MozTransform = str +"px,"+ (mtx.ty+0.5|0) +"px)"; 14242 if (!oldProps) { oldProps = this._oldProps = new createjs.DisplayProps(true, null); } 14243 oldProps.matrix.copy(mtx); 14244 } 14245 14246 if (oldProps.alpha != props.alpha) { 14247 style.opacity = ""+(props.alpha*n|0)/n; 14248 oldProps.alpha = props.alpha; 14249 } 14250 }; 14251 14252 14253 createjs.DOMElement = createjs.promote(DOMElement, "DisplayObject"); 14254}()); 14255 14256//############################################################################## 14257// Filter.js 14258//############################################################################## 14259 14260this.createjs = this.createjs||{}; 14261 14262(function() { 14263 "use strict"; 14264 14265 14266// constructor: 14267 /** 14268 * Base class that all filters should inherit from. Filters need to be applied to objects that have been cached using 14269 * the {{#crossLink "DisplayObject/cache"}}{{/crossLink}} method. If an object changes, please cache it again, or use 14270 * {{#crossLink "DisplayObject/updateCache"}}{{/crossLink}}. Note that the filters must be applied before caching. 14271 * 14272 * <h4>Example</h4> 14273 * 14274 * myInstance.filters = [ 14275 * new createjs.ColorFilter(0, 0, 0, 1, 255, 0, 0), 14276 * new createjs.BlurFilter(5, 5, 10) 14277 * ]; 14278 * myInstance.cache(0,0, 100, 100); 14279 * 14280 * Note that each filter can implement a {{#crossLink "Filter/getBounds"}}{{/crossLink}} method, which returns the 14281 * margins that need to be applied in order to fully display the filter. For example, the {{#crossLink "BlurFilter"}}{{/crossLink}} 14282 * will cause an object to feather outwards, resulting in a margin around the shape. 14283 * 14284 * <h4>EaselJS Filters</h4> 14285 * EaselJS comes with a number of pre-built filters: 14286 * <ul><li>{{#crossLink "AlphaMapFilter"}}{{/crossLink}} : Map a greyscale image to the alpha channel of a display object</li> 14287 * <li>{{#crossLink "AlphaMaskFilter"}}{{/crossLink}}: Map an image's alpha channel to the alpha channel of a display object</li> 14288 * <li>{{#crossLink "BlurFilter"}}{{/crossLink}}: Apply vertical and horizontal blur to a display object</li> 14289 * <li>{{#crossLink "ColorFilter"}}{{/crossLink}}: Color transform a display object</li> 14290 * <li>{{#crossLink "ColorMatrixFilter"}}{{/crossLink}}: Transform an image using a {{#crossLink "ColorMatrix"}}{{/crossLink}}</li> 14291 * </ul> 14292 * 14293 * @class Filter 14294 * @constructor 14295 **/ 14296 function Filter() { 14297 /** 14298 * A flag stating that this filter uses a context draw mode and cannot be batched into imageData processing. 14299 * @property usesContext 14300 * @type {boolean} 14301 * @default false 14302 */ 14303 this.usesContext = false; 14304 14305 /** 14306 * Another filter that is required to act as part of this filter and created and managed under the hood. 14307 * @private 14308 * @property _multiPass 14309 * @type {Filter} 14310 * @default null 14311 */ 14312 this._multiPass = null; 14313 14314 /** 14315 * Pre-processed template shader code. It will be parsed before being fed in into the shader compiler. 14316 * This should be based upon StageGL.SHADER_VERTEX_BODY_REGULAR 14317 * @property VTX_SHADER 14318 * @virtual 14319 * @type {String} 14320 * @readonly 14321 */ 14322 this.VTX_SHADER_BODY = null; 14323 14324 /** 14325 * Pre-processed template shader code. It will be parsed before being fed in into the shader compiler. 14326 * This should be based upon StageGL.SHADER_FRAGMENT_BODY_REGULAR 14327 * @property FRAG_SHADER 14328 * @virtual 14329 * @type {String} 14330 * @readonly 14331 */ 14332 this.FRAG_SHADER_BODY = null; 14333 } 14334 var p = Filter.prototype; 14335 14336// public methods: 14337 /** 14338 * Provides padding values for this filter. That is, how much the filter will extend the visual bounds of an object it is applied to. 14339 * @method getBounds 14340 * @param {Rectangle} [rect] If specified, the provided Rectangle instance will be expanded by the padding amounts and returned. 14341 * @return {Rectangle} If a `rect` param was provided, it is returned. If not, either a new rectangle with the padding values, or null if no padding is required for this filter. 14342 **/ 14343 p.getBounds = function(rect) { 14344 return rect; 14345 }; 14346 14347 /** 14348 * Assign any unique uniforms or other setup functionality here. 14349 * @method shaderParamSetup 14350 * @virtual 14351 * @param {WebGLContext} gl The context associated with the stage performing the render. 14352 * @param {StageGL} stage The stage instance that will be rendering. 14353 * @param {ShaderProgram} shaderProgram The compiled shader that is going to be used to perform the render. 14354 */ 14355 p.shaderParamSetup = function(gl, stage, shaderProgram) {}; 14356 14357 /** 14358 * Applies the filter to the specified context. 14359 * @method applyFilter 14360 * @param {CanvasRenderingContext2D} ctx The 2D context to use as the source. 14361 * @param {Number} x The x position to use for the source rect. 14362 * @param {Number} y The y position to use for the source rect. 14363 * @param {Number} width The width to use for the source rect. 14364 * @param {Number} height The height to use for the source rect. 14365 * @param {CanvasRenderingContext2D} [targetCtx] The 2D context to draw the result to. Defaults to the context passed to ctx. 14366 * @param {Number} [targetX] The x position to draw the result to. Defaults to the value passed to x. 14367 * @param {Number} [targetY] The y position to draw the result to. Defaults to the value passed to y. 14368 * @return {Boolean} If the filter was applied successfully. 14369 **/ 14370 p.applyFilter = function(ctx, x, y, width, height, targetCtx, targetX, targetY) { 14371 // this is the default behaviour because most filters access pixel data. It is overridden when not needed. 14372 targetCtx = targetCtx || ctx; 14373 if (targetX == null) { targetX = x; } 14374 if (targetY == null) { targetY = y; } 14375 try { 14376 var imageData = ctx.getImageData(x, y, width, height); 14377 } catch (e) { 14378 return false;
14379 } 14380 if (this._applyFilter(imageData)) { 14381 targetCtx.putImageData(imageData, targetX, targetY); 14382 return true; 14383 } 14384 return false; 14385 }; 14386 14387 /** 14388 * Returns a string representation of this object. 14389 * @method toString 14390 * @return {String} a string representation of the instance. 14391 **/ 14392 p.toString = function() { 14393 return "[Filter]"; 14394 }; 14395 14396 /** 14397 * Returns a clone of this Filter instance. 14398 * @method clone 14399 * @return {Filter} A clone of the current Filter instance. 14400 **/ 14401 p.clone = function() { 14402 return new Filter(); 14403 }; 14404 14405// private methods: 14406 /** 14407 * @method _applyFilter 14408 * @param {ImageData} imageData Target ImageData instance. 14409 * @return {Boolean} 14410 **/ 14411 p._applyFilter = function(imageData) { return true; }; 14412 14413 14414 createjs.Filter = Filter; 14415}()); 14416 14417//############################################################################## 14418// BitmapCache.js 14419//############################################################################## 14420 14421this.createjs = this.createjs||{}; 14422 14423(function() { 14424 "use strict"; 14425 14426 14427// constructor: 14428 /** 14429 * The BitmapCache is an internal representation of all the cache properties and logic required in order to "cache" 14430 * an object. This information and functionality used to be located on a {{#crossLink "DisplayObject/cache"}}{{/crossLink}} 14431 * method in {{#crossLink "DisplayObject"}}{{/crossLink}}, but was moved to its own class. 14432 * 14433 * Caching in this context is purely visual, and will render the DisplayObject out into an image to be used instead 14434 * of the object. The actual cache itself is still stored on the target with the {{#crossLink "DisplayObject/cacheCanvas:property"}}{{/crossLink}}. 14435 * Working with a singular image like a {{#crossLink "Bitmap"}}{{/crossLink}} there is little benefit to performing 14436 * a cache as it is already a single image. Caching is best done on containers containing multiple complex parts that 14437 * do not move often, so that rendering the image instead will improve overall rendering speed. A cached object will 14438 * not visually update until explicitly told to do so with a call to update, much like a Stage. If a cache is being 14439 * updated every frame it is likely not improving rendering performance. Cache are best used when updates will be sparse. 14440 * 14441 * Caching is also a co-requisite for applying filters to prevent expensive filters running constantly without need, 14442 * and to physically enable some effects. The BitmapCache is also responsible for applying filters to objects and 14443 * reads each {{#crossLink "Filter"}}{{/crossLink}} due to this relationship. Real-time Filters are not recommended 14444 * performance wise when dealing with a Context2D canvas. For best performance and to still allow for some visual 14445 * effects use a compositeOperation when possible. 14446 * @class BitmapCache 14447 * @constructor 14448 **/ 14449 function BitmapCache() { 14450 14451 // public: 14452 /** 14453 * Width of the cache relative to the target object. 14454 * @property width 14455 * @protected 14456 * @type {Number} 14457 * @default undefined 14458 **/ 14459 this.width = undefined; 14460 14461 /** 14462 * Height of the cache relative to the target object. 14463 * @property height 14464 * @protected 14465 * @type {Number} 14466 * @default undefined 14467 * @todo Should the width and height be protected? 14468 **/ 14469 this.height = undefined; 14470 14471 /** 14472 * Horizontal position of the cache relative to the target's origin. 14473 * @property x 14474 * @protected 14475 * @type {Number} 14476 * @default undefined 14477 **/ 14478 this.x = undefined; 14479 14480 /** 14481 * Vertical position of the cache relative to target's origin. 14482 * @property y 14483 * @protected 14484 * @type {Number} 14485 * @default undefined 14486 **/ 14487 this.y = undefined; 14488 14489 /** 14490 * The internal scale of the cache image, does not affects display size. This is useful to both increase and
14491 * decrease render quality. Objects with increased scales are more likely to look good when scaled up or rotated. 14492 * Objects with decreased scales can save on rendering performance. 14493 * @property scale 14494 * @protected 14495 * @type {Number} 14496 * @default 1 14497 **/ 14498 this.scale = 1; 14499 14500 /** 14501 * The x offset used for drawing into the cache itself, accounts for both transforms applied. 14502 * @property offX 14503 * @protected 14504 * @type {Number} 14505 * @default 0 14506 **/ 14507 this.offX = 0; 14508 14509 /** 14510 * The y offset used for drawing into the cache itself, accounts for both transforms applied. 14511 * @property offY 14512 * @protected 14513 * @type {Number} 14514 * @default 0 14515 **/ 14516 this.offY = 0; 14517 14518 /** 14519 * Track how many times the cache has been updated, mostly used for preventing duplicate cacheURLs. 14520 * This can be useful to see if a cache has been updated. 14521 * @property cacheID 14522 * @type {Number} 14523 * @default 0 14524 **/ 14525 this.cacheID = 0; 14526 14527 // protected: 14528 /** 14529 * The relative offset of the filter's x position, used for drawing the cache onto its container. 14530 * Re-calculated every update call before drawing. 14531 * @property _filterOffY 14532 * @protected 14533 * @type {Number} 14534 * @default 0 14535 **/ 14536 this._filterOffX = 0; 14537 14538 /** 14539 * The relative offset of the filter's y position, used for drawing the cache onto its container. 14540 * Re-calculated every update call before drawing. 14541 * @property _filterOffY 14542 * @protected 14543 * @type {Number} 14544 * @default 0 14545 **/ 14546 this._filterOffY = 0; 14547 14548 /** 14549 * The cacheID when a DataURL was requested. 14550 * @property _cacheDataURLID 14551 * @protected 14552 * @type {Number} 14553 * @default 0 14554 **/ 14555 this._cacheDataURLID = 0; 14556 14557 /** 14558 * The cache's DataURL, generated on-demand using the getter. 14559 * @property _cacheDataURL 14560 * @protected 14561 * @type {String} 14562 * @default null 14563 **/ 14564 this._cacheDataURL = null; 14565 14566 /** 14567 * Internal tracking of final bounding width, approximately width*scale; however, filters can complicate the actual value. 14568 * @property _drawWidth 14569 * @protected 14570 * @type {Number} 14571 * @default 0 14572 **/ 14573 this._drawWidth = 0; 14574 14575 /** 14576 * Internal tracking of final bounding height, approximately height*scale; however, filters can complicate the actual value. 14577 * @property _drawHeight 14578 * @protected 14579 * @type {Number} 14580 * @default 0 14581 **/ 14582 this._drawHeight = 0; 14583 } 14584 var p = BitmapCache.prototype; 14585 14586 /** 14587 * Returns the bounds that surround all applied filters, relies on each filter to describe how it changes bounds. 14588 * @method getFilterBounds 14589 * @param {DisplayObject} target The object to check the filter bounds for. 14590 * @param {Rectangle} [output=null] Optional parameter, if provided then calculated bounds will be applied to that object. 14591 * @return {Rectangle} bounds object representing the bounds with filters. 14592 * @static 14593 **/ 14594 BitmapCache.getFilterBounds = function(target, output) { 14595 if(!output){ output = new createjs.Rectangle(); } 14596 var filters = target.filters; 14597 var filterCount = filters && filters.length; 14598 if (!!filterCount <= 0) { return output; } 14599 14600 for(var i=0; i<filterCount; i++) { 14601 var f = filters[i]; 14602 if(!f || !f.getBounds){ continue; } 14603 var test = f.getBounds(); 14604 if(!test){ continue; } 14605 if(i==0) { 14606 output.setValues(test.x, test.y, test.width, test.height); 14607 } else { 14608 output.extend(test.x, test.y, test.width, test.height); 14609 } 14610 } 14611 14612 return output; 14613 }; 14614 14615// public methods: 14616 /** 14617 * Returns a string representation of this object. 14618 * @method toString 14619 * @return {String} a string representation of the instance. 14620 **/ 14621 p.toString = function() { 14622 return "[BitmapCache]"; 14623 }; 14624 14625 /** 14626 * Actually create the correct cache surface and properties associated with it. Caching and it's benefits are discussed 14627 * by the {{#crossLink "DisplayObject/cache"}}{{/crossLink}} function and this class description. Here are the detailed 14628 * specifics of how to use the options object. 14629 *
14630 * - If options.useGL is set to "new" a StageGL is created and contained on this for use when rendering the cache. 14631 * - If options.useGL is set to "stage" if the current stage is a StageGL it will be used. If not then it will default to "new". 14632 * - If options.useGL is a StageGL instance it will not create one but use the one provided. 14633 * - If options.useGL is undefined a Context 2D cache will be performed. 14634 * 14635 * This means you can use any combination of StageGL and 2D with either, neither, or both the stage and cache being 14636 * WebGL. Using "new" with a StageGL display list is highly unrecommended, but still an option. It should be avoided 14637 * due to negative performance reasons and the Image loading limitation noted in the class complications above. 14638 * 14639 * When "options.useGL" is set to the parent stage of the target and WebGL, performance is increased by using 14640 * "RenderTextures" instead of canvas elements. These are internal Textures on the graphics card stored in the GPU. 14641 * Because they are no longer canvases you cannot perform operations you could with a regular canvas. The benefit 14642 * is that this avoids the slowdown of copying the texture back and forth from the GPU to a Canvas element. 14643 * This means "stage" is the recommended option when available. 14644 * 14645 * A StageGL cache does not infer the ability to draw objects a StageGL cannot currently draw, i.e. do not use a 14646 * WebGL context cache when caching a Shape, Text, etc. 14647 * <h4>WebGL cache with a 2D context</h4> 14648 * 14649 * var stage = new createjs.Stage(); 14650 * var bmp = new createjs.Bitmap(src); 14651 * bmp.cache(0, 0, bmp.width, bmp.height, 1, {gl: "new"}); // no StageGL to use, so make one 14652 * 14653 * var shape = new createjs.Shape(); 14654 * shape.graphics.clear().fill("red").drawRect(0,0,20,20); 14655 * shape.cache(0, 0, 20, 20, 1); // cannot use WebGL cache 14656 * 14657 * <h4>WebGL cache with a WebGL context</h4> 14658 * 14659 * var stageGL = new createjs.StageGL(); 14660 * var bmp = new createjs.Bitmap(src); 14661 * bmp.cache(0, 0, bmp.width, bmp.height, 1, {gl: "stage"}); // use our StageGL to cache 14662 * 14663 * var shape = new createjs.Shape(); 14664 * shape.graphics.clear().fill("red").drawRect(0,0,20,20); 14665 * shape.cache(0, 0, 20, 20, 1); // cannot use WebGL cache 14666 * 14667 * You may wish to create your own StageGL instance to control factors like clear color, transparency, AA, and 14668 * others. If you do, pass a new instance in instead of "true", the library will automatically set the 14669 * {{#crossLink "StageGL/isCacheControlled"}}{{/crossLink}} to true on your instance. This will trigger it to behave 14670 * correctly, and not assume your main context is WebGL. 14671 * 14672 * @public 14673 * @method BitmapCache.cache 14674 * @param {Number} x The x coordinate origin for the cache region. 14675 * @param {Number} y The y coordinate origin for the cache region. 14676 * @param {Number} width The width of the cache region. 14677 * @param {Number} height The height of the cache region. 14678 * @param {Number} [scale=1] The scale at which the cache will be created. For example, if you cache a vector shape 14679 * using myShape.cache(0,0,100,100,2) then the resulting cacheCanvas will be 200x200 px. This lets you scale and 14680 * rotate cached elements with greater fidelity. Default is 1. 14681 * @param {Object} [options=undefined] Specify additional parameters for the cache logic 14682 * @param {undefined|"new"|"stage"|StageGL} [options.useGL=undefined] Select whether to use context 2D, or WebGL rendering, and 14683 * whether to make a new stage instance or use an existing one. See above for extensive details on use. 14684 * @for BitmapCache 14685 */ 14686 p.define = function(target, x, y, width, height, scale, options) { 14687 if(!target){ throw "No symbol to cache"; } 14688 this._options = options; 14689 this.target = target; 14690 14691 this.width = width >= 1 ? width : 1; 14692 this.height = height >= 1 ? height : 1; 14693 this.x = x || 0; 14694 this.y = y || 0; 14695 this.scale = scale || 1; 14696 14697 this.update(); 14698 }; 14699 14700 /** 14701 * Directly called via {{#crossLink "DisplayObject/updateCache:method"}}{{/crossLink}}, but also internally. This 14702 * has the dual responsibility of making sure the surface is ready to be drawn to, and performing the draw. For 14703 * full details of each behaviour, check the protected functions {{#crossLink "BitmapCache/_updateSurface"}}{{/crossLink}} 14704 * and {{#crossLink "BitmapCache/_drawToCache"}}{{/crossLink}} respectively. 14705 * @method update 14706 * @param {String} [compositeOperation=null] The DisplayObject this cache is linked to. 14707 **/ 14708 p.update = function(compositeOperation) { 14709 if(!this.target) { throw "define() must be called before update()"; } 14710 14711 var filterBounds = BitmapCache.getFilterBounds(this.target); 14712 var surface = this.target.cacheCanvas; 14713 14714 this._drawWidth = Math.ceil(this.width*this.scale) + filterBounds.width;
14715 this._drawHeight = Math.ceil(this.height*this.scale) + filterBounds.height; 14716 14717 if(!surface || this._drawWidth != surface.width || this._drawHeight != surface.height) { 14718 this._updateSurface(); 14719 } 14720 14721 this._filterOffX = filterBounds.x; 14722 this._filterOffY = filterBounds.y; 14723 this.offX = this.x*this.scale + this._filterOffX; 14724 this.offY = this.y*this.scale + this._filterOffY; 14725 14726 this._drawToCache(compositeOperation); 14727 14728 this.cacheID = this.cacheID?this.cacheID+1:1; 14729 }; 14730 14731 /** 14732 * Reset and release all the properties and memory associated with this cache. 14733 * @method release 14734 **/ 14735 p.release = function() { 14736 if (this._webGLCache) { 14737 // if it isn't cache controlled clean up after yourself 14738 if (!this._webGLCache.isCacheControlled) { 14739 if (this.__lastRT){ this.__lastRT = undefined; } 14740 if (this.__rtA){ this._webGLCache._killTextureObject(this.__rtA); } 14741 if (this.__rtB){ this._webGLCache._killTextureObject(this.__rtB); } 14742 if (this.target && this.target.cacheCanvas){ this._webGLCache._killTextureObject(this.target.cacheCanvas); } 14743 } 14744 // set the context to none and let the garbage collector get the rest when the canvas itself gets removed 14745 this._webGLCache = false; 14746 } else { 14747 var stage = this.target.stage; 14748 if (stage instanceof createjs.StageGL){ 14749 stage.releaseTexture(this.target.cacheCanvas); 14750 } 14751 } 14752 14753 this.target = this.target.cacheCanvas = null; 14754 this.cacheID = this._cacheDataURLID = this._cacheDataURL = undefined; 14755 this.width = this.height = this.x = this.y = this.offX = this.offY = 0; 14756 this.scale = 1; 14757 }; 14758 14759 /** 14760 * Returns a data URL for the cache, or `null` if this display object is not cached. 14761 * Uses {{#crossLink "BitmapCache/cacheID:property"}}{{/crossLink}} to ensure a new data URL is not generated if the 14762 * cache has not changed. 14763 * @method getCacheDataURL 14764 * @return {String} The image data url for the cache. 14765 **/ 14766 p.getCacheDataURL = function() { 14767 var cacheCanvas = this.target && this.target.cacheCanvas; 14768 if (!cacheCanvas) { return null; } 14769 if (this.cacheID != this._cacheDataURLID) { 14770 this._cacheDataURLID = this.cacheID; 14771 this._cacheDataURL = cacheCanvas.toDataURL?cacheCanvas.toDataURL():null; // incase function is 14772 } 14773 return this._cacheDataURL; 14774 }; 14775 14776 /** 14777 * Use context2D drawing commands to display the cache canvas being used. 14778 * @method draw 14779 * @param {CanvasRenderingContext2D} ctx The context to draw into. 14780 * @return {Boolean} Whether the draw was handled successfully. 14781 **/ 14782 p.draw = function(ctx) { 14783 if(!this.target) { return false; } 14784 ctx.drawImage(this.target.cacheCanvas, 14785 this.x + (this._filterOffX/this.scale), this.y + (this._filterOffY/this.scale), 14786 this._drawWidth/this.scale, this._drawHeight/this.scale 14787 ); 14788 return true; 14789 }; 14790 14791// private methods: 14792 /** 14793 * Create or resize the invisible canvas/surface that is needed for the display object(s) to draw to, 14794 * and in turn be used in their stead when drawing. The surface is resized to the size defined 14795 * by the width and height, factoring in scaling and filters. Adjust them to adjust the output size. 14796 * @method _updateSurface 14797 * @protected 14798 **/ 14799 p._updateSurface = function() { 14800 if (!this._options || !this._options.useGL) { 14801 var surface = this.target.cacheCanvas; 14802 14803 // create it if it's missing 14804 if(!surface) { 14805 surface = this.target.cacheCanvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); 14806 } 14807 14808 // now size it 14809 surface.width = this._drawWidth; 14810 surface.height = this._drawHeight; 14811 return; 14812 } 14813 14814 // create it if it's missing 14815 if (!this._webGLCache) {
14816 if (this._options.useGL === "stage") { 14817 if(!(this.target.stage && this.target.stage.isWebGL)){ 14818 var error = "Cannot use 'stage' for cache because the object's parent stage is "; 14819 error += this.target.stage ? "non WebGL." : "not set, please addChild to the correct stage."; 14820 throw error; 14821 } 14822 this.target.cacheCanvas = true; // will be replaced with RenderTexture, temporary positive value for old "isCached" checks 14823 this._webGLCache = this.target.stage; 14824 14825 } else if(this._options.useGL === "new") { 14826 this.target.cacheCanvas = document.createElement("canvas"); // we can turn off autopurge because we wont be making textures here 14827 this._webGLCache = new createjs.StageGL(this.target.cacheCanvas, {antialias: true, transparent: true, autoPurge: -1}); 14828 this._webGLCache.isCacheControlled = true; // use this flag to control stage sizing and final output 14829 14830 } else if(this._options.useGL instanceof createjs.StageGL) { 14831 this.target.cacheCanvas = true; // will be replaced with RenderTexture, temporary positive value for old "isCached" checks 14832 this._webGLCache = this._options.useGL; 14833 this._webGLCache.isCacheControlled = true; // use this flag to control stage sizing and final output 14834 14835 } else { 14836 throw "Invalid option provided to useGL, expected ['stage', 'new', StageGL, undefined], got "+ this._options.useGL; 14837 } 14838 } 14839 14840 // now size render surfaces 14841 var surface = this.target.cacheCanvas; 14842 var stageGL = this._webGLCache; 14843 14844 // if we have a dedicated stage we've gotta size it 14845 if (stageGL.isCacheControlled) { 14846 surface.width = this._drawWidth; 14847 surface.height = this._drawHeight; 14848 stageGL.updateViewport(this._drawWidth, this._drawHeight); 14849 } 14850 if (this.target.filters) { 14851 // with filters we can't tell how many we'll need but the most we'll ever need is two, so make them now 14852 stageGL.getTargetRenderTexture(this.target, this._drawWidth,this._drawHeight); 14853 stageGL.getTargetRenderTexture(this.target, this._drawWidth,this._drawHeight); 14854 } else { 14855 // without filters then we only need one RenderTexture, and that's only if its not a dedicated stage 14856 if (!stageGL.isCacheControlled) { 14857 stageGL.getTargetRenderTexture(this.target, this._drawWidth,this._drawHeight); 14858 } 14859 } 14860 }; 14861 14862 /** 14863 * Perform the cache draw out for context 2D now that the setup properties have been performed. 14864 * @method _drawToCache 14865 * @protected 14866 **/ 14867 p._drawToCache = function(compositeOperation) { 14868 var surface = this.target.cacheCanvas; 14869 var target = this.target; 14870 var webGL = this._webGLCache; 14871 14872 if (webGL){ 14873 //TODO: auto split blur into an x/y pass 14874 webGL.cacheDraw(target, target.filters, this); 14875 14876 // we may of swapped around which element the surface is, so we re-fetch it 14877 surface = this.target.cacheCanvas; 14878 14879 surface.width = this._drawWidth; 14880 surface.height = this._drawHeight; 14881 } else { 14882 var ctx = surface.getContext("2d"); 14883 14884 if (!compositeOperation) { 14885 ctx.clearRect(0, 0, this._drawWidth+1, this._drawHeight+1); 14886 } 14887 14888 ctx.save(); 14889 ctx.globalCompositeOperation = compositeOperation; 14890 ctx.setTransform(this.scale,0,0,this.scale, -this._filterOffX,-this._filterOffY); 14891 ctx.translate(-this.x, -this.y); 14892 target.draw(ctx, true); 14893 ctx.restore(); 14894 14895 14896 if (target.filters && target.filters.length) { 14897 this._applyFilters(ctx); 14898 } 14899 } 14900 surface._invalid = true; 14901 }; 14902 14903 /** 14904 * Work through every filter and apply its individual visual transformation. 14905 * @method _applyFilters 14906 * @protected 14907 **/ 14908 p._applyFilters = function(ctx) { 14909 var filters = this.target.filters; 14910 14911 var w = this._drawWidth; 14912 var h = this._drawHeight; 14913 14914 var data; 14915
14916 var i = 0, filter = filters[i]; 14917 do { // this is safe because we wouldn't be in apply filters without a filter count of at least 1 14918 if(filter.usesContext){ 14919 if(data) { 14920 ctx.putImageData(data, 0,0); 14921 data = null; 14922 } 14923 filter.applyFilter(ctx, 0,0, w,h); 14924 } else { 14925 if(!data) { 14926 data = ctx.getImageData(0,0, w,h); 14927 } 14928 filter._applyFilter(data); 14929 } 14930 14931 // work through the multipass if it's there, otherwise move on 14932 filter = filter._multiPass !== null ? filter._multiPass : filters[++i]; 14933 } while (filter); 14934 14935 //done 14936 if(data) { 14937 ctx.putImageData(data, 0,0); 14938 } 14939 }; 14940 14941 createjs.BitmapCache = BitmapCache; 14942}()); 14943 14944//############################################################################## 14945// BlurFilter.js 14946//############################################################################## 14947 14948this.createjs = this.createjs||{}; 14949 14950(function() { 14951 "use strict"; 14952 14953 14954// constructor: 14955 /** 14956 * Applies a box blur to DisplayObjects in context 2D and a Gaussian blur in webgl. Note that this filter is fairly 14957 * intensive, particularly if the quality is set higher than 1. 14958 * 14959 * <h4>Example</h4> 14960 * This example creates a red circle, and then applies a 5 pixel blur to it. It uses the {{#crossLink "Filter/getBounds"}}{{/crossLink}} 14961 * method to account for the spread that the blur causes. 14962 * 14963 * var shape = new createjs.Shape().set({x:100,y:100}); 14964 * shape.graphics.beginFill("#ff0000").drawCircle(0,0,50); 14965 * 14966 * var blurFilter = new createjs.BlurFilter(5, 5, 1); 14967 * shape.filters = [blurFilter]; 14968 * var bounds = blurFilter.getBounds(); 14969 * 14970 * shape.cache(-50+bounds.x, -50+bounds.y, 100+bounds.width, 100+bounds.height); 14971 * 14972 * See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters. 14973 * @class BlurFilter 14974 * @extends Filter 14975 * @constructor 14976 * @param {Number} [blurX=0] The horizontal blur radius in pixels. 14977 * @param {Number} [blurY=0] The vertical blur radius in pixels. 14978 * @param {Number} [quality=1] The number of blur iterations. 14979 **/ 14980 function BlurFilter( blurX, blurY, quality) { 14981 this.Filter_constructor(); 14982 14983 // public properties: 14984 /** 14985 * Horizontal blur radius in pixels 14986 * @property blurX 14987 * @default 0 14988 * @type Number 14989 **/ 14990 this._blurX = blurX; 14991 this._blurXTable = []; 14992 this._lastBlurX = null; 14993 14994 /** 14995 * Vertical blur radius in pixels 14996 * @property blurY 14997 * @default 0 14998 * @type Number 14999 **/ 15000 this._blurY = blurY; 15001 this._blurYTable = []; 15002 this._lastBlurY = null; 15003 15004 /** 15005 * Number of blur iterations. For example, a value of 1 will produce a rough blur. A value of 2 will produce a 15006 * smoother blur, but take twice as long to run. 15007 * @property quality 15008 * @default 1 15009 * @type Number 15010 **/ 15011 this._quality; 15012 this._lastQuality = null; 15013 15014 /** 15015 * This is a template to generate the shader for {{#crossLink FRAG_SHADER_BODY}}{{/crossLink}} 15016 */ 15017 this.FRAG_SHADER_TEMPLATE = ( 15018 "uniform float xWeight[{{blurX}}];" + 15019 "uniform float yWeight[{{blurY}}];" + 15020 "uniform vec2 textureOffset;" + 15021 "void main(void) {" + 15022 "vec4 color = vec4(0.0);" + 15023 15024 "float xAdj = ({{blurX}}.0-1.0)/2.0;" + 15025 "float yAdj = ({{blurY}}.0-1.0)/2.0;" + 15026 "vec2 sampleOffset;" + 15027 15028 "for(int i=0; i<{{blurX}}; i++) {" + 15029 "for(int j=0; j<{{blurY}}; j++) {" + 15030 "sampleOffset = vRenderCoord + (textureOffset * vec2(float(i)-xAdj, float(j)-yAdj));" + 15031 "color += texture2D(uSampler, sampleOffset) * (xWeight[i] * yWeight[j]);" + 15032 "}" + 15033 "}" + 15034 15035 "gl_FragColor = color.rgba;" + 15036 "}" 15037 ); 15038 15039 // update the filter using the setters 15040 if(isNaN(quality) || quality < 1){ quality = 1; } 15041 this.setQuality(quality|0); 15042 } 15043 var p = createjs.extend(BlurFilter, createjs.Filter); 15044 15045 // TODO: deprecated 15046 // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. 15047 15048 p.getBlurX = function() { return this._blurX; }; 15049 p.getBlurY = function() { return this._blurY; }; 15050 p.setBlurX = function(value) { 15051 if(isNaN(value) || value < 0){ value = 0; } 15052 this._blurX = value; 15053 }; 15054 p.setBlurY = function(value) { 15055 if(isNaN(value) || value < 0){ value = 0; } 15056 this._blurY = value; 15057 }; 15058 p.getQuality = function() { return this._quality; }; 15059 p.setQuality = function(value) { 15060 if(isNaN(value) || value < 0){ value = 0; } 15061 this._quality = value | 0; 15062 }; 15063 p._getShader = function() { 15064 var xChange = this._lastBlurX !== this._blurX; 15065 var yChange = this._lastBlurY !== this._blurY; 15066 var qChange = this._lastQuality !== this._quality; 15067 if(xChange || yChange || qChange) { 15068 if(xChange || qChange) { this._blurXTable = this._getTable(this._blurX * this._quality); } 15069 if(yChange || qChange) { this._blurYTable = this._getTable(this._blurY * this._quality); } 15070 this._updateShader(); 15071 this._lastBlurX = this._blurX; 15072 this._lastBlurY = this._blurY; 15073 this._lastQuality = this._quality; 15074 return undefined; // force a rebuild 15075 } 15076 return this._compiledShader; 15077 }; 15078 p._setShader = function() { this._compiledShader; }; 15079 15080 try { 15081 Object.defineProperties(p, { 15082 blurX: { get: p.getBlurX, set: p.setBlurX }, 15083 blurY: { get: p.getBlurY, set: p.setBlurY }, 15084 quality: { get: p.getQuality, set: p.setQuality }, 15085 _builtShader: { get: p._getShader, set: p._setShader} 15086 }); 15087 } catch (e) { console.log(e); } 15088 15089 /** 15090 * Internal lookup function to create gaussian distribution. 15091 * @method _getTable 15092 * @param {Number} spread How many steps in the curve. 15093 * @return {Array<Number>} An array with Math.ceil(spread*2) entries with appropriately distributed weights. 15094 */ 15095 p._getTable = function(spread) { 15096 var EDGE = 4.2; 15097 if(spread<=1) { return [1]; } 15098 15099 var result = [];
15100 var count = Math.ceil(spread*2); 15101 count += (count%2)?0:1; 15102 var adjust = (count/2)|0; 15103 for(var i = -adjust; i<=adjust; i++) { 15104 var x = (i/adjust)*EDGE; 15105 result.push(1/Math.sqrt(2*Math.PI) * Math.pow(Math.E, -(Math.pow(x,2)/4))); 15106 } 15107 var factor = result.reduce(function(a, b) { return a + b; }); 15108 return result.map(function(currentValue, index, array) { return currentValue/factor; }); 15109 }; 15110 15111 /** 15112 * Internal update function to create shader properties. 15113 * @method _updateShader 15114 */ 15115 p._updateShader = function() { 15116 if(this._blurX === undefined || this._blurY === undefined){ return; } 15117 var result = this.FRAG_SHADER_TEMPLATE; 15118 result = result.replace(/\{\{blurX\}\}/g, (this._blurXTable.length).toFixed(0)); 15119 result = result.replace(/\{\{blurY\}\}/g, (this._blurYTable.length).toFixed(0)); 15120 this.FRAG_SHADER_BODY = result; 15121 }; 15122 15123 /** docced in super class **/ 15124 p.shaderParamSetup = function(gl, stage, shaderProgram) { 15125 // load the normalized gaussian weight tables 15126 gl.uniform1fv( 15127 gl.getUniformLocation(shaderProgram, "xWeight"), 15128 this._blurXTable 15129 ); 15130 gl.uniform1fv( 15131 gl.getUniformLocation(shaderProgram, "yWeight"), 15132 this._blurYTable 15133 ); 15134 15135 // what is the size of a single pixel in -1, 1 (webGL) space 15136 gl.uniform2f( 15137 gl.getUniformLocation(shaderProgram, "textureOffset"), 15138 2/(stage._viewportWidth*this._quality), 2/(stage._viewportHeight*this._quality) 15139 ); 15140 }; 15141 15142// constants: 15143 /** 15144 * Array of multiply values for blur calculations. 15145 * @property MUL_TABLE 15146 * @type Array 15147 * @protected 15148 * @static 15149 **/ 15150 BlurFilter.MUL_TABLE = [1, 171, 205, 293, 57, 373, 79, 137, 241, 27, 391, 357, 41, 19, 283, 265, 497, 469, 443, 421, 25, 191, 365, 349, 335, 161, 155, 149, 9, 278, 269, 261, 505, 245, 475, 231, 449, 437, 213, 415, 405, 395, 193, 377, 369, 361, 353, 345, 169, 331, 325, 319, 313, 307, 301, 37, 145, 285, 281, 69, 271, 267, 263, 259, 509, 501, 493, 243, 479, 118, 465, 459, 113, 446, 55, 435, 429, 423, 209, 413, 51, 403, 199, 393, 97, 3, 379, 375, 371, 367, 363, 359, 355, 351, 347, 43, 85, 337, 333, 165, 327, 323, 5, 317, 157, 311, 77, 305, 303, 75, 297, 294, 73, 289, 287, 71, 141, 279, 277, 275, 68, 135, 67, 133, 33, 262, 260, 129, 511, 507, 503, 499, 495, 491, 61, 121, 481, 477, 237, 235, 467, 232, 115, 457, 227, 451, 7, 445, 221, 439, 218, 433, 215, 427, 425, 211, 419, 417, 207, 411, 409, 203, 202, 401, 399, 396, 197, 49, 389, 387, 385, 383, 95, 189, 47, 187, 93, 185, 23, 183, 91, 181, 45, 179, 89, 177, 11, 175, 87, 173, 345, 343, 341, 339, 337, 21, 167, 83, 331, 329, 327, 163, 81, 323, 321, 319, 159, 79, 315, 313, 39, 155, 309, 307, 153, 305, 303, 151, 75, 299, 149, 37, 295, 147, 73, 291, 145, 289, 287, 143, 285, 71, 141, 281, 35, 279, 139, 69, 275, 137, 273, 17, 271, 135, 269, 267, 133, 265, 33, 263, 131, 261, 130, 259, 129, 257, 1]; 15151 15152 /** 15153 * Array of shift values for blur calculations. 15154 * @property SHG_TABLE 15155 * @type Array 15156 * @protected 15157 * @static 15158 **/ 15159 BlurFilter.SHG_TABLE = [0, 9, 10, 11, 9, 12, 10, 11, 12, 9, 13, 13, 10, 9, 13, 13, 14, 14, 14, 14, 10, 13, 14, 14, 14, 13, 13, 13, 9, 14, 14, 14, 15, 14, 15, 14, 15, 15, 14, 15, 15, 15, 14, 15, 15, 15, 15, 15, 14, 15, 15, 15, 15, 15, 15, 12, 14, 15, 15, 13, 15, 15, 15, 15, 16, 16, 16, 15, 16, 14, 16, 16, 14, 16, 13, 16, 16, 16, 15, 16, 13, 16, 15, 16, 14, 9, 16, 16, 16, 16, 16, 16, 16, 16, 16, 13, 14, 16, 16, 15, 16, 16, 10, 16, 15, 16, 14, 16, 16, 14, 16, 16, 14, 16, 16, 14, 15, 16, 16, 16, 14, 15, 14, 15, 13, 16, 16, 15, 17, 17, 17, 17, 17, 17, 14, 15, 17, 17, 16, 16, 17, 16, 15, 17, 16, 17, 11, 17, 16, 17, 16, 17, 16, 17, 17, 16, 17, 17, 16, 17, 17, 16, 16, 17, 17, 17, 16, 14, 17, 17, 17, 17, 15, 16, 14, 16, 15, 16, 13, 16, 15, 16, 14, 16, 15, 16, 12, 16, 15, 16, 17, 17, 17, 17, 17, 13, 16, 15, 17, 17, 17, 16, 15, 17, 17, 17, 16, 15, 17, 17, 14, 16, 17, 17, 16, 17, 17, 16, 15, 17, 16, 14, 17, 16, 15, 17, 16, 17, 17, 16, 17, 15, 16, 17, 14, 17, 16, 15, 17, 16, 17, 13, 17, 16, 17, 17, 16, 17, 14, 17, 16, 17, 16, 17, 16, 17, 9]; 15160 15161// public methods: 15162 /** docced in super class **/ 15163 p.getBounds = function (rect) { 15164 var x = this.blurX|0, y = this.blurY| 0; 15165 if(x <= 0 && y <= 0) { return rect; }
15166 var q = Math.pow(this.quality, 0.2); 15167 return (rect || new createjs.Rectangle()).pad(y*q+1,x*q+1,y*q+1,x*q+1); 15168 }; 15169 15170 /** docced in super class **/ 15171 p.clone = function() { 15172 return new BlurFilter(this.blurX, this.blurY, this.quality); 15173 }; 15174 15175 /** docced in super class **/ 15176 p.toString = function() { 15177 return "[BlurFilter]"; 15178 }; 15179 15180 15181// private methods: 15182 15183 /** docced in super class **/ 15184 p._applyFilter = function (imageData) { 15185 var radiusX = this._blurX >> 1; 15186 if (isNaN(radiusX) || radiusX < 0) return false; 15187 var radiusY = this._blurY >> 1; 15188 if (isNaN(radiusY) || radiusY < 0) return false; 15189 if (radiusX == 0 && radiusY == 0) return false; 15190 15191 var iterations = this.quality; 15192 if (isNaN(iterations) || iterations < 1) iterations = 1; 15193 iterations |= 0; 15194 if (iterations > 3) iterations = 3; 15195 if (iterations < 1) iterations = 1; 15196 15197 var px = imageData.data; 15198 var x=0, y=0, i=0, p=0, yp=0, yi=0, yw=0, r=0, g=0, b=0, a=0, pr=0, pg=0, pb=0, pa=0; 15199 15200 var divx = (radiusX + radiusX + 1) | 0; 15201 var divy = (radiusY + radiusY + 1) | 0; 15202 var w = imageData.width | 0; 15203 var h = imageData.height | 0; 15204 15205 var w1 = (w - 1) | 0; 15206 var h1 = (h - 1) | 0; 15207 var rxp1 = (radiusX + 1) | 0; 15208 var ryp1 = (radiusY + 1) | 0; 15209 15210 var ssx = {r:0,b:0,g:0,a:0}; 15211 var sx = ssx; 15212 for ( i = 1; i < divx; i++ ) 15213 { 15214 sx = sx.n = {r:0,b:0,g:0,a:0}; 15215 } 15216 sx.n = ssx; 15217 15218 var ssy = {r:0,b:0,g:0,a:0}; 15219 var sy = ssy; 15220 for ( i = 1; i < divy; i++ ) 15221 { 15222 sy = sy.n = {r:0,b:0,g:0,a:0}; 15223 } 15224 sy.n = ssy; 15225 15226 var si = null; 15227 15228 15229 var mtx = BlurFilter.MUL_TABLE[radiusX] | 0; 15230 var stx = BlurFilter.SHG_TABLE[radiusX] | 0; 15231 var mty = BlurFilter.MUL_TABLE[radiusY] | 0; 15232 var sty = BlurFilter.SHG_TABLE[radiusY] | 0; 15233 15234 while (iterations-- > 0) { 15235 15236 yw = yi = 0; 15237 var ms = mtx; 15238 var ss = stx; 15239 for (y = h; --y > -1;) { 15240 r = rxp1 * (pr = px[(yi) | 0]); 15241 g = rxp1 * (pg = px[(yi + 1) | 0]); 15242 b = rxp1 * (pb = px[(yi + 2) | 0]); 15243 a = rxp1 * (pa = px[(yi + 3) | 0]); 15244 15245 sx = ssx; 15246 15247 for( i = rxp1; --i > -1; ) 15248 { 15249 sx.r = pr; 15250 sx.g = pg; 15251 sx.b = pb; 15252 sx.a = pa; 15253 sx = sx.n; 15254 } 15255 15256 for( i = 1; i < rxp1; i++ ) 15257 { 15258 p = (yi + ((w1 < i ? w1 : i) << 2)) | 0; 15259 r += ( sx.r = px[p]); 15260 g += ( sx.g = px[p+1]); 15261 b += ( sx.b = px[p+2]); 15262 a += ( sx.a = px[p+3]); 15263 15264 sx = sx.n; 15265 } 15266 15267 si = ssx; 15268 for ( x = 0; x < w; x++ ) 15269 { 15270 px[yi++] = (r * ms) >>> ss; 15271 px[yi++] = (g * ms) >>> ss; 15272 px[yi++] = (b * ms) >>> ss; 15273 px[yi++] = (a * ms) >>> ss; 15274 15275 p = ((yw + ((p = x + radiusX + 1) < w1 ? p : w1)) << 2); 15276 15277 r -= si.r - ( si.r = px[p]); 15278 g -= si.g - ( si.g = px[p+1]); 15279 b -= si.b - ( si.b = px[p+2]); 15280 a -= si.a - ( si.a = px[p+3]); 15281 15282 si = si.n; 15283 15284 } 15285 yw += w; 15286 } 15287 15288 ms = mty; 15289 ss = sty; 15290 for (x = 0; x < w; x++) { 15291 yi = (x << 2) | 0; 15292 15293 r = (ryp1 * (pr = px[yi])) | 0; 15294 g = (ryp1 * (pg = px[(yi + 1) | 0])) | 0; 15295 b = (ryp1 * (pb = px[(yi + 2) | 0])) | 0; 15296 a = (ryp1 * (pa = px[(yi + 3) | 0])) | 0; 15297 15298 sy = ssy; 15299 for( i = 0; i < ryp1; i++ ) 15300 { 15301 sy.r = pr; 15302 sy.g = pg; 15303 sy.b = pb; 15304 sy.a = pa; 15305 sy = sy.n; 15306 } 15307 15308 yp = w; 15309 15310 for( i = 1; i <= radiusY; i++ ) 15311 { 15312 yi = ( yp + x ) << 2; 15313 15314 r += ( sy.r = px[yi]); 15315 g += ( sy.g = px[yi+1]); 15316 b += ( sy.b = px[yi+2]); 15317 a += ( sy.a = px[yi+3]); 15318 15319 sy = sy.n; 15320 15321 if( i < h1 ) 15322 { 15323 yp += w; 15324 } 15325 } 15326 15327 yi = x; 15328 si = ssy; 15329 if ( iterations > 0 ) 15330 { 15331 for ( y = 0; y < h; y++ ) 15332 { 15333 p = yi << 2; 15334 px[p+3] = pa =(a * ms) >>> ss; 15335 if ( pa > 0 ) 15336 { 15337 px[p] = ((r * ms) >>> ss ); 15338 px[p+1] = ((g * ms) >>> ss ); 15339 px[p+2] = ((b * ms) >>> ss ); 15340 } else { 15341 px[p] = px[p+1] = px[p+2] = 0 15342 } 15343 15344 p = ( x + (( ( p = y + ryp1) < h1 ? p : h1 ) * w )) << 2; 15345 15346 r -= si.r - ( si.r = px[p]); 15347 g -= si.g - ( si.g = px[p+1]); 15348 b -= si.b - ( si.b = px[p+2]); 15349 a -= si.a - ( si.a = px[p+3]); 15350 15351 si = si.n; 15352 15353 yi += w; 15354 } 15355 } else { 15356 for ( y = 0; y < h; y++ ) 15357 { 15358 p = yi << 2; 15359 px[p+3] = pa =(a * ms) >>> ss; 15360 if ( pa > 0 ) 15361 { 15362 pa = 255 / pa; 15363 px[p] = ((r * ms) >>> ss ) * pa; 15364 px[p+1] = ((g * ms) >>> ss ) * pa; 15365 px[p+2] = ((b * ms) >>> ss ) * pa; 15366 } else { 15367 px[p] = px[p+1] = px[p+2] = 0 15368 } 15369 15370 p = ( x + (( ( p = y + ryp1) < h1 ? p : h1 ) * w )) << 2; 15371 15372 r -= si.r - ( si.r = px[p]); 15373 g -= si.g - ( si.g = px[p+1]); 15374 b -= si.b - ( si.b = px[p+2]); 15375 a -= si.a - ( si.a = px[p+3]); 15376 15377 si = si.n; 15378 15379 yi += w; 15380 } 15381 } 15382 } 15383 15384 } 15385 return true; 15386 }; 15387 15388 createjs.BlurFilter = createjs.promote(BlurFilter, "Filter"); 15389}()); 15390 15391//############################################################################## 15392// AlphaMapFilter.js 15393//############################################################################## 15394 15395this.createjs = this.createjs || {}; 15396 15397(function () { 15398 "use strict"; 15399 15400 15401// constructor: 15402 /**
15403 * Applies a greyscale alpha map image (or canvas) to the target, such that the alpha channel of the result will 15404 * be copied from the red channel of the map, and the RGB channels will be copied from the target. 15405 * 15406 * Generally, it is recommended that you use {{#crossLink "AlphaMaskFilter"}}{{/crossLink}}, because it has much 15407 * better performance. 15408 * 15409 * <h4>Example</h4> 15410 * This example draws a red->blue box, caches it, and then uses the cache canvas as an alpha map on a 100x100 image. 15411 * 15412 * var box = new createjs.Shape(); 15413 * box.graphics.beginLinearGradientFill(["#ff0000", "#0000ff"], [0, 1], 0, 0, 0, 100) 15414 * box.graphics.drawRect(0, 0, 100, 100); 15415 * box.cache(0, 0, 100, 100); 15416 * 15417 * var bmp = new createjs.Bitmap("path/to/image.jpg"); 15418 * bmp.filters = [ 15419 * new createjs.AlphaMapFilter(box.cacheCanvas) 15420 * ]; 15421 * bmp.cache(0, 0, 100, 100); 15422 * stage.addChild(bmp); 15423 * 15424 * See {{#crossLink "Filter"}}{{/crossLink}} for more information on applying filters. 15425 * @class AlphaMapFilter 15426 * @extends Filter 15427 * @constructor 15428 * @param {HTMLImageElement|HTMLCanvasElement} alphaMap The greyscale image (or canvas) to use as the alpha value for the 15429 * result. This should be exactly the same dimensions as the target. 15430 **/ 15431 function AlphaMapFilter(alphaMap) { 15432 this.Filter_constructor(); 15433 15434 // public properties: 15435 /** 15436 * The greyscale image (or canvas) to use as the alpha value for the result. This should be exactly the same 15437 * dimensions as the target. 15438 * @property alphaMap 15439 * @type HTMLImageElement|HTMLCanvasElement 15440 **/ 15441 this.alphaMap = alphaMap; 15442 15443 15444 // private properties: 15445 /** 15446 * @property _alphaMap 15447 * @protected 15448 * @type HTMLImageElement|HTMLCanvasElement 15449 **/ 15450 this._alphaMap = null; 15451 15452 /** 15453 * @property _mapData 15454 * @protected 15455 * @type Uint8ClampedArray 15456 **/ 15457 this._mapData = null; 15458 this._mapTexture = null; 15459 15460 this.FRAG_SHADER_BODY = ( 15461 "uniform sampler2D uAlphaSampler;"+ 15462 15463 "void main(void) {" + 15464 "vec4 color = texture2D(uSampler, vRenderCoord);" + 15465 "vec4 alphaMap = texture2D(uAlphaSampler, vTextureCoord);" + 15466 15467 // some image formats can have transparent white rgba(1,1,1, 0) when put on the GPU, this means we need a slight tweak 15468 // using ceil ensure that the colour will be used so long as it exists but pure transparency will be treated black 15469 "gl_FragColor = vec4(color.rgb, color.a * (alphaMap.r * ceil(alphaMap.a)));" + 15470 "}" 15471 ); 15472 } 15473 var p = createjs.extend(AlphaMapFilter, createjs.Filter); 15474 15475 // TODO: deprecated 15476 // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. 15477 15478 /** docced in super class **/ 15479 p.shaderParamSetup = function(gl, stage, shaderProgram) { 15480 if(!this._mapTexture) { this._mapTexture = gl.createTexture(); } 15481 15482 gl.activeTexture(gl.TEXTURE1); 15483 gl.bindTexture(gl.TEXTURE_2D, this._mapTexture); 15484 stage.setTextureParams(gl); 15485 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.alphaMap); 15486 15487 gl.uniform1i( 15488 gl.getUniformLocation(shaderProgram, "uAlphaSampler"), 15489 1 15490 ); 15491 }; 15492 15493// public methods: 15494 /** docced in super class **/ 15495 p.clone = function () { 15496 var o = new AlphaMapFilter(this.alphaMap); 15497 o._alphaMap = this._alphaMap; 15498 o._mapData = this._mapData; 15499 return o; 15500 }; 15501 15502 /** docced in super class **/ 15503 p.toString = function () { 15504 return "[AlphaMapFilter]"; 15505 }; 15506 15507 15508// private methods: 15509 /** docced in super class **/ 15510 p._applyFilter = function (imageData) { 15511 if (!this.alphaMap) { return true; } 15512 if (!this._prepAlphaMap()) { return false; } 15513
15514 // TODO: update to support scenarios where the target has different dimensions. 15515 var data = imageData.data; 15516 var map = this._mapData; 15517 for(var i=0, l=data.length; i<l; i += 4) { data[i + 3] = map[i] || 0; } 15518 15519 return true; 15520 }; 15521 15522 /** 15523 * @method _prepAlphaMap 15524 * @protected 15525 **/ 15526 p._prepAlphaMap = function () { 15527 if (!this.alphaMap) { return false; } 15528 if (this.alphaMap == this._alphaMap && this._mapData) { return true; } 15529 15530 this._mapData = null; 15531 var map = this._alphaMap = this.alphaMap; 15532 var canvas = map; 15533 var ctx; 15534 if (map instanceof HTMLCanvasElement) { 15535 ctx = canvas.getContext("2d"); 15536 } else { 15537 canvas = createjs.createCanvas ? createjs.createCanvas() : document.createElement("canvas"); 15538 canvas.width = map.width; 15539 canvas.height = map.height; 15540 ctx = canvas.getContext("2d"); 15541 ctx.drawImage(map, 0, 0); 15542 } 15543 15544 try { 15545 var imgData = ctx.getImageData(0, 0, map.width, map.height); 15546 } catch (e) { 15547 //if (!this.suppressCrossDomainErrors) throw new Error("unable to access local image data: " + e); 15548 return false; 15549 } 15550 15551 this._mapData = imgData.data; 15552 return true; 15553 }; 15554 15555 15556 createjs.AlphaMapFilter = createjs.promote(AlphaMapFilter, "Filter"); 15557}()); 15558 15559//############################################################################## 15560// AlphaMaskFilter.js 15561//############################################################################## 15562 15563this.createjs = this.createjs || {}; 15564 15565(function () { 15566 "use strict"; 15567 15568 15569// constructor: 15570 /** 15571 * Applies the alpha from the mask image (or canvas) to the target, such that the alpha channel of the result will 15572 * be derived from the mask, and the RGB channels will be copied from the target. This can be used, for example, to 15573 * apply an alpha mask to a display object. This can also be used to combine a JPG compressed RGB image with a PNG32 15574 * alpha mask, which can result in a much smaller file size than a single PNG32 containing ARGB. 15575 * 15576 * <b>IMPORTANT NOTE: This filter currently does not support the targetCtx, or targetX/Y parameters correctly.</b> 15577 * 15578 * <h4>Example</h4> 15579 * This example draws a gradient box, then caches it and uses the "cacheCanvas" as the alpha mask on a 100x100 image. 15580 * 15581 * var box = new createjs.Shape(); 15582 * box.graphics.beginLinearGradientFill(["#000000", "rgba(0, 0, 0, 0)"], [0, 1], 0, 0, 100, 100) 15583 * box.graphics.drawRect(0, 0, 100, 100); 15584 * box.cache(0, 0, 100, 100); 15585 * 15586 * var bmp = new createjs.Bitmap("path/to/image.jpg"); 15587 * bmp.filters = [ 15588 * new createjs.AlphaMaskFilter(box.cacheCanvas) 15589 * ]; 15590 * bmp.cache(0, 0, 100, 100); 15591 * 15592 * See {{#crossLink "Filter"}}{{/crossLink}} for more information on applying filters. 15593 * @class AlphaMaskFilter 15594 * @extends Filter 15595 * @constructor 15596 * @param {HTMLImageElement|HTMLCanvasElement} mask 15597 **/ 15598 function AlphaMaskFilter(mask) { 15599 this.Filter_constructor(); 15600 15601 // public properties: 15602 /** 15603 * The image (or canvas) to use as the mask. 15604 * @property mask 15605 * @type HTMLImageElement|HTMLCanvasElement 15606 **/ 15607 this.mask = mask; 15608 15609 /** docced in super class **/ 15610 this.usesContext = true; 15611 15612 this.FRAG_SHADER_BODY = ( 15613 "uniform sampler2D uAlphaSampler;"+ 15614 15615 "void main(void) {" + 15616 "vec4 color = texture2D(uSampler, vRenderCoord);" + 15617 "vec4 alphaMap = texture2D(uAlphaSampler, vTextureCoord);" + 15618 15619 "gl_FragColor = vec4(color.rgb, color.a * alphaMap.a);" + 15620 "}" 15621 ); 15622 } 15623 var p = createjs.extend(AlphaMaskFilter, createjs.Filter); 15624 15625 // TODO: deprecated 15626 // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. 15627 15628 /** docced in super class **/ 15629 p.shaderParamSetup = function(gl, stage, shaderProgram) { 15630 if(!this._mapTexture) { this._mapTexture = gl.createTexture(); } 15631 15632 gl.activeTexture(gl.TEXTURE1); 15633 gl.bindTexture(gl.TEXTURE_2D, this._mapTexture);
15634 stage.setTextureParams(gl); 15635 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.mask); 15636 15637 gl.uniform1i( 15638 gl.getUniformLocation(shaderProgram, "uAlphaSampler"), 15639 1 15640 ); 15641 }; 15642 15643// public methods: 15644 /** 15645 * Applies the filter to the specified context. 15646 * 15647 * <strong>IMPORTANT NOTE: This filter currently does not support the targetCtx, or targetX/Y parameters 15648 * correctly.</strong> 15649 * @method applyFilter 15650 * @param {CanvasRenderingContext2D} ctx The 2D context to use as the source. 15651 * @param {Number} x The x position to use for the source rect. 15652 * @param {Number} y The y position to use for the source rect. 15653 * @param {Number} width The width to use for the source rect. 15654 * @param {Number} height The height to use for the source rect. 15655 * @param {CanvasRenderingContext2D} [targetCtx] NOT SUPPORTED IN THIS FILTER. The 2D context to draw the result to. Defaults to the context passed to ctx. 15656 * @param {Number} [targetX] NOT SUPPORTED IN THIS FILTER. The x position to draw the result to. Defaults to the value passed to x. 15657 * @param {Number} [targetY] NOT SUPPORTED IN THIS FILTER. The y position to draw the result to. Defaults to the value passed to y. 15658 * @return {Boolean} If the filter was applied successfully. 15659 **/ 15660 p.applyFilter = function (ctx, x, y, width, height, targetCtx, targetX, targetY) { 15661 if (!this.mask) { return true; } 15662 targetCtx = targetCtx || ctx; 15663 if (targetX == null) { targetX = x; } 15664 if (targetY == null) { targetY = y; } 15665 15666 targetCtx.save(); 15667 if (ctx != targetCtx) { 15668 // TODO: support targetCtx and targetX/Y 15669 // clearRect, then draw the ctx in? 15670 return false; 15671 } 15672 15673 targetCtx.globalCompositeOperation = "destination-in"; 15674 targetCtx.drawImage(this.mask, targetX, targetY); 15675 targetCtx.restore(); 15676 return true; 15677 }; 15678 15679 /** docced in super class **/ 15680 p.clone = function () { 15681 return new AlphaMaskFilter(this.mask); 15682 }; 15683 15684 /** docced in super class **/ 15685 p.toString = function () { 15686 return "[AlphaMaskFilter]"; 15687 }; 15688 15689 15690 createjs.AlphaMaskFilter = createjs.promote(AlphaMaskFilter, "Filter"); 15691}()); 15692 15693//############################################################################## 15694// ColorFilter.js 15695//############################################################################## 15696 15697this.createjs = this.createjs||{}; 15698 15699(function() { 15700 "use strict"; 15701 15702 15703// constructor: 15704 /** 15705 * Applies a color transform to DisplayObjects. 15706 * 15707 * <h4>Example</h4> 15708 * This example draws a red circle, and then transforms it to Blue. This is accomplished by multiplying all the channels 15709 * to 0 (except alpha, which is set to 1), and then adding 255 to the blue channel. 15710 * 15711 * var shape = new createjs.Shape().set({x:100,y:100}); 15712 * shape.graphics.beginFill("#ff0000").drawCircle(0,0,50); 15713 * 15714 * shape.filters = [ 15715 * new createjs.ColorFilter(0,0,0,1, 0,0,255,0) 15716 * ]; 15717 * shape.cache(-50, -50, 100, 100); 15718 * 15719 * See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters. 15720 * @class ColorFilter 15721 * @param {Number} [redMultiplier=1] The amount to multiply against the red channel. This is a range between 0 and 1. 15722 * @param {Number} [greenMultiplier=1] The amount to multiply against the green channel. This is a range between 0 and 1. 15723 * @param {Number} [blueMultiplier=1] The amount to multiply against the blue channel. This is a range between 0 and 1. 15724 * @param {Number} [alphaMultiplier=1] The amount to multiply against the alpha channel. This is a range between 0 and 1. 15725 * @param {Number} [redOffset=0] The amount to add to the red channel after it has been multiplied. This is a range 15726 * between -255 and 255. 15727 * @param {Number} [greenOffset=0] The amount to add to the green channel after it has been multiplied. This is a range 15728 * between -255 and 255. 15729 * @param {Number} [blueOffset=0] The amount to add to the blue channel after it has been multiplied. This is a range 15730 * between -255 and 255. 15731 * @param {Number} [alphaOffset=0] The amount to add to the alpha channel after it has been multiplied. This is a range 15732 * between -255 and 255. 15733 * @constructor 15734 * @extends Filter 15735 **/ 15736 function ColorFilter(redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier, redOffset, greenOffset, blueOffset, alphaOffset) { 15737 this.Filter_constructor(); 15738 15739 // public properties: 15740 /** 15741 * Red channel multiplier. 15742 * @property redMultiplier 15743 * @type Number 15744 **/ 15745 this.redMultiplier = redMultiplier != null ? redMultiplier : 1; 15746 15747 /** 15748 * Green channel multiplier. 15749 * @property greenMultiplier 15750 * @type Number 15751 **/ 15752 this.greenMultiplier = greenMultiplier != null ? greenMultiplier : 1; 15753 15754 /** 15755 * Blue channel multiplier. 15756 * @property blueMultiplier 15757 * @type Number 15758 **/ 15759 this.blueMultiplier = blueMultiplier != null ? blueMultiplier : 1; 15760 15761 /** 15762 * Alpha channel multiplier. 15763 * @property alphaMultiplier 15764 * @type Number 15765 **/ 15766 this.alphaMultiplier = alphaMultiplier != null ? alphaMultiplier : 1; 15767 15768 /** 15769 * Red channel offset (added to value). 15770 * @property redOffset 15771 * @type Number 15772 **/ 15773 this.redOffset = redOffset || 0; 15774 15775 /** 15776 * Green channel offset (added to value). 15777 * @property greenOffset 15778 * @type Number 15779 **/ 15780 this.greenOffset = greenOffset || 0; 15781 15782 /** 15783 * Blue channel offset (added to value). 15784 * @property blueOffset 15785 * @type Number 15786 **/ 15787 this.blueOffset = blueOffset || 0; 15788 15789 /** 15790 * Alpha channel offset (added to value). 15791 * @property alphaOffset 15792 * @type Number 15793 **/ 15794 this.alphaOffset = alphaOffset || 0; 15795 15796 this.FRAG_SHADER_BODY = ( 15797 "uniform vec4 uColorMultiplier;" + 15798 "uniform vec4 uColorOffset;" + 15799 15800 "void main(void) {" + 15801 "vec4 color = texture2D(uSampler, vRenderCoord);" + 15802 15803 "gl_FragColor = (color * uColorMultiplier) + uColorOffset;" + 15804 "}" 15805 ); 15806 15807 } 15808 var p = createjs.extend(ColorFilter, createjs.Filter); 15809 15810 // TODO: deprecated 15811 // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. 15812 15813 15814// public methods: 15815 /** docced in super class **/ 15816 p.shaderParamSetup = function(gl, stage, shaderProgram) { 15817 gl.uniform4f( 15818 gl.getUniformLocation(shaderProgram, "uColorMultiplier"), 15819 this.redMultiplier, this.greenMultiplier, this.blueMultiplier, this.alphaMultiplier 15820 ); 15821 15822 gl.uniform4f( 15823 gl.getUniformLocation(shaderProgram, "uColorOffset"), 15824 this.redOffset/255, this.greenOffset/255, this.blueOffset/255, this.alphaOffset/255 15825 ); 15826 }; 15827 15828 /** docced in super class **/ 15829 p.toString = function() { 15830 return "[ColorFilter]"; 15831 }; 15832 15833 /** docced in super class **/ 15834 p.clone = function() { 15835 return new ColorFilter( 15836 this.redMultiplier, this.greenMultiplier, this.blueMultiplier, this.alphaMultiplier, 15837 this.redOffset, this.greenOffset, this.blueOffset, this.alphaOffset 15838 ); 15839 }; 15840 15841// private methods: 15842 /** docced in super class **/ 15843 p._applyFilter = function(imageData) { 15844 var data = imageData.data; 15845 var l = data.length; 15846 for (var i=0; i<l; i+=4) { 15847 data[i] = data[i]*this.redMultiplier+this.redOffset; 15848 data[i+1] = data[i+1]*this.greenMultiplier+this.greenOffset; 15849 data[i+2] = data[i+2]*this.blueMultiplier+this.blueOffset; 15850 data[i+3] = data[i+3]*this.alphaMultiplier+this.alphaOffset; 15851 } 15852 return true; 15853 }; 15854 15855 15856 createjs.ColorFilter = createjs.promote(ColorFilter, "Filter"); 15857}()); 15858 15859//############################################################################## 15860// ColorMatrix.js 15861//############################################################################## 15862 15863this.createjs = this.createjs||{}; 15864 15865(function() { 15866 "use strict"; 15867 15868 15869// constructor: 15870 /** 15871 * Provides helper functions for assembling a matrix for use with the {{#crossLink "ColorMatrixFilter"}}{{/crossLink}}. 15872 * Most methods return the instance to facilitate chained calls. 15873 * 15874 * <h4>Example</h4> 15875 * 15876 * myColorMatrix.adjustHue(20).adjustBrightness(50); 15877 * 15878 * See {{#crossLink "Filter"}}{{/crossLink}} for an example of how to apply filters, or {{#crossLink "ColorMatrixFilter"}}{{/crossLink}} 15879 * for an example of how to use ColorMatrix to change a DisplayObject's color. 15880 * @class ColorMatrix 15881 * @param {Number} brightness 15882 * @param {Number} contrast 15883 * @param {Number} saturation 15884 * @param {Number} hue 15885 * @constructor 15886 **/ 15887 function ColorMatrix(brightness, contrast, saturation, hue) { 15888 this.setColor(brightness, contrast, saturation, hue); 15889 } 15890 var p = ColorMatrix.prototype; 15891 15892// constants: 15893 /** 15894 * Array of delta values for contrast calculations. 15895 * @property DELTA_INDEX 15896 * @type Array 15897 * @protected 15898 * @static 15899 **/ 15900 ColorMatrix.DELTA_INDEX = [ 15901 0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11, 15902 0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24, 15903 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42, 15904 0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68, 15905 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98, 15906 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54, 15907 1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25, 15908 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8, 15909 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0, 15910 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8, 15911 10.0 15912 ]; 15913 15914 /** 15915 * Identity matrix values. 15916 * @property IDENTITY_MATRIX 15917 * @type Array 15918 * @protected 15919 * @static 15920 **/ 15921 ColorMatrix.IDENTITY_MATRIX = [ 15922 1,0,0,0,0, 15923 0,1,0,0,0, 15924 0,0,1,0,0, 15925 0,0,0,1,0, 15926 0,0,0,0,1 15927 ]; 15928 15929 /** 15930 * The constant length of a color matrix. 15931 * @property LENGTH 15932 * @type Number 15933 * @protected 15934 * @static 15935 **/ 15936 ColorMatrix.LENGTH = ColorMatrix.IDENTITY_MATRIX.length; 15937 15938 15939// public methods: 15940 /** 15941 * Resets the instance with the specified values. 15942 * @method setColor 15943 * @param {Number} brightness 15944 * @param {Number} contrast 15945 * @param {Number} saturation 15946 * @param {Number} hue 15947 * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) 15948 * @chainable 15949 */
15950 p.setColor = function(brightness,contrast,saturation,hue) { 15951 return this.reset().adjustColor(brightness,contrast,saturation,hue); 15952 }; 15953 15954 /** 15955 * Resets the matrix to identity values. 15956 * @method reset 15957 * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) 15958 * @chainable 15959 */ 15960 p.reset = function() { 15961 return this.copy(ColorMatrix.IDENTITY_MATRIX); 15962 }; 15963 15964 /** 15965 * Shortcut method to adjust brightness, contrast, saturation and hue. 15966 * Equivalent to calling adjustHue(hue), adjustContrast(contrast), 15967 * adjustBrightness(brightness), adjustSaturation(saturation), in that order. 15968 * @method adjustColor 15969 * @param {Number} brightness 15970 * @param {Number} contrast 15971 * @param {Number} saturation 15972 * @param {Number} hue 15973 * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) 15974 * @chainable 15975 **/ 15976 p.adjustColor = function(brightness,contrast,saturation,hue) { 15977 this.adjustHue(hue); 15978 this.adjustContrast(contrast); 15979 this.adjustBrightness(brightness); 15980 return this.adjustSaturation(saturation); 15981 }; 15982 15983 /** 15984 * Adjusts the brightness of pixel color by adding the specified value to the red, green and blue channels. 15985 * Positive values will make the image brighter, negative values will make it darker. 15986 * @method adjustBrightness 15987 * @param {Number} value A value between -255 & 255 that will be added to the RGB channels. 15988 * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) 15989 * @chainable 15990 **/ 15991 p.adjustBrightness = function(value) { 15992 if (value == 0 || isNaN(value)) { return this; } 15993 value = this._cleanValue(value,255); 15994 this._multiplyMatrix([ 15995 1,0,0,0,value, 15996 0,1,0,0,value, 15997 0,0,1,0,value, 15998 0,0,0,1,0, 15999 0,0,0,0,1 16000 ]); 16001 return this; 16002 }; 16003 16004 /** 16005 * Adjusts the contrast of pixel color. 16006 * Positive values will increase contrast, negative values will decrease contrast. 16007 * @method adjustContrast 16008 * @param {Number} value A value between -100 & 100. 16009 * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) 16010 * @chainable 16011 **/ 16012 p.adjustContrast = function(value) { 16013 if (value == 0 || isNaN(value)) { return this; } 16014 value = this._cleanValue(value,100); 16015 var x; 16016 if (value<0) { 16017 x = 127+value/100*127; 16018 } else { 16019 x = value%1; 16020 if (x == 0) { 16021 x = ColorMatrix.DELTA_INDEX[value]; 16022 } else { 16023 x = ColorMatrix.DELTA_INDEX[(value<<0)]*(1-x)+ColorMatrix.DELTA_INDEX[(value<<0)+1]*x; // use linear interpolation for more granularity. 16024 } 16025 x = x*127+127; 16026 } 16027 this._multiplyMatrix([ 16028 x/127,0,0,0,0.5*(127-x), 16029 0,x/127,0,0,0.5*(127-x), 16030 0,0,x/127,0,0.5*(127-x), 16031 0,0,0,1,0, 16032 0,0,0,0,1 16033 ]); 16034 return this; 16035 }; 16036 16037 /** 16038 * Adjusts the color saturation of the pixel. 16039 * Positive values will increase saturation, negative values will decrease saturation (trend towards greyscale). 16040 * @method adjustSaturation 16041 * @param {Number} value A value between -100 & 100. 16042 * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) 16043 * @chainable 16044 **/ 16045 p.adjustSaturation = function(value) { 16046 if (value == 0 || isNaN(value)) { return this; } 16047 value = this._cleanValue(value,100); 16048 var x = 1+((value > 0) ? 3*value/100 : value/100); 16049 var lumR = 0.3086; 16050 var lumG = 0.6094; 16051 var lumB = 0.0820; 16052 this._multiplyMatrix([ 16053 lumR*(1-x)+x,lumG*(1-x),lumB*(1-x),0,0, 16054 lumR*(1-x),lumG*(1-x)+x,lumB*(1-x),0,0, 16055 lumR*(1-x),lumG*(1-x),lumB*(1-x)+x,0,0, 16056 0,0,0,1,0, 16057 0,0,0,0,1 16058 ]); 16059 return this; 16060 }; 16061 16062 16063 /** 16064 * Adjusts the hue of the pixel color. 16065 * @method adjustHue 16066 * @param {Number} value A value between -180 & 180. 16067 * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) 16068 * @chainable 16069 **/ 16070 p.adjustHue = function(value) { 16071 if (value == 0 || isNaN(value)) { return this; } 16072 value = this._cleanValue(value,180)/180*Math.PI;
16073 var cosVal = Math.cos(value); 16074 var sinVal = Math.sin(value); 16075 var lumR = 0.213; 16076 var lumG = 0.715; 16077 var lumB = 0.072; 16078 this._multiplyMatrix([ 16079 lumR+cosVal*(1-lumR)+sinVal*(-lumR),lumG+cosVal*(-lumG)+sinVal*(-lumG),lumB+cosVal*(-lumB)+sinVal*(1-lumB),0,0, 16080 lumR+cosVal*(-lumR)+sinVal*(0.143),lumG+cosVal*(1-lumG)+sinVal*(0.140),lumB+cosVal*(-lumB)+sinVal*(-0.283),0,0, 16081 lumR+cosVal*(-lumR)+sinVal*(-(1-lumR)),lumG+cosVal*(-lumG)+sinVal*(lumG),lumB+cosVal*(1-lumB)+sinVal*(lumB),0,0, 16082 0,0,0,1,0, 16083 0,0,0,0,1 16084 ]); 16085 return this; 16086 }; 16087 16088 /** 16089 * Concatenates (multiplies) the specified matrix with this one. 16090 * @method concat 16091 * @param {Array} matrix An array or ColorMatrix instance. 16092 * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) 16093 * @chainable 16094 **/ 16095 p.concat = function(matrix) { 16096 matrix = this._fixMatrix(matrix); 16097 if (matrix.length != ColorMatrix.LENGTH) { return this; } 16098 this._multiplyMatrix(matrix); 16099 return this; 16100 }; 16101 16102 /** 16103 * Returns a clone of this ColorMatrix. 16104 * @method clone 16105 * @return {ColorMatrix} A clone of this ColorMatrix. 16106 **/ 16107 p.clone = function() { 16108 return (new ColorMatrix()).copy(this); 16109 }; 16110 16111 /** 16112 * Return a length 25 (5x5) array instance containing this matrix's values. 16113 * @method toArray 16114 * @return {Array} An array holding this matrix's values. 16115 **/ 16116 p.toArray = function() { 16117 var arr = []; 16118 for (var i= 0, l=ColorMatrix.LENGTH; i<l; i++) { 16119 arr[i] = this[i]; 16120 } 16121 return arr; 16122 }; 16123 16124 /** 16125 * Copy the specified matrix's values to this matrix. 16126 * @method copy 16127 * @param {Array} matrix An array or ColorMatrix instance. 16128 * @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.) 16129 * @chainable 16130 **/ 16131 p.copy = function(matrix) { 16132 var l = ColorMatrix.LENGTH; 16133 for (var i=0;i<l;i++) { 16134 this[i] = matrix[i]; 16135 } 16136 return this; 16137 }; 16138 16139 /** 16140 * Returns a string representation of this object. 16141 * @method toString 16142 * @return {String} a string representation of the instance. 16143 **/ 16144 p.toString = function() { 16145 return "[ColorMatrix]"; 16146 }; 16147 16148 16149// private methods: 16150 /** 16151 * @method _multiplyMatrix 16152 * @param {Array} matrix 16153 * @protected 16154 **/ 16155 p._multiplyMatrix = function(matrix) { 16156 var i, j, k, col = []; 16157 16158 for (i=0;i<5;i++) { 16159 for (j=0;j<5;j++) { 16160 col[j] = this[j+i*5]; 16161 } 16162 for (j=0;j<5;j++) { 16163 var val=0; 16164 for (k=0;k<5;k++) { 16165 val += matrix[j+k*5]*col[k]; 16166 } 16167 this[j+i*5] = val; 16168 } 16169 } 16170 }; 16171 16172 /** 16173 * Make sure values are within the specified range, hue has a limit of 180, brightness is 255, others are 100. 16174 * @method _cleanValue 16175 * @param {Number} value The raw number 16176 * @param {Number} limit The maximum that the number can be. The minimum is the limit * -1. 16177 * @protected 16178 **/ 16179 p._cleanValue = function(value, limit) { 16180 return Math.min(limit,Math.max(-limit,value)); 16181 }; 16182 16183 /** 16184 * Makes sure matrixes are 5x5 (25 long). 16185 * @method _fixMatrix 16186 * @param {Array} matrix 16187 * @protected 16188 **/ 16189 p._fixMatrix = function(matrix) { 16190 if (matrix instanceof ColorMatrix) { matrix = matrix.toArray(); } 16191 if (matrix.length < ColorMatrix.LENGTH) { 16192 matrix = matrix.slice(0,matrix.length).concat(ColorMatrix.IDENTITY_MATRIX.slice(matrix.length,ColorMatrix.LENGTH)); 16193 } else if (matrix.length > ColorMatrix.LENGTH) { 16194 matrix = matrix.slice(0,ColorMatrix.LENGTH); 16195 } 16196 return matrix; 16197 }; 16198 16199 16200 createjs.ColorMatrix = ColorMatrix; 16201}()); 16202 16203//############################################################################## 16204// ColorMatrixFilter.js 16205//############################################################################## 16206 16207this.createjs = this.createjs||{}; 16208 16209(function() { 16210 "use strict"; 16211 16212 16213// constructor: 16214 /** 16215 * Allows you to carry out complex color operations such as modifying saturation, brightness, or inverting. See the 16216 * {{#crossLink "ColorMatrix"}}{{/crossLink}} for more information on changing colors. For an easier color transform, 16217 * consider the {{#crossLink "ColorFilter"}}{{/crossLink}}. 16218 * 16219 * <h4>Example</h4> 16220 * This example creates a red circle, inverts its hue, and then saturates it to brighten it up. 16221 * 16222 * var shape = new createjs.Shape().set({x:100,y:100}); 16223 * shape.graphics.beginFill("#ff0000").drawCircle(0,0,50); 16224 * 16225 * var matrix = new createjs.ColorMatrix().adjustHue(180).adjustSaturation(100); 16226 * shape.filters = [ 16227 * new createjs.ColorMatrixFilter(matrix) 16228 * ]; 16229 * 16230 * shape.cache(-50, -50, 100, 100); 16231 * 16232 * See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters. 16233 * @class ColorMatrixFilter 16234 * @constructor 16235 * @extends Filter 16236 * @param {Array | ColorMatrix} matrix A 4x5 matrix describing the color operation to perform. See also the {{#crossLink "ColorMatrix"}}{{/crossLink}} 16237 * class. 16238 **/ 16239 function ColorMatrixFilter(matrix) { 16240 this.Filter_constructor(); 16241 16242 // public properties: 16243 /** 16244 * A 4x5 matrix describing the color operation to perform. See also the {{#crossLink "ColorMatrix"}}{{/crossLink}} 16245 * @property matrix 16246 * @type Array | ColorMatrix 16247 **/ 16248 this.matrix = matrix; 16249 16250 this.FRAG_SHADER_BODY = ( 16251 "uniform mat4 uColorMatrix;" + 16252 "uniform vec4 uColorMatrixOffset;" + 16253 16254 "void main(void) {" + 16255 "vec4 color = texture2D(uSampler, vRenderCoord);" + 16256 16257 "mat4 m = uColorMatrix;" + 16258 "vec4 newColor = vec4(0,0,0,0);" + 16259 "newColor.r = color.r*m[0][0] + color.g*m[0][1] + color.b*m[0][2] + color.a*m[0][3];" + 16260 "newColor.g = color.r*m[1][0] + color.g*m[1][1] + color.b*m[1][2] + color.a*m[1][3];" + 16261 "newColor.b = color.r*m[2][0] + color.g*m[2][1] + color.b*m[2][2] + color.a*m[2][3];" + 16262 "newColor.a = color.r*m[3][0] + color.g*m[3][1] + color.b*m[3][2] + color.a*m[3][3];" + 16263 16264 "gl_FragColor = newColor + uColorMatrixOffset;" + 16265 "}" 16266 ); 16267 } 16268 var p = createjs.extend(ColorMatrixFilter, createjs.Filter); 16269 16270 // TODO: deprecated 16271 // p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details. 16272 16273 /** docced in super class **/ 16274 p.shaderParamSetup = function(gl, stage, shaderProgram) { 16275 var mat = this.matrix; 16276 var colorMatrix = new Float32Array([ 16277 mat[0],mat[1],mat[2],mat[3], 16278 mat[5],mat[6],mat[7],mat[8], 16279 mat[10],mat[11],mat[12],mat[13], 16280 mat[15],mat[16],mat[17],mat[18] 16281 ]); 16282 16283 gl.uniformMatrix4fv( 16284 gl.getUniformLocation(shaderProgram, "uColorMatrix"), 16285 false, colorMatrix 16286 ); 16287 gl.uniform4f( 16288 gl.getUniformLocation(shaderProgram, "uColorMatrixOffset"), 16289 mat[4]/255, mat[9]/255, mat[14]/255, mat[19]/255 16290 ); 16291 }; 16292 16293// public methods: 16294 /** docced in super class **/ 16295 p.toString = function() { 16296 return "[ColorMatrixFilter]"; 16297 }; 16298 16299 /** docced in super class **/ 16300 p.clone = function() {
16301 return new ColorMatrixFilter(this.matrix); 16302 }; 16303 16304// private methods: 16305 /** docced in super class **/ 16306 p._applyFilter = function(imageData) { 16307 var data = imageData.data; 16308 var l = data.length; 16309 var r,g,b,a; 16310 var mtx = this.matrix; 16311 var m0 = mtx[0], m1 = mtx[1], m2 = mtx[2], m3 = mtx[3], m4 = mtx[4]; 16312 var m5 = mtx[5], m6 = mtx[6], m7 = mtx[7], m8 = mtx[8], m9 = mtx[9]; 16313 var m10 = mtx[10], m11 = mtx[11], m12 = mtx[12], m13 = mtx[13], m14 = mtx[14]; 16314 var m15 = mtx[15], m16 = mtx[16], m17 = mtx[17], m18 = mtx[18], m19 = mtx[19]; 16315 16316 for (var i=0; i<l; i+=4) { 16317 r = data[i]; 16318 g = data[i+1]; 16319 b = data[i+2]; 16320 a = data[i+3]; 16321 data[i] = r*m0+g*m1+b*m2+a*m3+m4; // red 16322 data[i+1] = r*m5+g*m6+b*m7+a*m8+m9; // green 16323 data[i+2] = r*m10+g*m11+b*m12+a*m13+m14; // blue 16324 data[i+3] = r*m15+g*m16+b*m17+a*m18+m19; // alpha 16325 } 16326 return true; 16327 }; 16328 16329 createjs.ColorMatrixFilter = createjs.promote(ColorMatrixFilter, "Filter"); 16330}()); 16331 16332//############################################################################## 16333// Touch.js 16334//############################################################################## 16335 16336this.createjs = this.createjs||{}; 16337 16338(function() { 16339 "use strict"; 16340 16341 16342// constructor: 16343 /** 16344 * Global utility for working with multi-touch enabled devices in EaselJS. Currently supports W3C Touch API (iOS and 16345 * modern Android browser) and the Pointer API (IE), including ms-prefixed events in IE10, and unprefixed in IE11. 16346 * 16347 * Ensure that you {{#crossLink "Touch/disable"}}{{/crossLink}} touch when cleaning up your application. You do not have 16348 * to check if touch is supported to enable it, as it will fail gracefully if it is not supported. 16349 * 16350 * <h4>Example</h4> 16351 * 16352 * var stage = new createjs.Stage("canvasId"); 16353 * createjs.Touch.enable(stage); 16354 * 16355 * <strong>Note:</strong> It is important to disable Touch on a stage that you are no longer using: 16356 * 16357 * createjs.Touch.disable(stage); 16358 * 16359 * @class Touch 16360 * @static 16361 **/ 16362 function Touch() { 16363 throw "Touch cannot be instantiated"; 16364 } 16365 16366 16367// public static methods: 16368 /** 16369 * Returns `true` if touch is supported in the current browser. 16370 * @method isSupported 16371 * @return {Boolean} Indicates whether touch is supported in the current browser. 16372 * @static 16373 **/ 16374 Touch.isSupported = function() { 16375 return !!(('ontouchstart' in window) // iOS & Android 16376 || (window.MSPointerEvent && window.navigator.msMaxTouchPoints > 0) // IE10 16377 || (window.PointerEvent && window.navigator.maxTouchPoints > 0)); // IE11+ 16378 }; 16379 16380 /** 16381 * Enables touch interaction for the specified EaselJS {{#crossLink "Stage"}}{{/crossLink}}. Currently supports iOS 16382 * (and compatible browsers, such as modern Android browsers), and IE10/11. Supports both single touch and 16383 * multi-touch modes. Extends the EaselJS {{#crossLink "MouseEvent"}}{{/crossLink}} model, but without support for 16384 * double click or over/out events. See the MouseEvent {{#crossLink "MouseEvent/pointerId:property"}}{{/crossLink}} 16385 * for more information. 16386 * @method enable 16387 * @param {Stage} stage The {{#crossLink "Stage"}}{{/crossLink}} to enable touch on. 16388 * @param {Boolean} [singleTouch=false] If `true`, only a single touch will be active at a time. 16389 * @param {Boolean} [allowDefault=false] If `true`, then default gesture actions (ex. scrolling, zooming) will be 16390 * allowed when the user is interacting with the target canvas. 16391 * @return {Boolean} Returns `true` if touch was successfully enabled on the target stage. 16392 * @static 16393 **/ 16394 Touch.enable = function(stage, singleTouch, allowDefault) { 16395 if (!stage || !stage.canvas || !Touch.isSupported()) { return false; } 16396 if (stage.__touch) { return true; } 16397 16398 // inject required properties on stage: 16399 stage.__touch = {pointers:{}, multitouch:!singleTouch, preventDefault:!allowDefault, count:0}; 16400
16401 // note that in the future we may need to disable the standard mouse event model before adding 16402 // these to prevent duplicate calls. It doesn't seem to be an issue with iOS devices though. 16403 if ('ontouchstart' in window) { Touch._IOS_enable(stage); } 16404 else if (window.PointerEvent || window.MSPointerEvent) { Touch._IE_enable(stage); } 16405 return true; 16406 }; 16407 16408 /** 16409 * Removes all listeners that were set up when calling `Touch.enable()` on a stage. 16410 * @method disable 16411 * @param {Stage} stage The {{#crossLink "Stage"}}{{/crossLink}} to disable touch on. 16412 * @static 16413 **/ 16414 Touch.disable = function(stage) { 16415 if (!stage) { return; } 16416 if ('ontouchstart' in window) { Touch._IOS_disable(stage); } 16417 else if (window.PointerEvent || window.MSPointerEvent) { Touch._IE_disable(stage); } 16418 16419 16420 delete stage.__touch; 16421 }; 16422 16423 16424// Private static methods: 16425 /** 16426 * @method _IOS_enable 16427 * @protected 16428 * @param {Stage} stage 16429 * @static 16430 **/ 16431 Touch._IOS_enable = function(stage) { 16432 var canvas = stage.canvas; 16433 var f = stage.__touch.f = function(e) { Touch._IOS_handleEvent(stage,e); }; 16434 canvas.addEventListener("touchstart", f, false); 16435 canvas.addEventListener("touchmove", f, false); 16436 canvas.addEventListener("touchend", f, false); 16437 canvas.addEventListener("touchcancel", f, false); 16438 }; 16439 16440 /** 16441 * @method _IOS_disable 16442 * @protected 16443 * @param {Stage} stage 16444 * @static 16445 **/ 16446 Touch._IOS_disable = function(stage) { 16447 var canvas = stage.canvas; 16448 if (!canvas) { return; } 16449 var f = stage.__touch.f; 16450 canvas.removeEventListener("touchstart", f, false); 16451 canvas.removeEventListener("touchmove", f, false); 16452 canvas.removeEventListener("touchend", f, false); 16453 canvas.removeEventListener("touchcancel", f, false); 16454 }; 16455 16456 /** 16457 * @method _IOS_handleEvent 16458 * @param {Stage} stage 16459 * @param {Object} e The event to handle 16460 * @protected 16461 * @static 16462 **/ 16463 Touch._IOS_handleEvent = function(stage, e) { 16464 if (!stage) { return; } 16465 if (stage.__touch.preventDefault) { e.preventDefault&&e.preventDefault(); } 16466 var touches = e.changedTouches; 16467 var type = e.type; 16468 for (var i= 0,l=touches.length; i<l; i++) { 16469 var touch = touches[i]; 16470 var id = touch.identifier; 16471 if (touch.target != stage.canvas) { continue; } 16472 16473 if (type === "touchstart") { 16474 this._handleStart(stage, id, e, touch.pageX, touch.pageY); 16475 } else if (type === "touchmove") { 16476 this._handleMove(stage, id, e, touch.pageX, touch.pageY); 16477 } else if (type === "touchend" || type === "touchcancel") { 16478 this._handleEnd(stage, id, e); 16479 } 16480 } 16481 }; 16482 16483 /** 16484 * @method _IE_enable 16485 * @protected 16486 * @param {Stage} stage 16487 * @static 16488 **/ 16489 Touch._IE_enable = function(stage) { 16490 var canvas = stage.canvas; 16491 var f = stage.__touch.f = function(e) { Touch._IE_handleEvent(stage,e); }; 16492 16493 if (window.PointerEvent === undefined) { 16494 canvas.addEventListener("MSPointerDown", f, false); 16495 window.addEventListener("MSPointerMove", f, false); 16496 window.addEventListener("MSPointerUp", f, false); 16497 window.addEventListener("MSPointerCancel", f, false); 16498 if (stage.__touch.preventDefault) { canvas.style.msTouchAction = "none"; } 16499 } else { 16500 canvas.addEventListener("pointerdown", f, false); 16501 window.addEventListener("pointermove", f, false); 16502 window.addEventListener("pointerup", f, false); 16503 window.addEventListener("pointercancel", f, false); 16504 if (stage.__touch.preventDefault) { canvas.style.touchAction = "none"; } 16505 16506 } 16507 stage.__touch.activeIDs = {}; 16508 }; 16509 16510 /** 16511 * @method _IE_disable 16512 * @protected 16513 * @param {Stage} stage 16514 * @static 16515 **/ 16516 Touch._IE_disable = function(stage) { 16517 var f = stage.__touch.f; 16518 16519 if (window.PointerEvent === undefined) { 16520 window.removeEventListener("MSPointerMove", f, false); 16521 window.removeEventListener("MSPointerUp", f, false); 16522 window.removeEventListener("MSPointerCancel", f, false); 16523 if (stage.canvas) { 16524 stage.canvas.removeEventListener("MSPointerDown", f, false); 16525 } 16526 } else { 16527 window.removeEventListener("pointermove", f, false); 16528 window.removeEventListener("pointerup", f, false); 16529 window.removeEventListener("pointercancel", f, false); 16530 if (stage.canvas) { 16531 stage.canvas.removeEventListener("pointerdown", f, false); 16532 } 16533 } 16534 }; 16535 16536 /** 16537 * @method _IE_handleEvent 16538 * @param {Stage} stage 16539 * @param {Object} e The event to handle. 16540 * @protected 16541 * @static 16542 **/ 16543 Touch._IE_handleEvent = function(stage, e) { 16544 if (!stage) { return; } 16545 if (stage.__touch.preventDefault) { e.preventDefault && e.preventDefault(); } 16546 var type = e.type; 16547 var id = e.pointerId; 16548 var ids = stage.__touch.activeIDs; 16549 16550 if (type === "MSPointerDown" || type === "pointerdown") { 16551 if (e.srcElement != stage.canvas) { return; } 16552 ids[id] = true; 16553 this._handleStart(stage, id, e, e.pageX, e.pageY); 16554 } else if (ids[id]) { // it's an id we're watching 16555 if (type === "MSPointerMove" || type === "pointermove") { 16556 this._handleMove(stage, id, e, e.pageX, e.pageY); 16557 } else if (type === "MSPointerUp" || type === "MSPointerCancel" 16558 || type === "pointerup" || type === "pointercancel") { 16559 delete(ids[id]); 16560 this._handleEnd(stage, id, e); 16561 } 16562 } 16563 }; 16564 16565 /** 16566 * @method _handleStart 16567 * @param {Stage} stage 16568 * @param {String|Number} id 16569 * @param {Object} e 16570 * @param {Number} x 16571 * @param {Number} y 16572 * @protected 16573 **/ 16574 Touch._handleStart = function(stage, id, e, x, y) { 16575 var props = stage.__touch; 16576 if (!props.multitouch && props.count) { return; } 16577 var ids = props.pointers; 16578 if (ids[id]) { return; } 16579 ids[id] = true; 16580 props.count++; 16581 stage._handlePointerDown(id, e, x, y); 16582 }; 16583 16584 /** 16585 * @method _handleMove 16586 * @param {Stage} stage 16587 * @param {String|Number} id 16588 * @param {Object} e 16589 * @param {Number} x 16590 * @param {Number} y 16591 * @protected 16592 **/ 16593 Touch._handleMove = function(stage, id, e, x, y) { 16594 if (!stage.__touch.pointers[id]) { return; } 16595 stage._handlePointerMove(id, e, x, y); 16596 }; 16597 16598 /** 16599 * @method _handleEnd 16600 * @param {Stage} stage 16601 * @param {String|Number} id 16602 * @param {Object} e 16603 * @protected 16604 **/ 16605 Touch._handleEnd = function(stage, id, e) { 16606 // TODO: cancel should be handled differently for proper UI (ex. an up would trigger a click, a cancel would more closely resemble an out). 16607 var props = stage.__touch; 16608 var ids = props.pointers; 16609 if (!ids[id]) { return; } 16610 props.count--; 16611 stage._handlePointerUp(id, e, true); 16612 delete(ids[id]); 16613 }; 16614 16615 16616 createjs.Touch = Touch; 16617}()); 16618 16619//############################################################################## 16620// version.js 16621//############################################################################## 16622 16623this.createjs = this.createjs || {}; 16624 16625(function() { 16626 "use strict"; 16627 16628 /** 16629 * Static class holding library specific information such as the version and buildDate of 16630 * the library. 16631 * @class EaselJS 16632 **/ 16633 var s = createjs.EaselJS = createjs.EaselJS || {}; 16634 16635 /** 16636 * The version string for this release. 16637 * @property version
16638 * @type String 16639 * @static 16640 **/ 16641 s.version = /*=version*/"1.0.0"; // injected by build process 16642 16643 /** 16644 * The build date for this release in UTC format. 16645 * @property buildDate 16646 * @type String 16647 * @static 16648 **/ 16649 s.buildDate = /*=date*/"Thu, 14 Sep 2017 19:47:53 GMT"; // injected by build process 16650 16651})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.