Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
mamayaya1
GitHub Repository: mamayaya1/game
Path: blob/main/projects/basketball-stars/assets/box2dweb/easeljs-0.8.2.combined.js
4627 views
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
34
this.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
*/
58
createjs.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
70
this.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
*/
113
createjs.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
130
this.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
*/
147
createjs.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
// Event.js
160
//##############################################################################
161
162
this.createjs = this.createjs||{};
163
164
(function() {
165
"use strict";
166
167
// constructor:
168
/**
169
* Contains properties and methods shared by all events for use with
170
* {{#crossLink "EventDispatcher"}}{{/crossLink}}.
171
*
172
* Note that Event objects are often reused, so you should never
173
* rely on an event object's state outside of the call stack it was received in.
174
* @class Event
175
* @param {String} type The event type.
176
* @param {Boolean} bubbles Indicates whether the event will bubble through the display list.
177
* @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled.
178
* @constructor
179
**/
180
function Event(type, bubbles, cancelable) {
181
182
183
// public properties:
184
/**
185
* The type of event.
186
* @property type
187
* @type String
188
**/
189
this.type = type;
190
191
/**
192
* The object that generated an event.
193
* @property target
194
* @type Object
195
* @default null
196
* @readonly
197
*/
198
this.target = null;
199
200
/**
201
* The current target that a bubbling event is being dispatched from. For non-bubbling events, this will
202
* always be the same as target. For example, if childObj.parent = parentObj, and a bubbling event
203
* is generated from childObj, then a listener on parentObj would receive the event with
204
* target=childObj (the original target) and currentTarget=parentObj (where the listener was added).
205
* @property currentTarget
206
* @type Object
207
* @default null
208
* @readonly
209
*/
210
this.currentTarget = null;
211
212
/**
213
* For bubbling events, this indicates the current event phase:<OL>
214
* <LI> capture phase: starting from the top parent to the target</LI>
215
* <LI> at target phase: currently being dispatched from the target</LI>
216
* <LI> bubbling phase: from the target to the top parent</LI>
217
* </OL>
218
* @property eventPhase
219
* @type Number
220
* @default 0
221
* @readonly
222
*/
223
this.eventPhase = 0;
224
225
/**
226
* Indicates whether the event will bubble through the display list.
227
* @property bubbles
228
* @type Boolean
229
* @default false
230
* @readonly
231
*/
232
this.bubbles = !!bubbles;
233
234
/**
235
* Indicates whether the default behaviour of this event can be cancelled via
236
* {{#crossLink "Event/preventDefault"}}{{/crossLink}}. This is set via the Event constructor.
237
* @property cancelable
238
* @type Boolean
239
* @default false
240
* @readonly
241
*/
242
this.cancelable = !!cancelable;
243
244
/**
245
* The epoch time at which this event was created.
246
* @property timeStamp
247
* @type Number
248
* @default 0
249
* @readonly
250
*/
251
this.timeStamp = (new Date()).getTime();
252
253
/**
254
* Indicates if {{#crossLink "Event/preventDefault"}}{{/crossLink}} has been called
255
* on this event.
256
* @property defaultPrevented
257
* @type Boolean
258
* @default false
259
* @readonly
260
*/
261
this.defaultPrevented = false;
262
263
/**
264
* Indicates if {{#crossLink "Event/stopPropagation"}}{{/crossLink}} or
265
* {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called on this event.
266
* @property propagationStopped
267
* @type Boolean
268
* @default false
269
* @readonly
270
*/
271
this.propagationStopped = false;
272
273
/**
274
* Indicates if {{#crossLink "Event/stopImmediatePropagation"}}{{/crossLink}} has been called
275
* on this event.
276
* @property immediatePropagationStopped
277
* @type Boolean
278
* @default false
279
* @readonly
280
*/
281
this.immediatePropagationStopped = false;
282
283
/**
284
* Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event.
285
* @property removed
286
* @type Boolean
287
* @default false
288
* @readonly
289
*/
290
this.removed = false;
291
}
292
var p = Event.prototype;
293
294
/**
295
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
296
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
297
* for details.
298
*
299
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
300
*
301
* @method initialize
302
* @protected
303
* @deprecated
304
*/
305
// p.initialize = function() {}; // searchable for devs wondering where it is.
306
307
// public methods:
308
/**
309
* Sets {{#crossLink "Event/defaultPrevented"}}{{/crossLink}} to true if the event is cancelable.
310
* Mirrors the DOM level 2 event standard. In general, cancelable events that have `preventDefault()` called will
311
* cancel the default behaviour associated with the event.
312
* @method preventDefault
313
**/
314
p.preventDefault = function() {
315
this.defaultPrevented = this.cancelable&&true;
316
};
317
318
/**
319
* Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} to true.
320
* Mirrors the DOM event standard.
321
* @method stopPropagation
322
**/
323
p.stopPropagation = function() {
324
this.propagationStopped = true;
325
};
326
327
/**
328
* Sets {{#crossLink "Event/propagationStopped"}}{{/crossLink}} and
329
* {{#crossLink "Event/immediatePropagationStopped"}}{{/crossLink}} to true.
330
* Mirrors the DOM event standard.
331
* @method stopImmediatePropagation
332
**/
333
p.stopImmediatePropagation = function() {
334
this.immediatePropagationStopped = this.propagationStopped = true;
335
};
336
337
/**
338
* Causes the active listener to be removed via removeEventListener();
339
*
340
* myBtn.addEventListener("click", function(evt) {
341
* // do stuff...
342
* evt.remove(); // removes this listener.
343
* });
344
*
345
* @method remove
346
**/
347
p.remove = function() {
348
this.removed = true;
349
};
350
351
/**
352
* Returns a clone of the Event instance.
353
* @method clone
354
* @return {Event} a clone of the Event instance.
355
**/
356
p.clone = function() {
357
return new Event(this.type, this.bubbles, this.cancelable);
358
};
359
360
/**
361
* Provides a chainable shortcut method for setting a number of properties on the instance.
362
*
363
* @method set
364
* @param {Object} props A generic object containing properties to copy to the instance.
365
* @return {Event} Returns the instance the method is called on (useful for chaining calls.)
366
* @chainable
367
*/
368
p.set = function(props) {
369
for (var n in props) { this[n] = props[n]; }
370
return this;
371
};
372
373
/**
374
* Returns a string representation of this object.
375
* @method toString
376
* @return {String} a string representation of the instance.
377
**/
378
p.toString = function() {
379
return "[Event (type="+this.type+")]";
380
};
381
382
createjs.Event = Event;
383
}());
384
385
//##############################################################################
386
// EventDispatcher.js
387
//##############################################################################
388
389
this.createjs = this.createjs||{};
390
391
(function() {
392
"use strict";
393
394
395
// constructor:
396
/**
397
* EventDispatcher provides methods for managing queues of event listeners and dispatching events.
398
*
399
* You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the
400
* EventDispatcher {{#crossLink "EventDispatcher/initialize"}}{{/crossLink}} method.
401
*
402
* Together with the CreateJS Event class, EventDispatcher provides an extended event model that is based on the
403
* DOM Level 2 event model, including addEventListener, removeEventListener, and dispatchEvent. It supports
404
* bubbling / capture, preventDefault, stopPropagation, stopImmediatePropagation, and handleEvent.
405
*
406
* EventDispatcher also exposes a {{#crossLink "EventDispatcher/on"}}{{/crossLink}} method, which makes it easier
407
* to create scoped listeners, listeners that only run once, and listeners with associated arbitrary data. The
408
* {{#crossLink "EventDispatcher/off"}}{{/crossLink}} method is merely an alias to
409
* {{#crossLink "EventDispatcher/removeEventListener"}}{{/crossLink}}.
410
*
411
* Another addition to the DOM Level 2 model is the {{#crossLink "EventDispatcher/removeAllEventListeners"}}{{/crossLink}}
412
* method, which can be used to listeners for all events, or listeners for a specific event. The Event object also
413
* includes a {{#crossLink "Event/remove"}}{{/crossLink}} method which removes the active listener.
414
*
415
* <h4>Example</h4>
416
* Add EventDispatcher capabilities to the "MyClass" class.
417
*
418
* EventDispatcher.initialize(MyClass.prototype);
419
*
420
* Add an event (see {{#crossLink "EventDispatcher/addEventListener"}}{{/crossLink}}).
421
*
422
* instance.addEventListener("eventName", handlerMethod);
423
* function handlerMethod(event) {
424
* console.log(event.target + " Was Clicked");
425
* }
426
*
427
* <b>Maintaining proper scope</b><br />
428
* Scope (ie. "this") can be be a challenge with events. Using the {{#crossLink "EventDispatcher/on"}}{{/crossLink}}
429
* method to subscribe to events simplifies this.
430
*
431
* instance.addEventListener("click", function(event) {
432
* console.log(instance == this); // false, scope is ambiguous.
433
* });
434
*
435
* instance.on("click", function(event) {
436
* console.log(instance == this); // true, "on" uses dispatcher scope by default.
437
* });
438
*
439
* If you want to use addEventListener instead, you may want to use function.bind() or a similar proxy to manage
440
* scope.
441
*
442
* <b>Browser support</b>
443
* The event model in CreateJS can be used separately from the suite in any project, however the inheritance model
444
* requires modern browsers (IE9+).
445
*
446
*
447
* @class EventDispatcher
448
* @constructor
449
**/
450
function EventDispatcher() {
451
452
453
// private properties:
454
/**
455
* @protected
456
* @property _listeners
457
* @type Object
458
**/
459
this._listeners = null;
460
461
/**
462
* @protected
463
* @property _captureListeners
464
* @type Object
465
**/
466
this._captureListeners = null;
467
}
468
var p = EventDispatcher.prototype;
469
470
/**
471
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
472
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
473
* for details.
474
*
475
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
476
*
477
* @method initialize
478
* @protected
479
* @deprecated
480
*/
481
// p.initialize = function() {}; // searchable for devs wondering where it is.
482
483
484
// static public methods:
485
/**
486
* Static initializer to mix EventDispatcher methods into a target object or prototype.
487
*
488
* EventDispatcher.initialize(MyClass.prototype); // add to the prototype of the class
489
* EventDispatcher.initialize(myObject); // add to a specific instance
490
*
491
* @method initialize
492
* @static
493
* @param {Object} target The target object to inject EventDispatcher methods into. This can be an instance or a
494
* prototype.
495
**/
496
EventDispatcher.initialize = function(target) {
497
target.addEventListener = p.addEventListener;
498
target.on = p.on;
499
target.removeEventListener = target.off = p.removeEventListener;
500
target.removeAllEventListeners = p.removeAllEventListeners;
501
target.hasEventListener = p.hasEventListener;
502
target.dispatchEvent = p.dispatchEvent;
503
target._dispatchEvent = p._dispatchEvent;
504
target.willTrigger = p.willTrigger;
505
};
506
507
508
// public methods:
509
/**
510
* Adds the specified event listener. Note that adding multiple listeners to the same function will result in
511
* multiple callbacks getting fired.
512
*
513
* <h4>Example</h4>
514
*
515
* displayObject.addEventListener("click", handleClick);
516
* function handleClick(event) {
517
* // Click happened.
518
* }
519
*
520
* @method addEventListener
521
* @param {String} type The string type of the event.
522
* @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when
523
* the event is dispatched.
524
* @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
525
* @return {Function | Object} Returns the listener for chaining or assignment.
526
**/
527
p.addEventListener = function(type, listener, useCapture) {
528
var listeners;
529
if (useCapture) {
530
listeners = this._captureListeners = this._captureListeners||{};
531
} else {
532
listeners = this._listeners = this._listeners||{};
533
}
534
var arr = listeners[type];
535
if (arr) { this.removeEventListener(type, listener, useCapture); }
536
arr = listeners[type]; // remove may have deleted the array
537
if (!arr) { listeners[type] = [listener]; }
538
else { arr.push(listener); }
539
return listener;
540
};
541
542
/**
543
* A shortcut method for using addEventListener that makes it easier to specify an execution scope, have a listener
544
* only run once, associate arbitrary data with the listener, and remove the listener.
545
*
546
* This method works by creating an anonymous wrapper function and subscribing it with addEventListener.
547
* The wrapper function is returned for use with `removeEventListener` (or `off`).
548
*
549
* <b>IMPORTANT:</b> To remove a listener added with `on`, you must pass in the returned wrapper function as the listener, or use
550
* {{#crossLink "Event/remove"}}{{/crossLink}}. Likewise, each time you call `on` a NEW wrapper function is subscribed, so multiple calls
551
* to `on` with the same params will create multiple listeners.
552
*
553
* <h4>Example</h4>
554
*
555
* var listener = myBtn.on("click", handleClick, null, false, {count:3});
556
* function handleClick(evt, data) {
557
* data.count -= 1;
558
* console.log(this == myBtn); // true - scope defaults to the dispatcher
559
* if (data.count == 0) {
560
* alert("clicked 3 times!");
561
* myBtn.off("click", listener);
562
* // alternately: evt.remove();
563
* }
564
* }
565
*
566
* @method on
567
* @param {String} type The string type of the event.
568
* @param {Function | Object} listener An object with a handleEvent method, or a function that will be called when
569
* the event is dispatched.
570
* @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).
571
* @param {Boolean} [once=false] If true, the listener will remove itself after the first time it is triggered.
572
* @param {*} [data] Arbitrary data that will be included as the second parameter when the listener is called.
573
* @param {Boolean} [useCapture=false] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
574
* @return {Function} Returns the anonymous function that was created and assigned as the listener. This is needed to remove the listener later using .removeEventListener.
575
**/
576
p.on = function(type, listener, scope, once, data, useCapture) {
577
if (listener.handleEvent) {
578
scope = scope||listener;
579
listener = listener.handleEvent;
580
}
581
scope = scope||this;
582
return this.addEventListener(type, function(evt) {
583
listener.call(scope, evt, data);
584
once&&evt.remove();
585
}, useCapture);
586
};
587
588
/**
589
* Removes the specified event listener.
590
*
591
* <b>Important Note:</b> that you must pass the exact function reference used when the event was added. If a proxy
592
* function, or function closure is used as the callback, the proxy/closure reference must be used - a new proxy or
593
* closure will not work.
594
*
595
* <h4>Example</h4>
596
*
597
* displayObject.removeEventListener("click", handleClick);
598
*
599
* @method removeEventListener
600
* @param {String} type The string type of the event.
601
* @param {Function | Object} listener The listener function or object.
602
* @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
603
**/
604
p.removeEventListener = function(type, listener, useCapture) {
605
var listeners = useCapture ? this._captureListeners : this._listeners;
606
if (!listeners) { return; }
607
var arr = listeners[type];
608
if (!arr) { return; }
609
for (var i=0,l=arr.length; i<l; i++) {
610
if (arr[i] == listener) {
611
if (l==1) { delete(listeners[type]); } // allows for faster checks.
612
else { arr.splice(i,1); }
613
break;
614
}
615
}
616
};
617
618
/**
619
* A shortcut to the removeEventListener method, with the same parameters and return value. This is a companion to the
620
* .on method.
621
*
622
* <b>IMPORTANT:</b> To remove a listener added with `on`, you must pass in the returned wrapper function as the listener. See
623
* {{#crossLink "EventDispatcher/on"}}{{/crossLink}} for an example.
624
*
625
* @method off
626
* @param {String} type The string type of the event.
627
* @param {Function | Object} listener The listener function or object.
628
* @param {Boolean} [useCapture] For events that bubble, indicates whether to listen for the event in the capture or bubbling/target phase.
629
**/
630
p.off = p.removeEventListener;
631
632
/**
633
* Removes all listeners for the specified type, or all listeners of all types.
634
*
635
* <h4>Example</h4>
636
*
637
* // Remove all listeners
638
* displayObject.removeAllEventListeners();
639
*
640
* // Remove all click listeners
641
* displayObject.removeAllEventListeners("click");
642
*
643
* @method removeAllEventListeners
644
* @param {String} [type] The string type of the event. If omitted, all listeners for all types will be removed.
645
**/
646
p.removeAllEventListeners = function(type) {
647
if (!type) { this._listeners = this._captureListeners = null; }
648
else {
649
if (this._listeners) { delete(this._listeners[type]); }
650
if (this._captureListeners) { delete(this._captureListeners[type]); }
651
}
652
};
653
654
/**
655
* Dispatches the specified event to all listeners.
656
*
657
* <h4>Example</h4>
658
*
659
* // Use a string event
660
* this.dispatchEvent("complete");
661
*
662
* // Use an Event instance
663
* var event = new createjs.Event("progress");
664
* this.dispatchEvent(event);
665
*
666
* @method dispatchEvent
667
* @param {Object | String | Event} eventObj An object with a "type" property, or a string type.
668
* While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used,
669
* dispatchEvent will construct an Event instance if necessary with the specified type. This latter approach can
670
* be used to avoid event object instantiation for non-bubbling events that may not have any listeners.
671
* @param {Boolean} [bubbles] Specifies the `bubbles` value when a string was passed to eventObj.
672
* @param {Boolean} [cancelable] Specifies the `cancelable` value when a string was passed to eventObj.
673
* @return {Boolean} Returns false if `preventDefault()` was called on a cancelable event, true otherwise.
674
**/
675
p.dispatchEvent = function(eventObj, bubbles, cancelable) {
676
if (typeof eventObj == "string") {
677
// skip everything if there's no listeners and it doesn't bubble:
678
var listeners = this._listeners;
679
if (!bubbles && (!listeners || !listeners[eventObj])) { return true; }
680
eventObj = new createjs.Event(eventObj, bubbles, cancelable);
681
} else if (eventObj.target && eventObj.clone) {
682
// redispatching an active event object, so clone it:
683
eventObj = eventObj.clone();
684
}
685
686
// TODO: it would be nice to eliminate this. Maybe in favour of evtObj instanceof Event? Or !!evtObj.createEvent
687
try { eventObj.target = this; } catch (e) {} // try/catch allows redispatching of native events
688
689
if (!eventObj.bubbles || !this.parent) {
690
this._dispatchEvent(eventObj, 2);
691
} else {
692
var top=this, list=[top];
693
while (top.parent) { list.push(top = top.parent); }
694
var i, l=list.length;
695
696
// capture & atTarget
697
for (i=l-1; i>=0 && !eventObj.propagationStopped; i--) {
698
list[i]._dispatchEvent(eventObj, 1+(i==0));
699
}
700
// bubbling
701
for (i=1; i<l && !eventObj.propagationStopped; i++) {
702
list[i]._dispatchEvent(eventObj, 3);
703
}
704
}
705
return !eventObj.defaultPrevented;
706
};
707
708
/**
709
* Indicates whether there is at least one listener for the specified event type.
710
* @method hasEventListener
711
* @param {String} type The string type of the event.
712
* @return {Boolean} Returns true if there is at least one listener for the specified event.
713
**/
714
p.hasEventListener = function(type) {
715
var listeners = this._listeners, captureListeners = this._captureListeners;
716
return !!((listeners && listeners[type]) || (captureListeners && captureListeners[type]));
717
};
718
719
/**
720
* Indicates whether there is at least one listener for the specified event type on this object or any of its
721
* ancestors (parent, parent's parent, etc). A return value of true indicates that if a bubbling event of the
722
* specified type is dispatched from this object, it will trigger at least one listener.
723
*
724
* This is similar to {{#crossLink "EventDispatcher/hasEventListener"}}{{/crossLink}}, but it searches the entire
725
* event flow for a listener, not just this object.
726
* @method willTrigger
727
* @param {String} type The string type of the event.
728
* @return {Boolean} Returns `true` if there is at least one listener for the specified event.
729
**/
730
p.willTrigger = function(type) {
731
var o = this;
732
while (o) {
733
if (o.hasEventListener(type)) { return true; }
734
o = o.parent;
735
}
736
return false;
737
};
738
739
/**
740
* @method toString
741
* @return {String} a string representation of the instance.
742
**/
743
p.toString = function() {
744
return "[EventDispatcher]";
745
};
746
747
748
// private methods:
749
/**
750
* @method _dispatchEvent
751
* @param {Object | String | Event} eventObj
752
* @param {Object} eventPhase
753
* @protected
754
**/
755
p._dispatchEvent = function(eventObj, eventPhase) {
756
var l, listeners = (eventPhase==1) ? this._captureListeners : this._listeners;
757
if (eventObj && listeners) {
758
var arr = listeners[eventObj.type];
759
if (!arr||!(l=arr.length)) { return; }
760
try { eventObj.currentTarget = this; } catch (e) {}
761
try { eventObj.eventPhase = eventPhase; } catch (e) {}
762
eventObj.removed = false;
763
764
arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch
765
for (var i=0; i<l && !eventObj.immediatePropagationStopped; i++) {
766
var o = arr[i];
767
if (o.handleEvent) { o.handleEvent(eventObj); }
768
else { o(eventObj); }
769
if (eventObj.removed) {
770
this.off(eventObj.type, o, eventPhase==1);
771
eventObj.removed = false;
772
}
773
}
774
}
775
};
776
777
778
createjs.EventDispatcher = EventDispatcher;
779
}());
780
781
//##############################################################################
782
// Ticker.js
783
//##############################################################################
784
785
this.createjs = this.createjs||{};
786
787
(function() {
788
"use strict";
789
790
791
// constructor:
792
/**
793
* The Ticker provides a centralized tick or heartbeat broadcast at a set interval. Listeners can subscribe to the tick
794
* event to be notified when a set time interval has elapsed.
795
*
796
* Note that the interval that the tick event is called is a target interval, and may be broadcast at a slower interval
797
* when under high CPU load. The Ticker class uses a static interface (ex. `Ticker.framerate = 30;`) and
798
* can not be instantiated.
799
*
800
* <h4>Example</h4>
801
*
802
* createjs.Ticker.addEventListener("tick", handleTick);
803
* function handleTick(event) {
804
* // Actions carried out each tick (aka frame)
805
* if (!event.paused) {
806
* // Actions carried out when the Ticker is not paused.
807
* }
808
* }
809
*
810
* @class Ticker
811
* @uses EventDispatcher
812
* @static
813
**/
814
function Ticker() {
815
throw "Ticker cannot be instantiated.";
816
}
817
818
819
// constants:
820
/**
821
* In this mode, Ticker uses the requestAnimationFrame API, but attempts to synch the ticks to target framerate. It
822
* uses a simple heuristic that compares the time of the RAF return to the target time for the current frame and
823
* dispatches the tick when the time is within a certain threshold.
824
*
825
* This mode has a higher variance for time between frames than {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}},
826
* but does not require that content be time based as with {{#crossLink "Ticker/RAF:property"}}{{/crossLink}} while
827
* gaining the benefits of that API (screen synch, background throttling).
828
*
829
* Variance is usually lowest for framerates that are a divisor of the RAF frequency. This is usually 60, so
830
* framerates of 10, 12, 15, 20, and 30 work well.
831
*
832
* Falls back to {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}} if the requestAnimationFrame API is not
833
* supported.
834
* @property RAF_SYNCHED
835
* @static
836
* @type {String}
837
* @default "synched"
838
* @readonly
839
**/
840
Ticker.RAF_SYNCHED = "synched";
841
842
/**
843
* In this mode, Ticker passes through the requestAnimationFrame heartbeat, ignoring the target framerate completely.
844
* Because requestAnimationFrame frequency is not deterministic, any content using this mode should be time based.
845
* You can leverage {{#crossLink "Ticker/getTime"}}{{/crossLink}} and the {{#crossLink "Ticker/tick:event"}}{{/crossLink}}
846
* event object's "delta" properties to make this easier.
847
*
848
* Falls back on {{#crossLink "Ticker/TIMEOUT:property"}}{{/crossLink}} if the requestAnimationFrame API is not
849
* supported.
850
* @property RAF
851
* @static
852
* @type {String}
853
* @default "raf"
854
* @readonly
855
**/
856
Ticker.RAF = "raf";
857
858
/**
859
* In this mode, Ticker uses the setTimeout API. This provides predictable, adaptive frame timing, but does not
860
* provide the benefits of requestAnimationFrame (screen synch, background throttling).
861
* @property TIMEOUT
862
* @static
863
* @type {String}
864
* @default "timeout"
865
* @readonly
866
**/
867
Ticker.TIMEOUT = "timeout";
868
869
870
// static events:
871
/**
872
* Dispatched each tick. The event will be dispatched to each listener even when the Ticker has been paused using
873
* {{#crossLink "Ticker/setPaused"}}{{/crossLink}}.
874
*
875
* <h4>Example</h4>
876
*
877
* createjs.Ticker.addEventListener("tick", handleTick);
878
* function handleTick(event) {
879
* console.log("Paused:", event.paused, event.delta);
880
* }
881
*
882
* @event tick
883
* @param {Object} target The object that dispatched the event.
884
* @param {String} type The event type.
885
* @param {Boolean} paused Indicates whether the ticker is currently paused.
886
* @param {Number} delta The time elapsed in ms since the last tick.
887
* @param {Number} time The total time in ms since Ticker was initialized.
888
* @param {Number} runTime The total time in ms that Ticker was not paused since it was initialized. For example,
889
* you could determine the amount of time that the Ticker has been paused since initialization with `time-runTime`.
890
* @since 0.6.0
891
*/
892
893
894
// public static properties:
895
/**
896
* Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}, and will be removed in a future version. If true, timingMode will
897
* use {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} by default.
898
* @deprecated Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}.
899
* @property useRAF
900
* @static
901
* @type {Boolean}
902
* @default false
903
**/
904
Ticker.useRAF = false;
905
906
/**
907
* Specifies the timing api (setTimeout or requestAnimationFrame) and mode to use. See
908
* {{#crossLink "Ticker/TIMEOUT"}}{{/crossLink}}, {{#crossLink "Ticker/RAF"}}{{/crossLink}}, and
909
* {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} for mode details.
910
* @property timingMode
911
* @static
912
* @type {String}
913
* @default Ticker.TIMEOUT
914
**/
915
Ticker.timingMode = null;
916
917
/**
918
* Specifies a maximum value for the delta property in the tick event object. This is useful when building time
919
* based animations and systems to prevent issues caused by large time gaps caused by background tabs, system sleep,
920
* alert dialogs, or other blocking routines. Double the expected frame duration is often an effective value
921
* (ex. maxDelta=50 when running at 40fps).
922
*
923
* This does not impact any other values (ex. time, runTime, etc), so you may experience issues if you enable maxDelta
924
* when using both delta and other values.
925
*
926
* If 0, there is no maximum.
927
* @property maxDelta
928
* @static
929
* @type {number}
930
* @default 0
931
*/
932
Ticker.maxDelta = 0;
933
934
/**
935
* When the ticker is paused, all listeners will still receive a tick event, but the <code>paused</code> property
936
* of the event will be `true`. Also, while paused the `runTime` will not increase. See {{#crossLink "Ticker/tick:event"}}{{/crossLink}},
937
* {{#crossLink "Ticker/getTime"}}{{/crossLink}}, and {{#crossLink "Ticker/getEventTime"}}{{/crossLink}} for more
938
* info.
939
*
940
* <h4>Example</h4>
941
*
942
* createjs.Ticker.addEventListener("tick", handleTick);
943
* createjs.Ticker.paused = true;
944
* function handleTick(event) {
945
* console.log(event.paused,
946
* createjs.Ticker.getTime(false),
947
* createjs.Ticker.getTime(true));
948
* }
949
*
950
* @property paused
951
* @static
952
* @type {Boolean}
953
* @default false
954
**/
955
Ticker.paused = false;
956
957
958
// mix-ins:
959
// EventDispatcher methods:
960
Ticker.removeEventListener = null;
961
Ticker.removeAllEventListeners = null;
962
Ticker.dispatchEvent = null;
963
Ticker.hasEventListener = null;
964
Ticker._listeners = null;
965
createjs.EventDispatcher.initialize(Ticker); // inject EventDispatcher methods.
966
Ticker._addEventListener = Ticker.addEventListener;
967
Ticker.addEventListener = function() {
968
!Ticker._inited&&Ticker.init();
969
return Ticker._addEventListener.apply(Ticker, arguments);
970
};
971
972
973
// private static properties:
974
/**
975
* @property _inited
976
* @static
977
* @type {Boolean}
978
* @protected
979
**/
980
Ticker._inited = false;
981
982
/**
983
* @property _startTime
984
* @static
985
* @type {Number}
986
* @protected
987
**/
988
Ticker._startTime = 0;
989
990
/**
991
* @property _pausedTime
992
* @static
993
* @type {Number}
994
* @protected
995
**/
996
Ticker._pausedTime=0;
997
998
/**
999
* The number of ticks that have passed
1000
* @property _ticks
1001
* @static
1002
* @type {Number}
1003
* @protected
1004
**/
1005
Ticker._ticks = 0;
1006
1007
/**
1008
* The number of ticks that have passed while Ticker has been paused
1009
* @property _pausedTicks
1010
* @static
1011
* @type {Number}
1012
* @protected
1013
**/
1014
Ticker._pausedTicks = 0;
1015
1016
/**
1017
* @property _interval
1018
* @static
1019
* @type {Number}
1020
* @protected
1021
**/
1022
Ticker._interval = 50;
1023
1024
/**
1025
* @property _lastTime
1026
* @static
1027
* @type {Number}
1028
* @protected
1029
**/
1030
Ticker._lastTime = 0;
1031
1032
/**
1033
* @property _times
1034
* @static
1035
* @type {Array}
1036
* @protected
1037
**/
1038
Ticker._times = null;
1039
1040
/**
1041
* @property _tickTimes
1042
* @static
1043
* @type {Array}
1044
* @protected
1045
**/
1046
Ticker._tickTimes = null;
1047
1048
/**
1049
* Stores the timeout or requestAnimationFrame id.
1050
* @property _timerId
1051
* @static
1052
* @type {Number}
1053
* @protected
1054
**/
1055
Ticker._timerId = null;
1056
1057
/**
1058
* True if currently using requestAnimationFrame, false if using setTimeout. This may be different than timingMode
1059
* if that property changed and a tick hasn't fired.
1060
* @property _raf
1061
* @static
1062
* @type {Boolean}
1063
* @protected
1064
**/
1065
Ticker._raf = true;
1066
1067
1068
// static getter / setters:
1069
/**
1070
* Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead.
1071
* @method setInterval
1072
* @static
1073
* @param {Number} interval
1074
* @deprecated
1075
**/
1076
Ticker.setInterval = function(interval) {
1077
Ticker._interval = interval;
1078
if (!Ticker._inited) { return; }
1079
Ticker._setupTick();
1080
};
1081
1082
/**
1083
* Use the {{#crossLink "Ticker/interval:property"}}{{/crossLink}} property instead.
1084
* @method getInterval
1085
* @static
1086
* @return {Number}
1087
* @deprecated
1088
**/
1089
Ticker.getInterval = function() {
1090
return Ticker._interval;
1091
};
1092
1093
/**
1094
* Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead.
1095
* @method setFPS
1096
* @static
1097
* @param {Number} value
1098
* @deprecated
1099
**/
1100
Ticker.setFPS = function(value) {
1101
Ticker.setInterval(1000/value);
1102
};
1103
1104
/**
1105
* Use the {{#crossLink "Ticker/framerate:property"}}{{/crossLink}} property instead.
1106
* @method getFPS
1107
* @static
1108
* @return {Number}
1109
* @deprecated
1110
**/
1111
Ticker.getFPS = function() {
1112
return 1000/Ticker._interval;
1113
};
1114
1115
/**
1116
* Indicates the target time (in milliseconds) between ticks. Default is 50 (20 FPS).
1117
* Note that actual time between ticks may be more than specified depending on CPU load.
1118
* This property is ignored if the ticker is using the `RAF` timing mode.
1119
* @property interval
1120
* @static
1121
* @type {Number}
1122
**/
1123
1124
/**
1125
* Indicates the target frame rate in frames per second (FPS). Effectively just a shortcut to `interval`, where
1126
* `framerate == 1000/interval`.
1127
* @property framerate
1128
* @static
1129
* @type {Number}
1130
**/
1131
try {
1132
Object.defineProperties(Ticker, {
1133
interval: { get: Ticker.getInterval, set: Ticker.setInterval },
1134
framerate: { get: Ticker.getFPS, set: Ticker.setFPS }
1135
});
1136
} catch (e) { console.log(e); }
1137
1138
1139
// public static methods:
1140
/**
1141
* Starts the tick. This is called automatically when the first listener is added.
1142
* @method init
1143
* @static
1144
**/
1145
Ticker.init = function() {
1146
if (Ticker._inited) { return; }
1147
Ticker._inited = true;
1148
Ticker._times = [];
1149
Ticker._tickTimes = [];
1150
Ticker._startTime = Ticker._getTime();
1151
Ticker._times.push(Ticker._lastTime = 0);
1152
Ticker.interval = Ticker._interval;
1153
};
1154
1155
/**
1156
* Stops the Ticker and removes all listeners. Use init() to restart the Ticker.
1157
* @method reset
1158
* @static
1159
**/
1160
Ticker.reset = function() {
1161
if (Ticker._raf) {
1162
var f = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame;
1163
f&&f(Ticker._timerId);
1164
} else {
1165
clearTimeout(Ticker._timerId);
1166
}
1167
Ticker.removeAllEventListeners("tick");
1168
Ticker._timerId = Ticker._times = Ticker._tickTimes = null;
1169
Ticker._startTime = Ticker._lastTime = Ticker._ticks = 0;
1170
Ticker._inited = false;
1171
};
1172
1173
/**
1174
* Returns the average time spent within a tick. This can vary significantly from the value provided by getMeasuredFPS
1175
* because it only measures the time spent within the tick execution stack.
1176
*
1177
* Example 1: With a target FPS of 20, getMeasuredFPS() returns 20fps, which indicates an average of 50ms between
1178
* the end of one tick and the end of the next. However, getMeasuredTickTime() returns 15ms. This indicates that
1179
* there may be up to 35ms of "idle" time between the end of one tick and the start of the next.
1180
*
1181
* Example 2: With a target FPS of 30, getFPS() returns 10fps, which indicates an average of 100ms between the end of
1182
* one tick and the end of the next. However, getMeasuredTickTime() returns 20ms. This would indicate that something
1183
* other than the tick is using ~80ms (another script, DOM rendering, etc).
1184
* @method getMeasuredTickTime
1185
* @static
1186
* @param {Number} [ticks] The number of previous ticks over which to measure the average time spent in a tick.
1187
* Defaults to the number of ticks per second. To get only the last tick's time, pass in 1.
1188
* @return {Number} The average time spent in a tick in milliseconds.
1189
**/
1190
Ticker.getMeasuredTickTime = function(ticks) {
1191
var ttl=0, times=Ticker._tickTimes;
1192
if (!times || times.length < 1) { return -1; }
1193
1194
// by default, calculate average for the past ~1 second:
1195
ticks = Math.min(times.length, ticks||(Ticker.getFPS()|0));
1196
for (var i=0; i<ticks; i++) { ttl += times[i]; }
1197
return ttl/ticks;
1198
};
1199
1200
/**
1201
* Returns the actual frames / ticks per second.
1202
* @method getMeasuredFPS
1203
* @static
1204
* @param {Number} [ticks] The number of previous ticks over which to measure the actual frames / ticks per second.
1205
* Defaults to the number of ticks per second.
1206
* @return {Number} The actual frames / ticks per second. Depending on performance, this may differ
1207
* from the target frames per second.
1208
**/
1209
Ticker.getMeasuredFPS = function(ticks) {
1210
var times = Ticker._times;
1211
if (!times || times.length < 2) { return -1; }
1212
1213
// by default, calculate fps for the past ~1 second:
1214
ticks = Math.min(times.length-1, ticks||(Ticker.getFPS()|0));
1215
return 1000/((times[0]-times[ticks])/ticks);
1216
};
1217
1218
/**
1219
* Use the {{#crossLink "Ticker/paused:property"}}{{/crossLink}} property instead.
1220
* @method setPaused
1221
* @static
1222
* @param {Boolean} value
1223
* @deprecated
1224
**/
1225
Ticker.setPaused = function(value) {
1226
// TODO: deprecated.
1227
Ticker.paused = value;
1228
};
1229
1230
/**
1231
* Use the {{#crossLink "Ticker/paused:property"}}{{/crossLink}} property instead.
1232
* @method getPaused
1233
* @static
1234
* @return {Boolean}
1235
* @deprecated
1236
**/
1237
Ticker.getPaused = function() {
1238
// TODO: deprecated.
1239
return Ticker.paused;
1240
};
1241
1242
/**
1243
* Returns the number of milliseconds that have elapsed since Ticker was initialized via {{#crossLink "Ticker/init"}}.
1244
* Returns -1 if Ticker has not been initialized. For example, you could use
1245
* this in a time synchronized animation to determine the exact amount of time that has elapsed.
1246
* @method getTime
1247
* @static
1248
* @param {Boolean} [runTime=false] If true only time elapsed while Ticker was not paused will be returned.
1249
* If false, the value returned will be total time elapsed since the first tick event listener was added.
1250
* @return {Number} Number of milliseconds that have elapsed since Ticker was initialized or -1.
1251
**/
1252
Ticker.getTime = function(runTime) {
1253
return Ticker._startTime ? Ticker._getTime() - (runTime ? Ticker._pausedTime : 0) : -1;
1254
};
1255
1256
/**
1257
* Similar to the {{#crossLink "Ticker/getTime"}}{{/crossLink}} method, but returns the time on the most recent {{#crossLink "Ticker/tick:event"}}{{/crossLink}}
1258
* event object.
1259
* @method getEventTime
1260
* @static
1261
* @param runTime {Boolean} [runTime=false] If true, the runTime property will be returned instead of time.
1262
* @returns {number} The time or runTime property from the most recent tick event or -1.
1263
*/
1264
Ticker.getEventTime = function(runTime) {
1265
return Ticker._startTime ? (Ticker._lastTime || Ticker._startTime) - (runTime ? Ticker._pausedTime : 0) : -1;
1266
};
1267
1268
/**
1269
* Returns the number of ticks that have been broadcast by Ticker.
1270
* @method getTicks
1271
* @static
1272
* @param {Boolean} pauseable Indicates whether to include ticks that would have been broadcast
1273
* while Ticker was paused. If true only tick events broadcast while Ticker is not paused will be returned.
1274
* If false, tick events that would have been broadcast while Ticker was paused will be included in the return
1275
* value. The default value is false.
1276
* @return {Number} of ticks that have been broadcast.
1277
**/
1278
Ticker.getTicks = function(pauseable) {
1279
return Ticker._ticks - (pauseable ? Ticker._pausedTicks : 0);
1280
};
1281
1282
1283
// private static methods:
1284
/**
1285
* @method _handleSynch
1286
* @static
1287
* @protected
1288
**/
1289
Ticker._handleSynch = function() {
1290
Ticker._timerId = null;
1291
Ticker._setupTick();
1292
1293
// run if enough time has elapsed, with a little bit of flexibility to be early:
1294
if (Ticker._getTime() - Ticker._lastTime >= (Ticker._interval-1)*0.97) {
1295
Ticker._tick();
1296
}
1297
};
1298
1299
/**
1300
* @method _handleRAF
1301
* @static
1302
* @protected
1303
**/
1304
Ticker._handleRAF = function() {
1305
Ticker._timerId = null;
1306
Ticker._setupTick();
1307
Ticker._tick();
1308
};
1309
1310
/**
1311
* @method _handleTimeout
1312
* @static
1313
* @protected
1314
**/
1315
Ticker._handleTimeout = function() {
1316
Ticker._timerId = null;
1317
Ticker._setupTick();
1318
Ticker._tick();
1319
};
1320
1321
/**
1322
* @method _setupTick
1323
* @static
1324
* @protected
1325
**/
1326
Ticker._setupTick = function() {
1327
if (Ticker._timerId != null) { return; } // avoid duplicates
1328
1329
var mode = Ticker.timingMode||(Ticker.useRAF&&Ticker.RAF_SYNCHED);
1330
if (mode == Ticker.RAF_SYNCHED || mode == Ticker.RAF) {
1331
var f = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame;
1332
if (f) {
1333
Ticker._timerId = f(mode == Ticker.RAF ? Ticker._handleRAF : Ticker._handleSynch);
1334
Ticker._raf = true;
1335
return;
1336
}
1337
}
1338
Ticker._raf = false;
1339
Ticker._timerId = setTimeout(Ticker._handleTimeout, Ticker._interval);
1340
};
1341
1342
/**
1343
* @method _tick
1344
* @static
1345
* @protected
1346
**/
1347
Ticker._tick = function() {
1348
var paused = Ticker.paused;
1349
var time = Ticker._getTime();
1350
var elapsedTime = time-Ticker._lastTime;
1351
Ticker._lastTime = time;
1352
Ticker._ticks++;
1353
1354
if (paused) {
1355
Ticker._pausedTicks++;
1356
Ticker._pausedTime += elapsedTime;
1357
}
1358
1359
if (Ticker.hasEventListener("tick")) {
1360
var event = new createjs.Event("tick");
1361
var maxDelta = Ticker.maxDelta;
1362
event.delta = (maxDelta && elapsedTime > maxDelta) ? maxDelta : elapsedTime;
1363
event.paused = paused;
1364
event.time = time;
1365
event.runTime = time-Ticker._pausedTime;
1366
Ticker.dispatchEvent(event);
1367
}
1368
1369
Ticker._tickTimes.unshift(Ticker._getTime()-time);
1370
while (Ticker._tickTimes.length > 100) { Ticker._tickTimes.pop(); }
1371
1372
Ticker._times.unshift(time);
1373
while (Ticker._times.length > 100) { Ticker._times.pop(); }
1374
};
1375
1376
/**
1377
* @method _getTime
1378
* @static
1379
* @protected
1380
**/
1381
var now = window.performance && (performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow);
1382
Ticker._getTime = function() {
1383
return ((now&&now.call(performance))||(new Date().getTime())) - Ticker._startTime;
1384
};
1385
1386
1387
createjs.Ticker = Ticker;
1388
}());
1389
1390
//##############################################################################
1391
// UID.js
1392
//##############################################################################
1393
1394
this.createjs = this.createjs||{};
1395
1396
(function() {
1397
"use strict";
1398
1399
1400
// constructor:
1401
/**
1402
* Global utility for generating sequential unique ID numbers. The UID class uses a static interface (ex. <code>UID.get()</code>)
1403
* and should not be instantiated.
1404
* @class UID
1405
* @static
1406
**/
1407
function UID() {
1408
throw "UID cannot be instantiated";
1409
}
1410
1411
1412
// private static properties:
1413
/**
1414
* @property _nextID
1415
* @type Number
1416
* @protected
1417
**/
1418
UID._nextID = 0;
1419
1420
1421
// public static methods:
1422
/**
1423
* Returns the next unique id.
1424
* @method get
1425
* @return {Number} The next unique id
1426
* @static
1427
**/
1428
UID.get = function() {
1429
return UID._nextID++;
1430
};
1431
1432
1433
createjs.UID = UID;
1434
}());
1435
1436
//##############################################################################
1437
// MouseEvent.js
1438
//##############################################################################
1439
1440
this.createjs = this.createjs||{};
1441
1442
(function() {
1443
"use strict";
1444
1445
1446
// constructor:
1447
/**
1448
* Passed as the parameter to all mouse/pointer/touch related events. For a listing of mouse events and their properties,
1449
* see the {{#crossLink "DisplayObject"}}{{/crossLink}} and {{#crossLink "Stage"}}{{/crossLink}} event listings.
1450
* @class MouseEvent
1451
* @param {String} type The event type.
1452
* @param {Boolean} bubbles Indicates whether the event will bubble through the display list.
1453
* @param {Boolean} cancelable Indicates whether the default behaviour of this event can be cancelled.
1454
* @param {Number} stageX The normalized x position relative to the stage.
1455
* @param {Number} stageY The normalized y position relative to the stage.
1456
* @param {MouseEvent} nativeEvent The native DOM event related to this mouse event.
1457
* @param {Number} pointerID The unique id for the pointer.
1458
* @param {Boolean} primary Indicates whether this is the primary pointer in a multitouch environment.
1459
* @param {Number} rawX The raw x position relative to the stage.
1460
* @param {Number} rawY The raw y position relative to the stage.
1461
* @param {DisplayObject} relatedTarget The secondary target for the event.
1462
* @extends Event
1463
* @constructor
1464
**/
1465
function MouseEvent(type, bubbles, cancelable, stageX, stageY, nativeEvent, pointerID, primary, rawX, rawY, relatedTarget) {
1466
this.Event_constructor(type, bubbles, cancelable);
1467
1468
1469
// public properties:
1470
/**
1471
* The normalized x position on the stage. This will always be within the range 0 to stage width.
1472
* @property stageX
1473
* @type Number
1474
*/
1475
this.stageX = stageX;
1476
1477
/**
1478
* The normalized y position on the stage. This will always be within the range 0 to stage height.
1479
* @property stageY
1480
* @type Number
1481
**/
1482
this.stageY = stageY;
1483
1484
/**
1485
* The raw x position relative to the stage. Normally this will be the same as the stageX value, unless
1486
* stage.mouseMoveOutside is true and the pointer is outside of the stage bounds.
1487
* @property rawX
1488
* @type Number
1489
*/
1490
this.rawX = (rawX==null)?stageX:rawX;
1491
1492
/**
1493
* The raw y position relative to the stage. Normally this will be the same as the stageY value, unless
1494
* stage.mouseMoveOutside is true and the pointer is outside of the stage bounds.
1495
* @property rawY
1496
* @type Number
1497
*/
1498
this.rawY = (rawY==null)?stageY:rawY;
1499
1500
/**
1501
* The native MouseEvent generated by the browser. The properties and API for this
1502
* event may differ between browsers. This property will be null if the
1503
* EaselJS property was not directly generated from a native MouseEvent.
1504
* @property nativeEvent
1505
* @type HtmlMouseEvent
1506
* @default null
1507
**/
1508
this.nativeEvent = nativeEvent;
1509
1510
/**
1511
* The unique id for the pointer (touch point or cursor). This will be either -1 for the mouse, or the system
1512
* supplied id value.
1513
* @property pointerID
1514
* @type {Number}
1515
*/
1516
this.pointerID = pointerID;
1517
1518
/**
1519
* Indicates whether this is the primary pointer in a multitouch environment. This will always be true for the mouse.
1520
* For touch pointers, the first pointer in the current stack will be considered the primary pointer.
1521
* @property primary
1522
* @type {Boolean}
1523
*/
1524
this.primary = !!primary;
1525
1526
/**
1527
* The secondary target for the event, if applicable. This is used for mouseout/rollout
1528
* events to indicate the object that the mouse entered from, mouseover/rollover for the object the mouse exited,
1529
* and stagemousedown/stagemouseup events for the object that was the under the cursor, if any.
1530
*
1531
* Only valid interaction targets will be returned (ie. objects with mouse listeners or a cursor set).
1532
* @property relatedTarget
1533
* @type {DisplayObject}
1534
*/
1535
this.relatedTarget = relatedTarget;
1536
}
1537
var p = createjs.extend(MouseEvent, createjs.Event);
1538
1539
// TODO: deprecated
1540
// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
1541
1542
1543
// getter / setters:
1544
/**
1545
* Returns the x position of the mouse in the local coordinate system of the current target (ie. the dispatcher).
1546
* @property localX
1547
* @type {Number}
1548
* @readonly
1549
*/
1550
p._get_localX = function() {
1551
return this.currentTarget.globalToLocal(this.rawX, this.rawY).x;
1552
};
1553
1554
/**
1555
* Returns the y position of the mouse in the local coordinate system of the current target (ie. the dispatcher).
1556
* @property localY
1557
* @type {Number}
1558
* @readonly
1559
*/
1560
p._get_localY = function() {
1561
return this.currentTarget.globalToLocal(this.rawX, this.rawY).y;
1562
};
1563
1564
/**
1565
* Indicates whether the event was generated by a touch input (versus a mouse input).
1566
* @property isTouch
1567
* @type {Boolean}
1568
* @readonly
1569
*/
1570
p._get_isTouch = function() {
1571
return this.pointerID !== -1;
1572
};
1573
1574
1575
try {
1576
Object.defineProperties(p, {
1577
localX: { get: p._get_localX },
1578
localY: { get: p._get_localY },
1579
isTouch: { get: p._get_isTouch }
1580
});
1581
} catch (e) {} // TODO: use Log
1582
1583
1584
// public methods:
1585
/**
1586
* Returns a clone of the MouseEvent instance.
1587
* @method clone
1588
* @return {MouseEvent} a clone of the MouseEvent instance.
1589
**/
1590
p.clone = function() {
1591
return new MouseEvent(this.type, this.bubbles, this.cancelable, this.stageX, this.stageY, this.nativeEvent, this.pointerID, this.primary, this.rawX, this.rawY);
1592
};
1593
1594
/**
1595
* Returns a string representation of this object.
1596
* @method toString
1597
* @return {String} a string representation of the instance.
1598
**/
1599
p.toString = function() {
1600
return "[MouseEvent (type="+this.type+" stageX="+this.stageX+" stageY="+this.stageY+")]";
1601
};
1602
1603
1604
createjs.MouseEvent = createjs.promote(MouseEvent, "Event");
1605
}());
1606
1607
//##############################################################################
1608
// Matrix2D.js
1609
//##############################################################################
1610
1611
this.createjs = this.createjs||{};
1612
1613
(function() {
1614
"use strict";
1615
1616
1617
// constructor:
1618
/**
1619
* Represents an affine transformation matrix, and provides tools for constructing and concatenating matrices.
1620
*
1621
* This matrix can be visualized as:
1622
*
1623
* [ a c tx
1624
* b d ty
1625
* 0 0 1 ]
1626
*
1627
* Note the locations of b and c.
1628
*
1629
* @class Matrix2D
1630
* @param {Number} [a=1] Specifies the a property for the new matrix.
1631
* @param {Number} [b=0] Specifies the b property for the new matrix.
1632
* @param {Number} [c=0] Specifies the c property for the new matrix.
1633
* @param {Number} [d=1] Specifies the d property for the new matrix.
1634
* @param {Number} [tx=0] Specifies the tx property for the new matrix.
1635
* @param {Number} [ty=0] Specifies the ty property for the new matrix.
1636
* @constructor
1637
**/
1638
function Matrix2D(a, b, c, d, tx, ty) {
1639
this.setValues(a,b,c,d,tx,ty);
1640
1641
// public properties:
1642
// assigned in the setValues method.
1643
/**
1644
* Position (0, 0) in a 3x3 affine transformation matrix.
1645
* @property a
1646
* @type Number
1647
**/
1648
1649
/**
1650
* Position (0, 1) in a 3x3 affine transformation matrix.
1651
* @property b
1652
* @type Number
1653
**/
1654
1655
/**
1656
* Position (1, 0) in a 3x3 affine transformation matrix.
1657
* @property c
1658
* @type Number
1659
**/
1660
1661
/**
1662
* Position (1, 1) in a 3x3 affine transformation matrix.
1663
* @property d
1664
* @type Number
1665
**/
1666
1667
/**
1668
* Position (2, 0) in a 3x3 affine transformation matrix.
1669
* @property tx
1670
* @type Number
1671
**/
1672
1673
/**
1674
* Position (2, 1) in a 3x3 affine transformation matrix.
1675
* @property ty
1676
* @type Number
1677
**/
1678
}
1679
var p = Matrix2D.prototype;
1680
1681
/**
1682
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
1683
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
1684
* for details.
1685
*
1686
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
1687
*
1688
* @method initialize
1689
* @protected
1690
* @deprecated
1691
*/
1692
// p.initialize = function() {}; // searchable for devs wondering where it is.
1693
1694
1695
// constants:
1696
/**
1697
* Multiplier for converting degrees to radians. Used internally by Matrix2D.
1698
* @property DEG_TO_RAD
1699
* @static
1700
* @final
1701
* @type Number
1702
* @readonly
1703
**/
1704
Matrix2D.DEG_TO_RAD = Math.PI/180;
1705
1706
1707
// static public properties:
1708
/**
1709
* An identity matrix, representing a null transformation.
1710
* @property identity
1711
* @static
1712
* @type Matrix2D
1713
* @readonly
1714
**/
1715
Matrix2D.identity = null; // set at bottom of class definition.
1716
1717
1718
// public methods:
1719
/**
1720
* Sets the specified values on this instance.
1721
* @method setValues
1722
* @param {Number} [a=1] Specifies the a property for the new matrix.
1723
* @param {Number} [b=0] Specifies the b property for the new matrix.
1724
* @param {Number} [c=0] Specifies the c property for the new matrix.
1725
* @param {Number} [d=1] Specifies the d property for the new matrix.
1726
* @param {Number} [tx=0] Specifies the tx property for the new matrix.
1727
* @param {Number} [ty=0] Specifies the ty property for the new matrix.
1728
* @return {Matrix2D} This instance. Useful for chaining method calls.
1729
*/
1730
p.setValues = function(a, b, c, d, tx, ty) {
1731
// don't forget to update docs in the constructor if these change:
1732
this.a = (a == null) ? 1 : a;
1733
this.b = b || 0;
1734
this.c = c || 0;
1735
this.d = (d == null) ? 1 : d;
1736
this.tx = tx || 0;
1737
this.ty = ty || 0;
1738
return this;
1739
};
1740
1741
/**
1742
* Appends the specified matrix properties to this matrix. All parameters are required.
1743
* This is the equivalent of multiplying `(this matrix) * (specified matrix)`.
1744
* @method append
1745
* @param {Number} a
1746
* @param {Number} b
1747
* @param {Number} c
1748
* @param {Number} d
1749
* @param {Number} tx
1750
* @param {Number} ty
1751
* @return {Matrix2D} This matrix. Useful for chaining method calls.
1752
**/
1753
p.append = function(a, b, c, d, tx, ty) {
1754
var a1 = this.a;
1755
var b1 = this.b;
1756
var c1 = this.c;
1757
var d1 = this.d;
1758
if (a != 1 || b != 0 || c != 0 || d != 1) {
1759
this.a = a1*a+c1*b;
1760
this.b = b1*a+d1*b;
1761
this.c = a1*c+c1*d;
1762
this.d = b1*c+d1*d;
1763
}
1764
this.tx = a1*tx+c1*ty+this.tx;
1765
this.ty = b1*tx+d1*ty+this.ty;
1766
return this;
1767
};
1768
1769
/**
1770
* Prepends the specified matrix properties to this matrix.
1771
* This is the equivalent of multiplying `(specified matrix) * (this matrix)`.
1772
* All parameters are required.
1773
* @method prepend
1774
* @param {Number} a
1775
* @param {Number} b
1776
* @param {Number} c
1777
* @param {Number} d
1778
* @param {Number} tx
1779
* @param {Number} ty
1780
* @return {Matrix2D} This matrix. Useful for chaining method calls.
1781
**/
1782
p.prepend = function(a, b, c, d, tx, ty) {
1783
var a1 = this.a;
1784
var c1 = this.c;
1785
var tx1 = this.tx;
1786
1787
this.a = a*a1+c*this.b;
1788
this.b = b*a1+d*this.b;
1789
this.c = a*c1+c*this.d;
1790
this.d = b*c1+d*this.d;
1791
this.tx = a*tx1+c*this.ty+tx;
1792
this.ty = b*tx1+d*this.ty+ty;
1793
return this;
1794
};
1795
1796
/**
1797
* Appends the specified matrix to this matrix.
1798
* This is the equivalent of multiplying `(this matrix) * (specified matrix)`.
1799
* @method appendMatrix
1800
* @param {Matrix2D} matrix
1801
* @return {Matrix2D} This matrix. Useful for chaining method calls.
1802
**/
1803
p.appendMatrix = function(matrix) {
1804
return this.append(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
1805
};
1806
1807
/**
1808
* Prepends the specified matrix to this matrix.
1809
* This is the equivalent of multiplying `(specified matrix) * (this matrix)`.
1810
* For example, you could calculate the combined transformation for a child object using:
1811
*
1812
* var o = myDisplayObject;
1813
* var mtx = o.getMatrix();
1814
* while (o = o.parent) {
1815
* // prepend each parent's transformation in turn:
1816
* o.prependMatrix(o.getMatrix());
1817
* }
1818
* @method prependMatrix
1819
* @param {Matrix2D} matrix
1820
* @return {Matrix2D} This matrix. Useful for chaining method calls.
1821
**/
1822
p.prependMatrix = function(matrix) {
1823
return this.prepend(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
1824
};
1825
1826
/**
1827
* Generates matrix properties from the specified display object transform properties, and appends them to this matrix.
1828
* For example, you can use this to generate a matrix representing the transformations of a display object:
1829
*
1830
* var mtx = new createjs.Matrix2D();
1831
* mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation);
1832
* @method appendTransform
1833
* @param {Number} x
1834
* @param {Number} y
1835
* @param {Number} scaleX
1836
* @param {Number} scaleY
1837
* @param {Number} rotation
1838
* @param {Number} skewX
1839
* @param {Number} skewY
1840
* @param {Number} regX Optional.
1841
* @param {Number} regY Optional.
1842
* @return {Matrix2D} This matrix. Useful for chaining method calls.
1843
**/
1844
p.appendTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) {
1845
if (rotation%360) {
1846
var r = rotation*Matrix2D.DEG_TO_RAD;
1847
var cos = Math.cos(r);
1848
var sin = Math.sin(r);
1849
} else {
1850
cos = 1;
1851
sin = 0;
1852
}
1853
1854
if (skewX || skewY) {
1855
// TODO: can this be combined into a single append operation?
1856
skewX *= Matrix2D.DEG_TO_RAD;
1857
skewY *= Matrix2D.DEG_TO_RAD;
1858
this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y);
1859
this.append(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, 0, 0);
1860
} else {
1861
this.append(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, x, y);
1862
}
1863
1864
if (regX || regY) {
1865
// append the registration offset:
1866
this.tx -= regX*this.a+regY*this.c;
1867
this.ty -= regX*this.b+regY*this.d;
1868
}
1869
return this;
1870
};
1871
1872
/**
1873
* Generates matrix properties from the specified display object transform properties, and prepends them to this matrix.
1874
* For example, you could calculate the combined transformation for a child object using:
1875
*
1876
* var o = myDisplayObject;
1877
* var mtx = new createjs.Matrix2D();
1878
* do {
1879
* // prepend each parent's transformation in turn:
1880
* mtx.prependTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.regX, o.regY);
1881
* } while (o = o.parent);
1882
*
1883
* Note that the above example would not account for {{#crossLink "DisplayObject/transformMatrix:property"}}{{/crossLink}}
1884
* values. See {{#crossLink "Matrix2D/prependMatrix"}}{{/crossLink}} for an example that does.
1885
* @method prependTransform
1886
* @param {Number} x
1887
* @param {Number} y
1888
* @param {Number} scaleX
1889
* @param {Number} scaleY
1890
* @param {Number} rotation
1891
* @param {Number} skewX
1892
* @param {Number} skewY
1893
* @param {Number} regX Optional.
1894
* @param {Number} regY Optional.
1895
* @return {Matrix2D} This matrix. Useful for chaining method calls.
1896
**/
1897
p.prependTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) {
1898
if (rotation%360) {
1899
var r = rotation*Matrix2D.DEG_TO_RAD;
1900
var cos = Math.cos(r);
1901
var sin = Math.sin(r);
1902
} else {
1903
cos = 1;
1904
sin = 0;
1905
}
1906
1907
if (regX || regY) {
1908
// prepend the registration offset:
1909
this.tx -= regX; this.ty -= regY;
1910
}
1911
if (skewX || skewY) {
1912
// TODO: can this be combined into a single prepend operation?
1913
skewX *= Matrix2D.DEG_TO_RAD;
1914
skewY *= Matrix2D.DEG_TO_RAD;
1915
this.prepend(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, 0, 0);
1916
this.prepend(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y);
1917
} else {
1918
this.prepend(cos*scaleX, sin*scaleX, -sin*scaleY, cos*scaleY, x, y);
1919
}
1920
return this;
1921
};
1922
1923
/**
1924
* Applies a clockwise rotation transformation to the matrix.
1925
* @method rotate
1926
* @param {Number} angle The angle to rotate by, in degrees. To use a value in radians, multiply it by `180/Math.PI`.
1927
* @return {Matrix2D} This matrix. Useful for chaining method calls.
1928
**/
1929
p.rotate = function(angle) {
1930
angle = angle*Matrix2D.DEG_TO_RAD;
1931
var cos = Math.cos(angle);
1932
var sin = Math.sin(angle);
1933
1934
var a1 = this.a;
1935
var b1 = this.b;
1936
1937
this.a = a1*cos+this.c*sin;
1938
this.b = b1*cos+this.d*sin;
1939
this.c = -a1*sin+this.c*cos;
1940
this.d = -b1*sin+this.d*cos;
1941
return this;
1942
};
1943
1944
/**
1945
* Applies a skew transformation to the matrix.
1946
* @method skew
1947
* @param {Number} skewX The amount to skew horizontally in degrees. To use a value in radians, multiply it by `180/Math.PI`.
1948
* @param {Number} skewY The amount to skew vertically in degrees.
1949
* @return {Matrix2D} This matrix. Useful for chaining method calls.
1950
*/
1951
p.skew = function(skewX, skewY) {
1952
skewX = skewX*Matrix2D.DEG_TO_RAD;
1953
skewY = skewY*Matrix2D.DEG_TO_RAD;
1954
this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), 0, 0);
1955
return this;
1956
};
1957
1958
/**
1959
* Applies a scale transformation to the matrix.
1960
* @method scale
1961
* @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.
1962
* @param {Number} y The amount to scale vertically.
1963
* @return {Matrix2D} This matrix. Useful for chaining method calls.
1964
**/
1965
p.scale = function(x, y) {
1966
this.a *= x;
1967
this.b *= x;
1968
this.c *= y;
1969
this.d *= y;
1970
//this.tx *= x;
1971
//this.ty *= y;
1972
return this;
1973
};
1974
1975
/**
1976
* Translates the matrix on the x and y axes.
1977
* @method translate
1978
* @param {Number} x
1979
* @param {Number} y
1980
* @return {Matrix2D} This matrix. Useful for chaining method calls.
1981
**/
1982
p.translate = function(x, y) {
1983
this.tx += this.a*x + this.c*y;
1984
this.ty += this.b*x + this.d*y;
1985
return this;
1986
};
1987
1988
/**
1989
* Sets the properties of the matrix to those of an identity matrix (one that applies a null transformation).
1990
* @method identity
1991
* @return {Matrix2D} This matrix. Useful for chaining method calls.
1992
**/
1993
p.identity = function() {
1994
this.a = this.d = 1;
1995
this.b = this.c = this.tx = this.ty = 0;
1996
return this;
1997
};
1998
1999
/**
2000
* Inverts the matrix, causing it to perform the opposite transformation.
2001
* @method invert
2002
* @return {Matrix2D} This matrix. Useful for chaining method calls.
2003
**/
2004
p.invert = function() {
2005
var a1 = this.a;
2006
var b1 = this.b;
2007
var c1 = this.c;
2008
var d1 = this.d;
2009
var tx1 = this.tx;
2010
var n = a1*d1-b1*c1;
2011
2012
this.a = d1/n;
2013
this.b = -b1/n;
2014
this.c = -c1/n;
2015
this.d = a1/n;
2016
this.tx = (c1*this.ty-d1*tx1)/n;
2017
this.ty = -(a1*this.ty-b1*tx1)/n;
2018
return this;
2019
};
2020
2021
/**
2022
* Returns true if the matrix is an identity matrix.
2023
* @method isIdentity
2024
* @return {Boolean}
2025
**/
2026
p.isIdentity = function() {
2027
return this.tx === 0 && this.ty === 0 && this.a === 1 && this.b === 0 && this.c === 0 && this.d === 1;
2028
};
2029
2030
/**
2031
* Returns true if this matrix is equal to the specified matrix (all property values are equal).
2032
* @method equals
2033
* @param {Matrix2D} matrix The matrix to compare.
2034
* @return {Boolean}
2035
**/
2036
p.equals = function(matrix) {
2037
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;
2038
};
2039
2040
/**
2041
* Transforms a point according to this matrix.
2042
* @method transformPoint
2043
* @param {Number} x The x component of the point to transform.
2044
* @param {Number} y The y component of the point to transform.
2045
* @param {Point | Object} [pt] An object to copy the result into. If omitted a generic object with x/y properties will be returned.
2046
* @return {Point} This matrix. Useful for chaining method calls.
2047
**/
2048
p.transformPoint = function(x, y, pt) {
2049
pt = pt||{};
2050
pt.x = x*this.a+y*this.c+this.tx;
2051
pt.y = x*this.b+y*this.d+this.ty;
2052
return pt;
2053
};
2054
2055
/**
2056
* Decomposes the matrix into transform properties (x, y, scaleX, scaleY, and rotation). Note that these values
2057
* may not match the transform properties you used to generate the matrix, though they will produce the same visual
2058
* results.
2059
* @method decompose
2060
* @param {Object} target The object to apply the transform properties to. If null, then a new object will be returned.
2061
* @return {Object} The target, or a new generic object with the transform properties applied.
2062
*/
2063
p.decompose = function(target) {
2064
// 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
2065
if (target == null) { target = {}; }
2066
target.x = this.tx;
2067
target.y = this.ty;
2068
target.scaleX = Math.sqrt(this.a * this.a + this.b * this.b);
2069
target.scaleY = Math.sqrt(this.c * this.c + this.d * this.d);
2070
2071
var skewX = Math.atan2(-this.c, this.d);
2072
var skewY = Math.atan2(this.b, this.a);
2073
2074
var delta = Math.abs(1-skewX/skewY);
2075
if (delta < 0.00001) { // effectively identical, can use rotation:
2076
target.rotation = skewY/Matrix2D.DEG_TO_RAD;
2077
if (this.a < 0 && this.d >= 0) {
2078
target.rotation += (target.rotation <= 0) ? 180 : -180;
2079
}
2080
target.skewX = target.skewY = 0;
2081
} else {
2082
target.skewX = skewX/Matrix2D.DEG_TO_RAD;
2083
target.skewY = skewY/Matrix2D.DEG_TO_RAD;
2084
}
2085
return target;
2086
};
2087
2088
/**
2089
* Copies all properties from the specified matrix to this matrix.
2090
* @method copy
2091
* @param {Matrix2D} matrix The matrix to copy properties from.
2092
* @return {Matrix2D} This matrix. Useful for chaining method calls.
2093
*/
2094
p.copy = function(matrix) {
2095
return this.setValues(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
2096
};
2097
2098
/**
2099
* Returns a clone of the Matrix2D instance.
2100
* @method clone
2101
* @return {Matrix2D} a clone of the Matrix2D instance.
2102
**/
2103
p.clone = function() {
2104
return new Matrix2D(this.a, this.b, this.c, this.d, this.tx, this.ty);
2105
};
2106
2107
/**
2108
* Returns a string representation of this object.
2109
* @method toString
2110
* @return {String} a string representation of the instance.
2111
**/
2112
p.toString = function() {
2113
return "[Matrix2D (a="+this.a+" b="+this.b+" c="+this.c+" d="+this.d+" tx="+this.tx+" ty="+this.ty+")]";
2114
};
2115
2116
// this has to be populated after the class is defined:
2117
Matrix2D.identity = new Matrix2D();
2118
2119
2120
createjs.Matrix2D = Matrix2D;
2121
}());
2122
2123
//##############################################################################
2124
// DisplayProps.js
2125
//##############################################################################
2126
2127
this.createjs = this.createjs||{};
2128
2129
(function() {
2130
"use strict";
2131
2132
/**
2133
* Used for calculating and encapsulating display related properties.
2134
* @class DisplayProps
2135
* @param {Number} [visible=true] Visible value.
2136
* @param {Number} [alpha=1] Alpha value.
2137
* @param {Number} [shadow=null] A Shadow instance or null.
2138
* @param {Number} [compositeOperation=null] A compositeOperation value or null.
2139
* @param {Number} [matrix] A transformation matrix. Defaults to a new identity matrix.
2140
* @constructor
2141
**/
2142
function DisplayProps(visible, alpha, shadow, compositeOperation, matrix) {
2143
this.setValues(visible, alpha, shadow, compositeOperation, matrix);
2144
2145
// public properties:
2146
// assigned in the setValues method.
2147
/**
2148
* Property representing the alpha that will be applied to a display object.
2149
* @property alpha
2150
* @type Number
2151
**/
2152
2153
/**
2154
* Property representing the shadow that will be applied to a display object.
2155
* @property shadow
2156
* @type Shadow
2157
**/
2158
2159
/**
2160
* Property representing the compositeOperation that will be applied to a display object.
2161
* You can find a list of valid composite operations at:
2162
* <a href="https://developer.mozilla.org/en/Canvas_tutorial/Compositing">https://developer.mozilla.org/en/Canvas_tutorial/Compositing</a>
2163
* @property compositeOperation
2164
* @type String
2165
**/
2166
2167
/**
2168
* Property representing the value for visible that will be applied to a display object.
2169
* @property visible
2170
* @type Boolean
2171
**/
2172
2173
/**
2174
* The transformation matrix that will be applied to a display object.
2175
* @property matrix
2176
* @type Matrix2D
2177
**/
2178
}
2179
var p = DisplayProps.prototype;
2180
2181
// initialization:
2182
/**
2183
* Reinitializes the instance with the specified values.
2184
* @method setValues
2185
* @param {Number} [visible=true] Visible value.
2186
* @param {Number} [alpha=1] Alpha value.
2187
* @param {Number} [shadow=null] A Shadow instance or null.
2188
* @param {Number} [compositeOperation=null] A compositeOperation value or null.
2189
* @param {Number} [matrix] A transformation matrix. Defaults to an identity matrix.
2190
* @return {DisplayProps} This instance. Useful for chaining method calls.
2191
* @chainable
2192
*/
2193
p.setValues = function (visible, alpha, shadow, compositeOperation, matrix) {
2194
this.visible = visible == null ? true : !!visible;
2195
this.alpha = alpha == null ? 1 : alpha;
2196
this.shadow = shadow;
2197
this.compositeOperation = compositeOperation;
2198
this.matrix = matrix || (this.matrix&&this.matrix.identity()) || new createjs.Matrix2D();
2199
return this;
2200
};
2201
2202
// public methods:
2203
/**
2204
* Appends the specified display properties. This is generally used to apply a child's properties its parent's.
2205
* @method append
2206
* @param {Boolean} visible desired visible value
2207
* @param {Number} alpha desired alpha value
2208
* @param {Shadow} shadow desired shadow value
2209
* @param {String} compositeOperation desired composite operation value
2210
* @param {Matrix2D} [matrix] a Matrix2D instance
2211
* @return {DisplayProps} This instance. Useful for chaining method calls.
2212
* @chainable
2213
*/
2214
p.append = function(visible, alpha, shadow, compositeOperation, matrix) {
2215
this.alpha *= alpha;
2216
this.shadow = shadow || this.shadow;
2217
this.compositeOperation = compositeOperation || this.compositeOperation;
2218
this.visible = this.visible && visible;
2219
matrix&&this.matrix.appendMatrix(matrix);
2220
return this;
2221
};
2222
2223
/**
2224
* Prepends the specified display properties. This is generally used to apply a parent's properties to a child's.
2225
* For example, to get the combined display properties that would be applied to a child, you could use:
2226
*
2227
* var o = myDisplayObject;
2228
* var props = new createjs.DisplayProps();
2229
* do {
2230
* // prepend each parent's props in turn:
2231
* props.prepend(o.visible, o.alpha, o.shadow, o.compositeOperation, o.getMatrix());
2232
* } while (o = o.parent);
2233
*
2234
* @method prepend
2235
* @param {Boolean} visible desired visible value
2236
* @param {Number} alpha desired alpha value
2237
* @param {Shadow} shadow desired shadow value
2238
* @param {String} compositeOperation desired composite operation value
2239
* @param {Matrix2D} [matrix] a Matrix2D instance
2240
* @return {DisplayProps} This instance. Useful for chaining method calls.
2241
* @chainable
2242
*/
2243
p.prepend = function(visible, alpha, shadow, compositeOperation, matrix) {
2244
this.alpha *= alpha;
2245
this.shadow = this.shadow || shadow;
2246
this.compositeOperation = this.compositeOperation || compositeOperation;
2247
this.visible = this.visible && visible;
2248
matrix&&this.matrix.prependMatrix(matrix);
2249
return this;
2250
};
2251
2252
/**
2253
* Resets this instance and its matrix to default values.
2254
* @method identity
2255
* @return {DisplayProps} This instance. Useful for chaining method calls.
2256
* @chainable
2257
*/
2258
p.identity = function() {
2259
this.visible = true;
2260
this.alpha = 1;
2261
this.shadow = this.compositeOperation = null;
2262
this.matrix.identity();
2263
return this;
2264
};
2265
2266
/**
2267
* Returns a clone of the DisplayProps instance. Clones the associated matrix.
2268
* @method clone
2269
* @return {DisplayProps} a clone of the DisplayProps instance.
2270
**/
2271
p.clone = function() {
2272
return new DisplayProps(this.alpha, this.shadow, this.compositeOperation, this.visible, this.matrix.clone());
2273
};
2274
2275
// private methods:
2276
2277
createjs.DisplayProps = DisplayProps;
2278
})();
2279
2280
//##############################################################################
2281
// Point.js
2282
//##############################################################################
2283
2284
this.createjs = this.createjs||{};
2285
2286
(function() {
2287
"use strict";
2288
2289
2290
// constructor:
2291
/**
2292
* Represents a point on a 2 dimensional x / y coordinate system.
2293
*
2294
* <h4>Example</h4>
2295
*
2296
* var point = new createjs.Point(0, 100);
2297
*
2298
* @class Point
2299
* @param {Number} [x=0] X position.
2300
* @param {Number} [y=0] Y position.
2301
* @constructor
2302
**/
2303
function Point(x, y) {
2304
this.setValues(x, y);
2305
2306
2307
// public properties:
2308
// assigned in the setValues method.
2309
/**
2310
* X position.
2311
* @property x
2312
* @type Number
2313
**/
2314
2315
/**
2316
* Y position.
2317
* @property y
2318
* @type Number
2319
**/
2320
}
2321
var p = Point.prototype;
2322
2323
/**
2324
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
2325
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
2326
* for details.
2327
*
2328
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
2329
*
2330
* @method initialize
2331
* @protected
2332
* @deprecated
2333
*/
2334
// p.initialize = function() {}; // searchable for devs wondering where it is.
2335
2336
2337
// public methods:
2338
/**
2339
* Sets the specified values on this instance.
2340
* @method setValues
2341
* @param {Number} [x=0] X position.
2342
* @param {Number} [y=0] Y position.
2343
* @return {Point} This instance. Useful for chaining method calls.
2344
* @chainable
2345
*/
2346
p.setValues = function(x, y) {
2347
this.x = x||0;
2348
this.y = y||0;
2349
return this;
2350
};
2351
2352
/**
2353
* Copies all properties from the specified point to this point.
2354
* @method copy
2355
* @param {Point} point The point to copy properties from.
2356
* @return {Point} This point. Useful for chaining method calls.
2357
* @chainable
2358
*/
2359
p.copy = function(point) {
2360
this.x = point.x;
2361
this.y = point.y;
2362
return this;
2363
};
2364
2365
/**
2366
* Returns a clone of the Point instance.
2367
* @method clone
2368
* @return {Point} a clone of the Point instance.
2369
**/
2370
p.clone = function() {
2371
return new Point(this.x, this.y);
2372
};
2373
2374
/**
2375
* Returns a string representation of this object.
2376
* @method toString
2377
* @return {String} a string representation of the instance.
2378
**/
2379
p.toString = function() {
2380
return "[Point (x="+this.x+" y="+this.y+")]";
2381
};
2382
2383
2384
createjs.Point = Point;
2385
}());
2386
2387
//##############################################################################
2388
// Rectangle.js
2389
//##############################################################################
2390
2391
this.createjs = this.createjs||{};
2392
2393
(function() {
2394
"use strict";
2395
2396
2397
// constructor:
2398
/**
2399
* Represents a rectangle as defined by the points (x, y) and (x+width, y+height).
2400
*
2401
* <h4>Example</h4>
2402
*
2403
* var rect = new createjs.Rectangle(0, 0, 100, 100);
2404
*
2405
* @class Rectangle
2406
* @param {Number} [x=0] X position.
2407
* @param {Number} [y=0] Y position.
2408
* @param {Number} [width=0] The width of the Rectangle.
2409
* @param {Number} [height=0] The height of the Rectangle.
2410
* @constructor
2411
**/
2412
function Rectangle(x, y, width, height) {
2413
this.setValues(x, y, width, height);
2414
2415
2416
// public properties:
2417
// assigned in the setValues method.
2418
/**
2419
* X position.
2420
* @property x
2421
* @type Number
2422
**/
2423
2424
/**
2425
* Y position.
2426
* @property y
2427
* @type Number
2428
**/
2429
2430
/**
2431
* Width.
2432
* @property width
2433
* @type Number
2434
**/
2435
2436
/**
2437
* Height.
2438
* @property height
2439
* @type Number
2440
**/
2441
}
2442
var p = Rectangle.prototype;
2443
2444
/**
2445
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
2446
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
2447
* for details.
2448
*
2449
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
2450
*
2451
* @method initialize
2452
* @protected
2453
* @deprecated
2454
*/
2455
// p.initialize = function() {}; // searchable for devs wondering where it is.
2456
2457
2458
// public methods:
2459
/**
2460
* Sets the specified values on this instance.
2461
* @method setValues
2462
* @param {Number} [x=0] X position.
2463
* @param {Number} [y=0] Y position.
2464
* @param {Number} [width=0] The width of the Rectangle.
2465
* @param {Number} [height=0] The height of the Rectangle.
2466
* @return {Rectangle} This instance. Useful for chaining method calls.
2467
* @chainable
2468
*/
2469
p.setValues = function(x, y, width, height) {
2470
// don't forget to update docs in the constructor if these change:
2471
this.x = x||0;
2472
this.y = y||0;
2473
this.width = width||0;
2474
this.height = height||0;
2475
return this;
2476
};
2477
2478
/**
2479
* Extends the rectangle's bounds to include the described point or rectangle.
2480
* @method extend
2481
* @param {Number} x X position of the point or rectangle.
2482
* @param {Number} y Y position of the point or rectangle.
2483
* @param {Number} [width=0] The width of the rectangle.
2484
* @param {Number} [height=0] The height of the rectangle.
2485
* @return {Rectangle} This instance. Useful for chaining method calls.
2486
* @chainable
2487
*/
2488
p.extend = function(x, y, width, height) {
2489
width = width||0;
2490
height = height||0;
2491
if (x+width > this.x+this.width) { this.width = x+width-this.x; }
2492
if (y+height > this.y+this.height) { this.height = y+height-this.y; }
2493
if (x < this.x) { this.width += this.x-x; this.x = x; }
2494
if (y < this.y) { this.height += this.y-y; this.y = y; }
2495
return this;
2496
};
2497
2498
/**
2499
* Adds the specified padding to the rectangle's bounds.
2500
* @method pad
2501
* @param {Number} top
2502
* @param {Number} left
2503
* @param {Number} right
2504
* @param {Number} bottom
2505
* @return {Rectangle} This instance. Useful for chaining method calls.
2506
* @chainable
2507
*/
2508
p.pad = function(top, left, bottom, right) {
2509
this.x -= left;
2510
this.y -= top;
2511
this.width += left+right;
2512
this.height += top+bottom;
2513
return this;
2514
};
2515
2516
/**
2517
* Copies all properties from the specified rectangle to this rectangle.
2518
* @method copy
2519
* @param {Rectangle} rectangle The rectangle to copy properties from.
2520
* @return {Rectangle} This rectangle. Useful for chaining method calls.
2521
* @chainable
2522
*/
2523
p.copy = function(rectangle) {
2524
return this.setValues(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
2525
};
2526
2527
/**
2528
* Returns true if this rectangle fully encloses the described point or rectangle.
2529
* @method contains
2530
* @param {Number} x X position of the point or rectangle.
2531
* @param {Number} y Y position of the point or rectangle.
2532
* @param {Number} [width=0] The width of the rectangle.
2533
* @param {Number} [height=0] The height of the rectangle.
2534
* @return {Boolean} True if the described point or rectangle is contained within this rectangle.
2535
*/
2536
p.contains = function(x, y, width, height) {
2537
width = width||0;
2538
height = height||0;
2539
return (x >= this.x && x+width <= this.x+this.width && y >= this.y && y+height <= this.y+this.height);
2540
};
2541
2542
/**
2543
* Returns a new rectangle which contains this rectangle and the specified rectangle.
2544
* @method union
2545
* @param {Rectangle} rect The rectangle to calculate a union with.
2546
* @return {Rectangle} A new rectangle describing the union.
2547
*/
2548
p.union = function(rect) {
2549
return this.clone().extend(rect.x, rect.y, rect.width, rect.height);
2550
};
2551
2552
/**
2553
* Returns a new rectangle which describes the intersection (overlap) of this rectangle and the specified rectangle,
2554
* or null if they do not intersect.
2555
* @method intersection
2556
* @param {Rectangle} rect The rectangle to calculate an intersection with.
2557
* @return {Rectangle} A new rectangle describing the intersection or null.
2558
*/
2559
p.intersection = function(rect) {
2560
var x1 = rect.x, y1 = rect.y, x2 = x1+rect.width, y2 = y1+rect.height;
2561
if (this.x > x1) { x1 = this.x; }
2562
if (this.y > y1) { y1 = this.y; }
2563
if (this.x + this.width < x2) { x2 = this.x + this.width; }
2564
if (this.y + this.height < y2) { y2 = this.y + this.height; }
2565
return (x2 <= x1 || y2 <= y1) ? null : new Rectangle(x1, y1, x2-x1, y2-y1);
2566
};
2567
2568
/**
2569
* Returns true if the specified rectangle intersects (has any overlap) with this rectangle.
2570
* @method intersects
2571
* @param {Rectangle} rect The rectangle to compare.
2572
* @return {Boolean} True if the rectangles intersect.
2573
*/
2574
p.intersects = function(rect) {
2575
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);
2576
};
2577
2578
/**
2579
* Returns true if the width or height are equal or less than 0.
2580
* @method isEmpty
2581
* @return {Boolean} True if the rectangle is empty.
2582
*/
2583
p.isEmpty = function() {
2584
return this.width <= 0 || this.height <= 0;
2585
};
2586
2587
/**
2588
* Returns a clone of the Rectangle instance.
2589
* @method clone
2590
* @return {Rectangle} a clone of the Rectangle instance.
2591
**/
2592
p.clone = function() {
2593
return new Rectangle(this.x, this.y, this.width, this.height);
2594
};
2595
2596
/**
2597
* Returns a string representation of this object.
2598
* @method toString
2599
* @return {String} a string representation of the instance.
2600
**/
2601
p.toString = function() {
2602
return "[Rectangle (x="+this.x+" y="+this.y+" width="+this.width+" height="+this.height+")]";
2603
};
2604
2605
2606
createjs.Rectangle = Rectangle;
2607
}());
2608
2609
//##############################################################################
2610
// ButtonHelper.js
2611
//##############################################################################
2612
2613
this.createjs = this.createjs||{};
2614
2615
(function() {
2616
"use strict";
2617
2618
2619
// constructor:
2620
/**
2621
* The ButtonHelper is a helper class to create interactive buttons from {{#crossLink "MovieClip"}}{{/crossLink}} or
2622
* {{#crossLink "Sprite"}}{{/crossLink}} instances. This class will intercept mouse events from an object, and
2623
* automatically call {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} or {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}},
2624
* to the respective animation labels, add a pointer cursor, and allows the user to define a hit state frame.
2625
*
2626
* The ButtonHelper instance does not need to be added to the stage, but a reference should be maintained to prevent
2627
* garbage collection.
2628
*
2629
* Note that over states will not work unless you call {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}.
2630
*
2631
* <h4>Example</h4>
2632
*
2633
* var helper = new createjs.ButtonHelper(myInstance, "out", "over", "down", false, myInstance, "hit");
2634
* myInstance.addEventListener("click", handleClick);
2635
* function handleClick(event) {
2636
* // Click Happened.
2637
* }
2638
*
2639
* @class ButtonHelper
2640
* @param {Sprite|MovieClip} target The instance to manage.
2641
* @param {String} [outLabel="out"] The label or animation to go to when the user rolls out of the button.
2642
* @param {String} [overLabel="over"] The label or animation to go to when the user rolls over the button.
2643
* @param {String} [downLabel="down"] The label or animation to go to when the user presses the button.
2644
* @param {Boolean} [play=false] If the helper should call "gotoAndPlay" or "gotoAndStop" on the button when changing
2645
* states.
2646
* @param {DisplayObject} [hitArea] An optional item to use as the hit state for the button. If this is not defined,
2647
* then the button's visible states will be used instead. Note that the same instance as the "target" argument can be
2648
* used for the hitState.
2649
* @param {String} [hitLabel] The label or animation on the hitArea instance that defines the hitArea bounds. If this is
2650
* null, then the default state of the hitArea will be used. *
2651
* @constructor
2652
*/
2653
function ButtonHelper(target, outLabel, overLabel, downLabel, play, hitArea, hitLabel) {
2654
if (!target.addEventListener) { return; }
2655
2656
2657
// public properties:
2658
/**
2659
* The target for this button helper.
2660
* @property target
2661
* @type MovieClip | Sprite
2662
* @readonly
2663
**/
2664
this.target = target;
2665
2666
/**
2667
* The label name or frame number to display when the user mouses out of the target. Defaults to "over".
2668
* @property overLabel
2669
* @type String | Number
2670
**/
2671
this.overLabel = overLabel == null ? "over" : overLabel;
2672
2673
/**
2674
* The label name or frame number to display when the user mouses over the target. Defaults to "out".
2675
* @property outLabel
2676
* @type String | Number
2677
**/
2678
this.outLabel = outLabel == null ? "out" : outLabel;
2679
2680
/**
2681
* The label name or frame number to display when the user presses on the target. Defaults to "down".
2682
* @property downLabel
2683
* @type String | Number
2684
**/
2685
this.downLabel = downLabel == null ? "down" : downLabel;
2686
2687
/**
2688
* If true, then ButtonHelper will call gotoAndPlay, if false, it will use gotoAndStop. Default is false.
2689
* @property play
2690
* @default false
2691
* @type Boolean
2692
**/
2693
this.play = play;
2694
2695
2696
// private properties
2697
/**
2698
* @property _isPressed
2699
* @type Boolean
2700
* @protected
2701
**/
2702
this._isPressed = false;
2703
2704
/**
2705
* @property _isOver
2706
* @type Boolean
2707
* @protected
2708
**/
2709
this._isOver = false;
2710
2711
/**
2712
* @property _enabled
2713
* @type Boolean
2714
* @protected
2715
**/
2716
this._enabled = false;
2717
2718
// setup:
2719
target.mouseChildren = false; // prevents issues when children are removed from the display list when state changes.
2720
this.enabled = true;
2721
this.handleEvent({});
2722
if (hitArea) {
2723
if (hitLabel) {
2724
hitArea.actionsEnabled = false;
2725
hitArea.gotoAndStop&&hitArea.gotoAndStop(hitLabel);
2726
}
2727
target.hitArea = hitArea;
2728
}
2729
}
2730
var p = ButtonHelper.prototype;
2731
2732
/**
2733
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
2734
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
2735
* for details.
2736
*
2737
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
2738
*
2739
* @method initialize
2740
* @protected
2741
* @deprecated
2742
*/
2743
// p.initialize = function() {}; // searchable for devs wondering where it is.
2744
2745
2746
// getter / setters:
2747
/**
2748
* Use the {{#crossLink "ButtonHelper/enabled:property"}}{{/crossLink}} property instead.
2749
* @method setEnabled
2750
* @param {Boolean} value
2751
* @deprecated
2752
**/
2753
p.setEnabled = function(value) { // TODO: deprecated.
2754
if (value == this._enabled) { return; }
2755
var o = this.target;
2756
this._enabled = value;
2757
if (value) {
2758
o.cursor = "pointer";
2759
o.addEventListener("rollover", this);
2760
o.addEventListener("rollout", this);
2761
o.addEventListener("mousedown", this);
2762
o.addEventListener("pressup", this);
2763
if (o._reset) { o.__reset = o._reset; o._reset = this._reset;}
2764
} else {
2765
o.cursor = null;
2766
o.removeEventListener("rollover", this);
2767
o.removeEventListener("rollout", this);
2768
o.removeEventListener("mousedown", this);
2769
o.removeEventListener("pressup", this);
2770
if (o.__reset) { o._reset = o.__reset; delete(o.__reset); }
2771
}
2772
};
2773
/**
2774
* Use the {{#crossLink "ButtonHelper/enabled:property"}}{{/crossLink}} property instead.
2775
* @method getEnabled
2776
* @return {Boolean}
2777
* @deprecated
2778
**/
2779
p.getEnabled = function() {
2780
return this._enabled;
2781
};
2782
2783
/**
2784
* Enables or disables the button functionality on the target.
2785
* @property enabled
2786
* @type {Boolean}
2787
**/
2788
try {
2789
Object.defineProperties(p, {
2790
enabled: { get: p.getEnabled, set: p.setEnabled }
2791
});
2792
} catch (e) {} // TODO: use Log
2793
2794
2795
// public methods:
2796
/**
2797
* Returns a string representation of this object.
2798
* @method toString
2799
* @return {String} a string representation of the instance.
2800
**/
2801
p.toString = function() {
2802
return "[ButtonHelper]";
2803
};
2804
2805
2806
// private methods:
2807
/**
2808
* @method handleEvent
2809
* @param {Object} evt The mouse event to handle.
2810
* @protected
2811
**/
2812
p.handleEvent = function(evt) {
2813
var label, t = this.target, type = evt.type;
2814
if (type == "mousedown") {
2815
this._isPressed = true;
2816
label = this.downLabel;
2817
} else if (type == "pressup") {
2818
this._isPressed = false;
2819
label = this._isOver ? this.overLabel : this.outLabel;
2820
} else if (type == "rollover") {
2821
this._isOver = true;
2822
label = this._isPressed ? this.downLabel : this.overLabel;
2823
} else { // rollout and default
2824
this._isOver = false;
2825
label = this._isPressed ? this.overLabel : this.outLabel;
2826
}
2827
if (this.play) {
2828
t.gotoAndPlay&&t.gotoAndPlay(label);
2829
} else {
2830
t.gotoAndStop&&t.gotoAndStop(label);
2831
}
2832
};
2833
2834
/**
2835
* Injected into target. Preserves the paused state through a reset.
2836
* @method _reset
2837
* @protected
2838
**/
2839
p._reset = function() {
2840
// TODO: explore better ways to handle this issue. This is hacky & disrupts object signatures.
2841
var p = this.paused;
2842
this.__reset();
2843
this.paused = p;
2844
};
2845
2846
2847
createjs.ButtonHelper = ButtonHelper;
2848
}());
2849
2850
//##############################################################################
2851
// Shadow.js
2852
//##############################################################################
2853
2854
this.createjs = this.createjs||{};
2855
2856
(function() {
2857
"use strict";
2858
2859
2860
// constructor:
2861
/**
2862
* This class encapsulates the properties required to define a shadow to apply to a {{#crossLink "DisplayObject"}}{{/crossLink}}
2863
* via its <code>shadow</code> property.
2864
*
2865
* <h4>Example</h4>
2866
*
2867
* myImage.shadow = new createjs.Shadow("#000000", 5, 5, 10);
2868
*
2869
* @class Shadow
2870
* @constructor
2871
* @param {String} color The color of the shadow. This can be any valid CSS color value.
2872
* @param {Number} offsetX The x offset of the shadow in pixels.
2873
* @param {Number} offsetY The y offset of the shadow in pixels.
2874
* @param {Number} blur The size of the blurring effect.
2875
**/
2876
function Shadow(color, offsetX, offsetY, blur) {
2877
2878
2879
// public properties:
2880
/**
2881
* The color of the shadow. This can be any valid CSS color value.
2882
* @property color
2883
* @type String
2884
* @default null
2885
*/
2886
this.color = color||"black";
2887
2888
/** The x offset of the shadow.
2889
* @property offsetX
2890
* @type Number
2891
* @default 0
2892
*/
2893
this.offsetX = offsetX||0;
2894
2895
/** The y offset of the shadow.
2896
* @property offsetY
2897
* @type Number
2898
* @default 0
2899
*/
2900
this.offsetY = offsetY||0;
2901
2902
/** The blur of the shadow.
2903
* @property blur
2904
* @type Number
2905
* @default 0
2906
*/
2907
this.blur = blur||0;
2908
}
2909
var p = Shadow.prototype;
2910
2911
/**
2912
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
2913
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
2914
* for details.
2915
*
2916
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
2917
*
2918
* @method initialize
2919
* @protected
2920
* @deprecated
2921
*/
2922
// p.initialize = function() {}; // searchable for devs wondering where it is.
2923
2924
2925
// static public properties:
2926
/**
2927
* An identity shadow object (all properties are set to 0).
2928
* @property identity
2929
* @type Shadow
2930
* @static
2931
* @final
2932
* @readonly
2933
**/
2934
Shadow.identity = new Shadow("transparent", 0, 0, 0);
2935
2936
2937
// public methods:
2938
/**
2939
* Returns a string representation of this object.
2940
* @method toString
2941
* @return {String} a string representation of the instance.
2942
**/
2943
p.toString = function() {
2944
return "[Shadow]";
2945
};
2946
2947
/**
2948
* Returns a clone of this Shadow instance.
2949
* @method clone
2950
* @return {Shadow} A clone of the current Shadow instance.
2951
**/
2952
p.clone = function() {
2953
return new Shadow(this.color, this.offsetX, this.offsetY, this.blur);
2954
};
2955
2956
2957
createjs.Shadow = Shadow;
2958
}());
2959
2960
//##############################################################################
2961
// SpriteSheet.js
2962
//##############################################################################
2963
2964
this.createjs = this.createjs||{};
2965
2966
(function() {
2967
"use strict";
2968
2969
2970
// constructor:
2971
/**
2972
* Encapsulates the properties and methods associated with a sprite sheet. A sprite sheet is a series of images (usually
2973
* animation frames) combined into a larger image (or images). For example, an animation consisting of eight 100x100
2974
* images could be combined into a single 400x200 sprite sheet (4 frames across by 2 high).
2975
*
2976
* The data passed to the SpriteSheet constructor defines:
2977
* <ol>
2978
* <li> The source image or images to use.</li>
2979
* <li> The positions of individual image frames.</li>
2980
* <li> Sequences of frames that form named animations. Optional.</li>
2981
* <li> The target playback framerate. Optional.</li>
2982
* </ol>
2983
* <h3>SpriteSheet Format</h3>
2984
* SpriteSheets are an object with two required properties (`images` and `frames`), and two optional properties
2985
* (`framerate` and `animations`). This makes them easy to define in javascript code, or in JSON.
2986
*
2987
* <h4>images</h4>
2988
* An array of source images. Images can be either an HTMlimage
2989
* instance, or a uri to an image. The former is recommended to control preloading.
2990
*
2991
* images: [image1, "path/to/image2.png"],
2992
*
2993
* <h4>frames</h4>
2994
* Defines the individual frames. There are two supported formats for frame data:
2995
* When all of the frames are the same size (in a grid), use an object with `width`, `height`, `regX`, `regY`,
2996
* and `count` properties.
2997
*
2998
* <ul>
2999
* <li>`width` & `height` are required and specify the dimensions of the frames</li>
3000
* <li>`regX` & `regY` indicate the registration point or "origin" of the frames</li>
3001
* <li>`spacing` indicate the spacing between frames</li>
3002
* <li>`margin` specify the margin around the image(s)</li>
3003
* <li>`count` allows you to specify the total number of frames in the spritesheet; if omitted, this will
3004
* be calculated based on the dimensions of the source images and the frames. Frames will be assigned
3005
* indexes based on their position in the source images (left to right, top to bottom).</li>
3006
* </ul>
3007
*
3008
* frames: {width:64, height:64, count:20, regX: 32, regY:64, spacing:0, margin:0}
3009
*
3010
* If the frames are of different sizes, use an array of frame definitions. Each definition is itself an array
3011
* with 4 required and 3 optional entries, in the order:
3012
*
3013
* <ul>
3014
* <li>The first four, `x`, `y`, `width`, and `height` are required and define the frame rectangle.</li>
3015
* <li>The fifth, `imageIndex`, specifies the index of the source image (defaults to 0)</li>
3016
* <li>The last two, `regX` and `regY` specify the registration point of the frame</li>
3017
* </ul>
3018
*
3019
* frames: [
3020
* // x, y, width, height, imageIndex*, regX*, regY*
3021
* [64, 0, 96, 64],
3022
* [0, 0, 64, 64, 1, 32, 32]
3023
* // etc.
3024
* ]
3025
*
3026
* <h4>animations</h4>
3027
* Optional. An object defining sequences of frames to play as named animations. Each property corresponds to an
3028
* animation of the same name. Each animation must specify the frames to play, and may
3029
* also include a relative playback `speed` (ex. 2 would playback at double speed, 0.5 at half), and
3030
* the name of the `next` animation to sequence to after it completes.
3031
*
3032
* There are three formats supported for defining the frames in an animation, which can be mixed and matched as appropriate:
3033
* <ol>
3034
* <li>for a single frame animation, you can simply specify the frame index
3035
*
3036
* animations: {
3037
* sit: 7
3038
* }
3039
*
3040
* </li>
3041
* <li>
3042
* for an animation of consecutive frames, you can use an array with two required, and two optional entries
3043
* in the order: `start`, `end`, `next`, and `speed`. This will play the frames from start to end inclusive.
3044
*
3045
* animations: {
3046
* // start, end, next*, speed*
3047
* run: [0, 8],
3048
* jump: [9, 12, "run", 2]
3049
* }
3050
*
3051
* </li>
3052
* <li>
3053
* for non-consecutive frames, you can use an object with a `frames` property defining an array of frame
3054
* indexes to play in order. The object can also specify `next` and `speed` properties.
3055
*
3056
* animations: {
3057
* walk: {
3058
* frames: [1,2,3,3,2,1]
3059
* },
3060
* shoot: {
3061
* frames: [1,4,5,6],
3062
* next: "walk",
3063
* speed: 0.5
3064
* }
3065
* }
3066
*
3067
* </li>
3068
* </ol>
3069
* <strong>Note:</strong> the `speed` property was added in EaselJS 0.7.0. Earlier versions had a `frequency`
3070
* property instead, which was the inverse of `speed`. For example, a value of "4" would be 1/4 normal speed in
3071
* earlier versions, but is 4x normal speed in EaselJS 0.7.0+.
3072
*
3073
* <h4>framerate</h4>
3074
* Optional. Indicates the default framerate to play this spritesheet at in frames per second. See
3075
* {{#crossLink "SpriteSheet/framerate:property"}}{{/crossLink}} for more information.
3076
*
3077
* framerate: 20
3078
*
3079
* Note that the Sprite framerate will only work if the stage update method is provided with the {{#crossLink "Ticker/tick:event"}}{{/crossLink}}
3080
* event generated by the {{#crossLink "Ticker"}}{{/crossLink}}.
3081
*
3082
* createjs.Ticker.on("tick", handleTick);
3083
* function handleTick(event) {
3084
* stage.update(event);
3085
* }
3086
*
3087
* <h3>Example</h3>
3088
* To define a simple sprite sheet, with a single image "sprites.jpg" arranged in a regular 50x50 grid with three
3089
* animations: "stand" showing the first frame, "run" looping frame 1-5 inclusive, and "jump" playing frame 6-8 and
3090
* sequencing back to run.
3091
*
3092
* var data = {
3093
* images: ["sprites.jpg"],
3094
* frames: {width:50, height:50},
3095
* animations: {
3096
* stand:0,
3097
* run:[1,5],
3098
* jump:[6,8,"run"]
3099
* }
3100
* };
3101
* var spriteSheet = new createjs.SpriteSheet(data);
3102
* var animation = new createjs.Sprite(spriteSheet, "run");
3103
*
3104
* <h3>Generating SpriteSheet Images</h3>
3105
* Spritesheets can be created manually by combining images in PhotoShop, and specifying the frame size or
3106
* coordinates manually, however there are a number of tools that facilitate this.
3107
* <ul>
3108
* <li>Exporting SpriteSheets or HTML5 content from Flash Pro supports the EaselJS SpriteSheet format.</li>
3109
* <li>The popular <a href="https://www.codeandweb.com/texturepacker/easeljs" target="_blank">Texture Packer</a> has
3110
* EaselJS support.
3111
* <li>SWF animations in Flash can be exported to SpriteSheets using <a href="http://createjs.com/zoe" target="_blank"></a></li>
3112
* </ul>
3113
*
3114
* <h3>Cross Origin Issues</h3>
3115
* <strong>Warning:</strong> Images loaded cross-origin will throw cross-origin security errors when interacted with
3116
* using:
3117
* <ul>
3118
* <li>a mouse</li>
3119
* <li>methods such as {{#crossLink "Container/getObjectUnderPoint"}}{{/crossLink}}</li>
3120
* <li>Filters (see {{#crossLink "Filter"}}{{/crossLink}})</li>
3121
* <li>caching (see {{#crossLink "DisplayObject/cache"}}{{/crossLink}})</li>
3122
* </ul>
3123
* You can get around this by setting `crossOrigin` property on your images before passing them to EaselJS, or
3124
* setting the `crossOrigin` property on PreloadJS' LoadQueue or LoadItems.
3125
*
3126
* var image = new Image();
3127
* img.crossOrigin="Anonymous";
3128
* img.src = "http://server-with-CORS-support.com/path/to/image.jpg";
3129
*
3130
* If you pass string paths to SpriteSheets, they will not work cross-origin. The server that stores the image must
3131
* support cross-origin requests, or this will not work. For more information, check out
3132
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS" target="_blank">CORS overview on MDN</a>.
3133
*
3134
* @class SpriteSheet
3135
* @constructor
3136
* @param {Object} data An object describing the SpriteSheet data.
3137
* @extends EventDispatcher
3138
**/
3139
function SpriteSheet(data) {
3140
this.EventDispatcher_constructor();
3141
3142
3143
// public properties:
3144
/**
3145
* Indicates whether all images are finished loading.
3146
* @property complete
3147
* @type Boolean
3148
* @readonly
3149
**/
3150
this.complete = true;
3151
3152
/**
3153
* Specifies the framerate to use by default for Sprite instances using the SpriteSheet. See the Sprite class
3154
* {{#crossLink "Sprite/framerate:property"}}{{/crossLink}} for more information.
3155
* @property framerate
3156
* @type Number
3157
**/
3158
this.framerate = 0;
3159
3160
3161
// private properties:
3162
/**
3163
* @property _animations
3164
* @protected
3165
* @type Array
3166
**/
3167
this._animations = null;
3168
3169
/**
3170
* @property _frames
3171
* @protected
3172
* @type Array
3173
**/
3174
this._frames = null;
3175
3176
/**
3177
* @property _images
3178
* @protected
3179
* @type Array
3180
**/
3181
this._images = null;
3182
3183
/**
3184
* @property _data
3185
* @protected
3186
* @type Object
3187
**/
3188
this._data = null;
3189
3190
/**
3191
* @property _loadCount
3192
* @protected
3193
* @type Number
3194
**/
3195
this._loadCount = 0;
3196
3197
// only used for simple frame defs:
3198
/**
3199
* @property _frameHeight
3200
* @protected
3201
* @type Number
3202
**/
3203
this._frameHeight = 0;
3204
3205
/**
3206
* @property _frameWidth
3207
* @protected
3208
* @type Number
3209
**/
3210
this._frameWidth = 0;
3211
3212
/**
3213
* @property _numFrames
3214
* @protected
3215
* @type Number
3216
**/
3217
this._numFrames = 0;
3218
3219
/**
3220
* @property _regX
3221
* @protected
3222
* @type Number
3223
**/
3224
this._regX = 0;
3225
3226
/**
3227
* @property _regY
3228
* @protected
3229
* @type Number
3230
**/
3231
this._regY = 0;
3232
3233
/**
3234
* @property _spacing
3235
* @protected
3236
* @type Number
3237
**/
3238
this._spacing = 0;
3239
3240
/**
3241
* @property _margin
3242
* @protected
3243
* @type Number
3244
**/
3245
this._margin = 0;
3246
3247
// setup:
3248
this._parseData(data);
3249
}
3250
var p = createjs.extend(SpriteSheet, createjs.EventDispatcher);
3251
3252
// TODO: deprecated
3253
// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
3254
3255
3256
// events:
3257
/**
3258
* Dispatched when all images are loaded. Note that this only fires if the images
3259
* were not fully loaded when the sprite sheet was initialized. You should check the complete property
3260
* to prior to adding a listener. Ex.
3261
*
3262
* var sheet = new createjs.SpriteSheet(data);
3263
* if (!sheet.complete) {
3264
* // not preloaded, listen for the complete event:
3265
* sheet.addEventListener("complete", handler);
3266
* }
3267
*
3268
* @event complete
3269
* @param {Object} target The object that dispatched the event.
3270
* @param {String} type The event type.
3271
* @since 0.6.0
3272
*/
3273
3274
/**
3275
* Dispatched when getFrame is called with a valid frame index. This is primarily intended for use by {{#crossLink "SpriteSheetBuilder"}}{{/crossLink}}
3276
* when doing on-demand rendering.
3277
* @event getframe
3278
* @param {Number} index The frame index.
3279
* @param {Object} frame The frame object that getFrame will return.
3280
*/
3281
3282
/**
3283
* Dispatched when an image encounters an error. A SpriteSheet will dispatch an error event for each image that
3284
* encounters an error, and will still dispatch a {{#crossLink "SpriteSheet/complete:event"}}{{/crossLink}}
3285
* event once all images are finished processing, even if an error is encountered.
3286
* @event error
3287
* @param {String} src The source of the image that failed to load.
3288
* @since 0.8.2
3289
*/
3290
3291
3292
// getter / setters:
3293
/**
3294
* Use the {{#crossLink "SpriteSheet/animations:property"}}{{/crossLink}} property instead.
3295
* @method getAnimations
3296
* @return {Array}
3297
* @deprecated
3298
**/
3299
p.getAnimations = function() {
3300
return this._animations.slice();
3301
};
3302
3303
/**
3304
* Returns an array of all available animation names available on this sprite sheet as strings.
3305
* @property animations
3306
* @type {Array}
3307
* @readonly
3308
**/
3309
try {
3310
Object.defineProperties(p, {
3311
animations: { get: p.getAnimations }
3312
});
3313
} catch (e) {}
3314
3315
3316
// public methods:
3317
/**
3318
* Returns the total number of frames in the specified animation, or in the whole sprite
3319
* sheet if the animation param is omitted. Returns 0 if the spritesheet relies on calculated frame counts, and
3320
* the images have not been fully loaded.
3321
* @method getNumFrames
3322
* @param {String} animation The name of the animation to get a frame count for.
3323
* @return {Number} The number of frames in the animation, or in the entire sprite sheet if the animation param is omitted.
3324
*/
3325
p.getNumFrames = function(animation) {
3326
if (animation == null) {
3327
return this._frames ? this._frames.length : this._numFrames || 0;
3328
} else {
3329
var data = this._data[animation];
3330
if (data == null) { return 0; }
3331
else { return data.frames.length; }
3332
}
3333
};
3334
3335
/**
3336
* Returns an object defining the specified animation. The returned object contains:<UL>
3337
* <li>frames: an array of the frame ids in the animation</li>
3338
* <li>speed: the playback speed for this animation</li>
3339
* <li>name: the name of the animation</li>
3340
* <li>next: the default animation to play next. If the animation loops, the name and next property will be the
3341
* same.</li>
3342
* </UL>
3343
* @method getAnimation
3344
* @param {String} name The name of the animation to get.
3345
* @return {Object} a generic object with frames, speed, name, and next properties.
3346
**/
3347
p.getAnimation = function(name) {
3348
return this._data[name];
3349
};
3350
3351
/**
3352
* Returns an object specifying the image and source rect of the specified frame. The returned object has:<UL>
3353
* <li>an image property holding a reference to the image object in which the frame is found</li>
3354
* <li>a rect property containing a Rectangle instance which defines the boundaries for the frame within that
3355
* image.</li>
3356
* <li> A regX and regY property corresponding to the regX/Y values for the frame.
3357
* </UL>
3358
* @method getFrame
3359
* @param {Number} frameIndex The index of the frame.
3360
* @return {Object} a generic object with image and rect properties. Returns null if the frame does not exist.
3361
**/
3362
p.getFrame = function(frameIndex) {
3363
var frame;
3364
if (this._frames && (frame=this._frames[frameIndex])) { return frame; }
3365
return null;
3366
};
3367
3368
/**
3369
* Returns a {{#crossLink "Rectangle"}}{{/crossLink}} instance defining the bounds of the specified frame relative
3370
* to the origin. For example, a 90 x 70 frame with a regX of 50 and a regY of 40 would return:
3371
*
3372
* [x=-50, y=-40, width=90, height=70]
3373
*
3374
* @method getFrameBounds
3375
* @param {Number} frameIndex The index of the frame.
3376
* @param {Rectangle} [rectangle] A Rectangle instance to copy the values into. By default a new instance is created.
3377
* @return {Rectangle} A Rectangle instance. Returns null if the frame does not exist, or the image is not fully loaded.
3378
**/
3379
p.getFrameBounds = function(frameIndex, rectangle) {
3380
var frame = this.getFrame(frameIndex);
3381
return frame ? (rectangle||new createjs.Rectangle()).setValues(-frame.regX, -frame.regY, frame.rect.width, frame.rect.height) : null;
3382
};
3383
3384
/**
3385
* Returns a string representation of this object.
3386
* @method toString
3387
* @return {String} a string representation of the instance.
3388
**/
3389
p.toString = function() {
3390
return "[SpriteSheet]";
3391
};
3392
3393
/**
3394
* SpriteSheet cannot be cloned. A SpriteSheet can be shared by multiple Sprite instances without cloning it.
3395
* @method clone
3396
**/
3397
p.clone = function() {
3398
throw("SpriteSheet cannot be cloned.")
3399
};
3400
3401
// private methods:
3402
/**
3403
* @method _parseData
3404
* @param {Object} data An object describing the SpriteSheet data.
3405
* @protected
3406
**/
3407
p._parseData = function(data) {
3408
var i,l,o,a;
3409
if (data == null) { return; }
3410
3411
this.framerate = data.framerate||0;
3412
3413
// parse images:
3414
if (data.images && (l=data.images.length) > 0) {
3415
a = this._images = [];
3416
for (i=0; i<l; i++) {
3417
var img = data.images[i];
3418
if (typeof img == "string") {
3419
var src = img;
3420
img = document.createElement("img");
3421
img.src = src;
3422
}
3423
a.push(img);
3424
if (!img.getContext && !img.naturalWidth) {
3425
this._loadCount++;
3426
this.complete = false;
3427
(function(o, src) { img.onload = function() { o._handleImageLoad(src); } })(this, src);
3428
(function(o, src) { img.onerror = function() { o._handleImageError(src); } })(this, src);
3429
}
3430
}
3431
}
3432
3433
// parse frames:
3434
if (data.frames == null) { // nothing
3435
} else if (Array.isArray(data.frames)) {
3436
this._frames = [];
3437
a = data.frames;
3438
for (i=0,l=a.length;i<l;i++) {
3439
var arr = a[i];
3440
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 });
3441
}
3442
} else {
3443
o = data.frames;
3444
this._frameWidth = o.width;
3445
this._frameHeight = o.height;
3446
this._regX = o.regX||0;
3447
this._regY = o.regY||0;
3448
this._spacing = o.spacing||0;
3449
this._margin = o.margin||0;
3450
this._numFrames = o.count;
3451
if (this._loadCount == 0) { this._calculateFrames(); }
3452
}
3453
3454
// parse animations:
3455
this._animations = [];
3456
if ((o=data.animations) != null) {
3457
this._data = {};
3458
var name;
3459
for (name in o) {
3460
var anim = {name:name};
3461
var obj = o[name];
3462
if (typeof obj == "number") { // single frame
3463
a = anim.frames = [obj];
3464
} else if (Array.isArray(obj)) { // simple
3465
if (obj.length == 1) { anim.frames = [obj[0]]; }
3466
else {
3467
anim.speed = obj[3];
3468
anim.next = obj[2];
3469
a = anim.frames = [];
3470
for (i=obj[0];i<=obj[1];i++) {
3471
a.push(i);
3472
}
3473
}
3474
} else { // complex
3475
anim.speed = obj.speed;
3476
anim.next = obj.next;
3477
var frames = obj.frames;
3478
a = anim.frames = (typeof frames == "number") ? [frames] : frames.slice(0);
3479
}
3480
if (anim.next === true || anim.next === undefined) { anim.next = name; } // loop
3481
if (anim.next === false || (a.length < 2 && anim.next == name)) { anim.next = null; } // stop
3482
if (!anim.speed) { anim.speed = 1; }
3483
this._animations.push(name);
3484
this._data[name] = anim;
3485
}
3486
}
3487
};
3488
3489
/**
3490
* @method _handleImageLoad
3491
* @protected
3492
**/
3493
p._handleImageLoad = function(src) {
3494
if (--this._loadCount == 0) {
3495
this._calculateFrames();
3496
this.complete = true;
3497
this.dispatchEvent("complete");
3498
}
3499
};
3500
3501
/**
3502
* @method _handleImageError
3503
* @protected
3504
*/
3505
p._handleImageError = function (src) {
3506
var errorEvent = new createjs.Event("error");
3507
errorEvent.src = src;
3508
this.dispatchEvent(errorEvent);
3509
3510
// Complete is still dispatched.
3511
if (--this._loadCount == 0) {
3512
this.dispatchEvent("complete");
3513
}
3514
};
3515
3516
/**
3517
* @method _calculateFrames
3518
* @protected
3519
**/
3520
p._calculateFrames = function() {
3521
if (this._frames || this._frameWidth == 0) { return; }
3522
3523
this._frames = [];
3524
3525
var maxFrames = this._numFrames || 100000; // if we go over this, something is wrong.
3526
var frameCount = 0, frameWidth = this._frameWidth, frameHeight = this._frameHeight;
3527
var spacing = this._spacing, margin = this._margin;
3528
3529
imgLoop:
3530
for (var i=0, imgs=this._images; i<imgs.length; i++) {
3531
var img = imgs[i], imgW = img.width, imgH = img.height;
3532
3533
var y = margin;
3534
while (y <= imgH-margin-frameHeight) {
3535
var x = margin;
3536
while (x <= imgW-margin-frameWidth) {
3537
if (frameCount >= maxFrames) { break imgLoop; }
3538
frameCount++;
3539
this._frames.push({
3540
image: img,
3541
rect: new createjs.Rectangle(x, y, frameWidth, frameHeight),
3542
regX: this._regX,
3543
regY: this._regY
3544
});
3545
x += frameWidth+spacing;
3546
}
3547
y += frameHeight+spacing;
3548
}
3549
}
3550
this._numFrames = frameCount;
3551
};
3552
3553
3554
createjs.SpriteSheet = createjs.promote(SpriteSheet, "EventDispatcher");
3555
}());
3556
3557
//##############################################################################
3558
// Graphics.js
3559
//##############################################################################
3560
3561
this.createjs = this.createjs||{};
3562
3563
(function() {
3564
"use strict";
3565
3566
3567
// constructor:
3568
/**
3569
* The Graphics class exposes an easy to use API for generating vector drawing instructions and drawing them to a
3570
* specified context. Note that you can use Graphics without any dependency on the EaselJS framework by calling {{#crossLink "Graphics/draw"}}{{/crossLink}}
3571
* directly, or it can be used with the {{#crossLink "Shape"}}{{/crossLink}} object to draw vector graphics within the
3572
* context of an EaselJS display list.
3573
*
3574
* There are two approaches to working with Graphics object: calling methods on a Graphics instance (the "Graphics API"), or
3575
* instantiating Graphics command objects and adding them to the graphics queue via {{#crossLink "Graphics/append"}}{{/crossLink}}.
3576
* The former abstracts the latter, simplifying beginning and ending paths, fills, and strokes.
3577
*
3578
* var g = new createjs.Graphics();
3579
* g.setStrokeStyle(1);
3580
* g.beginStroke("#000000");
3581
* g.beginFill("red");
3582
* g.drawCircle(0,0,30);
3583
*
3584
* All drawing methods in Graphics return the Graphics instance, so they can be chained together. For example,
3585
* the following line of code would generate the instructions to draw a rectangle with a red stroke and blue fill:
3586
*
3587
* myGraphics.beginStroke("red").beginFill("blue").drawRect(20, 20, 100, 50);
3588
*
3589
* Each graphics API call generates a command object (see below). The last command to be created can be accessed via
3590
* {{#crossLink "Graphics/command:property"}}{{/crossLink}}:
3591
*
3592
* var fillCommand = myGraphics.beginFill("red").command;
3593
* // ... later, update the fill style/color:
3594
* fillCommand.style = "blue";
3595
* // or change it to a bitmap fill:
3596
* fillCommand.bitmap(myImage);
3597
*
3598
* For more direct control of rendering, you can instantiate and append command objects to the graphics queue directly. In this case, you
3599
* need to manage path creation manually, and ensure that fill/stroke is applied to a defined path:
3600
*
3601
* // start a new path. Graphics.beginCmd is a reusable BeginPath instance:
3602
* myGraphics.append(createjs.Graphics.beginCmd);
3603
* // we need to define the path before applying the fill:
3604
* var circle = new createjs.Graphics.Circle(0,0,30);
3605
* myGraphics.append(circle);
3606
* // fill the path we just defined:
3607
* var fill = new createjs.Graphics.Fill("red");
3608
* myGraphics.append(fill);
3609
*
3610
* These approaches can be used together, for example to insert a custom command:
3611
*
3612
* myGraphics.beginFill("red");
3613
* var customCommand = new CustomSpiralCommand(etc);
3614
* myGraphics.append(customCommand);
3615
* myGraphics.beginFill("blue");
3616
* myGraphics.drawCircle(0, 0, 30);
3617
*
3618
* See {{#crossLink "Graphics/append"}}{{/crossLink}} for more info on creating custom commands.
3619
*
3620
* <h4>Tiny API</h4>
3621
* The Graphics class also includes a "tiny API", which is one or two-letter methods that are shortcuts for all of the
3622
* Graphics methods. These methods are great for creating compact instructions, and is used by the Toolkit for CreateJS
3623
* to generate readable code. All tiny methods are marked as protected, so you can view them by enabling protected
3624
* descriptions in the docs.
3625
*
3626
* <table>
3627
* <tr><td><b>Tiny</b></td><td><b>Method</b></td><td><b>Tiny</b></td><td><b>Method</b></td></tr>
3628
* <tr><td>mt</td><td>{{#crossLink "Graphics/moveTo"}}{{/crossLink}} </td>
3629
* <td>lt</td> <td>{{#crossLink "Graphics/lineTo"}}{{/crossLink}}</td></tr>
3630
* <tr><td>a/at</td><td>{{#crossLink "Graphics/arc"}}{{/crossLink}} / {{#crossLink "Graphics/arcTo"}}{{/crossLink}} </td>
3631
* <td>bt</td><td>{{#crossLink "Graphics/bezierCurveTo"}}{{/crossLink}} </td></tr>
3632
* <tr><td>qt</td><td>{{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} (also curveTo)</td>
3633
* <td>r</td><td>{{#crossLink "Graphics/rect"}}{{/crossLink}} </td></tr>
3634
* <tr><td>cp</td><td>{{#crossLink "Graphics/closePath"}}{{/crossLink}} </td>
3635
* <td>c</td><td>{{#crossLink "Graphics/clear"}}{{/crossLink}} </td></tr>
3636
* <tr><td>f</td><td>{{#crossLink "Graphics/beginFill"}}{{/crossLink}} </td>
3637
* <td>lf</td><td>{{#crossLink "Graphics/beginLinearGradientFill"}}{{/crossLink}} </td></tr>
3638
* <tr><td>rf</td><td>{{#crossLink "Graphics/beginRadialGradientFill"}}{{/crossLink}} </td>
3639
* <td>bf</td><td>{{#crossLink "Graphics/beginBitmapFill"}}{{/crossLink}} </td></tr>
3640
* <tr><td>ef</td><td>{{#crossLink "Graphics/endFill"}}{{/crossLink}} </td>
3641
* <td>ss / sd</td><td>{{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} / {{#crossLink "Graphics/setStrokeDash"}}{{/crossLink}} </td></tr>
3642
* <tr><td>s</td><td>{{#crossLink "Graphics/beginStroke"}}{{/crossLink}} </td>
3643
* <td>ls</td><td>{{#crossLink "Graphics/beginLinearGradientStroke"}}{{/crossLink}} </td></tr>
3644
* <tr><td>rs</td><td>{{#crossLink "Graphics/beginRadialGradientStroke"}}{{/crossLink}} </td>
3645
* <td>bs</td><td>{{#crossLink "Graphics/beginBitmapStroke"}}{{/crossLink}} </td></tr>
3646
* <tr><td>es</td><td>{{#crossLink "Graphics/endStroke"}}{{/crossLink}} </td>
3647
* <td>dr</td><td>{{#crossLink "Graphics/drawRect"}}{{/crossLink}} </td></tr>
3648
* <tr><td>rr</td><td>{{#crossLink "Graphics/drawRoundRect"}}{{/crossLink}} </td>
3649
* <td>rc</td><td>{{#crossLink "Graphics/drawRoundRectComplex"}}{{/crossLink}} </td></tr>
3650
* <tr><td>dc</td><td>{{#crossLink "Graphics/drawCircle"}}{{/crossLink}} </td>
3651
* <td>de</td><td>{{#crossLink "Graphics/drawEllipse"}}{{/crossLink}} </td></tr>
3652
* <tr><td>dp</td><td>{{#crossLink "Graphics/drawPolyStar"}}{{/crossLink}} </td>
3653
* <td>p</td><td>{{#crossLink "Graphics/decodePath"}}{{/crossLink}} </td></tr>
3654
* </table>
3655
*
3656
* Here is the above example, using the tiny API instead.
3657
*
3658
* myGraphics.s("red").f("blue").r(20, 20, 100, 50);
3659
*
3660
* @class Graphics
3661
* @constructor
3662
**/
3663
function Graphics() {
3664
3665
3666
// public properties
3667
/**
3668
* Holds a reference to the last command that was created or appended. For example, you could retain a reference
3669
* to a Fill command in order to dynamically update the color later by using:
3670
*
3671
* var myFill = myGraphics.beginFill("red").command;
3672
* // update color later:
3673
* myFill.style = "yellow";
3674
*
3675
* @property command
3676
* @type Object
3677
**/
3678
this.command = null;
3679
3680
3681
// private properties
3682
/**
3683
* @property _stroke
3684
* @protected
3685
* @type {Stroke}
3686
**/
3687
this._stroke = null;
3688
3689
/**
3690
* @property _strokeStyle
3691
* @protected
3692
* @type {StrokeStyle}
3693
**/
3694
this._strokeStyle = null;
3695
3696
/**
3697
* @property _oldStrokeStyle
3698
* @protected
3699
* @type {StrokeStyle}
3700
**/
3701
this._oldStrokeStyle = null;
3702
3703
/**
3704
* @property _strokeDash
3705
* @protected
3706
* @type {StrokeDash}
3707
**/
3708
this._strokeDash = null;
3709
3710
/**
3711
* @property _oldStrokeDash
3712
* @protected
3713
* @type {StrokeDash}
3714
**/
3715
this._oldStrokeDash = null;
3716
3717
/**
3718
* @property _strokeIgnoreScale
3719
* @protected
3720
* @type Boolean
3721
**/
3722
this._strokeIgnoreScale = false;
3723
3724
/**
3725
* @property _fill
3726
* @protected
3727
* @type {Fill}
3728
**/
3729
this._fill = null;
3730
3731
/**
3732
* @property _instructions
3733
* @protected
3734
* @type {Array}
3735
**/
3736
this._instructions = [];
3737
3738
/**
3739
* Indicates the last instruction index that was committed.
3740
* @property _commitIndex
3741
* @protected
3742
* @type {Number}
3743
**/
3744
this._commitIndex = 0;
3745
3746
/**
3747
* Uncommitted instructions.
3748
* @property _activeInstructions
3749
* @protected
3750
* @type {Array}
3751
**/
3752
this._activeInstructions = [];
3753
3754
/**
3755
* This indicates that there have been changes to the activeInstruction list since the last updateInstructions call.
3756
* @property _dirty
3757
* @protected
3758
* @type {Boolean}
3759
* @default false
3760
**/
3761
this._dirty = false;
3762
3763
/**
3764
* Index to draw from if a store operation has happened.
3765
* @property _storeIndex
3766
* @protected
3767
* @type {Number}
3768
* @default 0
3769
**/
3770
this._storeIndex = 0;
3771
3772
// setup:
3773
this.clear();
3774
}
3775
var p = Graphics.prototype;
3776
var G = Graphics; // shortcut
3777
3778
/**
3779
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
3780
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
3781
* for details.
3782
*
3783
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
3784
*
3785
* @method initialize
3786
* @protected
3787
* @deprecated
3788
*/
3789
// p.initialize = function() {}; // searchable for devs wondering where it is.
3790
3791
3792
// static public methods:
3793
/**
3794
* Returns a CSS compatible color string based on the specified RGB numeric color values in the format
3795
* "rgba(255,255,255,1.0)", or if alpha is null then in the format "rgb(255,255,255)". For example,
3796
*
3797
* createjs.Graphics.getRGB(50, 100, 150, 0.5);
3798
* // Returns "rgba(50,100,150,0.5)"
3799
*
3800
* It also supports passing a single hex color value as the first param, and an optional alpha value as the second
3801
* param. For example,
3802
*
3803
* createjs.Graphics.getRGB(0xFF00FF, 0.2);
3804
* // Returns "rgba(255,0,255,0.2)"
3805
*
3806
* @method getRGB
3807
* @static
3808
* @param {Number} r The red component for the color, between 0 and 0xFF (255).
3809
* @param {Number} g The green component for the color, between 0 and 0xFF (255).
3810
* @param {Number} b The blue component for the color, between 0 and 0xFF (255).
3811
* @param {Number} [alpha] The alpha component for the color where 0 is fully transparent and 1 is fully opaque.
3812
* @return {String} A CSS compatible color string based on the specified RGB numeric color values in the format
3813
* "rgba(255,255,255,1.0)", or if alpha is null then in the format "rgb(255,255,255)".
3814
**/
3815
Graphics.getRGB = function(r, g, b, alpha) {
3816
if (r != null && b == null) {
3817
alpha = g;
3818
b = r&0xFF;
3819
g = r>>8&0xFF;
3820
r = r>>16&0xFF;
3821
}
3822
if (alpha == null) {
3823
return "rgb("+r+","+g+","+b+")";
3824
} else {
3825
return "rgba("+r+","+g+","+b+","+alpha+")";
3826
}
3827
};
3828
3829
/**
3830
* Returns a CSS compatible color string based on the specified HSL numeric color values in the format "hsla(360,100,100,1.0)",
3831
* or if alpha is null then in the format "hsl(360,100,100)".
3832
*
3833
* createjs.Graphics.getHSL(150, 100, 70);
3834
* // Returns "hsl(150,100,70)"
3835
*
3836
* @method getHSL
3837
* @static
3838
* @param {Number} hue The hue component for the color, between 0 and 360.
3839
* @param {Number} saturation The saturation component for the color, between 0 and 100.
3840
* @param {Number} lightness The lightness component for the color, between 0 and 100.
3841
* @param {Number} [alpha] The alpha component for the color where 0 is fully transparent and 1 is fully opaque.
3842
* @return {String} A CSS compatible color string based on the specified HSL numeric color values in the format
3843
* "hsla(360,100,100,1.0)", or if alpha is null then in the format "hsl(360,100,100)".
3844
**/
3845
Graphics.getHSL = function(hue, saturation, lightness, alpha) {
3846
if (alpha == null) {
3847
return "hsl("+(hue%360)+","+saturation+"%,"+lightness+"%)";
3848
} else {
3849
return "hsla("+(hue%360)+","+saturation+"%,"+lightness+"%,"+alpha+")";
3850
}
3851
};
3852
3853
3854
// static properties:
3855
/**
3856
* A reusable instance of {{#crossLink "Graphics/BeginPath"}}{{/crossLink}} to avoid
3857
* unnecessary instantiation.
3858
* @property beginCmd
3859
* @type {Graphics.BeginPath}
3860
* @static
3861
**/
3862
// defined at the bottom of this file.
3863
3864
/**
3865
* Map of Base64 characters to values. Used by {{#crossLink "Graphics/decodePath"}}{{/crossLink}}.
3866
* @property BASE_64
3867
* @static
3868
* @final
3869
* @readonly
3870
* @type {Object}
3871
**/
3872
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};
3873
3874
/**
3875
* Maps numeric values for the caps parameter of {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} to
3876
* corresponding string values. This is primarily for use with the tiny API. The mappings are as follows: 0 to
3877
* "butt", 1 to "round", and 2 to "square".
3878
* For example, to set the line caps to "square":
3879
*
3880
* myGraphics.ss(16, 2);
3881
*
3882
* @property STROKE_CAPS_MAP
3883
* @static
3884
* @final
3885
* @readonly
3886
* @type {Array}
3887
**/
3888
Graphics.STROKE_CAPS_MAP = ["butt", "round", "square"];
3889
3890
/**
3891
* Maps numeric values for the joints parameter of {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} to
3892
* corresponding string values. This is primarily for use with the tiny API. The mappings are as follows: 0 to
3893
* "miter", 1 to "round", and 2 to "bevel".
3894
* For example, to set the line joints to "bevel":
3895
*
3896
* myGraphics.ss(16, 0, 2);
3897
*
3898
* @property STROKE_JOINTS_MAP
3899
* @static
3900
* @final
3901
* @readonly
3902
* @type {Array}
3903
**/
3904
Graphics.STROKE_JOINTS_MAP = ["miter", "round", "bevel"];
3905
3906
/**
3907
* @property _ctx
3908
* @static
3909
* @protected
3910
* @type {CanvasRenderingContext2D}
3911
**/
3912
var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"));
3913
if (canvas.getContext) {
3914
Graphics._ctx = canvas.getContext("2d");
3915
canvas.width = canvas.height = 1;
3916
}
3917
3918
3919
// getter / setters:
3920
/**
3921
* Use the {{#crossLink "Graphics/instructions:property"}}{{/crossLink}} property instead.
3922
* @method getInstructions
3923
* @return {Array}
3924
* @deprecated
3925
**/
3926
p.getInstructions = function() {
3927
this._updateInstructions();
3928
return this._instructions;
3929
};
3930
3931
/**
3932
* Returns the graphics instructions array. Each entry is a graphics command object (ex. Graphics.Fill, Graphics.Rect)
3933
* Modifying the returned array directly is not recommended, and is likely to result in unexpected behaviour.
3934
*
3935
* This property is mainly intended for introspection of the instructions (ex. for graphics export).
3936
* @property instructions
3937
* @type {Array}
3938
* @readonly
3939
**/
3940
try {
3941
Object.defineProperties(p, {
3942
instructions: { get: p.getInstructions }
3943
});
3944
} catch (e) {}
3945
3946
3947
// public methods:
3948
/**
3949
* Returns true if this Graphics instance has no drawing commands.
3950
* @method isEmpty
3951
* @return {Boolean} Returns true if this Graphics instance has no drawing commands.
3952
**/
3953
p.isEmpty = function() {
3954
return !(this._instructions.length || this._activeInstructions.length);
3955
};
3956
3957
/**
3958
* Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
3959
* Returns true if the draw was handled (useful for overriding functionality).
3960
*
3961
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
3962
* @method draw
3963
* @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
3964
* @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.
3965
**/
3966
p.draw = function(ctx, data) {
3967
this._updateInstructions();
3968
var instr = this._instructions;
3969
for (var i=this._storeIndex, l=instr.length; i<l; i++) {
3970
instr[i].exec(ctx, data);
3971
}
3972
};
3973
3974
/**
3975
* Draws only the path described for this Graphics instance, skipping any non-path instructions, including fill and
3976
* stroke descriptions. Used for <code>DisplayObject.mask</code> to draw the clipping path, for example.
3977
*
3978
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
3979
* @method drawAsPath
3980
* @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
3981
**/
3982
p.drawAsPath = function(ctx) {
3983
this._updateInstructions();
3984
var instr, instrs = this._instructions;
3985
for (var i=this._storeIndex, l=instrs.length; i<l; i++) {
3986
// the first command is always a beginPath command.
3987
if ((instr = instrs[i]).path !== false) { instr.exec(ctx); }
3988
}
3989
};
3990
3991
3992
// public methods that map directly to context 2D calls:
3993
/**
3994
* Moves the drawing point to the specified position. A tiny API method "mt" also exists.
3995
* @method moveTo
3996
* @param {Number} x The x coordinate the drawing point should move to.
3997
* @param {Number} y The y coordinate the drawing point should move to.
3998
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls).
3999
* @chainable
4000
**/
4001
p.moveTo = function(x, y) {
4002
return this.append(new G.MoveTo(x,y), true);
4003
};
4004
4005
/**
4006
* Draws a line from the current drawing point to the specified position, which become the new current drawing
4007
* point. Note that you *must* call {{#crossLink "Graphics/moveTo"}}{{/crossLink}} before the first `lineTo()`.
4008
* A tiny API method "lt" also exists.
4009
*
4010
* For detailed information, read the
4011
* <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#complex-shapes-(paths)">
4012
* whatwg spec</a>.
4013
* @method lineTo
4014
* @param {Number} x The x coordinate the drawing point should draw to.
4015
* @param {Number} y The y coordinate the drawing point should draw to.
4016
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4017
* @chainable
4018
**/
4019
p.lineTo = function(x, y) {
4020
return this.append(new G.LineTo(x,y));
4021
};
4022
4023
/**
4024
* Draws an arc with the specified control points and radius. For detailed information, read the
4025
* <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arcto">
4026
* whatwg spec</a>. A tiny API method "at" also exists.
4027
* @method arcTo
4028
* @param {Number} x1
4029
* @param {Number} y1
4030
* @param {Number} x2
4031
* @param {Number} y2
4032
* @param {Number} radius
4033
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4034
* @chainable
4035
**/
4036
p.arcTo = function(x1, y1, x2, y2, radius) {
4037
return this.append(new G.ArcTo(x1, y1, x2, y2, radius));
4038
};
4039
4040
/**
4041
* Draws an arc defined by the radius, startAngle and endAngle arguments, centered at the position (x, y). For
4042
* example, to draw a full circle with a radius of 20 centered at (100, 100):
4043
*
4044
* arc(100, 100, 20, 0, Math.PI*2);
4045
*
4046
* For detailed information, read the
4047
* <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arc">whatwg spec</a>.
4048
* A tiny API method "a" also exists.
4049
* @method arc
4050
* @param {Number} x
4051
* @param {Number} y
4052
* @param {Number} radius
4053
* @param {Number} startAngle Measured in radians.
4054
* @param {Number} endAngle Measured in radians.
4055
* @param {Boolean} anticlockwise
4056
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4057
* @chainable
4058
**/
4059
p.arc = function(x, y, radius, startAngle, endAngle, anticlockwise) {
4060
return this.append(new G.Arc(x, y, radius, startAngle, endAngle, anticlockwise));
4061
};
4062
4063
/**
4064
* Draws a quadratic curve from the current drawing point to (x, y) using the control point (cpx, cpy). For detailed
4065
* information, read the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-quadraticcurveto">
4066
* whatwg spec</a>. A tiny API method "qt" also exists.
4067
* @method quadraticCurveTo
4068
* @param {Number} cpx
4069
* @param {Number} cpy
4070
* @param {Number} x
4071
* @param {Number} y
4072
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4073
* @chainable
4074
**/
4075
p.quadraticCurveTo = function(cpx, cpy, x, y) {
4076
return this.append(new G.QuadraticCurveTo(cpx, cpy, x, y));
4077
};
4078
4079
/**
4080
* Draws a bezier curve from the current drawing point to (x, y) using the control points (cp1x, cp1y) and (cp2x,
4081
* cp2y). For detailed information, read the
4082
* <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-beziercurveto">
4083
* whatwg spec</a>. A tiny API method "bt" also exists.
4084
* @method bezierCurveTo
4085
* @param {Number} cp1x
4086
* @param {Number} cp1y
4087
* @param {Number} cp2x
4088
* @param {Number} cp2y
4089
* @param {Number} x
4090
* @param {Number} y
4091
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4092
* @chainable
4093
**/
4094
p.bezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
4095
return this.append(new G.BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y));
4096
};
4097
4098
/**
4099
* Draws a rectangle at (x, y) with the specified width and height using the current fill and/or stroke.
4100
* For detailed information, read the
4101
* <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-rect">
4102
* whatwg spec</a>. A tiny API method "r" also exists.
4103
* @method rect
4104
* @param {Number} x
4105
* @param {Number} y
4106
* @param {Number} w Width of the rectangle
4107
* @param {Number} h Height of the rectangle
4108
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4109
* @chainable
4110
**/
4111
p.rect = function(x, y, w, h) {
4112
return this.append(new G.Rect(x, y, w, h));
4113
};
4114
4115
/**
4116
* Closes the current path, effectively drawing a line from the current drawing point to the first drawing point specified
4117
* since the fill or stroke was last set. A tiny API method "cp" also exists.
4118
* @method closePath
4119
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4120
* @chainable
4121
**/
4122
p.closePath = function() {
4123
return this._activeInstructions.length ? this.append(new G.ClosePath()) : this;
4124
};
4125
4126
4127
// public methods that roughly map to Flash graphics APIs:
4128
/**
4129
* Clears all drawing instructions, effectively resetting this Graphics instance. Any line and fill styles will need
4130
* to be redefined to draw shapes following a clear call. A tiny API method "c" also exists.
4131
* @method clear
4132
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4133
* @chainable
4134
**/
4135
p.clear = function() {
4136
this._instructions.length = this._activeInstructions.length = this._commitIndex = 0;
4137
this._strokeStyle = this._oldStrokeStyle = this._stroke = this._fill = this._strokeDash = this._oldStrokeDash = null;
4138
this._dirty = this._strokeIgnoreScale = false;
4139
return this;
4140
};
4141
4142
/**
4143
* Begins a fill with the specified color. This ends the current sub-path. A tiny API method "f" also exists.
4144
* @method beginFill
4145
* @param {String} color A CSS compatible color value (ex. "red", "#FF0000", or "rgba(255,0,0,0.5)"). Setting to
4146
* null will result in no fill.
4147
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4148
* @chainable
4149
**/
4150
p.beginFill = function(color) {
4151
return this._setFill(color ? new G.Fill(color) : null);
4152
};
4153
4154
/**
4155
* Begins a linear gradient fill defined by the line (x0, y0) to (x1, y1). This ends the current sub-path. For
4156
* example, the following code defines a black to white vertical gradient ranging from 20px to 120px, and draws a
4157
* square to display it:
4158
*
4159
* myGraphics.beginLinearGradientFill(["#000","#FFF"], [0, 1], 0, 20, 0, 120).drawRect(20, 20, 120, 120);
4160
*
4161
* A tiny API method "lf" also exists.
4162
* @method beginLinearGradientFill
4163
* @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define a gradient
4164
* drawing from red to blue.
4165
* @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 0.9] would draw
4166
* the first color to 10% then interpolating to the second color at 90%.
4167
* @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size.
4168
* @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size.
4169
* @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size.
4170
* @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size.
4171
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4172
* @chainable
4173
**/
4174
p.beginLinearGradientFill = function(colors, ratios, x0, y0, x1, y1) {
4175
return this._setFill(new G.Fill().linearGradient(colors, ratios, x0, y0, x1, y1));
4176
};
4177
4178
/**
4179
* Begins a radial gradient fill. This ends the current sub-path. For example, the following code defines a red to
4180
* blue radial gradient centered at (100, 100), with a radius of 50, and draws a circle to display it:
4181
*
4182
* myGraphics.beginRadialGradientFill(["#F00","#00F"], [0, 1], 100, 100, 0, 100, 100, 50).drawCircle(100, 100, 50);
4183
*
4184
* A tiny API method "rf" also exists.
4185
* @method beginRadialGradientFill
4186
* @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
4187
* a gradient drawing from red to blue.
4188
* @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
4189
* 0.9] would draw the first color to 10% then interpolating to the second color at 90%.
4190
* @param {Number} x0 Center position of the inner circle that defines the gradient.
4191
* @param {Number} y0 Center position of the inner circle that defines the gradient.
4192
* @param {Number} r0 Radius of the inner circle that defines the gradient.
4193
* @param {Number} x1 Center position of the outer circle that defines the gradient.
4194
* @param {Number} y1 Center position of the outer circle that defines the gradient.
4195
* @param {Number} r1 Radius of the outer circle that defines the gradient.
4196
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4197
* @chainable
4198
**/
4199
p.beginRadialGradientFill = function(colors, ratios, x0, y0, r0, x1, y1, r1) {
4200
return this._setFill(new G.Fill().radialGradient(colors, ratios, x0, y0, r0, x1, y1, r1));
4201
};
4202
4203
/**
4204
* Begins a pattern fill using the specified image. This ends the current sub-path. A tiny API method "bf" also
4205
* exists.
4206
* @method beginBitmapFill
4207
* @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use
4208
* as the pattern. Must be loaded prior to creating a bitmap fill, or the fill will be empty.
4209
* @param {String} repetition Optional. Indicates whether to repeat the image in the fill area. One of "repeat",
4210
* "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". Note that Firefox does not support "repeat-x" or
4211
* "repeat-y" (latest tests were in FF 20.0), and will default to "repeat".
4212
* @param {Matrix2D} matrix Optional. Specifies a transformation matrix for the bitmap fill. This transformation
4213
* will be applied relative to the parent transform.
4214
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4215
* @chainable
4216
**/
4217
p.beginBitmapFill = function(image, repetition, matrix) {
4218
return this._setFill(new G.Fill(null,matrix).bitmap(image, repetition));
4219
};
4220
4221
/**
4222
* Ends the current sub-path, and begins a new one with no fill. Functionally identical to <code>beginFill(null)</code>.
4223
* A tiny API method "ef" also exists.
4224
* @method endFill
4225
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4226
* @chainable
4227
**/
4228
p.endFill = function() {
4229
return this.beginFill();
4230
};
4231
4232
/**
4233
* Sets the stroke style. Like all drawing methods, this can be chained, so you can define
4234
* the stroke style and color in a single line of code like so:
4235
*
4236
* myGraphics.setStrokeStyle(8,"round").beginStroke("#F00");
4237
*
4238
* A tiny API method "ss" also exists.
4239
* @method setStrokeStyle
4240
* @param {Number} thickness The width of the stroke.
4241
* @param {String | Number} [caps=0] Indicates the type of caps to use at the end of lines. One of butt,
4242
* round, or square. Defaults to "butt". Also accepts the values 0 (butt), 1 (round), and 2 (square) for use with
4243
* the tiny API.
4244
* @param {String | Number} [joints=0] Specifies the type of joints that should be used where two lines meet.
4245
* One of bevel, round, or miter. Defaults to "miter". Also accepts the values 0 (miter), 1 (round), and 2 (bevel)
4246
* for use with the tiny API.
4247
* @param {Number} [miterLimit=10] If joints is set to "miter", then you can specify a miter limit ratio which
4248
* controls at what point a mitered joint will be clipped.
4249
* @param {Boolean} [ignoreScale=false] If true, the stroke will be drawn at the specified thickness regardless
4250
* of active transformations.
4251
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4252
* @chainable
4253
**/
4254
p.setStrokeStyle = function(thickness, caps, joints, miterLimit, ignoreScale) {
4255
this._updateInstructions(true);
4256
this._strokeStyle = this.command = new G.StrokeStyle(thickness, caps, joints, miterLimit, ignoreScale);
4257
4258
// ignoreScale lives on Stroke, not StrokeStyle, so we do a little trickery:
4259
if (this._stroke) { this._stroke.ignoreScale = ignoreScale; }
4260
this._strokeIgnoreScale = ignoreScale;
4261
return this;
4262
};
4263
4264
/**
4265
* Sets or clears the stroke dash pattern.
4266
*
4267
* myGraphics.setStrokeDash([20, 10], 0);
4268
*
4269
* A tiny API method `sd` also exists.
4270
* @method setStrokeDash
4271
* @param {Array} [segments] An array specifying the dash pattern, alternating between line and gap.
4272
* For example, `[20,10]` would create a pattern of 20 pixel lines with 10 pixel gaps between them.
4273
* Passing null or an empty array will clear the existing stroke dash.
4274
* @param {Number} [offset=0] The offset of the dash pattern. For example, you could increment this value to create a "marching ants" effect.
4275
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4276
* @chainable
4277
**/
4278
p.setStrokeDash = function(segments, offset) {
4279
this._updateInstructions(true);
4280
this._strokeDash = this.command = new G.StrokeDash(segments, offset);
4281
return this;
4282
};
4283
4284
/**
4285
* Begins a stroke with the specified color. This ends the current sub-path. A tiny API method "s" also exists.
4286
* @method beginStroke
4287
* @param {String} color A CSS compatible color value (ex. "#FF0000", "red", or "rgba(255,0,0,0.5)"). Setting to
4288
* null will result in no stroke.
4289
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4290
* @chainable
4291
**/
4292
p.beginStroke = function(color) {
4293
return this._setStroke(color ? new G.Stroke(color) : null);
4294
};
4295
4296
/**
4297
* Begins a linear gradient stroke defined by the line (x0, y0) to (x1, y1). This ends the current sub-path. For
4298
* example, the following code defines a black to white vertical gradient ranging from 20px to 120px, and draws a
4299
* square to display it:
4300
*
4301
* myGraphics.setStrokeStyle(10).
4302
* beginLinearGradientStroke(["#000","#FFF"], [0, 1], 0, 20, 0, 120).drawRect(20, 20, 120, 120);
4303
*
4304
* A tiny API method "ls" also exists.
4305
* @method beginLinearGradientStroke
4306
* @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
4307
* a gradient drawing from red to blue.
4308
* @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
4309
* 0.9] would draw the first color to 10% then interpolating to the second color at 90%.
4310
* @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size.
4311
* @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size.
4312
* @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size.
4313
* @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size.
4314
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4315
* @chainable
4316
**/
4317
p.beginLinearGradientStroke = function(colors, ratios, x0, y0, x1, y1) {
4318
return this._setStroke(new G.Stroke().linearGradient(colors, ratios, x0, y0, x1, y1));
4319
};
4320
4321
/**
4322
* Begins a radial gradient stroke. This ends the current sub-path. For example, the following code defines a red to
4323
* blue radial gradient centered at (100, 100), with a radius of 50, and draws a rectangle to display it:
4324
*
4325
* myGraphics.setStrokeStyle(10)
4326
* .beginRadialGradientStroke(["#F00","#00F"], [0, 1], 100, 100, 0, 100, 100, 50)
4327
* .drawRect(50, 90, 150, 110);
4328
*
4329
* A tiny API method "rs" also exists.
4330
* @method beginRadialGradientStroke
4331
* @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
4332
* a gradient drawing from red to blue.
4333
* @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
4334
* 0.9] would draw the first color to 10% then interpolating to the second color at 90%, then draw the second color
4335
* to 100%.
4336
* @param {Number} x0 Center position of the inner circle that defines the gradient.
4337
* @param {Number} y0 Center position of the inner circle that defines the gradient.
4338
* @param {Number} r0 Radius of the inner circle that defines the gradient.
4339
* @param {Number} x1 Center position of the outer circle that defines the gradient.
4340
* @param {Number} y1 Center position of the outer circle that defines the gradient.
4341
* @param {Number} r1 Radius of the outer circle that defines the gradient.
4342
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4343
* @chainable
4344
**/
4345
p.beginRadialGradientStroke = function(colors, ratios, x0, y0, r0, x1, y1, r1) {
4346
return this._setStroke(new G.Stroke().radialGradient(colors, ratios, x0, y0, r0, x1, y1, r1));
4347
};
4348
4349
/**
4350
* Begins a pattern fill using the specified image. This ends the current sub-path. Note that unlike bitmap fills,
4351
* strokes do not currently support a matrix parameter due to limitations in the canvas API. A tiny API method "bs"
4352
* also exists.
4353
* @method beginBitmapStroke
4354
* @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use
4355
* as the pattern. Must be loaded prior to creating a bitmap fill, or the fill will be empty.
4356
* @param {String} [repetition=repeat] Optional. Indicates whether to repeat the image in the fill area. One of
4357
* "repeat", "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat".
4358
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4359
* @chainable
4360
**/
4361
p.beginBitmapStroke = function(image, repetition) {
4362
// NOTE: matrix is not supported for stroke because transforms on strokes also affect the drawn stroke width.
4363
return this._setStroke(new G.Stroke().bitmap(image, repetition));
4364
};
4365
4366
/**
4367
* Ends the current sub-path, and begins a new one with no stroke. Functionally identical to <code>beginStroke(null)</code>.
4368
* A tiny API method "es" also exists.
4369
* @method endStroke
4370
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4371
* @chainable
4372
**/
4373
p.endStroke = function() {
4374
return this.beginStroke();
4375
};
4376
4377
/**
4378
* Maps the familiar ActionScript <code>curveTo()</code> method to the functionally similar {{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}}
4379
* method.
4380
* @method quadraticCurveTo
4381
* @param {Number} cpx
4382
* @param {Number} cpy
4383
* @param {Number} x
4384
* @param {Number} y
4385
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4386
* @chainable
4387
**/
4388
p.curveTo = p.quadraticCurveTo;
4389
4390
/**
4391
*
4392
* Maps the familiar ActionScript <code>drawRect()</code> method to the functionally similar {{#crossLink "Graphics/rect"}}{{/crossLink}}
4393
* method.
4394
* @method drawRect
4395
* @param {Number} x
4396
* @param {Number} y
4397
* @param {Number} w Width of the rectangle
4398
* @param {Number} h Height of the rectangle
4399
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4400
* @chainable
4401
**/
4402
p.drawRect = p.rect;
4403
4404
/**
4405
* Draws a rounded rectangle with all corners with the specified radius.
4406
* @method drawRoundRect
4407
* @param {Number} x
4408
* @param {Number} y
4409
* @param {Number} w
4410
* @param {Number} h
4411
* @param {Number} radius Corner radius.
4412
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4413
* @chainable
4414
**/
4415
p.drawRoundRect = function(x, y, w, h, radius) {
4416
return this.drawRoundRectComplex(x, y, w, h, radius, radius, radius, radius);
4417
};
4418
4419
/**
4420
* Draws a rounded rectangle with different corner radii. Supports positive and negative corner radii. A tiny API
4421
* method "rc" also exists.
4422
* @method drawRoundRectComplex
4423
* @param {Number} x The horizontal coordinate to draw the round rect.
4424
* @param {Number} y The vertical coordinate to draw the round rect.
4425
* @param {Number} w The width of the round rect.
4426
* @param {Number} h The height of the round rect.
4427
* @param {Number} radiusTL Top left corner radius.
4428
* @param {Number} radiusTR Top right corner radius.
4429
* @param {Number} radiusBR Bottom right corner radius.
4430
* @param {Number} radiusBL Bottom left corner radius.
4431
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4432
* @chainable
4433
**/
4434
p.drawRoundRectComplex = function(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL) {
4435
return this.append(new G.RoundRect(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL));
4436
};
4437
4438
/**
4439
* Draws a circle with the specified radius at (x, y).
4440
*
4441
* var g = new createjs.Graphics();
4442
* g.setStrokeStyle(1);
4443
* g.beginStroke(createjs.Graphics.getRGB(0,0,0));
4444
* g.beginFill(createjs.Graphics.getRGB(255,0,0));
4445
* g.drawCircle(0,0,3);
4446
*
4447
* var s = new createjs.Shape(g);
4448
* s.x = 100;
4449
* s.y = 100;
4450
*
4451
* stage.addChild(s);
4452
* stage.update();
4453
*
4454
* A tiny API method "dc" also exists.
4455
* @method drawCircle
4456
* @param {Number} x x coordinate center point of circle.
4457
* @param {Number} y y coordinate center point of circle.
4458
* @param {Number} radius Radius of circle.
4459
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4460
* @chainable
4461
**/
4462
p.drawCircle = function(x, y, radius) {
4463
return this.append(new G.Circle(x, y, radius));
4464
};
4465
4466
/**
4467
* Draws an ellipse (oval) with a specified width (w) and height (h). Similar to {{#crossLink "Graphics/drawCircle"}}{{/crossLink}},
4468
* except the width and height can be different. A tiny API method "de" also exists.
4469
* @method drawEllipse
4470
* @param {Number} x The left coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}}
4471
* which draws from center.
4472
* @param {Number} y The top coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}}
4473
* which draws from the center.
4474
* @param {Number} w The height (horizontal diameter) of the ellipse. The horizontal radius will be half of this
4475
* number.
4476
* @param {Number} h The width (vertical diameter) of the ellipse. The vertical radius will be half of this number.
4477
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4478
* @chainable
4479
**/
4480
p.drawEllipse = function(x, y, w, h) {
4481
return this.append(new G.Ellipse(x, y, w, h));
4482
};
4483
4484
/**
4485
* Draws a star if pointSize is greater than 0, or a regular polygon if pointSize is 0 with the specified number of
4486
* points. For example, the following code will draw a familiar 5 pointed star shape centered at 100, 100 and with a
4487
* radius of 50:
4488
*
4489
* myGraphics.beginFill("#FF0").drawPolyStar(100, 100, 50, 5, 0.6, -90);
4490
* // Note: -90 makes the first point vertical
4491
*
4492
* A tiny API method "dp" also exists.
4493
*
4494
* @method drawPolyStar
4495
* @param {Number} x Position of the center of the shape.
4496
* @param {Number} y Position of the center of the shape.
4497
* @param {Number} radius The outer radius of the shape.
4498
* @param {Number} sides The number of points on the star or sides on the polygon.
4499
* @param {Number} pointSize The depth or "pointy-ness" of the star points. A pointSize of 0 will draw a regular
4500
* polygon (no points), a pointSize of 1 will draw nothing because the points are infinitely pointy.
4501
* @param {Number} angle The angle of the first point / corner. For example a value of 0 will draw the first point
4502
* directly to the right of the center.
4503
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4504
* @chainable
4505
**/
4506
p.drawPolyStar = function(x, y, radius, sides, pointSize, angle) {
4507
return this.append(new G.PolyStar(x, y, radius, sides, pointSize, angle));
4508
};
4509
4510
// TODO: deprecated.
4511
/**
4512
* Removed in favour of using custom command objects with {{#crossLink "Graphics/append"}}{{/crossLink}}.
4513
* @method inject
4514
* @deprecated
4515
**/
4516
4517
/**
4518
* Appends a graphics command object to the graphics queue. Command objects expose an "exec" method
4519
* that accepts two parameters: the Context2D to operate on, and an arbitrary data object passed into
4520
* {{#crossLink "Graphics/draw"}}{{/crossLink}}. The latter will usually be the Shape instance that called draw.
4521
*
4522
* This method is used internally by Graphics methods, such as drawCircle, but can also be used directly to insert
4523
* built-in or custom graphics commands. For example:
4524
*
4525
* // attach data to our shape, so we can access it during the draw:
4526
* myShape.color = "red";
4527
*
4528
* // append a Circle command object:
4529
* myShape.graphics.append(new createjs.Graphics.Circle(50, 50, 30));
4530
*
4531
* // append a custom command object with an exec method that sets the fill style
4532
* // based on the shape's data, and then fills the circle.
4533
* myShape.graphics.append({exec:function(ctx, shape) {
4534
* ctx.fillStyle = shape.color;
4535
* ctx.fill();
4536
* }});
4537
*
4538
* @method append
4539
* @param {Object} command A graphics command object exposing an "exec" method.
4540
* @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.
4541
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4542
* @chainable
4543
**/
4544
p.append = function(command, clean) {
4545
this._activeInstructions.push(command);
4546
this.command = command;
4547
if (!clean) { this._dirty = true; }
4548
return this;
4549
};
4550
4551
/**
4552
* Decodes a compact encoded path string into a series of draw instructions.
4553
* This format is not intended to be human readable, and is meant for use by authoring tools.
4554
* The format uses a base64 character set, with each character representing 6 bits, to define a series of draw
4555
* commands.
4556
*
4557
* Each command is comprised of a single "header" character followed by a variable number of alternating x and y
4558
* position values. Reading the header bits from left to right (most to least significant): bits 1 to 3 specify the
4559
* type of operation (0-moveTo, 1-lineTo, 2-quadraticCurveTo, 3-bezierCurveTo, 4-closePath, 5-7 unused). Bit 4
4560
* indicates whether position values use 12 bits (2 characters) or 18 bits (3 characters), with a one indicating the
4561
* latter. Bits 5 and 6 are currently unused.
4562
*
4563
* Following the header is a series of 0 (closePath), 2 (moveTo, lineTo), 4 (quadraticCurveTo), or 6 (bezierCurveTo)
4564
* parameters. These parameters are alternating x/y positions represented by 2 or 3 characters (as indicated by the
4565
* 4th bit in the command char). These characters consist of a 1 bit sign (1 is negative, 0 is positive), followed
4566
* by an 11 (2 char) or 17 (3 char) bit integer value. All position values are in tenths of a pixel. Except in the
4567
* case of move operations which are absolute, this value is a delta from the previous x or y position (as
4568
* appropriate).
4569
*
4570
* For example, the string "A3cAAMAu4AAA" represents a line starting at -150,0 and ending at 150,0.
4571
* <br />A - bits 000000. First 3 bits (000) indicate a moveTo operation. 4th bit (0) indicates 2 chars per
4572
* parameter.
4573
* <br />n0 - 110111011100. Absolute x position of -150.0px. First bit indicates a negative value, remaining bits
4574
* indicate 1500 tenths of a pixel.
4575
* <br />AA - 000000000000. Absolute y position of 0.
4576
* <br />I - 001100. First 3 bits (001) indicate a lineTo operation. 4th bit (1) indicates 3 chars per parameter.
4577
* <br />Au4 - 000000101110111000. An x delta of 300.0px, which is added to the previous x value of -150.0px to
4578
* provide an absolute position of +150.0px.
4579
* <br />AAA - 000000000000000000. A y delta value of 0.
4580
*
4581
* A tiny API method "p" also exists.
4582
* @method decodePath
4583
* @param {String} str The path string to decode.
4584
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4585
* @chainable
4586
**/
4587
p.decodePath = function(str) {
4588
var instructions = [this.moveTo, this.lineTo, this.quadraticCurveTo, this.bezierCurveTo, this.closePath];
4589
var paramCount = [2, 2, 4, 6, 0];
4590
var i=0, l=str.length;
4591
var params = [];
4592
var x=0, y=0;
4593
var base64 = Graphics.BASE_64;
4594
4595
while (i<l) {
4596
var c = str.charAt(i);
4597
var n = base64[c];
4598
var fi = n>>3; // highest order bits 1-3 code for operation.
4599
var f = instructions[fi];
4600
// check that we have a valid instruction & that the unused bits are empty:
4601
if (!f || (n&3)) { throw("bad path data (@"+i+"): "+c); }
4602
var pl = paramCount[fi];
4603
if (!fi) { x=y=0; } // move operations reset the position.
4604
params.length = 0;
4605
i++;
4606
var charCount = (n>>2&1)+2; // 4th header bit indicates number size for this operation.
4607
for (var p=0; p<pl; p++) {
4608
var num = base64[str.charAt(i)];
4609
var sign = (num>>5) ? -1 : 1;
4610
num = ((num&31)<<6)|(base64[str.charAt(i+1)]);
4611
if (charCount == 3) { num = (num<<6)|(base64[str.charAt(i+2)]); }
4612
num = sign*num/10;
4613
if (p%2) { x = (num += x); }
4614
else { y = (num += y); }
4615
params[p] = num;
4616
i += charCount;
4617
}
4618
f.apply(this,params);
4619
}
4620
return this;
4621
};
4622
4623
/**
4624
* Stores all graphics commands so they won't be executed in future draws. Calling store() a second time adds to
4625
* the existing store. This also affects `drawAsPath()`.
4626
*
4627
* This is useful in cases where you are creating vector graphics in an iterative manner (ex. generative art), so
4628
* that only new graphics need to be drawn (which can provide huge performance benefits), but you wish to retain all
4629
* of the vector instructions for later use (ex. scaling, modifying, or exporting).
4630
*
4631
* Note that calling store() will force the active path (if any) to be ended in a manner similar to changing
4632
* the fill or stroke.
4633
*
4634
* For example, consider a application where the user draws lines with the mouse. As each line segment (or collection of
4635
* segments) are added to a Shape, it can be rasterized using {{#crossLink "DisplayObject/updateCache"}}{{/crossLink}},
4636
* and then stored, so that it can be redrawn at a different scale when the application is resized, or exported to SVG.
4637
*
4638
* // set up cache:
4639
* myShape.cache(0,0,500,500,scale);
4640
*
4641
* // when the user drags, draw a new line:
4642
* myShape.graphics.moveTo(oldX,oldY).lineTo(newX,newY);
4643
* // then draw it into the existing cache:
4644
* myShape.updateCache("source-over");
4645
* // store the new line, so it isn't redrawn next time:
4646
* myShape.store();
4647
*
4648
* // then, when the window resizes, we can re-render at a different scale:
4649
* // first, unstore all our lines:
4650
* myShape.unstore();
4651
* // then cache using the new scale:
4652
* myShape.cache(0,0,500,500,newScale);
4653
* // finally, store the existing commands again:
4654
* myShape.store();
4655
*
4656
* @method store
4657
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4658
* @chainable
4659
**/
4660
p.store = function() {
4661
this._updateInstructions(true);
4662
this._storeIndex = this._instructions.length;
4663
return this;
4664
};
4665
4666
/**
4667
* Unstores any graphics commands that were previously stored using {{#crossLink "Graphics/store"}}{{/crossLink}}
4668
* so that they will be executed in subsequent draw calls.
4669
*
4670
* @method unstore
4671
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4672
* @chainable
4673
**/
4674
p.unstore = function() {
4675
this._storeIndex = 0;
4676
return this;
4677
};
4678
4679
/**
4680
* Returns a clone of this Graphics instance. Note that the individual command objects are not cloned.
4681
* @method clone
4682
* @return {Graphics} A clone of the current Graphics instance.
4683
**/
4684
p.clone = function() {
4685
var o = new Graphics();
4686
o.command = this.command;
4687
o._stroke = this._stroke;
4688
o._strokeStyle = this._strokeStyle;
4689
o._strokeDash = this._strokeDash;
4690
o._strokeIgnoreScale = this._strokeIgnoreScale;
4691
o._fill = this._fill;
4692
o._instructions = this._instructions.slice();
4693
o._commitIndex = this._commitIndex;
4694
o._activeInstructions = this._activeInstructions.slice();
4695
o._dirty = this._dirty;
4696
o._storeIndex = this._storeIndex;
4697
return o;
4698
};
4699
4700
/**
4701
* Returns a string representation of this object.
4702
* @method toString
4703
* @return {String} a string representation of the instance.
4704
**/
4705
p.toString = function() {
4706
return "[Graphics]";
4707
};
4708
4709
4710
// tiny API:
4711
/**
4712
* Shortcut to moveTo.
4713
* @method mt
4714
* @param {Number} x The x coordinate the drawing point should move to.
4715
* @param {Number} y The y coordinate the drawing point should move to.
4716
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls).
4717
* @chainable
4718
* @protected
4719
**/
4720
p.mt = p.moveTo;
4721
4722
/**
4723
* Shortcut to lineTo.
4724
* @method lt
4725
* @param {Number} x The x coordinate the drawing point should draw to.
4726
* @param {Number} y The y coordinate the drawing point should draw to.
4727
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4728
* @chainable
4729
* @protected
4730
**/
4731
p.lt = p.lineTo;
4732
4733
/**
4734
* Shortcut to arcTo.
4735
* @method at
4736
* @param {Number} x1
4737
* @param {Number} y1
4738
* @param {Number} x2
4739
* @param {Number} y2
4740
* @param {Number} radius
4741
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4742
* @chainable
4743
* @protected
4744
**/
4745
p.at = p.arcTo;
4746
4747
/**
4748
* Shortcut to bezierCurveTo.
4749
* @method bt
4750
* @param {Number} cp1x
4751
* @param {Number} cp1y
4752
* @param {Number} cp2x
4753
* @param {Number} cp2y
4754
* @param {Number} x
4755
* @param {Number} y
4756
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4757
* @chainable
4758
* @protected
4759
**/
4760
p.bt = p.bezierCurveTo;
4761
4762
/**
4763
* Shortcut to quadraticCurveTo / curveTo.
4764
* @method qt
4765
* @param {Number} cpx
4766
* @param {Number} cpy
4767
* @param {Number} x
4768
* @param {Number} y
4769
* @protected
4770
* @chainable
4771
**/
4772
p.qt = p.quadraticCurveTo;
4773
4774
/**
4775
* Shortcut to arc.
4776
* @method a
4777
* @param {Number} x
4778
* @param {Number} y
4779
* @param {Number} radius
4780
* @param {Number} startAngle Measured in radians.
4781
* @param {Number} endAngle Measured in radians.
4782
* @param {Boolean} anticlockwise
4783
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4784
* @protected
4785
* @chainable
4786
**/
4787
p.a = p.arc;
4788
4789
/**
4790
* Shortcut to rect.
4791
* @method r
4792
* @param {Number} x
4793
* @param {Number} y
4794
* @param {Number} w Width of the rectangle
4795
* @param {Number} h Height of the rectangle
4796
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4797
* @chainable
4798
* @protected
4799
**/
4800
p.r = p.rect;
4801
4802
/**
4803
* Shortcut to closePath.
4804
* @method cp
4805
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4806
* @chainable
4807
* @protected
4808
**/
4809
p.cp = p.closePath;
4810
4811
/**
4812
* Shortcut to clear.
4813
* @method c
4814
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4815
* @chainable
4816
* @protected
4817
**/
4818
p.c = p.clear;
4819
4820
/**
4821
* Shortcut to beginFill.
4822
* @method f
4823
* @param {String} color A CSS compatible color value (ex. "red", "#FF0000", or "rgba(255,0,0,0.5)"). Setting to
4824
* null will result in no fill.
4825
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4826
* @chainable
4827
* @protected
4828
**/
4829
p.f = p.beginFill;
4830
4831
/**
4832
* Shortcut to beginLinearGradientFill.
4833
* @method lf
4834
* @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define a gradient
4835
* drawing from red to blue.
4836
* @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1, 0.9] would draw
4837
* the first color to 10% then interpolating to the second color at 90%.
4838
* @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size.
4839
* @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size.
4840
* @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size.
4841
* @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size.
4842
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4843
* @chainable
4844
* @protected
4845
**/
4846
p.lf = p.beginLinearGradientFill;
4847
4848
/**
4849
* Shortcut to beginRadialGradientFill.
4850
* @method rf
4851
* @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
4852
* a gradient drawing from red to blue.
4853
* @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
4854
* 0.9] would draw the first color to 10% then interpolating to the second color at 90%.
4855
* @param {Number} x0 Center position of the inner circle that defines the gradient.
4856
* @param {Number} y0 Center position of the inner circle that defines the gradient.
4857
* @param {Number} r0 Radius of the inner circle that defines the gradient.
4858
* @param {Number} x1 Center position of the outer circle that defines the gradient.
4859
* @param {Number} y1 Center position of the outer circle that defines the gradient.
4860
* @param {Number} r1 Radius of the outer circle that defines the gradient.
4861
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4862
* @chainable
4863
* @protected
4864
**/
4865
p.rf = p.beginRadialGradientFill;
4866
4867
/**
4868
* Shortcut to beginBitmapFill.
4869
* @method bf
4870
* @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use
4871
* as the pattern.
4872
* @param {String} repetition Optional. Indicates whether to repeat the image in the fill area. One of "repeat",
4873
* "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat". Note that Firefox does not support "repeat-x" or
4874
* "repeat-y" (latest tests were in FF 20.0), and will default to "repeat".
4875
* @param {Matrix2D} matrix Optional. Specifies a transformation matrix for the bitmap fill. This transformation
4876
* will be applied relative to the parent transform.
4877
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4878
* @chainable
4879
* @protected
4880
**/
4881
p.bf = p.beginBitmapFill;
4882
4883
/**
4884
* Shortcut to endFill.
4885
* @method ef
4886
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4887
* @chainable
4888
* @protected
4889
**/
4890
p.ef = p.endFill;
4891
4892
/**
4893
* Shortcut to setStrokeStyle.
4894
* @method ss
4895
* @param {Number} thickness The width of the stroke.
4896
* @param {String | Number} [caps=0] Indicates the type of caps to use at the end of lines. One of butt,
4897
* round, or square. Defaults to "butt". Also accepts the values 0 (butt), 1 (round), and 2 (square) for use with
4898
* the tiny API.
4899
* @param {String | Number} [joints=0] Specifies the type of joints that should be used where two lines meet.
4900
* One of bevel, round, or miter. Defaults to "miter". Also accepts the values 0 (miter), 1 (round), and 2 (bevel)
4901
* for use with the tiny API.
4902
* @param {Number} [miterLimit=10] If joints is set to "miter", then you can specify a miter limit ratio which
4903
* controls at what point a mitered joint will be clipped.
4904
* @param {Boolean} [ignoreScale=false] If true, the stroke will be drawn at the specified thickness regardless
4905
* of active transformations.
4906
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4907
* @chainable
4908
* @protected
4909
**/
4910
p.ss = p.setStrokeStyle;
4911
4912
/**
4913
* Shortcut to setStrokeDash.
4914
* @method sd
4915
* @param {Array} [segments] An array specifying the dash pattern, alternating between line and gap.
4916
* For example, [20,10] would create a pattern of 20 pixel lines with 10 pixel gaps between them.
4917
* Passing null or an empty array will clear any existing dash.
4918
* @param {Number} [offset=0] The offset of the dash pattern. For example, you could increment this value to create a "marching ants" effect.
4919
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4920
* @chainable
4921
* @protected
4922
**/
4923
p.sd = p.setStrokeDash;
4924
4925
/**
4926
* Shortcut to beginStroke.
4927
* @method s
4928
* @param {String} color A CSS compatible color value (ex. "#FF0000", "red", or "rgba(255,0,0,0.5)"). Setting to
4929
* null will result in no stroke.
4930
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4931
* @chainable
4932
* @protected
4933
**/
4934
p.s = p.beginStroke;
4935
4936
/**
4937
* Shortcut to beginLinearGradientStroke.
4938
* @method ls
4939
* @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
4940
* a gradient drawing from red to blue.
4941
* @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
4942
* 0.9] would draw the first color to 10% then interpolating to the second color at 90%.
4943
* @param {Number} x0 The position of the first point defining the line that defines the gradient direction and size.
4944
* @param {Number} y0 The position of the first point defining the line that defines the gradient direction and size.
4945
* @param {Number} x1 The position of the second point defining the line that defines the gradient direction and size.
4946
* @param {Number} y1 The position of the second point defining the line that defines the gradient direction and size.
4947
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4948
* @chainable
4949
* @protected
4950
**/
4951
p.ls = p.beginLinearGradientStroke;
4952
4953
/**
4954
* Shortcut to beginRadialGradientStroke.
4955
* @method rs
4956
* @param {Array} colors An array of CSS compatible color values. For example, ["#F00","#00F"] would define
4957
* a gradient drawing from red to blue.
4958
* @param {Array} ratios An array of gradient positions which correspond to the colors. For example, [0.1,
4959
* 0.9] would draw the first color to 10% then interpolating to the second color at 90%, then draw the second color
4960
* to 100%.
4961
* @param {Number} x0 Center position of the inner circle that defines the gradient.
4962
* @param {Number} y0 Center position of the inner circle that defines the gradient.
4963
* @param {Number} r0 Radius of the inner circle that defines the gradient.
4964
* @param {Number} x1 Center position of the outer circle that defines the gradient.
4965
* @param {Number} y1 Center position of the outer circle that defines the gradient.
4966
* @param {Number} r1 Radius of the outer circle that defines the gradient.
4967
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4968
* @chainable
4969
* @protected
4970
**/
4971
p.rs = p.beginRadialGradientStroke;
4972
4973
/**
4974
* Shortcut to beginBitmapStroke.
4975
* @method bs
4976
* @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image The Image, Canvas, or Video object to use
4977
* as the pattern.
4978
* @param {String} [repetition=repeat] Optional. Indicates whether to repeat the image in the fill area. One of
4979
* "repeat", "repeat-x", "repeat-y", or "no-repeat". Defaults to "repeat".
4980
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4981
* @chainable
4982
* @protected
4983
**/
4984
p.bs = p.beginBitmapStroke;
4985
4986
/**
4987
* Shortcut to endStroke.
4988
* @method es
4989
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
4990
* @chainable
4991
* @protected
4992
**/
4993
p.es = p.endStroke;
4994
4995
/**
4996
* Shortcut to drawRect.
4997
* @method dr
4998
* @param {Number} x
4999
* @param {Number} y
5000
* @param {Number} w Width of the rectangle
5001
* @param {Number} h Height of the rectangle
5002
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
5003
* @chainable
5004
* @protected
5005
**/
5006
p.dr = p.drawRect;
5007
5008
/**
5009
* Shortcut to drawRoundRect.
5010
* @method rr
5011
* @param {Number} x
5012
* @param {Number} y
5013
* @param {Number} w
5014
* @param {Number} h
5015
* @param {Number} radius Corner radius.
5016
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
5017
* @chainable
5018
* @protected
5019
**/
5020
p.rr = p.drawRoundRect;
5021
5022
/**
5023
* Shortcut to drawRoundRectComplex.
5024
* @method rc
5025
* @param {Number} x The horizontal coordinate to draw the round rect.
5026
* @param {Number} y The vertical coordinate to draw the round rect.
5027
* @param {Number} w The width of the round rect.
5028
* @param {Number} h The height of the round rect.
5029
* @param {Number} radiusTL Top left corner radius.
5030
* @param {Number} radiusTR Top right corner radius.
5031
* @param {Number} radiusBR Bottom right corner radius.
5032
* @param {Number} radiusBL Bottom left corner radius.
5033
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
5034
* @chainable
5035
* @protected
5036
**/
5037
p.rc = p.drawRoundRectComplex;
5038
5039
/**
5040
* Shortcut to drawCircle.
5041
* @method dc
5042
* @param {Number} x x coordinate center point of circle.
5043
* @param {Number} y y coordinate center point of circle.
5044
* @param {Number} radius Radius of circle.
5045
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
5046
* @chainable
5047
* @protected
5048
**/
5049
p.dc = p.drawCircle;
5050
5051
/**
5052
* Shortcut to drawEllipse.
5053
* @method de
5054
* @param {Number} x The left coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}}
5055
* which draws from center.
5056
* @param {Number} y The top coordinate point of the ellipse. Note that this is different from {{#crossLink "Graphics/drawCircle"}}{{/crossLink}}
5057
* which draws from the center.
5058
* @param {Number} w The height (horizontal diameter) of the ellipse. The horizontal radius will be half of this
5059
* number.
5060
* @param {Number} h The width (vertical diameter) of the ellipse. The vertical radius will be half of this number.
5061
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
5062
* @chainable
5063
* @protected
5064
**/
5065
p.de = p.drawEllipse;
5066
5067
/**
5068
* Shortcut to drawPolyStar.
5069
* @method dp
5070
* @param {Number} x Position of the center of the shape.
5071
* @param {Number} y Position of the center of the shape.
5072
* @param {Number} radius The outer radius of the shape.
5073
* @param {Number} sides The number of points on the star or sides on the polygon.
5074
* @param {Number} pointSize The depth or "pointy-ness" of the star points. A pointSize of 0 will draw a regular
5075
* polygon (no points), a pointSize of 1 will draw nothing because the points are infinitely pointy.
5076
* @param {Number} angle The angle of the first point / corner. For example a value of 0 will draw the first point
5077
* directly to the right of the center.
5078
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
5079
* @chainable
5080
* @protected
5081
**/
5082
p.dp = p.drawPolyStar;
5083
5084
/**
5085
* Shortcut to decodePath.
5086
* @method p
5087
* @param {String} str The path string to decode.
5088
* @return {Graphics} The Graphics instance the method is called on (useful for chaining calls.)
5089
* @chainable
5090
* @protected
5091
**/
5092
p.p = p.decodePath;
5093
5094
5095
// private methods:
5096
/**
5097
* @method _updateInstructions
5098
* @param commit
5099
* @protected
5100
**/
5101
p._updateInstructions = function(commit) {
5102
var instr = this._instructions, active = this._activeInstructions, commitIndex = this._commitIndex;
5103
5104
if (this._dirty && active.length) {
5105
instr.length = commitIndex; // remove old, uncommitted commands
5106
instr.push(Graphics.beginCmd);
5107
5108
var l = active.length, ll = instr.length;
5109
instr.length = ll+l;
5110
for (var i=0; i<l; i++) { instr[i+ll] = active[i]; }
5111
5112
if (this._fill) { instr.push(this._fill); }
5113
if (this._stroke) {
5114
// doesn't need to be re-applied if it hasn't changed.
5115
if (this._strokeDash !== this._oldStrokeDash) {
5116
this._oldStrokeDash = this._strokeDash;
5117
instr.push(this._strokeDash);
5118
}
5119
if (this._strokeStyle !== this._oldStrokeStyle) {
5120
this._oldStrokeStyle = this._strokeStyle;
5121
instr.push(this._strokeStyle);
5122
}
5123
instr.push(this._stroke);
5124
}
5125
5126
this._dirty = false;
5127
}
5128
5129
if (commit) {
5130
active.length = 0;
5131
this._commitIndex = instr.length;
5132
}
5133
};
5134
5135
/**
5136
* @method _setFill
5137
* @param fill
5138
* @protected
5139
**/
5140
p._setFill = function(fill) {
5141
this._updateInstructions(true);
5142
this.command = this._fill = fill;
5143
return this;
5144
};
5145
5146
/**
5147
* @method _setStroke
5148
* @param stroke
5149
* @protected
5150
**/
5151
p._setStroke = function(stroke) {
5152
this._updateInstructions(true);
5153
if (this.command = this._stroke = stroke) {
5154
stroke.ignoreScale = this._strokeIgnoreScale;
5155
}
5156
return this;
5157
};
5158
5159
// Command Objects:
5160
/**
5161
* @namespace Graphics
5162
*/
5163
/**
5164
* 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.
5165
* @class LineTo
5166
* @constructor
5167
* @param {Number} x
5168
* @param {Number} y
5169
**/
5170
/**
5171
* @property x
5172
* @type Number
5173
*/
5174
/**
5175
* @property y
5176
* @type Number
5177
*/
5178
/**
5179
* Execute the Graphics command in the provided Canvas context.
5180
* @method exec
5181
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5182
*/
5183
(G.LineTo = function(x, y) {
5184
this.x = x; this.y = y;
5185
}).prototype.exec = function(ctx) { ctx.lineTo(this.x,this.y); };
5186
5187
/**
5188
* Graphics command object. See {{#crossLink "Graphics/moveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5189
* @class MoveTo
5190
* @constructor
5191
* @param {Number} x
5192
* @param {Number} y
5193
**/
5194
/**
5195
* @property x
5196
* @type Number
5197
*/
5198
/**
5199
* @property y
5200
* @type Number
5201
*/
5202
/**
5203
* @method exec
5204
* @param {CanvasRenderingContext2D} ctx
5205
*/
5206
(G.MoveTo = function(x, y) {
5207
this.x = x; this.y = y;
5208
}).prototype.exec = function(ctx) { ctx.moveTo(this.x, this.y); };
5209
5210
5211
/**
5212
* Graphics command object. See {{#crossLink "Graphics/arcTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5213
* @class ArcTo
5214
* @constructor
5215
* @param {Number} x1
5216
* @param {Number} y1
5217
* @param {Number} x2
5218
* @param {Number} y2
5219
* @param {Number} radius
5220
**/
5221
/**
5222
* @property x1
5223
* @type Number
5224
*/
5225
/**
5226
* @property y1
5227
* @type Number
5228
*/
5229
/**
5230
* @property x2
5231
* @type Number
5232
*/
5233
/**
5234
* @property y2
5235
* @type Number
5236
*/
5237
/**
5238
* @property radius
5239
* @type Number
5240
*/
5241
/**
5242
* Execute the Graphics command in the provided Canvas context.
5243
* @method exec
5244
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5245
*/
5246
(G.ArcTo = function(x1, y1, x2, y2, radius) {
5247
this.x1 = x1; this.y1 = y1;
5248
this.x2 = x2; this.y2 = y2;
5249
this.radius = radius;
5250
}).prototype.exec = function(ctx) { ctx.arcTo(this.x1, this.y1, this.x2, this.y2, this.radius); };
5251
5252
/**
5253
* Graphics command object. See {{#crossLink "Graphics/arc"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5254
* @class Arc
5255
* @constructor
5256
* @param {Number} x
5257
* @param {Number} y
5258
* @param {Number} radius
5259
* @param {Number} startAngle
5260
* @param {Number} endAngle
5261
* @param {Number} anticlockwise
5262
**/
5263
/**
5264
* @property x
5265
* @type Number
5266
*/
5267
/**
5268
* @property y
5269
* @type Number
5270
*/
5271
/**
5272
* @property radius
5273
* @type Number
5274
*/
5275
/**
5276
* @property startAngle
5277
* @type Number
5278
*/
5279
/**
5280
* @property endAngle
5281
* @type Number
5282
*/
5283
/**
5284
* @property anticlockwise
5285
* @type Number
5286
*/
5287
/**
5288
* Execute the Graphics command in the provided Canvas context.
5289
* @method exec
5290
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5291
*/
5292
(G.Arc = function(x, y, radius, startAngle, endAngle, anticlockwise) {
5293
this.x = x; this.y = y;
5294
this.radius = radius;
5295
this.startAngle = startAngle; this.endAngle = endAngle;
5296
this.anticlockwise = !!anticlockwise;
5297
}).prototype.exec = function(ctx) { ctx.arc(this.x, this.y, this.radius, this.startAngle, this.endAngle, this.anticlockwise); };
5298
5299
/**
5300
* Graphics command object. See {{#crossLink "Graphics/quadraticCurveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5301
* @class QuadraticCurveTo
5302
* @constructor
5303
* @param {Number} cpx
5304
* @param {Number} cpy
5305
* @param {Number} x
5306
* @param {Number} y
5307
**/
5308
/**
5309
* @property cpx
5310
* @type Number
5311
*/
5312
/**
5313
* @property cpy
5314
* @type Number
5315
*/
5316
/**
5317
* @property x
5318
* @type Number
5319
*/
5320
/**
5321
* @property y
5322
* @type Number
5323
*/
5324
/**
5325
* Execute the Graphics command in the provided Canvas context.
5326
* @method exec
5327
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5328
*/
5329
(G.QuadraticCurveTo = function(cpx, cpy, x, y) {
5330
this.cpx = cpx; this.cpy = cpy;
5331
this.x = x; this.y = y;
5332
}).prototype.exec = function(ctx) { ctx.quadraticCurveTo(this.cpx, this.cpy, this.x, this.y); };
5333
5334
/**
5335
* Graphics command object. See {{#crossLink "Graphics/bezierCurveTo"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5336
* @class BezierCurveTo
5337
* @constructor
5338
* @param {Number} cp1x
5339
* @param {Number} cp1y
5340
* @param {Number} cp2x
5341
* @param {Number} cp2y
5342
* @param {Number} x
5343
* @param {Number} y
5344
**/
5345
/**
5346
* @property cp1x
5347
* @type Number
5348
*/
5349
/**
5350
* @property cp1y
5351
* @type Number
5352
*/
5353
/**
5354
* @property cp2x
5355
* @type Number
5356
*/
5357
/**
5358
* @property cp2y
5359
* @type Number
5360
*/
5361
/**
5362
* @property x
5363
* @type Number
5364
*/
5365
/**
5366
* @property y
5367
* @type Number
5368
*/
5369
/**
5370
* Execute the Graphics command in the provided Canvas context.
5371
* @method exec
5372
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5373
*/
5374
(G.BezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) {
5375
this.cp1x = cp1x; this.cp1y = cp1y;
5376
this.cp2x = cp2x; this.cp2y = cp2y;
5377
this.x = x; this.y = y;
5378
}).prototype.exec = function(ctx) { ctx.bezierCurveTo(this.cp1x, this.cp1y, this.cp2x, this.cp2y, this.x, this.y); };
5379
5380
/**
5381
* Graphics command object. See {{#crossLink "Graphics/rect"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5382
* @class Rect
5383
* @constructor
5384
* @param {Number} x
5385
* @param {Number} y
5386
* @param {Number} w
5387
* @param {Number} h
5388
**/
5389
/**
5390
* @property x
5391
* @type Number
5392
*/
5393
/**
5394
* @property y
5395
* @type Number
5396
*/
5397
/**
5398
* @property w
5399
* @type Number
5400
*/
5401
/**
5402
* @property h
5403
* @type Number
5404
*/
5405
/**
5406
* Execute the Graphics command in the provided Canvas context.
5407
* @method exec
5408
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5409
*/
5410
(G.Rect = function(x, y, w, h) {
5411
this.x = x; this.y = y;
5412
this.w = w; this.h = h;
5413
}).prototype.exec = function(ctx) { ctx.rect(this.x, this.y, this.w, this.h); };
5414
5415
/**
5416
* Graphics command object. See {{#crossLink "Graphics/closePath"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5417
* @class ClosePath
5418
* @constructor
5419
**/
5420
/**
5421
* Execute the Graphics command in the provided Canvas context.
5422
* @method exec
5423
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5424
*/
5425
(G.ClosePath = function() {
5426
}).prototype.exec = function(ctx) { ctx.closePath(); };
5427
5428
/**
5429
* Graphics command object to begin a new path. See {{#crossLink "Graphics"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5430
* @class BeginPath
5431
* @constructor
5432
**/
5433
/**
5434
* Execute the Graphics command in the provided Canvas context.
5435
* @method exec
5436
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5437
*/
5438
(G.BeginPath = function() {
5439
}).prototype.exec = function(ctx) { ctx.beginPath(); };
5440
5441
/**
5442
* Graphics command object. See {{#crossLink "Graphics/beginFill"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5443
* @class Fill
5444
* @constructor
5445
* @param {Object} style A valid Context2D fillStyle.
5446
* @param {Matrix2D} matrix
5447
**/
5448
/**
5449
* A valid Context2D fillStyle.
5450
* @property style
5451
* @type Object
5452
*/
5453
/**
5454
* @property matrix
5455
* @type Matrix2D
5456
*/
5457
/**
5458
* Execute the Graphics command in the provided Canvas context.
5459
* @method exec
5460
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5461
*/
5462
p = (G.Fill = function(style, matrix) {
5463
this.style = style;
5464
this.matrix = matrix;
5465
}).prototype;
5466
p.exec = function(ctx) {
5467
if (!this.style) { return; }
5468
ctx.fillStyle = this.style;
5469
var mtx = this.matrix;
5470
if (mtx) { ctx.save(); ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty); }
5471
ctx.fill();
5472
if (mtx) { ctx.restore(); }
5473
};
5474
/**
5475
* Creates a linear gradient style and assigns it to {{#crossLink "Fill/style:property"}}{{/crossLink}}.
5476
* See {{#crossLink "Graphics/beginLinearGradientFill"}}{{/crossLink}} for more information.
5477
* @method linearGradient
5478
* @param {Array} colors
5479
*
5480
* @param {Array} ratios
5481
* @param {Number} x0
5482
* @param {Number} y0
5483
* @param {Number} x1
5484
* @param {Number} y1
5485
* @return {Fill} Returns this Fill object for chaining or assignment.
5486
*/
5487
p.linearGradient = function(colors, ratios, x0, y0, x1, y1) {
5488
var o = this.style = Graphics._ctx.createLinearGradient(x0, y0, x1, y1);
5489
for (var i=0, l=colors.length; i<l; i++) { o.addColorStop(ratios[i], colors[i]); }
5490
o.props = {colors:colors, ratios:ratios, x0:x0, y0:y0, x1:x1, y1:y1, type:"linear"};
5491
return this;
5492
};
5493
/**
5494
* Creates a radial gradient style and assigns it to {{#crossLink "Fill/style:property"}}{{/crossLink}}.
5495
* See {{#crossLink "Graphics/beginRadialGradientFill"}}{{/crossLink}} for more information.
5496
* @method radialGradient
5497
* @param {Array} colors
5498
* @param {Array} ratios
5499
* @param {Number} x0
5500
* @param {Number} y0
5501
* @param {Number} r0
5502
* @param {Number} x1
5503
* @param {Number} y1
5504
* @param {Number} r1
5505
* @return {Fill} Returns this Fill object for chaining or assignment.
5506
*/
5507
p.radialGradient = function(colors, ratios, x0, y0, r0, x1, y1, r1) {
5508
var o = this.style = Graphics._ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
5509
for (var i=0, l=colors.length; i<l; i++) { o.addColorStop(ratios[i], colors[i]); }
5510
o.props = {colors:colors, ratios:ratios, x0:x0, y0:y0, r0:r0, x1:x1, y1:y1, r1:r1, type:"radial"};
5511
return this;
5512
};
5513
/**
5514
* Creates a bitmap fill style and assigns it to the {{#crossLink "Fill/style:property"}}{{/crossLink}}.
5515
* See {{#crossLink "Graphics/beginBitmapFill"}}{{/crossLink}} for more information.
5516
* @method bitmap
5517
* @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement} image Must be loaded prior to creating a bitmap fill, or the fill will be empty.
5518
* @param {String} [repetition] One of: repeat, repeat-x, repeat-y, or no-repeat.
5519
* @return {Fill} Returns this Fill object for chaining or assignment.
5520
*/
5521
p.bitmap = function(image, repetition) {
5522
if (image.naturalWidth || image.getContext || image.readyState >= 2) {
5523
var o = this.style = Graphics._ctx.createPattern(image, repetition || "");
5524
o.props = {image: image, repetition: repetition, type: "bitmap"};
5525
}
5526
return this;
5527
};
5528
p.path = false;
5529
5530
/**
5531
* Graphics command object. See {{#crossLink "Graphics/beginStroke"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5532
* @class Stroke
5533
* @constructor
5534
* @param {Object} style A valid Context2D fillStyle.
5535
* @param {Boolean} ignoreScale
5536
**/
5537
/**
5538
* A valid Context2D strokeStyle.
5539
* @property style
5540
* @type Object
5541
*/
5542
/**
5543
* @property ignoreScale
5544
* @type Boolean
5545
*/
5546
/**
5547
* Execute the Graphics command in the provided Canvas context.
5548
* @method exec
5549
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5550
*/
5551
p = (G.Stroke = function(style, ignoreScale) {
5552
this.style = style;
5553
this.ignoreScale = ignoreScale;
5554
}).prototype;
5555
p.exec = function(ctx) {
5556
if (!this.style) { return; }
5557
ctx.strokeStyle = this.style;
5558
if (this.ignoreScale) { ctx.save(); ctx.setTransform(1,0,0,1,0,0); }
5559
ctx.stroke();
5560
if (this.ignoreScale) { ctx.restore(); }
5561
};
5562
/**
5563
* Creates a linear gradient style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}.
5564
* See {{#crossLink "Graphics/beginLinearGradientStroke"}}{{/crossLink}} for more information.
5565
* @method linearGradient
5566
* @param {Array} colors
5567
* @param {Array} ratios
5568
* @param {Number} x0
5569
* @param {Number} y0
5570
* @param {Number} x1
5571
* @param {Number} y1
5572
* @return {Fill} Returns this Stroke object for chaining or assignment.
5573
*/
5574
p.linearGradient = G.Fill.prototype.linearGradient;
5575
/**
5576
* Creates a radial gradient style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}.
5577
* See {{#crossLink "Graphics/beginRadialGradientStroke"}}{{/crossLink}} for more information.
5578
* @method radialGradient
5579
* @param {Array} colors
5580
* @param {Array} ratios
5581
* @param {Number} x0
5582
* @param {Number} y0
5583
* @param {Number} r0
5584
* @param {Number} x1
5585
* @param {Number} y1
5586
* @param {Number} r1
5587
* @return {Fill} Returns this Stroke object for chaining or assignment.
5588
*/
5589
p.radialGradient = G.Fill.prototype.radialGradient;
5590
/**
5591
* Creates a bitmap fill style and assigns it to {{#crossLink "Stroke/style:property"}}{{/crossLink}}.
5592
* See {{#crossLink "Graphics/beginBitmapStroke"}}{{/crossLink}} for more information.
5593
* @method bitmap
5594
* @param {HTMLImageElement} image
5595
* @param {String} [repetition] One of: repeat, repeat-x, repeat-y, or no-repeat.
5596
* @return {Fill} Returns this Stroke object for chaining or assignment.
5597
*/
5598
p.bitmap = G.Fill.prototype.bitmap;
5599
p.path = false;
5600
5601
/**
5602
* Graphics command object. See {{#crossLink "Graphics/setStrokeStyle"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5603
* @class StrokeStyle
5604
* @constructor
5605
* @param {Number} width
5606
* @param {String} [caps=butt]
5607
* @param {String} [joints=miter]
5608
* @param {Number} [miterLimit=10]
5609
* @param {Boolean} [ignoreScale=false]
5610
**/
5611
/**
5612
* @property width
5613
* @type Number
5614
*/
5615
/**
5616
* One of: butt, round, square
5617
* @property caps
5618
* @type String
5619
*/
5620
/**
5621
* One of: round, bevel, miter
5622
* @property joints
5623
* @type String
5624
*/
5625
/**
5626
* @property miterLimit
5627
* @type Number
5628
*/
5629
/**
5630
* Execute the Graphics command in the provided Canvas context.
5631
* @method exec
5632
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5633
*/
5634
p = (G.StrokeStyle = function(width, caps, joints, miterLimit, ignoreScale) {
5635
this.width = width;
5636
this.caps = caps;
5637
this.joints = joints;
5638
this.miterLimit = miterLimit;
5639
this.ignoreScale = ignoreScale;
5640
}).prototype;
5641
p.exec = function(ctx) {
5642
ctx.lineWidth = (this.width == null ? "1" : this.width);
5643
ctx.lineCap = (this.caps == null ? "butt" : (isNaN(this.caps) ? this.caps : Graphics.STROKE_CAPS_MAP[this.caps]));
5644
ctx.lineJoin = (this.joints == null ? "miter" : (isNaN(this.joints) ? this.joints : Graphics.STROKE_JOINTS_MAP[this.joints]));
5645
ctx.miterLimit = (this.miterLimit == null ? "10" : this.miterLimit);
5646
ctx.ignoreScale = (this.ignoreScale == null ? false : this.ignoreScale);
5647
};
5648
p.path = false;
5649
5650
/**
5651
* Graphics command object. See {{#crossLink "Graphics/setStrokeDash"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5652
* @class StrokeDash
5653
* @constructor
5654
* @param {Array} [segments]
5655
* @param {Number} [offset=0]
5656
**/
5657
/**
5658
* @property segments
5659
* @type Array
5660
*/
5661
/**
5662
* @property offset
5663
* @type Number
5664
*/
5665
/**
5666
* Execute the Graphics command in the provided Canvas context.
5667
* @method exec
5668
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5669
*/
5670
(G.StrokeDash = function(segments, offset) {
5671
this.segments = segments;
5672
this.offset = offset||0;
5673
}).prototype.exec = function(ctx) {
5674
if (ctx.setLineDash) { // feature detection.
5675
ctx.setLineDash(this.segments|| G.StrokeDash.EMPTY_SEGMENTS); // instead of [] to reduce churn.
5676
ctx.lineDashOffset = this.offset||0;
5677
}
5678
};
5679
/**
5680
* The default value for segments (ie. no dash).
5681
* @property EMPTY_SEGMENTS
5682
* @static
5683
* @final
5684
* @readonly
5685
* @protected
5686
* @type {Array}
5687
**/
5688
G.StrokeDash.EMPTY_SEGMENTS = [];
5689
5690
/**
5691
* Graphics command object. See {{#crossLink "Graphics/drawRoundRectComplex"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5692
* @class RoundRect
5693
* @constructor
5694
* @param {Number} x
5695
* @param {Number} y
5696
* @param {Number} w
5697
* @param {Number} h
5698
* @param {Number} radiusTL
5699
* @param {Number} radiusTR
5700
* @param {Number} radiusBR
5701
* @param {Number} radiusBL
5702
**/
5703
/**
5704
* @property x
5705
* @type Number
5706
*/
5707
/**
5708
* @property y
5709
* @type Number
5710
*/
5711
/**
5712
* @property w
5713
* @type Number
5714
*/
5715
/**
5716
* @property h
5717
* @type Number
5718
*/
5719
/**
5720
* @property radiusTL
5721
* @type Number
5722
*/
5723
/**
5724
* @property radiusTR
5725
* @type Number
5726
*/
5727
/**
5728
* @property radiusBR
5729
* @type Number
5730
*/
5731
/**
5732
* @property radiusBL
5733
* @type Number
5734
*/
5735
/**
5736
* Execute the Graphics command in the provided Canvas context.
5737
* @method exec
5738
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5739
*/
5740
(G.RoundRect = function(x, y, w, h, radiusTL, radiusTR, radiusBR, radiusBL) {
5741
this.x = x; this.y = y;
5742
this.w = w; this.h = h;
5743
this.radiusTL = radiusTL; this.radiusTR = radiusTR;
5744
this.radiusBR = radiusBR; this.radiusBL = radiusBL;
5745
}).prototype.exec = function(ctx) {
5746
var max = (w<h?w:h)/2;
5747
var mTL=0, mTR=0, mBR=0, mBL=0;
5748
var x = this.x, y = this.y, w = this.w, h = this.h;
5749
var rTL = this.radiusTL, rTR = this.radiusTR, rBR = this.radiusBR, rBL = this.radiusBL;
5750
5751
if (rTL < 0) { rTL *= (mTL=-1); }
5752
if (rTL > max) { rTL = max; }
5753
if (rTR < 0) { rTR *= (mTR=-1); }
5754
if (rTR > max) { rTR = max; }
5755
if (rBR < 0) { rBR *= (mBR=-1); }
5756
if (rBR > max) { rBR = max; }
5757
if (rBL < 0) { rBL *= (mBL=-1); }
5758
if (rBL > max) { rBL = max; }
5759
5760
ctx.moveTo(x+w-rTR, y);
5761
ctx.arcTo(x+w+rTR*mTR, y-rTR*mTR, x+w, y+rTR, rTR);
5762
ctx.lineTo(x+w, y+h-rBR);
5763
ctx.arcTo(x+w+rBR*mBR, y+h+rBR*mBR, x+w-rBR, y+h, rBR);
5764
ctx.lineTo(x+rBL, y+h);
5765
ctx.arcTo(x-rBL*mBL, y+h+rBL*mBL, x, y+h-rBL, rBL);
5766
ctx.lineTo(x, y+rTL);
5767
ctx.arcTo(x-rTL*mTL, y-rTL*mTL, x+rTL, y, rTL);
5768
ctx.closePath();
5769
};
5770
5771
/**
5772
* Graphics command object. See {{#crossLink "Graphics/drawCircle"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5773
* @class Circle
5774
* @constructor
5775
* @param {Number} x
5776
* @param {Number} y
5777
* @param {Number} radius
5778
**/
5779
/**
5780
* @property x
5781
* @type Number
5782
*/
5783
/**
5784
* @property y
5785
* @type Number
5786
*/
5787
/**
5788
* @property radius
5789
* @type Number
5790
*/
5791
/**
5792
* Execute the Graphics command in the provided Canvas context.
5793
* @method exec
5794
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5795
*/
5796
(G.Circle = function(x, y, radius) {
5797
this.x = x; this.y = y;
5798
this.radius = radius;
5799
}).prototype.exec = function(ctx) { ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2); };
5800
5801
/**
5802
* Graphics command object. See {{#crossLink "Graphics/drawEllipse"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5803
* @class Ellipse
5804
* @constructor
5805
* @param {Number} x
5806
* @param {Number} y
5807
* @param {Number} w
5808
* @param {Number} h
5809
**/
5810
/**
5811
* @property x
5812
* @type Number
5813
*/
5814
/**
5815
* @property y
5816
* @type Number
5817
*/
5818
/**
5819
* @property w
5820
* @type Number
5821
*/
5822
/**
5823
* @property h
5824
* @type Number
5825
*/
5826
/**
5827
* Execute the Graphics command in the provided Canvas context.
5828
* @method exec
5829
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5830
*/
5831
(G.Ellipse = function(x, y, w, h) {
5832
this.x = x; this.y = y;
5833
this.w = w; this.h = h;
5834
}).prototype.exec = function(ctx) {
5835
var x = this.x, y = this.y;
5836
var w = this.w, h = this.h;
5837
5838
var k = 0.5522848;
5839
var ox = (w / 2) * k;
5840
var oy = (h / 2) * k;
5841
var xe = x + w;
5842
var ye = y + h;
5843
var xm = x + w / 2;
5844
var ym = y + h / 2;
5845
5846
ctx.moveTo(x, ym);
5847
ctx.bezierCurveTo(x, ym-oy, xm-ox, y, xm, y);
5848
ctx.bezierCurveTo(xm+ox, y, xe, ym-oy, xe, ym);
5849
ctx.bezierCurveTo(xe, ym+oy, xm+ox, ye, xm, ye);
5850
ctx.bezierCurveTo(xm-ox, ye, x, ym+oy, x, ym);
5851
};
5852
5853
/**
5854
* Graphics command object. See {{#crossLink "Graphics/drawPolyStar"}}{{/crossLink}} and {{#crossLink "Graphics/append"}}{{/crossLink}} for more information.
5855
* @class PolyStar
5856
* @constructor
5857
* @param {Number} x
5858
* @param {Number} y
5859
* @param {Number} radius
5860
* @param {Number} sides
5861
* @param {Number} pointSize
5862
* @param {Number} angle
5863
**/
5864
/**
5865
* @property x
5866
* @type Number
5867
*/
5868
/**
5869
* @property y
5870
* @type Number
5871
*/
5872
/**
5873
* @property radius
5874
* @type Number
5875
*/
5876
/**
5877
* @property sides
5878
* @type Number
5879
*/
5880
/**
5881
* @property pointSize
5882
* @type Number
5883
*/
5884
/**
5885
* @property angle
5886
* @type Number
5887
*/
5888
/**
5889
* Execute the Graphics command in the provided Canvas context.
5890
* @method exec
5891
* @param {CanvasRenderingContext2D} ctx The canvas rendering context
5892
*/
5893
(G.PolyStar = function(x, y, radius, sides, pointSize, angle) {
5894
this.x = x; this.y = y;
5895
this.radius = radius;
5896
this.sides = sides;
5897
this.pointSize = pointSize;
5898
this.angle = angle;
5899
}).prototype.exec = function(ctx) {
5900
var x = this.x, y = this.y;
5901
var radius = this.radius;
5902
var angle = (this.angle||0)/180*Math.PI;
5903
var sides = this.sides;
5904
var ps = 1-(this.pointSize||0);
5905
var a = Math.PI/sides;
5906
5907
ctx.moveTo(x+Math.cos(angle)*radius, y+Math.sin(angle)*radius);
5908
for (var i=0; i<sides; i++) {
5909
angle += a;
5910
if (ps != 1) {
5911
ctx.lineTo(x+Math.cos(angle)*radius*ps, y+Math.sin(angle)*radius*ps);
5912
}
5913
angle += a;
5914
ctx.lineTo(x+Math.cos(angle)*radius, y+Math.sin(angle)*radius);
5915
}
5916
ctx.closePath();
5917
};
5918
5919
// docced above.
5920
Graphics.beginCmd = new G.BeginPath(); // so we don't have to instantiate multiple instances.
5921
5922
5923
createjs.Graphics = Graphics;
5924
}());
5925
5926
//##############################################################################
5927
// DisplayObject.js
5928
//##############################################################################
5929
5930
this.createjs = this.createjs||{};
5931
5932
(function() {
5933
"use strict";
5934
5935
5936
// constructor:
5937
/**
5938
* DisplayObject is an abstract class that should not be constructed directly. Instead construct subclasses such as
5939
* {{#crossLink "Container"}}{{/crossLink}}, {{#crossLink "Bitmap"}}{{/crossLink}}, and {{#crossLink "Shape"}}{{/crossLink}}.
5940
* DisplayObject is the base class for all display classes in the EaselJS library. It defines the core properties and
5941
* methods that are shared between all display objects, such as transformation properties (x, y, scaleX, scaleY, etc),
5942
* caching, and mouse handlers.
5943
* @class DisplayObject
5944
* @extends EventDispatcher
5945
* @constructor
5946
**/
5947
function DisplayObject() {
5948
this.EventDispatcher_constructor();
5949
5950
5951
// public properties:
5952
/**
5953
* The alpha (transparency) for this display object. 0 is fully transparent, 1 is fully opaque.
5954
* @property alpha
5955
* @type {Number}
5956
* @default 1
5957
**/
5958
this.alpha = 1;
5959
5960
/**
5961
* If a cache is active, this returns the canvas that holds the cached version of this display object. See {{#crossLink "cache"}}{{/crossLink}}
5962
* for more information.
5963
* @property cacheCanvas
5964
* @type {HTMLCanvasElement | Object}
5965
* @default null
5966
* @readonly
5967
**/
5968
this.cacheCanvas = null;
5969
5970
/**
5971
* Returns an ID number that uniquely identifies the current cache for this display object. This can be used to
5972
* determine if the cache has changed since a previous check.
5973
* @property cacheID
5974
* @type {Number}
5975
* @default 0
5976
*/
5977
this.cacheID = 0;
5978
5979
/**
5980
* Unique ID for this display object. Makes display objects easier for some uses.
5981
* @property id
5982
* @type {Number}
5983
* @default -1
5984
**/
5985
this.id = createjs.UID.get();
5986
5987
/**
5988
* Indicates whether to include this object when running mouse interactions. Setting this to `false` for children
5989
* of a {{#crossLink "Container"}}{{/crossLink}} will cause events on the Container to not fire when that child is
5990
* clicked. Setting this property to `false` does not prevent the {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}}
5991
* method from returning the child.
5992
*
5993
* <strong>Note:</strong> In EaselJS 0.7.0, the mouseEnabled property will not work properly with nested Containers. Please
5994
* 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
5995
* provided in the next release of EaselJS.
5996
* @property mouseEnabled
5997
* @type {Boolean}
5998
* @default true
5999
**/
6000
this.mouseEnabled = true;
6001
6002
/**
6003
* If false, the tick will not run on this display object (or its children). This can provide some performance benefits.
6004
* In addition to preventing the "tick" event from being dispatched, it will also prevent tick related updates
6005
* on some display objects (ex. Sprite & MovieClip frame advancing, DOMElement visibility handling).
6006
* @property tickEnabled
6007
* @type Boolean
6008
* @default true
6009
**/
6010
this.tickEnabled = true;
6011
6012
/**
6013
* An optional name for this display object. Included in {{#crossLink "DisplayObject/toString"}}{{/crossLink}} . Useful for
6014
* debugging.
6015
* @property name
6016
* @type {String}
6017
* @default null
6018
**/
6019
this.name = null;
6020
6021
/**
6022
* A reference to the {{#crossLink "Container"}}{{/crossLink}} or {{#crossLink "Stage"}}{{/crossLink}} object that
6023
* contains this display object, or null if it has not been added
6024
* to one.
6025
* @property parent
6026
* @final
6027
* @type {Container}
6028
* @default null
6029
* @readonly
6030
**/
6031
this.parent = null;
6032
6033
/**
6034
* The left offset for this display object's registration point. For example, to make a 100x100px Bitmap rotate
6035
* around its center, you would set regX and {{#crossLink "DisplayObject/regY:property"}}{{/crossLink}} to 50.
6036
* @property regX
6037
* @type {Number}
6038
* @default 0
6039
**/
6040
this.regX = 0;
6041
6042
/**
6043
* The y offset for this display object's registration point. For example, to make a 100x100px Bitmap rotate around
6044
* its center, you would set {{#crossLink "DisplayObject/regX:property"}}{{/crossLink}} and regY to 50.
6045
* @property regY
6046
* @type {Number}
6047
* @default 0
6048
**/
6049
this.regY = 0;
6050
6051
/**
6052
* The rotation in degrees for this display object.
6053
* @property rotation
6054
* @type {Number}
6055
* @default 0
6056
**/
6057
this.rotation = 0;
6058
6059
/**
6060
* The factor to stretch this display object horizontally. For example, setting scaleX to 2 will stretch the display
6061
* object to twice its nominal width. To horizontally flip an object, set the scale to a negative number.
6062
* @property scaleX
6063
* @type {Number}
6064
* @default 1
6065
**/
6066
this.scaleX = 1;
6067
6068
/**
6069
* The factor to stretch this display object vertically. For example, setting scaleY to 0.5 will stretch the display
6070
* object to half its nominal height. To vertically flip an object, set the scale to a negative number.
6071
* @property scaleY
6072
* @type {Number}
6073
* @default 1
6074
**/
6075
this.scaleY = 1;
6076
6077
/**
6078
* The factor to skew this display object horizontally.
6079
* @property skewX
6080
* @type {Number}
6081
* @default 0
6082
**/
6083
this.skewX = 0;
6084
6085
/**
6086
* The factor to skew this display object vertically.
6087
* @property skewY
6088
* @type {Number}
6089
* @default 0
6090
**/
6091
this.skewY = 0;
6092
6093
/**
6094
* A shadow object that defines the shadow to render on this display object. Set to `null` to remove a shadow. If
6095
* null, this property is inherited from the parent container.
6096
* @property shadow
6097
* @type {Shadow}
6098
* @default null
6099
**/
6100
this.shadow = null;
6101
6102
/**
6103
* Indicates whether this display object should be rendered to the canvas and included when running the Stage
6104
* {{#crossLink "Stage/getObjectsUnderPoint"}}{{/crossLink}} method.
6105
* @property visible
6106
* @type {Boolean}
6107
* @default true
6108
**/
6109
this.visible = true;
6110
6111
/**
6112
* The x (horizontal) position of the display object, relative to its parent.
6113
* @property x
6114
* @type {Number}
6115
* @default 0
6116
**/
6117
this.x = 0;
6118
6119
/** The y (vertical) position of the display object, relative to its parent.
6120
* @property y
6121
* @type {Number}
6122
* @default 0
6123
**/
6124
this.y = 0;
6125
6126
/**
6127
* If set, defines the transformation for this display object, overriding all other transformation properties
6128
* (x, y, rotation, scale, skew).
6129
* @property transformMatrix
6130
* @type {Matrix2D}
6131
* @default null
6132
**/
6133
this.transformMatrix = null;
6134
6135
/**
6136
* The composite operation indicates how the pixels of this display object will be composited with the elements
6137
* behind it. If `null`, this property is inherited from the parent container. For more information, read the
6138
* <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#compositing">
6139
* whatwg spec on compositing</a>.
6140
* @property compositeOperation
6141
* @type {String}
6142
* @default null
6143
**/
6144
this.compositeOperation = null;
6145
6146
/**
6147
* Indicates whether the display object should be drawn to a whole pixel when
6148
* {{#crossLink "Stage/snapToPixelEnabled"}}{{/crossLink}} is true. To enable/disable snapping on whole
6149
* categories of display objects, set this value on the prototype (Ex. Text.prototype.snapToPixel = true).
6150
* @property snapToPixel
6151
* @type {Boolean}
6152
* @default true
6153
**/
6154
this.snapToPixel = true;
6155
6156
/**
6157
* An array of Filter objects to apply to this display object. Filters are only applied / updated when {{#crossLink "cache"}}{{/crossLink}}
6158
* or {{#crossLink "updateCache"}}{{/crossLink}} is called on the display object, and only apply to the area that is
6159
* cached.
6160
* @property filters
6161
* @type {Array}
6162
* @default null
6163
**/
6164
this.filters = null;
6165
6166
/**
6167
* A Shape instance that defines a vector mask (clipping path) for this display object. The shape's transformation
6168
* will be applied relative to the display object's parent coordinates (as if it were a child of the parent).
6169
* @property mask
6170
* @type {Shape}
6171
* @default null
6172
*/
6173
this.mask = null;
6174
6175
/**
6176
* A display object that will be tested when checking mouse interactions or testing {{#crossLink "Container/getObjectsUnderPoint"}}{{/crossLink}}.
6177
* The hit area will have its transformation applied relative to this display object's coordinate space (as though
6178
* the hit test object were a child of this display object and relative to its regX/Y). The hitArea will be tested
6179
* using only its own `alpha` value regardless of the alpha value on the target display object, or the target's
6180
* ancestors (parents).
6181
*
6182
* If set on a {{#crossLink "Container"}}{{/crossLink}}, children of the Container will not receive mouse events.
6183
* This is similar to setting {{#crossLink "mouseChildren"}}{{/crossLink}} to false.
6184
*
6185
* Note that hitArea is NOT currently used by the `hitTest()` method, nor is it supported for {{#crossLink "Stage"}}{{/crossLink}}.
6186
* @property hitArea
6187
* @type {DisplayObject}
6188
* @default null
6189
*/
6190
this.hitArea = null;
6191
6192
/**
6193
* A CSS cursor (ex. "pointer", "help", "text", etc) that will be displayed when the user hovers over this display
6194
* object. You must enable mouseover events using the {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}} method to
6195
* use this property. Setting a non-null cursor on a Container will override the cursor set on its descendants.
6196
* @property cursor
6197
* @type {String}
6198
* @default null
6199
*/
6200
this.cursor = null;
6201
6202
6203
// private properties:
6204
/**
6205
* @property _cacheOffsetX
6206
* @protected
6207
* @type {Number}
6208
* @default 0
6209
**/
6210
this._cacheOffsetX = 0;
6211
6212
/**
6213
* @property _cacheOffsetY
6214
* @protected
6215
* @type {Number}
6216
* @default 0
6217
**/
6218
this._cacheOffsetY = 0;
6219
6220
/**
6221
* @property _filterOffsetX
6222
* @protected
6223
* @type {Number}
6224
* @default 0
6225
**/
6226
this._filterOffsetX = 0;
6227
6228
/**
6229
* @property _filterOffsetY
6230
* @protected
6231
* @type {Number}
6232
* @default 0
6233
**/
6234
this._filterOffsetY = 0;
6235
6236
/**
6237
* @property _cacheScale
6238
* @protected
6239
* @type {Number}
6240
* @default 1
6241
**/
6242
this._cacheScale = 1;
6243
6244
/**
6245
* @property _cacheDataURLID
6246
* @protected
6247
* @type {Number}
6248
* @default 0
6249
*/
6250
this._cacheDataURLID = 0;
6251
6252
/**
6253
* @property _cacheDataURL
6254
* @protected
6255
* @type {String}
6256
* @default null
6257
*/
6258
this._cacheDataURL = null;
6259
6260
/**
6261
* @property _props
6262
* @protected
6263
* @type {DisplayObject}
6264
* @default null
6265
**/
6266
this._props = new createjs.DisplayProps();
6267
6268
/**
6269
* @property _rectangle
6270
* @protected
6271
* @type {Rectangle}
6272
* @default null
6273
**/
6274
this._rectangle = new createjs.Rectangle();
6275
6276
/**
6277
* @property _bounds
6278
* @protected
6279
* @type {Rectangle}
6280
* @default null
6281
**/
6282
this._bounds = null;
6283
}
6284
var p = createjs.extend(DisplayObject, createjs.EventDispatcher);
6285
6286
// TODO: deprecated
6287
// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
6288
6289
// static properties:
6290
/**
6291
* Listing of mouse event names. Used in _hasMouseEventListener.
6292
* @property _MOUSE_EVENTS
6293
* @protected
6294
* @static
6295
* @type {Array}
6296
**/
6297
DisplayObject._MOUSE_EVENTS = ["click","dblclick","mousedown","mouseout","mouseover","pressmove","pressup","rollout","rollover"];
6298
6299
/**
6300
* Suppresses errors generated when using features like hitTest, mouse events, and {{#crossLink "getObjectsUnderPoint"}}{{/crossLink}}
6301
* with cross domain content.
6302
* @property suppressCrossDomainErrors
6303
* @static
6304
* @type {Boolean}
6305
* @default false
6306
**/
6307
DisplayObject.suppressCrossDomainErrors = false;
6308
6309
/**
6310
* @property _snapToPixelEnabled
6311
* @protected
6312
* @static
6313
* @type {Boolean}
6314
* @default false
6315
**/
6316
DisplayObject._snapToPixelEnabled = false; // stage.snapToPixelEnabled is temporarily copied here during a draw to provide global access.
6317
6318
/**
6319
* @property _hitTestCanvas
6320
* @type {HTMLCanvasElement | Object}
6321
* @static
6322
* @protected
6323
**/
6324
/**
6325
* @property _hitTestContext
6326
* @type {CanvasRenderingContext2D}
6327
* @static
6328
* @protected
6329
**/
6330
var canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); // prevent errors on load in browsers without canvas.
6331
if (canvas.getContext) {
6332
DisplayObject._hitTestCanvas = canvas;
6333
DisplayObject._hitTestContext = canvas.getContext("2d");
6334
canvas.width = canvas.height = 1;
6335
}
6336
6337
/**
6338
* @property _nextCacheID
6339
* @type {Number}
6340
* @static
6341
* @protected
6342
**/
6343
DisplayObject._nextCacheID = 1;
6344
6345
6346
// events:
6347
/**
6348
* Dispatched when the user presses their left mouse button over the display object. See the
6349
* {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
6350
* @event mousedown
6351
* @since 0.6.0
6352
*/
6353
6354
/**
6355
* Dispatched when the user presses their left mouse button and then releases it while over the display object.
6356
* See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
6357
* @event click
6358
* @since 0.6.0
6359
*/
6360
6361
/**
6362
* Dispatched when the user double clicks their left mouse button over this display object.
6363
* See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
6364
* @event dblclick
6365
* @since 0.6.0
6366
*/
6367
6368
/**
6369
* Dispatched when the user's mouse enters this display object. This event must be enabled using
6370
* {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. See also {{#crossLink "DisplayObject/rollover:event"}}{{/crossLink}}.
6371
* See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
6372
* @event mouseover
6373
* @since 0.6.0
6374
*/
6375
6376
/**
6377
* Dispatched when the user's mouse leaves this display object. This event must be enabled using
6378
* {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}. See also {{#crossLink "DisplayObject/rollout:event"}}{{/crossLink}}.
6379
* See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
6380
* @event mouseout
6381
* @since 0.6.0
6382
*/
6383
6384
/**
6385
* This event is similar to {{#crossLink "DisplayObject/mouseover:event"}}{{/crossLink}}, with the following
6386
* differences: it does not bubble, and it considers {{#crossLink "Container"}}{{/crossLink}} instances as an
6387
* aggregate of their content.
6388
*
6389
* For example, myContainer contains two overlapping children: shapeA and shapeB. The user moves their mouse over
6390
* shapeA and then directly on to shapeB. With a listener for {{#crossLink "mouseover:event"}}{{/crossLink}} on
6391
* myContainer, two events would be received, each targeting a child element:<OL>
6392
* <LI>when the mouse enters shapeA (target=shapeA)</LI>
6393
* <LI>when the mouse enters shapeB (target=shapeB)</LI>
6394
* </OL>
6395
* However, with a listener for "rollover" instead, only a single event is received when the mouse first enters
6396
* the aggregate myContainer content (target=myContainer).
6397
*
6398
* This event must be enabled using {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}.
6399
* See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
6400
* @event rollover
6401
* @since 0.7.0
6402
*/
6403
6404
/**
6405
* This event is similar to {{#crossLink "DisplayObject/mouseout:event"}}{{/crossLink}}, with the following
6406
* differences: it does not bubble, and it considers {{#crossLink "Container"}}{{/crossLink}} instances as an
6407
* aggregate of their content.
6408
*
6409
* For example, myContainer contains two overlapping children: shapeA and shapeB. The user moves their mouse over
6410
* shapeA, then directly on to shapeB, then off both. With a listener for {{#crossLink "mouseout:event"}}{{/crossLink}}
6411
* on myContainer, two events would be received, each targeting a child element:<OL>
6412
* <LI>when the mouse leaves shapeA (target=shapeA)</LI>
6413
* <LI>when the mouse leaves shapeB (target=shapeB)</LI>
6414
* </OL>
6415
* However, with a listener for "rollout" instead, only a single event is received when the mouse leaves
6416
* the aggregate myContainer content (target=myContainer).
6417
*
6418
* This event must be enabled using {{#crossLink "Stage/enableMouseOver"}}{{/crossLink}}.
6419
* See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
6420
* @event rollout
6421
* @since 0.7.0
6422
*/
6423
6424
/**
6425
* After a {{#crossLink "DisplayObject/mousedown:event"}}{{/crossLink}} occurs on a display object, a pressmove
6426
* event will be generated on that object whenever the mouse moves until the mouse press is released. This can be
6427
* useful for dragging and similar operations.
6428
* @event pressmove
6429
* @since 0.7.0
6430
*/
6431
6432
/**
6433
* After a {{#crossLink "DisplayObject/mousedown:event"}}{{/crossLink}} occurs on a display object, a pressup event
6434
* will be generated on that object when that mouse press is released. This can be useful for dragging and similar
6435
* operations.
6436
* @event pressup
6437
* @since 0.7.0
6438
*/
6439
6440
/**
6441
* Dispatched when the display object is added to a parent container.
6442
* @event added
6443
*/
6444
6445
/**
6446
* Dispatched when the display object is removed from its parent container.
6447
* @event removed
6448
*/
6449
6450
/**
6451
* Dispatched on each display object on a stage whenever the stage updates. This occurs immediately before the
6452
* rendering (draw) pass. When {{#crossLink "Stage/update"}}{{/crossLink}} is called, first all display objects on
6453
* the stage dispatch the tick event, then all of the display objects are drawn to stage. Children will have their
6454
* {{#crossLink "tick:event"}}{{/crossLink}} event dispatched in order of their depth prior to the event being
6455
* dispatched on their parent.
6456
* @event tick
6457
* @param {Object} target The object that dispatched the event.
6458
* @param {String} type The event type.
6459
* @param {Array} params An array containing any arguments that were passed to the Stage.update() method. For
6460
* example if you called stage.update("hello"), then the params would be ["hello"].
6461
* @since 0.6.0
6462
*/
6463
6464
6465
// getter / setters:
6466
/**
6467
* Use the {{#crossLink "DisplayObject/stage:property"}}{{/crossLink}} property instead.
6468
* @method getStage
6469
* @return {Stage}
6470
* @deprecated
6471
**/
6472
p.getStage = function() {
6473
// uses dynamic access to avoid circular dependencies;
6474
var o = this, _Stage = createjs["Stage"];
6475
while (o.parent) { o = o.parent; }
6476
if (o instanceof _Stage) { return o; }
6477
return null;
6478
};
6479
6480
/**
6481
* Returns the Stage instance that this display object will be rendered on, or null if it has not been added to one.
6482
* @property stage
6483
* @type {Stage}
6484
* @readonly
6485
**/
6486
try {
6487
Object.defineProperties(p, {
6488
stage: { get: p.getStage }
6489
});
6490
} catch (e) {}
6491
6492
6493
// public methods:
6494
/**
6495
* Returns true or false indicating whether the display object would be visible if drawn to a canvas.
6496
* This does not account for whether it would be visible within the boundaries of the stage.
6497
*
6498
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
6499
* @method isVisible
6500
* @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
6501
**/
6502
p.isVisible = function() {
6503
return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0);
6504
};
6505
6506
/**
6507
* Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
6508
* Returns <code>true</code> if the draw was handled (useful for overriding functionality).
6509
*
6510
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
6511
* @method draw
6512
* @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
6513
* @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. For example,
6514
* used for drawing the cache (to prevent it from simply drawing an existing cache back into itself).
6515
* @return {Boolean}
6516
**/
6517
p.draw = function(ctx, ignoreCache) {
6518
var cacheCanvas = this.cacheCanvas;
6519
if (ignoreCache || !cacheCanvas) { return false; }
6520
var scale = this._cacheScale;
6521
ctx.drawImage(cacheCanvas, this._cacheOffsetX+this._filterOffsetX, this._cacheOffsetY+this._filterOffsetY, cacheCanvas.width/scale, cacheCanvas.height/scale);
6522
return true;
6523
};
6524
6525
/**
6526
* Applies this display object's transformation, alpha, globalCompositeOperation, clipping path (mask), and shadow
6527
* to the specified context. This is typically called prior to {{#crossLink "DisplayObject/draw"}}{{/crossLink}}.
6528
* @method updateContext
6529
* @param {CanvasRenderingContext2D} ctx The canvas 2D to update.
6530
**/
6531
p.updateContext = function(ctx) {
6532
var o=this, mask=o.mask, mtx= o._props.matrix;
6533
6534
if (mask && mask.graphics && !mask.graphics.isEmpty()) {
6535
mask.getMatrix(mtx);
6536
ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty);
6537
6538
mask.graphics.drawAsPath(ctx);
6539
ctx.clip();
6540
6541
mtx.invert();
6542
ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty);
6543
}
6544
6545
this.getMatrix(mtx);
6546
var tx = mtx.tx, ty = mtx.ty;
6547
if (DisplayObject._snapToPixelEnabled && o.snapToPixel) {
6548
tx = tx + (tx < 0 ? -0.5 : 0.5) | 0;
6549
ty = ty + (ty < 0 ? -0.5 : 0.5) | 0;
6550
}
6551
ctx.transform(mtx.a, mtx.b, mtx.c, mtx.d, tx, ty);
6552
ctx.globalAlpha *= o.alpha;
6553
if (o.compositeOperation) { ctx.globalCompositeOperation = o.compositeOperation; }
6554
if (o.shadow) { this._applyShadow(ctx, o.shadow); }
6555
};
6556
6557
/**
6558
* Draws the display object into a new canvas, which is then used for subsequent draws. For complex content
6559
* that does not change frequently (ex. a Container with many children that do not move, or a complex vector Shape),
6560
* this can provide for much faster rendering because the content does not need to be re-rendered each tick. The
6561
* cached display object can be moved, rotated, faded, etc freely, however if its content changes, you must
6562
* manually update the cache by calling <code>updateCache()</code> or <code>cache()</code> again. You must specify
6563
* the cache area via the x, y, w, and h parameters. This defines the rectangle that will be rendered and cached
6564
* using this display object's coordinates.
6565
*
6566
* <h4>Example</h4>
6567
* For example if you defined a Shape that drew a circle at 0, 0 with a radius of 25:
6568
*
6569
* var shape = new createjs.Shape();
6570
* shape.graphics.beginFill("#ff0000").drawCircle(0, 0, 25);
6571
* myShape.cache(-25, -25, 50, 50);
6572
*
6573
* Note that filters need to be defined <em>before</em> the cache is applied. Check out the {{#crossLink "Filter"}}{{/crossLink}}
6574
* class for more information. Some filters (ex. BlurFilter) will not work as expected in conjunction with the scale param.
6575
*
6576
* Usually, the resulting cacheCanvas will have the dimensions width*scale by height*scale, however some filters (ex. BlurFilter)
6577
* will add padding to the canvas dimensions.
6578
*
6579
* @method cache
6580
* @param {Number} x The x coordinate origin for the cache region.
6581
* @param {Number} y The y coordinate origin for the cache region.
6582
* @param {Number} width The width of the cache region.
6583
* @param {Number} height The height of the cache region.
6584
* @param {Number} [scale=1] The scale at which the cache will be created. For example, if you cache a vector shape using
6585
* myShape.cache(0,0,100,100,2) then the resulting cacheCanvas will be 200x200 px. This lets you scale and rotate
6586
* cached elements with greater fidelity. Default is 1.
6587
**/
6588
p.cache = function(x, y, width, height, scale) {
6589
// draw to canvas.
6590
scale = scale||1;
6591
if (!this.cacheCanvas) { this.cacheCanvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); }
6592
this._cacheWidth = width;
6593
this._cacheHeight = height;
6594
this._cacheOffsetX = x;
6595
this._cacheOffsetY = y;
6596
this._cacheScale = scale;
6597
this.updateCache();
6598
};
6599
6600
/**
6601
* Redraws the display object to its cache. Calling updateCache without an active cache will throw an error.
6602
* If compositeOperation is null the current cache will be cleared prior to drawing. Otherwise the display object
6603
* will be drawn over the existing cache using the specified compositeOperation.
6604
*
6605
* <h4>Example</h4>
6606
* Clear the current graphics of a cached shape, draw some new instructions, and then update the cache. The new line
6607
* will be drawn on top of the old one.
6608
*
6609
* // Not shown: Creating the shape, and caching it.
6610
* shapeInstance.clear();
6611
* shapeInstance.setStrokeStyle(3).beginStroke("#ff0000").moveTo(100, 100).lineTo(200,200);
6612
* shapeInstance.updateCache();
6613
*
6614
* @method updateCache
6615
* @param {String} compositeOperation The compositeOperation to use, or null to clear the cache and redraw it.
6616
* <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#compositing">
6617
* whatwg spec on compositing</a>.
6618
**/
6619
p.updateCache = function(compositeOperation) {
6620
var cacheCanvas = this.cacheCanvas;
6621
if (!cacheCanvas) { throw "cache() must be called before updateCache()"; }
6622
var scale = this._cacheScale, offX = this._cacheOffsetX*scale, offY = this._cacheOffsetY*scale;
6623
var w = this._cacheWidth, h = this._cacheHeight, ctx = cacheCanvas.getContext("2d");
6624
6625
var fBounds = this._getFilterBounds();
6626
offX += (this._filterOffsetX = fBounds.x);
6627
offY += (this._filterOffsetY = fBounds.y);
6628
6629
w = Math.ceil(w*scale) + fBounds.width;
6630
h = Math.ceil(h*scale) + fBounds.height;
6631
if (w != cacheCanvas.width || h != cacheCanvas.height) {
6632
// TODO: it would be nice to preserve the content if there is a compositeOperation.
6633
cacheCanvas.width = w;
6634
cacheCanvas.height = h;
6635
} else if (!compositeOperation) {
6636
ctx.clearRect(0, 0, w+1, h+1);
6637
}
6638
6639
ctx.save();
6640
ctx.globalCompositeOperation = compositeOperation;
6641
ctx.setTransform(scale, 0, 0, scale, -offX, -offY);
6642
this.draw(ctx, true);
6643
// TODO: filters and cache scale don't play well together at present.
6644
this._applyFilters();
6645
ctx.restore();
6646
this.cacheID = DisplayObject._nextCacheID++;
6647
};
6648
6649
/**
6650
* Clears the current cache. See {{#crossLink "DisplayObject/cache"}}{{/crossLink}} for more information.
6651
* @method uncache
6652
**/
6653
p.uncache = function() {
6654
this._cacheDataURL = this.cacheCanvas = null;
6655
this.cacheID = this._cacheOffsetX = this._cacheOffsetY = this._filterOffsetX = this._filterOffsetY = 0;
6656
this._cacheScale = 1;
6657
};
6658
6659
/**
6660
* Returns a data URL for the cache, or null if this display object is not cached.
6661
* Uses cacheID to ensure a new data URL is not generated if the cache has not changed.
6662
* @method getCacheDataURL
6663
* @return {String} The image data url for the cache.
6664
**/
6665
p.getCacheDataURL = function() {
6666
if (!this.cacheCanvas) { return null; }
6667
if (this.cacheID != this._cacheDataURLID) { this._cacheDataURL = this.cacheCanvas.toDataURL(); }
6668
return this._cacheDataURL;
6669
};
6670
6671
/**
6672
* Transforms the specified x and y position from the coordinate space of the display object
6673
* to the global (stage) coordinate space. For example, this could be used to position an HTML label
6674
* over a specific point on a nested display object. Returns a Point instance with x and y properties
6675
* correlating to the transformed coordinates on the stage.
6676
*
6677
* <h4>Example</h4>
6678
*
6679
* displayObject.x = 300;
6680
* displayObject.y = 200;
6681
* stage.addChild(displayObject);
6682
* var point = displayObject.localToGlobal(100, 100);
6683
* // Results in x=400, y=300
6684
*
6685
* @method localToGlobal
6686
* @param {Number} x The x position in the source display object to transform.
6687
* @param {Number} y The y position in the source display object to transform.
6688
* @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned.
6689
* @return {Point} A Point instance with x and y properties correlating to the transformed coordinates
6690
* on the stage.
6691
**/
6692
p.localToGlobal = function(x, y, pt) {
6693
return this.getConcatenatedMatrix(this._props.matrix).transformPoint(x,y, pt||new createjs.Point());
6694
};
6695
6696
/**
6697
* Transforms the specified x and y position from the global (stage) coordinate space to the
6698
* coordinate space of the display object. For example, this could be used to determine
6699
* the current mouse position within the display object. Returns a Point instance with x and y properties
6700
* correlating to the transformed position in the display object's coordinate space.
6701
*
6702
* <h4>Example</h4>
6703
*
6704
* displayObject.x = 300;
6705
* displayObject.y = 200;
6706
* stage.addChild(displayObject);
6707
* var point = displayObject.globalToLocal(100, 100);
6708
* // Results in x=-200, y=-100
6709
*
6710
* @method globalToLocal
6711
* @param {Number} x The x position on the stage to transform.
6712
* @param {Number} y The y position on the stage to transform.
6713
* @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned.
6714
* @return {Point} A Point instance with x and y properties correlating to the transformed position in the
6715
* display object's coordinate space.
6716
**/
6717
p.globalToLocal = function(x, y, pt) {
6718
return this.getConcatenatedMatrix(this._props.matrix).invert().transformPoint(x,y, pt||new createjs.Point());
6719
};
6720
6721
/**
6722
* Transforms the specified x and y position from the coordinate space of this display object to the coordinate
6723
* space of the target display object. Returns a Point instance with x and y properties correlating to the
6724
* transformed position in the target's coordinate space. Effectively the same as using the following code with
6725
* {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}} and {{#crossLink "DisplayObject/globalToLocal"}}{{/crossLink}}.
6726
*
6727
* var pt = this.localToGlobal(x, y);
6728
* pt = target.globalToLocal(pt.x, pt.y);
6729
*
6730
* @method localToLocal
6731
* @param {Number} x The x position in the source display object to transform.
6732
* @param {Number} y The y position on the source display object to transform.
6733
* @param {DisplayObject} target The target display object to which the coordinates will be transformed.
6734
* @param {Point | Object} [pt] An object to copy the result into. If omitted a new Point object with x/y properties will be returned.
6735
* @return {Point} Returns a Point instance with x and y properties correlating to the transformed position
6736
* in the target's coordinate space.
6737
**/
6738
p.localToLocal = function(x, y, target, pt) {
6739
pt = this.localToGlobal(x, y, pt);
6740
return target.globalToLocal(pt.x, pt.y, pt);
6741
};
6742
6743
/**
6744
* Shortcut method to quickly set the transform properties on the display object. All parameters are optional.
6745
* Omitted parameters will have the default value set.
6746
*
6747
* <h4>Example</h4>
6748
*
6749
* displayObject.setTransform(100, 100, 2, 2);
6750
*
6751
* @method setTransform
6752
* @param {Number} [x=0] The horizontal translation (x position) in pixels
6753
* @param {Number} [y=0] The vertical translation (y position) in pixels
6754
* @param {Number} [scaleX=1] The horizontal scale, as a percentage of 1
6755
* @param {Number} [scaleY=1] the vertical scale, as a percentage of 1
6756
* @param {Number} [rotation=0] The rotation, in degrees
6757
* @param {Number} [skewX=0] The horizontal skew factor
6758
* @param {Number} [skewY=0] The vertical skew factor
6759
* @param {Number} [regX=0] The horizontal registration point in pixels
6760
* @param {Number} [regY=0] The vertical registration point in pixels
6761
* @return {DisplayObject} Returns this instance. Useful for chaining commands.
6762
* @chainable
6763
*/
6764
p.setTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) {
6765
this.x = x || 0;
6766
this.y = y || 0;
6767
this.scaleX = scaleX == null ? 1 : scaleX;
6768
this.scaleY = scaleY == null ? 1 : scaleY;
6769
this.rotation = rotation || 0;
6770
this.skewX = skewX || 0;
6771
this.skewY = skewY || 0;
6772
this.regX = regX || 0;
6773
this.regY = regY || 0;
6774
return this;
6775
};
6776
6777
/**
6778
* Returns a matrix based on this object's current transform.
6779
* @method getMatrix
6780
* @param {Matrix2D} matrix Optional. A Matrix2D object to populate with the calculated values. If null, a new
6781
* Matrix object is returned.
6782
* @return {Matrix2D} A matrix representing this display object's transform.
6783
**/
6784
p.getMatrix = function(matrix) {
6785
var o = this, mtx = matrix&&matrix.identity() || new createjs.Matrix2D();
6786
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);
6787
};
6788
6789
/**
6790
* Generates a Matrix2D object representing the combined transform of the display object and all of its
6791
* parent Containers up to the highest level ancestor (usually the {{#crossLink "Stage"}}{{/crossLink}}). This can
6792
* be used to transform positions between coordinate spaces, such as with {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}}
6793
* and {{#crossLink "DisplayObject/globalToLocal"}}{{/crossLink}}.
6794
* @method getConcatenatedMatrix
6795
* @param {Matrix2D} [matrix] A {{#crossLink "Matrix2D"}}{{/crossLink}} object to populate with the calculated values.
6796
* If null, a new Matrix2D object is returned.
6797
* @return {Matrix2D} The combined matrix.
6798
**/
6799
p.getConcatenatedMatrix = function(matrix) {
6800
var o = this, mtx = this.getMatrix(matrix);
6801
while (o = o.parent) {
6802
mtx.prependMatrix(o.getMatrix(o._props.matrix));
6803
}
6804
return mtx;
6805
};
6806
6807
/**
6808
* Generates a DisplayProps object representing the combined display properties of the object and all of its
6809
* parent Containers up to the highest level ancestor (usually the {{#crossLink "Stage"}}{{/crossLink}}).
6810
* @method getConcatenatedDisplayProps
6811
* @param {DisplayProps} [props] A {{#crossLink "DisplayProps"}}{{/crossLink}} object to populate with the calculated values.
6812
* If null, a new DisplayProps object is returned.
6813
* @return {DisplayProps} The combined display properties.
6814
**/
6815
p.getConcatenatedDisplayProps = function(props) {
6816
props = props ? props.identity() : new createjs.DisplayProps();
6817
var o = this, mtx = o.getMatrix(props.matrix);
6818
do {
6819
props.prepend(o.visible, o.alpha, o.shadow, o.compositeOperation);
6820
6821
// 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.
6822
// this could be simplified (ie. just done as part of the prepend above) if we switched to using a pool.
6823
if (o != this) { mtx.prependMatrix(o.getMatrix(o._props.matrix)); }
6824
} while (o = o.parent);
6825
return props;
6826
};
6827
6828
/**
6829
* Tests whether the display object intersects the specified point in <em>local</em> coordinates (ie. draws a pixel
6830
* with alpha > 0 at the specified position). This ignores the alpha, shadow, hitArea, mask, and compositeOperation
6831
* of the display object.
6832
*
6833
* <h4>Example</h4>
6834
*
6835
* var myShape = new createjs.Shape();
6836
* myShape.graphics.beginFill("red").drawRect(100, 100, 20, 50);
6837
*
6838
* console.log(myShape.hitTest(10,10); // false
6839
* console.log(myShape.hitTest(110, 25); // true
6840
*
6841
* Note that to use Stage coordinates (such as {{#crossLink "Stage/mouseX:property"}}{{/crossLink}}), they must
6842
* first be converted to local coordinates:
6843
*
6844
* stage.addEventListener("stagemousedown", handleMouseDown);
6845
* function handleMouseDown(event) {
6846
* var p = myShape.globalToLocal(stage.mouseX, stage.mouseY);
6847
* var hit = myShape.hitTest(p.x, p.y);
6848
* }
6849
*
6850
* Shape-to-shape collision is not currently supported by EaselJS.
6851
*
6852
* @method hitTest
6853
* @param {Number} x The x position to check in the display object's local coordinates.
6854
* @param {Number} y The y position to check in the display object's local coordinates.
6855
* @return {Boolean} A Boolean indicating whether a visible portion of the DisplayObject intersect the specified
6856
* local Point.
6857
*/
6858
p.hitTest = function(x, y) {
6859
var ctx = DisplayObject._hitTestContext;
6860
ctx.setTransform(1, 0, 0, 1, -x, -y);
6861
this.draw(ctx);
6862
6863
var hit = this._testHit(ctx);
6864
ctx.setTransform(1, 0, 0, 1, 0, 0);
6865
ctx.clearRect(0, 0, 2, 2);
6866
return hit;
6867
};
6868
6869
/**
6870
* Provides a chainable shortcut method for setting a number of properties on the instance.
6871
*
6872
* <h4>Example</h4>
6873
*
6874
* var myGraphics = new createjs.Graphics().beginFill("#ff0000").drawCircle(0, 0, 25);
6875
* var shape = stage.addChild(new createjs.Shape()).set({graphics:myGraphics, x:100, y:100, alpha:0.5});
6876
*
6877
* @method set
6878
* @param {Object} props A generic object containing properties to copy to the DisplayObject instance.
6879
* @return {DisplayObject} Returns the instance the method is called on (useful for chaining calls.)
6880
* @chainable
6881
*/
6882
p.set = function(props) {
6883
for (var n in props) { this[n] = props[n]; }
6884
return this;
6885
};
6886
6887
/**
6888
* Returns a rectangle representing this object's bounds in its local coordinate system (ie. with no transformation).
6889
* Objects that have been cached will return the bounds of the cache.
6890
*
6891
* Not all display objects can calculate their own bounds (ex. Shape). For these objects, you can use
6892
* {{#crossLink "DisplayObject/setBounds"}}{{/crossLink}} so that they are included when calculating Container
6893
* bounds.
6894
*
6895
* <table>
6896
* <tr><td><b>All</b></td><td>
6897
* All display objects support setting bounds manually using setBounds(). Likewise, display objects that
6898
* have been cached using cache() will return the bounds of their cache. Manual and cache bounds will override
6899
* the automatic calculations listed below.
6900
* </td></tr>
6901
* <tr><td><b>Bitmap</b></td><td>
6902
* Returns the width and height of the sourceRect (if specified) or image, extending from (x=0,y=0).
6903
* </td></tr>
6904
* <tr><td><b>Sprite</b></td><td>
6905
* Returns the bounds of the current frame. May have non-zero x/y if a frame registration point was specified
6906
* in the spritesheet data. See also {{#crossLink "SpriteSheet/getFrameBounds"}}{{/crossLink}}
6907
* </td></tr>
6908
* <tr><td><b>Container</b></td><td>
6909
* Returns the aggregate (combined) bounds of all children that return a non-null value from getBounds().
6910
* </td></tr>
6911
* <tr><td><b>Shape</b></td><td>
6912
* Does not currently support automatic bounds calculations. Use setBounds() to manually define bounds.
6913
* </td></tr>
6914
* <tr><td><b>Text</b></td><td>
6915
* Returns approximate bounds. Horizontal values (x/width) are quite accurate, but vertical values (y/height) are
6916
* not, especially when using textBaseline values other than "top".
6917
* </td></tr>
6918
* <tr><td><b>BitmapText</b></td><td>
6919
* Returns approximate bounds. Values will be more accurate if spritesheet frame registration points are close
6920
* to (x=0,y=0).
6921
* </td></tr>
6922
* </table>
6923
*
6924
* Bounds can be expensive to calculate for some objects (ex. text, or containers with many children), and
6925
* are recalculated each time you call getBounds(). You can prevent recalculation on static objects by setting the
6926
* bounds explicitly:
6927
*
6928
* var bounds = obj.getBounds();
6929
* obj.setBounds(bounds.x, bounds.y, bounds.width, bounds.height);
6930
* // getBounds will now use the set values, instead of recalculating
6931
*
6932
* To reduce memory impact, the returned Rectangle instance may be reused internally; clone the instance or copy its
6933
* values if you need to retain it.
6934
*
6935
* var myBounds = obj.getBounds().clone();
6936
* // OR:
6937
* myRect.copy(obj.getBounds());
6938
*
6939
* @method getBounds
6940
* @return {Rectangle} A Rectangle instance representing the bounds, or null if bounds are not available for this
6941
* object.
6942
**/
6943
p.getBounds = function() {
6944
if (this._bounds) { return this._rectangle.copy(this._bounds); }
6945
var cacheCanvas = this.cacheCanvas;
6946
if (cacheCanvas) {
6947
var scale = this._cacheScale;
6948
return this._rectangle.setValues(this._cacheOffsetX, this._cacheOffsetY, cacheCanvas.width/scale, cacheCanvas.height/scale);
6949
}
6950
return null;
6951
};
6952
6953
/**
6954
* Returns a rectangle representing this object's bounds in its parent's coordinate system (ie. with transformations applied).
6955
* Objects that have been cached will return the transformed bounds of the cache.
6956
*
6957
* Not all display objects can calculate their own bounds (ex. Shape). For these objects, you can use
6958
* {{#crossLink "DisplayObject/setBounds"}}{{/crossLink}} so that they are included when calculating Container
6959
* bounds.
6960
*
6961
* To reduce memory impact, the returned Rectangle instance may be reused internally; clone the instance or copy its
6962
* values if you need to retain it.
6963
*
6964
* Container instances calculate aggregate bounds for all children that return bounds via getBounds.
6965
* @method getTransformedBounds
6966
* @return {Rectangle} A Rectangle instance representing the bounds, or null if bounds are not available for this object.
6967
**/
6968
p.getTransformedBounds = function() {
6969
return this._getBounds();
6970
};
6971
6972
/**
6973
* Allows you to manually specify the bounds of an object that either cannot calculate their own bounds (ex. Shape &
6974
* Text) for future reference, or so the object can be included in Container bounds. Manually set bounds will always
6975
* override calculated bounds.
6976
*
6977
* The bounds should be specified in the object's local (untransformed) coordinates. For example, a Shape instance
6978
* with a 25px radius circle centered at 0,0 would have bounds of (-25, -25, 50, 50).
6979
* @method setBounds
6980
* @param {Number} x The x origin of the bounds. Pass null to remove the manual bounds.
6981
* @param {Number} y The y origin of the bounds.
6982
* @param {Number} width The width of the bounds.
6983
* @param {Number} height The height of the bounds.
6984
**/
6985
p.setBounds = function(x, y, width, height) {
6986
if (x == null) { this._bounds = x; }
6987
this._bounds = (this._bounds || new createjs.Rectangle()).setValues(x, y, width, height);
6988
};
6989
6990
/**
6991
* Returns a clone of this DisplayObject. Some properties that are specific to this instance's current context are
6992
* reverted to their defaults (for example .parent). Caches are not maintained across clones, and some elements
6993
* are copied by reference (masks, individual filter instances, hit area)
6994
* @method clone
6995
* @return {DisplayObject} A clone of the current DisplayObject instance.
6996
**/
6997
p.clone = function() {
6998
return this._cloneProps(new DisplayObject());
6999
};
7000
7001
/**
7002
* Returns a string representation of this object.
7003
* @method toString
7004
* @return {String} a string representation of the instance.
7005
**/
7006
p.toString = function() {
7007
return "[DisplayObject (name="+ this.name +")]";
7008
};
7009
7010
7011
// private methods:
7012
// separated so it can be used more easily in subclasses:
7013
/**
7014
* @method _cloneProps
7015
* @param {DisplayObject} o The DisplayObject instance which will have properties from the current DisplayObject
7016
* instance copied into.
7017
* @return {DisplayObject} o
7018
* @protected
7019
**/
7020
p._cloneProps = function(o) {
7021
o.alpha = this.alpha;
7022
o.mouseEnabled = this.mouseEnabled;
7023
o.tickEnabled = this.tickEnabled;
7024
o.name = this.name;
7025
o.regX = this.regX;
7026
o.regY = this.regY;
7027
o.rotation = this.rotation;
7028
o.scaleX = this.scaleX;
7029
o.scaleY = this.scaleY;
7030
o.shadow = this.shadow;
7031
o.skewX = this.skewX;
7032
o.skewY = this.skewY;
7033
o.visible = this.visible;
7034
o.x = this.x;
7035
o.y = this.y;
7036
o.compositeOperation = this.compositeOperation;
7037
o.snapToPixel = this.snapToPixel;
7038
o.filters = this.filters==null?null:this.filters.slice(0);
7039
o.mask = this.mask;
7040
o.hitArea = this.hitArea;
7041
o.cursor = this.cursor;
7042
o._bounds = this._bounds;
7043
return o;
7044
};
7045
7046
/**
7047
* @method _applyShadow
7048
* @protected
7049
* @param {CanvasRenderingContext2D} ctx
7050
* @param {Shadow} shadow
7051
**/
7052
p._applyShadow = function(ctx, shadow) {
7053
shadow = shadow || Shadow.identity;
7054
ctx.shadowColor = shadow.color;
7055
ctx.shadowOffsetX = shadow.offsetX;
7056
ctx.shadowOffsetY = shadow.offsetY;
7057
ctx.shadowBlur = shadow.blur;
7058
};
7059
7060
7061
/**
7062
* @method _tick
7063
* @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.
7064
* @protected
7065
**/
7066
p._tick = function(evtObj) {
7067
// because tick can be really performance sensitive, check for listeners before calling dispatchEvent.
7068
var ls = this._listeners;
7069
if (ls && ls["tick"]) {
7070
// reset & reuse the event object to avoid construction / GC costs:
7071
evtObj.target = null;
7072
evtObj.propagationStopped = evtObj.immediatePropagationStopped = false;
7073
this.dispatchEvent(evtObj);
7074
}
7075
};
7076
7077
/**
7078
* @method _testHit
7079
* @protected
7080
* @param {CanvasRenderingContext2D} ctx
7081
* @return {Boolean}
7082
**/
7083
p._testHit = function(ctx) {
7084
try {
7085
var hit = ctx.getImageData(0, 0, 1, 1).data[3] > 1;
7086
} catch (e) {
7087
if (!DisplayObject.suppressCrossDomainErrors) {
7088
throw "An error has occurred. This is most likely due to security restrictions on reading canvas pixel data with local or cross-domain images.";
7089
}
7090
}
7091
return hit;
7092
};
7093
7094
/**
7095
* @method _applyFilters
7096
* @protected
7097
**/
7098
p._applyFilters = function() {
7099
if (!this.filters || this.filters.length == 0 || !this.cacheCanvas) { return; }
7100
var l = this.filters.length;
7101
var ctx = this.cacheCanvas.getContext("2d");
7102
var w = this.cacheCanvas.width;
7103
var h = this.cacheCanvas.height;
7104
for (var i=0; i<l; i++) {
7105
this.filters[i].applyFilter(ctx, 0, 0, w, h);
7106
}
7107
};
7108
7109
/**
7110
* @method _getFilterBounds
7111
* @return {Rectangle}
7112
* @protected
7113
**/
7114
p._getFilterBounds = function(rect) {
7115
var l, filters = this.filters, bounds = this._rectangle.setValues(0,0,0,0);
7116
if (!filters || !(l=filters.length)) { return bounds; }
7117
7118
for (var i=0; i<l; i++) {
7119
var f = this.filters[i];
7120
f.getBounds&&f.getBounds(bounds);
7121
}
7122
return bounds;
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
7190
this.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 display 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
* @return {Number}
7261
* @deprecated
7262
**/
7263
p.getNumChildren = function() {
7264
return this.children.length;
7265
};
7266
7267
/**
7268
* Returns the number of children in the container.
7269
* @property numChildren
7270
* @type {Number}
7271
* @readonly
7272
**/
7273
try {
7274
Object.defineProperties(p, {
7275
numChildren: { get: p.getNumChildren }
7276
});
7277
} catch (e) {}
7278
7279
7280
// public methods:
7281
/**
7282
* Constructor alias for backwards compatibility. This method will be removed in future versions.
7283
* Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}.
7284
* @method initialize
7285
* @deprecated in favour of `createjs.promote()`
7286
**/
7287
p.initialize = Container; // TODO: deprecated.
7288
7289
/**
7290
* Returns true or false indicating whether the display object would be visible if drawn to a canvas.
7291
* This does not account for whether it would be visible within the boundaries of the stage.
7292
*
7293
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
7294
* @method isVisible
7295
* @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
7296
**/
7297
p.isVisible = function() {
7298
var hasContent = this.cacheCanvas || this.children.length;
7299
return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent);
7300
};
7301
7302
/**
7303
* Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
7304
* Returns true if the draw was handled (useful for overriding functionality).
7305
*
7306
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
7307
* @method draw
7308
* @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
7309
* @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache.
7310
* For example, used for drawing the cache (to prevent it from simply drawing an existing cache back
7311
* into itself).
7312
**/
7313
p.draw = function(ctx, ignoreCache) {
7314
if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; }
7315
7316
// this ensures we don't have issues with display list changes that occur during a draw:
7317
var list = this.children.slice();
7318
for (var i=0,l=list.length; i<l; i++) {
7319
var child = list[i];
7320
if (!child.isVisible()) { continue; }
7321
7322
// draw the child:
7323
ctx.save();
7324
child.updateContext(ctx);
7325
child.draw(ctx);
7326
ctx.restore();
7327
}
7328
return true;
7329
};
7330
7331
/**
7332
* Adds a child to the top of the display list.
7333
*
7334
* <h4>Example</h4>
7335
*
7336
* container.addChild(bitmapInstance);
7337
*
7338
* You can also add multiple children at once:
7339
*
7340
* container.addChild(bitmapInstance, shapeInstance, textInstance);
7341
*
7342
* @method addChild
7343
* @param {DisplayObject} child The display object to add.
7344
* @return {DisplayObject} The child that was added, or the last child if multiple children were added.
7345
**/
7346
p.addChild = function(child) {
7347
if (child == null) { return child; }
7348
var l = arguments.length;
7349
if (l > 1) {
7350
for (var i=0; i<l; i++) { this.addChild(arguments[i]); }
7351
return arguments[l-1];
7352
}
7353
if (child.parent) { child.parent.removeChild(child); }
7354
child.parent = this;
7355
this.children.push(child);
7356
child.dispatchEvent("added");
7357
return child;
7358
};
7359
7360
/**
7361
* Adds a child to the display list at the specified index, bumping children at equal or greater indexes up one, and
7362
* setting its parent to this Container.
7363
*
7364
* <h4>Example</h4>
7365
*
7366
* addChildAt(child1, index);
7367
*
7368
* You can also add multiple children, such as:
7369
*
7370
* addChildAt(child1, child2, ..., index);
7371
*
7372
* The index must be between 0 and numChildren. For example, to add myShape under otherShape in the display list,
7373
* you could use:
7374
*
7375
* container.addChildAt(myShape, container.getChildIndex(otherShape));
7376
*
7377
* This would also bump otherShape's index up by one. Fails silently if the index is out of range.
7378
*
7379
* @method addChildAt
7380
* @param {DisplayObject} child The display object to add.
7381
* @param {Number} index The index to add the child at.
7382
* @return {DisplayObject} Returns the last child that was added, or the last child if multiple children were added.
7383
**/
7384
p.addChildAt = function(child, index) {
7385
var l = arguments.length;
7386
var indx = arguments[l-1]; // can't use the same name as the index param or it replaces arguments[1]
7387
if (indx < 0 || indx > this.children.length) { return arguments[l-2]; }
7388
if (l > 2) {
7389
for (var i=0; i<l-1; i++) { this.addChildAt(arguments[i], indx+i); }
7390
return arguments[l-2];
7391
}
7392
if (child.parent) { child.parent.removeChild(child); }
7393
child.parent = this;
7394
this.children.splice(index, 0, child);
7395
child.dispatchEvent("added");
7396
return child;
7397
};
7398
7399
/**
7400
* Removes the specified child from the display list. Note that it is faster to use removeChildAt() if the index is
7401
* already known.
7402
*
7403
* <h4>Example</h4>
7404
*
7405
* container.removeChild(child);
7406
*
7407
* You can also remove multiple children:
7408
*
7409
* removeChild(child1, child2, ...);
7410
*
7411
* Returns true if the child (or children) was removed, or false if it was not in the display list.
7412
* @method removeChild
7413
* @param {DisplayObject} child The child to remove.
7414
* @return {Boolean} true if the child (or children) was removed, or false if it was not in the display list.
7415
**/
7416
p.removeChild = function(child) {
7417
var l = arguments.length;
7418
if (l > 1) {
7419
var good = true;
7420
for (var i=0; i<l; i++) { good = good && this.removeChild(arguments[i]); }
7421
return good;
7422
}
7423
return this.removeChildAt(createjs.indexOf(this.children, child));
7424
};
7425
7426
/**
7427
* Removes the child at the specified index from the display list, and sets its parent to null.
7428
*
7429
* <h4>Example</h4>
7430
*
7431
* container.removeChildAt(2);
7432
*
7433
* You can also remove multiple children:
7434
*
7435
* container.removeChild(2, 7, ...)
7436
*
7437
* Returns true if the child (or children) was removed, or false if any index was out of range.
7438
* @method removeChildAt
7439
* @param {Number} index The index of the child to remove.
7440
* @return {Boolean} true if the child (or children) was removed, or false if any index was out of range.
7441
**/
7442
p.removeChildAt = function(index) {
7443
var l = arguments.length;
7444
if (l > 1) {
7445
var a = [];
7446
for (var i=0; i<l; i++) { a[i] = arguments[i]; }
7447
a.sort(function(a, b) { return b-a; });
7448
var good = true;
7449
for (var i=0; i<l; i++) { good = good && this.removeChildAt(a[i]); }
7450
return good;
7451
}
7452
if (index < 0 || index > this.children.length-1) { return false; }
7453
var child = this.children[index];
7454
if (child) { child.parent = null; }
7455
this.children.splice(index, 1);
7456
child.dispatchEvent("removed");
7457
return true;
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
* @method _getObjectsUnderPoint
7740
* @param {Number} x
7741
* @param {Number} y
7742
* @param {Array} arr
7743
* @param {Boolean} mouse If true, it will respect mouse interaction properties like mouseEnabled, mouseChildren, and active listeners.
7744
* @param {Boolean} activeListener If true, there is an active mouse event listener on a parent object.
7745
* @param {Number} currentDepth Indicates the current depth of the search.
7746
* @return {DisplayObject}
7747
* @protected
7748
**/
7749
p._getObjectsUnderPoint = function(x, y, arr, mouse, activeListener, currentDepth) {
7750
currentDepth = currentDepth || 0;
7751
if (!currentDepth && !this._testMask(this, x, y)) { return null; }
7752
var mtx, ctx = createjs.DisplayObject._hitTestContext;
7753
activeListener = activeListener || (mouse&&this._hasMouseEventListener());
7754
7755
// draw children one at a time, and check if we get a hit:
7756
var children = this.children, l = children.length;
7757
for (var i=l-1; i>=0; i--) {
7758
var child = children[i];
7759
var hitArea = child.hitArea;
7760
if (!child.visible || (!hitArea && !child.isVisible()) || (mouse && !child.mouseEnabled)) { continue; }
7761
if (!hitArea && !this._testMask(child, x, y)) { continue; }
7762
7763
// if a child container has a hitArea then we only need to check its hitArea, so we can treat it as a normal DO:
7764
if (!hitArea && child instanceof Container) {
7765
var result = child._getObjectsUnderPoint(x, y, arr, mouse, activeListener, currentDepth+1);
7766
if (!arr && result) { return (mouse && !this.mouseChildren) ? this : result; }
7767
} else {
7768
if (mouse && !activeListener && !child._hasMouseEventListener()) { continue; }
7769
7770
// 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.
7771
var props = child.getConcatenatedDisplayProps(child._props);
7772
mtx = props.matrix;
7773
7774
if (hitArea) {
7775
mtx.appendMatrix(hitArea.getMatrix(hitArea._props.matrix));
7776
props.alpha = hitArea.alpha;
7777
}
7778
7779
ctx.globalAlpha = props.alpha;
7780
ctx.setTransform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx-x, mtx.ty-y);
7781
(hitArea||child).draw(ctx);
7782
if (!this._testHit(ctx)) { continue; }
7783
ctx.setTransform(1, 0, 0, 1, 0, 0);
7784
ctx.clearRect(0, 0, 2, 2);
7785
if (arr) { arr.push(child); }
7786
else { return (mouse && !this.mouseChildren) ? this : child; }
7787
}
7788
}
7789
return null;
7790
};
7791
7792
/**
7793
* @method _testMask
7794
* @param {DisplayObject} target
7795
* @param {Number} x
7796
* @param {Number} y
7797
* @return {Boolean} Indicates whether the x/y is within the masked region.
7798
* @protected
7799
**/
7800
p._testMask = function(target, x, y) {
7801
var mask = target.mask;
7802
if (!mask || !mask.graphics || mask.graphics.isEmpty()) { return true; }
7803
7804
var mtx = this._props.matrix, parent = target.parent;
7805
mtx = parent ? parent.getConcatenatedMatrix(mtx) : mtx.identity();
7806
mtx = mask.getMatrix(mask._props.matrix).prependMatrix(mtx);
7807
7808
var ctx = createjs.DisplayObject._hitTestContext;
7809
ctx.setTransform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx-x, mtx.ty-y);
7810
7811
// draw the mask as a solid fill:
7812
mask.graphics.drawAsPath(ctx);
7813
ctx.fillStyle = "#000";
7814
ctx.fill();
7815
7816
if (!this._testHit(ctx)) { return false; }
7817
ctx.setTransform(1, 0, 0, 1, 0, 0);
7818
ctx.clearRect(0, 0, 2, 2);
7819
7820
return true;
7821
};
7822
7823
/**
7824
* @method _getBounds
7825
* @param {Matrix2D} matrix
7826
* @param {Boolean} ignoreTransform If true, does not apply this object's transform.
7827
* @return {Rectangle}
7828
* @protected
7829
**/
7830
p._getBounds = function(matrix, ignoreTransform) {
7831
var bounds = this.DisplayObject_getBounds();
7832
if (bounds) { return this._transformBounds(bounds, matrix, ignoreTransform); }
7833
7834
var mtx = this._props.matrix;
7835
mtx = ignoreTransform ? mtx.identity() : this.getMatrix(mtx);
7836
if (matrix) { mtx.prependMatrix(matrix); }
7837
7838
var l = this.children.length, rect=null;
7839
for (var i=0; i<l; i++) {
7840
var child = this.children[i];
7841
if (!child.visible || !(bounds = child._getBounds(mtx))) { continue; }
7842
if (rect) { rect.extend(bounds.x, bounds.y, bounds.width, bounds.height); }
7843
else { rect = bounds.clone(); }
7844
}
7845
return rect;
7846
};
7847
7848
7849
createjs.Container = createjs.promote(Container, "DisplayObject");
7850
}());
7851
7852
//##############################################################################
7853
// Stage.js
7854
//##############################################################################
7855
7856
this.createjs = this.createjs||{};
7857
7858
(function() {
7859
"use strict";
7860
7861
7862
// constructor:
7863
/**
7864
* A stage is the root level {{#crossLink "Container"}}{{/crossLink}} for a display list. Each time its {{#crossLink "Stage/tick"}}{{/crossLink}}
7865
* method is called, it will render its display list to its target canvas.
7866
*
7867
* <h4>Example</h4>
7868
* This example creates a stage, adds a child to it, then uses {{#crossLink "Ticker"}}{{/crossLink}} to update the child
7869
* and redraw the stage using {{#crossLink "Stage/update"}}{{/crossLink}}.
7870
*
7871
* var stage = new createjs.Stage("canvasElementId");
7872
* var image = new createjs.Bitmap("imagePath.png");
7873
* stage.addChild(image);
7874
* createjs.Ticker.addEventListener("tick", handleTick);
7875
* function handleTick(event) {
7876
* image.x += 10;
7877
* stage.update();
7878
* }
7879
*
7880
* @class Stage
7881
* @extends Container
7882
* @constructor
7883
* @param {HTMLCanvasElement | String | Object} canvas A canvas object that the Stage will render to, or the string id
7884
* of a canvas object in the current document.
7885
**/
7886
function Stage(canvas) {
7887
this.Container_constructor();
7888
7889
7890
// public properties:
7891
/**
7892
* Indicates whether the stage should automatically clear the canvas before each render. You can set this to <code>false</code>
7893
* to manually control clearing (for generative art, or when pointing multiple stages at the same canvas for
7894
* example).
7895
*
7896
* <h4>Example</h4>
7897
*
7898
* var stage = new createjs.Stage("canvasId");
7899
* stage.autoClear = false;
7900
*
7901
* @property autoClear
7902
* @type Boolean
7903
* @default true
7904
**/
7905
this.autoClear = true;
7906
7907
/**
7908
* The canvas the stage will render to. Multiple stages can share a single canvas, but you must disable autoClear for all but the
7909
* first stage that will be ticked (or they will clear each other's render).
7910
*
7911
* When changing the canvas property you must disable the events on the old canvas, and enable events on the
7912
* new canvas or mouse events will not work as expected. For example:
7913
*
7914
* myStage.enableDOMEvents(false);
7915
* myStage.canvas = anotherCanvas;
7916
* myStage.enableDOMEvents(true);
7917
*
7918
* @property canvas
7919
* @type HTMLCanvasElement | Object
7920
**/
7921
this.canvas = (typeof canvas == "string") ? document.getElementById(canvas) : canvas;
7922
7923
/**
7924
* The current mouse X position on the canvas. If the mouse leaves the canvas, this will indicate the most recent
7925
* position over the canvas, and mouseInBounds will be set to false.
7926
* @property mouseX
7927
* @type Number
7928
* @readonly
7929
**/
7930
this.mouseX = 0;
7931
7932
/**
7933
* The current mouse Y position on the canvas. If the mouse leaves the canvas, this will indicate the most recent
7934
* position over the canvas, and mouseInBounds will be set to false.
7935
* @property mouseY
7936
* @type Number
7937
* @readonly
7938
**/
7939
this.mouseY = 0;
7940
7941
/**
7942
* Specifies the area of the stage to affect when calling update. This can be use to selectively
7943
* re-draw specific regions of the canvas. If null, the whole canvas area is drawn.
7944
* @property drawRect
7945
* @type {Rectangle}
7946
*/
7947
this.drawRect = null;
7948
7949
/**
7950
* Indicates whether display objects should be rendered on whole pixels. You can set the
7951
* {{#crossLink "DisplayObject/snapToPixel"}}{{/crossLink}} property of
7952
* display objects to false to enable/disable this behaviour on a per instance basis.
7953
* @property snapToPixelEnabled
7954
* @type Boolean
7955
* @default false
7956
**/
7957
this.snapToPixelEnabled = false;
7958
7959
/**
7960
* Indicates whether the mouse is currently within the bounds of the canvas.
7961
* @property mouseInBounds
7962
* @type Boolean
7963
* @default false
7964
**/
7965
this.mouseInBounds = false;
7966
7967
/**
7968
* If true, tick callbacks will be called on all display objects on the stage prior to rendering to the canvas.
7969
* @property tickOnUpdate
7970
* @type Boolean
7971
* @default true
7972
**/
7973
this.tickOnUpdate = true;
7974
7975
/**
7976
* If true, mouse move events will continue to be called when the mouse leaves the target canvas. See
7977
* {{#crossLink "Stage/mouseInBounds:property"}}{{/crossLink}}, and {{#crossLink "MouseEvent"}}{{/crossLink}}
7978
* x/y/rawX/rawY.
7979
* @property mouseMoveOutside
7980
* @type Boolean
7981
* @default false
7982
**/
7983
this.mouseMoveOutside = false;
7984
7985
7986
/**
7987
* Prevents selection of other elements in the html page if the user clicks and drags, or double clicks on the canvas.
7988
* This works by calling `preventDefault()` on any mousedown events (or touch equivalent) originating on the canvas.
7989
* @property preventSelection
7990
* @type Boolean
7991
* @default true
7992
**/
7993
this.preventSelection = true;
7994
7995
/**
7996
* The hitArea property is not supported for Stage.
7997
* @property hitArea
7998
* @type {DisplayObject}
7999
* @default null
8000
*/
8001
8002
8003
// private properties:
8004
/**
8005
* Holds objects with data for each active pointer id. Each object has the following properties:
8006
* x, y, event, target, overTarget, overX, overY, inBounds, posEvtObj (native event that last updated position)
8007
* @property _pointerData
8008
* @type {Object}
8009
* @private
8010
*/
8011
this._pointerData = {};
8012
8013
/**
8014
* Number of active pointers.
8015
* @property _pointerCount
8016
* @type {Object}
8017
* @private
8018
*/
8019
this._pointerCount = 0;
8020
8021
/**
8022
* The ID of the primary pointer.
8023
* @property _primaryPointerID
8024
* @type {Object}
8025
* @private
8026
*/
8027
this._primaryPointerID = null;
8028
8029
/**
8030
* @property _mouseOverIntervalID
8031
* @protected
8032
* @type Number
8033
**/
8034
this._mouseOverIntervalID = null;
8035
8036
/**
8037
* @property _nextStage
8038
* @protected
8039
* @type Stage
8040
**/
8041
this._nextStage = null;
8042
8043
/**
8044
* @property _prevStage
8045
* @protected
8046
* @type Stage
8047
**/
8048
this._prevStage = null;
8049
8050
8051
// initialize:
8052
this.enableDOMEvents(true);
8053
}
8054
var p = createjs.extend(Stage, createjs.Container);
8055
8056
/**
8057
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
8058
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
8059
* for details.
8060
*
8061
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
8062
*
8063
* @method initialize
8064
* @protected
8065
* @deprecated
8066
*/
8067
// p.initialize = function() {}; // searchable for devs wondering where it is.
8068
8069
8070
// events:
8071
/**
8072
* Dispatched when the user moves the mouse over the canvas.
8073
* See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
8074
* @event stagemousemove
8075
* @since 0.6.0
8076
*/
8077
8078
/**
8079
* Dispatched when the user presses their left mouse button on the canvas. See the {{#crossLink "MouseEvent"}}{{/crossLink}}
8080
* class for a listing of event properties.
8081
* @event stagemousedown
8082
* @since 0.6.0
8083
*/
8084
8085
/**
8086
* 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).
8087
* You can use {{#crossLink "Stage/mouseInBounds:property"}}{{/crossLink}} to check whether the mouse is currently within the stage bounds.
8088
* See the {{#crossLink "MouseEvent"}}{{/crossLink}} class for a listing of event properties.
8089
* @event stagemouseup
8090
* @since 0.6.0
8091
*/
8092
8093
/**
8094
* Dispatched when the mouse moves from within the canvas area (mouseInBounds == true) to outside it (mouseInBounds == false).
8095
* This is currently only dispatched for mouse input (not touch). See the {{#crossLink "MouseEvent"}}{{/crossLink}}
8096
* class for a listing of event properties.
8097
* @event mouseleave
8098
* @since 0.7.0
8099
*/
8100
8101
/**
8102
* Dispatched when the mouse moves into the canvas area (mouseInBounds == false) from outside it (mouseInBounds == true).
8103
* This is currently only dispatched for mouse input (not touch). See the {{#crossLink "MouseEvent"}}{{/crossLink}}
8104
* class for a listing of event properties.
8105
* @event mouseenter
8106
* @since 0.7.0
8107
*/
8108
8109
/**
8110
* Dispatched each update immediately before the tick event is propagated through the display list.
8111
* You can call preventDefault on the event object to cancel propagating the tick event.
8112
* @event tickstart
8113
* @since 0.7.0
8114
*/
8115
8116
/**
8117
* Dispatched each update immediately after the tick event is propagated through the display list. Does not fire if
8118
* tickOnUpdate is false. Precedes the "drawstart" event.
8119
* @event tickend
8120
* @since 0.7.0
8121
*/
8122
8123
/**
8124
* Dispatched each update immediately before the canvas is cleared and the display list is drawn to it.
8125
* You can call preventDefault on the event object to cancel the draw.
8126
* @event drawstart
8127
* @since 0.7.0
8128
*/
8129
8130
/**
8131
* Dispatched each update immediately after the display list is drawn to the canvas and the canvas context is restored.
8132
* @event drawend
8133
* @since 0.7.0
8134
*/
8135
8136
8137
// getter / setters:
8138
/**
8139
* Specifies a target stage that will have mouse / touch interactions relayed to it after this stage handles them.
8140
* This can be useful in cases where you have multiple layered canvases and want user interactions
8141
* events to pass through. For example, this would relay mouse events from topStage to bottomStage:
8142
*
8143
* topStage.nextStage = bottomStage;
8144
*
8145
* To disable relaying, set nextStage to null.
8146
*
8147
* MouseOver, MouseOut, RollOver, and RollOut interactions are also passed through using the mouse over settings
8148
* of the top-most stage, but are only processed if the target stage has mouse over interactions enabled.
8149
* Considerations when using roll over in relay targets:<OL>
8150
* <LI> The top-most (first) stage must have mouse over interactions enabled (via enableMouseOver)</LI>
8151
* <LI> All stages that wish to participate in mouse over interaction must enable them via enableMouseOver</LI>
8152
* <LI> All relay targets will share the frequency value of the top-most stage</LI>
8153
* </OL>
8154
* To illustrate, in this example the targetStage would process mouse over interactions at 10hz (despite passing
8155
* 30 as it's desired frequency):
8156
* topStage.nextStage = targetStage;
8157
* topStage.enableMouseOver(10);
8158
* targetStage.enableMouseOver(30);
8159
*
8160
* If the target stage's canvas is completely covered by this stage's canvas, you may also want to disable its
8161
* DOM events using:
8162
*
8163
* targetStage.enableDOMEvents(false);
8164
*
8165
* @property nextStage
8166
* @type {Stage}
8167
**/
8168
p._get_nextStage = function() {
8169
return this._nextStage;
8170
};
8171
p._set_nextStage = function(value) {
8172
if (this._nextStage) { this._nextStage._prevStage = null; }
8173
if (value) { value._prevStage = this; }
8174
this._nextStage = value;
8175
};
8176
8177
try {
8178
Object.defineProperties(p, {
8179
nextStage: { get: p._get_nextStage, set: p._set_nextStage }
8180
});
8181
} catch (e) {} // TODO: use Log
8182
8183
8184
// public methods:
8185
/**
8186
* Each time the update method is called, the stage will call {{#crossLink "Stage/tick"}}{{/crossLink}}
8187
* unless {{#crossLink "Stage/tickOnUpdate:property"}}{{/crossLink}} is set to false,
8188
* and then render the display list to the canvas.
8189
*
8190
* @method update
8191
* @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.
8192
**/
8193
p.update = function(props) {
8194
if (!this.canvas) { return; }
8195
if (this.tickOnUpdate) { this.tick(props); }
8196
if (this.dispatchEvent("drawstart", false, true) === false) { return; }
8197
createjs.DisplayObject._snapToPixelEnabled = this.snapToPixelEnabled;
8198
var r = this.drawRect, ctx = this.canvas.getContext("2d");
8199
ctx.setTransform(1, 0, 0, 1, 0, 0);
8200
if (this.autoClear) {
8201
if (r) { ctx.clearRect(r.x, r.y, r.width, r.height); }
8202
else { ctx.clearRect(0, 0, this.canvas.width+1, this.canvas.height+1); }
8203
}
8204
ctx.save();
8205
if (this.drawRect) {
8206
ctx.beginPath();
8207
ctx.rect(r.x, r.y, r.width, r.height);
8208
ctx.clip();
8209
}
8210
this.updateContext(ctx);
8211
this.draw(ctx, false);
8212
ctx.restore();
8213
this.dispatchEvent("drawend");
8214
};
8215
8216
/**
8217
* Propagates a tick event through the display list. This is automatically called by {{#crossLink "Stage/update"}}{{/crossLink}}
8218
* unless {{#crossLink "Stage/tickOnUpdate:property"}}{{/crossLink}} is set to false.
8219
*
8220
* If a props object is passed to `tick()`, then all of its properties will be copied to the event object that is
8221
* propagated to listeners.
8222
*
8223
* Some time-based features in EaselJS (for example {{#crossLink "Sprite/framerate"}}{{/crossLink}} require that
8224
* a {{#crossLink "Ticker/tick:event"}}{{/crossLink}} event object (or equivalent object with a delta property) be
8225
* passed as the `props` parameter to `tick()`. For example:
8226
*
8227
* Ticker.on("tick", handleTick);
8228
* function handleTick(evtObj) {
8229
* // clone the event object from Ticker, and add some custom data to it:
8230
* var evt = evtObj.clone().set({greeting:"hello", name:"world"});
8231
*
8232
* // pass it to stage.update():
8233
* myStage.update(evt); // subsequently calls tick() with the same param
8234
* }
8235
*
8236
* // ...
8237
* myDisplayObject.on("tick", handleDisplayObjectTick);
8238
* function handleDisplayObjectTick(evt) {
8239
* console.log(evt.delta); // the delta property from the Ticker tick event object
8240
* console.log(evt.greeting, evt.name); // custom data: "hello world"
8241
* }
8242
*
8243
* @method tick
8244
* @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.
8245
**/
8246
p.tick = function(props) {
8247
if (!this.tickEnabled || this.dispatchEvent("tickstart", false, true) === false) { return; }
8248
var evtObj = new createjs.Event("tick");
8249
if (props) {
8250
for (var n in props) {
8251
if (props.hasOwnProperty(n)) { evtObj[n] = props[n]; }
8252
}
8253
}
8254
this._tick(evtObj);
8255
this.dispatchEvent("tickend");
8256
};
8257
8258
/**
8259
* Default event handler that calls the Stage {{#crossLink "Stage/update"}}{{/crossLink}} method when a {{#crossLink "DisplayObject/tick:event"}}{{/crossLink}}
8260
* event is received. This allows you to register a Stage instance as a event listener on {{#crossLink "Ticker"}}{{/crossLink}}
8261
* directly, using:
8262
*
8263
* Ticker.addEventListener("tick", myStage");
8264
*
8265
* Note that if you subscribe to ticks using this pattern, then the tick event object will be passed through to
8266
* display object tick handlers, instead of <code>delta</code> and <code>paused</code> parameters.
8267
* @property handleEvent
8268
* @type Function
8269
**/
8270
p.handleEvent = function(evt) {
8271
if (evt.type == "tick") { this.update(evt); }
8272
};
8273
8274
/**
8275
* Clears the target canvas. Useful if {{#crossLink "Stage/autoClear:property"}}{{/crossLink}} is set to `false`.
8276
* @method clear
8277
**/
8278
p.clear = function() {
8279
if (!this.canvas) { return; }
8280
var ctx = this.canvas.getContext("2d");
8281
ctx.setTransform(1, 0, 0, 1, 0, 0);
8282
ctx.clearRect(0, 0, this.canvas.width+1, this.canvas.height+1);
8283
};
8284
8285
/**
8286
* Returns a data url that contains a Base64-encoded image of the contents of the stage. The returned data url can
8287
* be specified as the src value of an image element.
8288
* @method toDataURL
8289
* @param {String} [backgroundColor] The background color to be used for the generated image. Any valid CSS color
8290
* value is allowed. The default value is a transparent background.
8291
* @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
8292
* is passed in, or if the browser does not support the specified MIME type, the default value will be used.
8293
* @return {String} a Base64 encoded image.
8294
**/
8295
p.toDataURL = function(backgroundColor, mimeType) {
8296
var data, ctx = this.canvas.getContext('2d'), w = this.canvas.width, h = this.canvas.height;
8297
8298
if (backgroundColor) {
8299
data = ctx.getImageData(0, 0, w, h);
8300
var compositeOperation = ctx.globalCompositeOperation;
8301
ctx.globalCompositeOperation = "destination-over";
8302
8303
ctx.fillStyle = backgroundColor;
8304
ctx.fillRect(0, 0, w, h);
8305
}
8306
8307
var dataURL = this.canvas.toDataURL(mimeType||"image/png");
8308
8309
if(backgroundColor) {
8310
ctx.putImageData(data, 0, 0);
8311
ctx.globalCompositeOperation = compositeOperation;
8312
}
8313
8314
return dataURL;
8315
};
8316
8317
/**
8318
* Enables or disables (by passing a frequency of 0) mouse over ({{#crossLink "DisplayObject/mouseover:event"}}{{/crossLink}}
8319
* and {{#crossLink "DisplayObject/mouseout:event"}}{{/crossLink}}) and roll over events ({{#crossLink "DisplayObject/rollover:event"}}{{/crossLink}}
8320
* and {{#crossLink "DisplayObject/rollout:event"}}{{/crossLink}}) for this stage's display list. These events can
8321
* be expensive to generate, so they are disabled by default. The frequency of the events can be controlled
8322
* independently of mouse move events via the optional `frequency` parameter.
8323
*
8324
* <h4>Example</h4>
8325
*
8326
* var stage = new createjs.Stage("canvasId");
8327
* stage.enableMouseOver(10); // 10 updates per second
8328
*
8329
* @method enableMouseOver
8330
* @param {Number} [frequency=20] Optional param specifying the maximum number of times per second to broadcast
8331
* mouse over/out events. Set to 0 to disable mouse over events completely. Maximum is 50. A lower frequency is less
8332
* responsive, but uses less CPU.
8333
**/
8334
p.enableMouseOver = function(frequency) {
8335
if (this._mouseOverIntervalID) {
8336
clearInterval(this._mouseOverIntervalID);
8337
this._mouseOverIntervalID = null;
8338
if (frequency == 0) {
8339
this._testMouseOver(true);
8340
}
8341
}
8342
if (frequency == null) { frequency = 20; }
8343
else if (frequency <= 0) { return; }
8344
var o = this;
8345
this._mouseOverIntervalID = setInterval(function(){ o._testMouseOver(); }, 1000/Math.min(50,frequency));
8346
};
8347
8348
/**
8349
* Enables or disables the event listeners that stage adds to DOM elements (window, document and canvas). It is good
8350
* practice to disable events when disposing of a Stage instance, otherwise the stage will continue to receive
8351
* events from the page.
8352
*
8353
* When changing the canvas property you must disable the events on the old canvas, and enable events on the
8354
* new canvas or mouse events will not work as expected. For example:
8355
*
8356
* myStage.enableDOMEvents(false);
8357
* myStage.canvas = anotherCanvas;
8358
* myStage.enableDOMEvents(true);
8359
*
8360
* @method enableDOMEvents
8361
* @param {Boolean} [enable=true] Indicates whether to enable or disable the events. Default is true.
8362
**/
8363
p.enableDOMEvents = function(enable) {
8364
if (enable == null) { enable = true; }
8365
var n, o, ls = this._eventListeners;
8366
if (!enable && ls) {
8367
for (n in ls) {
8368
o = ls[n];
8369
o.t.removeEventListener(n, o.f, false);
8370
}
8371
this._eventListeners = null;
8372
} else if (enable && !ls && this.canvas) {
8373
var t = window.addEventListener ? window : document;
8374
var _this = this;
8375
ls = this._eventListeners = {};
8376
ls["mouseup"] = {t:t, f:function(e) { _this._handleMouseUp(e)} };
8377
ls["mousemove"] = {t:t, f:function(e) { _this._handleMouseMove(e)} };
8378
ls["dblclick"] = {t:this.canvas, f:function(e) { _this._handleDoubleClick(e)} };
8379
ls["mousedown"] = {t:this.canvas, f:function(e) { _this._handleMouseDown(e)} };
8380
8381
for (n in ls) {
8382
o = ls[n];
8383
o.t.addEventListener(n, o.f, false);
8384
}
8385
}
8386
};
8387
8388
/**
8389
* Stage instances cannot be cloned.
8390
* @method clone
8391
**/
8392
p.clone = function() {
8393
throw("Stage cannot be cloned.");
8394
};
8395
8396
/**
8397
* Returns a string representation of this object.
8398
* @method toString
8399
* @return {String} a string representation of the instance.
8400
**/
8401
p.toString = function() {
8402
return "[Stage (name="+ this.name +")]";
8403
};
8404
8405
8406
// private methods:
8407
/**
8408
* @method _getElementRect
8409
* @protected
8410
* @param {HTMLElement} e
8411
**/
8412
p._getElementRect = function(e) {
8413
var bounds;
8414
try { bounds = e.getBoundingClientRect(); } // this can fail on disconnected DOM elements in IE9
8415
catch (err) { bounds = {top: e.offsetTop, left: e.offsetLeft, width:e.offsetWidth, height:e.offsetHeight}; }
8416
8417
var offX = (window.pageXOffset || document.scrollLeft || 0) - (document.clientLeft || document.body.clientLeft || 0);
8418
var offY = (window.pageYOffset || document.scrollTop || 0) - (document.clientTop || document.body.clientTop || 0);
8419
8420
var styles = window.getComputedStyle ? getComputedStyle(e,null) : e.currentStyle; // IE <9 compatibility.
8421
var padL = parseInt(styles.paddingLeft)+parseInt(styles.borderLeftWidth);
8422
var padT = parseInt(styles.paddingTop)+parseInt(styles.borderTopWidth);
8423
var padR = parseInt(styles.paddingRight)+parseInt(styles.borderRightWidth);
8424
var padB = parseInt(styles.paddingBottom)+parseInt(styles.borderBottomWidth);
8425
8426
// note: in some browsers bounds properties are read only.
8427
return {
8428
left: bounds.left+offX+padL,
8429
right: bounds.right+offX-padR,
8430
top: bounds.top+offY+padT,
8431
bottom: bounds.bottom+offY-padB
8432
}
8433
};
8434
8435
/**
8436
* @method _getPointerData
8437
* @protected
8438
* @param {Number} id
8439
**/
8440
p._getPointerData = function(id) {
8441
var data = this._pointerData[id];
8442
if (!data) { data = this._pointerData[id] = {x:0,y:0}; }
8443
return data;
8444
};
8445
8446
/**
8447
* @method _handleMouseMove
8448
* @protected
8449
* @param {MouseEvent} e
8450
**/
8451
p._handleMouseMove = function(e) {
8452
if(!e){ e = window.event; }
8453
this._handlePointerMove(-1, e, e.pageX, e.pageY);
8454
};
8455
8456
/**
8457
* @method _handlePointerMove
8458
* @protected
8459
* @param {Number} id
8460
* @param {Event} e
8461
* @param {Number} pageX
8462
* @param {Number} pageY
8463
* @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage.
8464
**/
8465
p._handlePointerMove = function(id, e, pageX, pageY, owner) {
8466
if (this._prevStage && owner === undefined) { return; } // redundant listener.
8467
if (!this.canvas) { return; }
8468
var nextStage=this._nextStage, o=this._getPointerData(id);
8469
8470
var inBounds = o.inBounds;
8471
this._updatePointerPosition(id, e, pageX, pageY);
8472
if (inBounds || o.inBounds || this.mouseMoveOutside) {
8473
if (id === -1 && o.inBounds == !inBounds) {
8474
this._dispatchMouseEvent(this, (inBounds ? "mouseleave" : "mouseenter"), false, id, o, e);
8475
}
8476
8477
this._dispatchMouseEvent(this, "stagemousemove", false, id, o, e);
8478
this._dispatchMouseEvent(o.target, "pressmove", true, id, o, e);
8479
}
8480
8481
nextStage&&nextStage._handlePointerMove(id, e, pageX, pageY, null);
8482
};
8483
8484
/**
8485
* @method _updatePointerPosition
8486
* @protected
8487
* @param {Number} id
8488
* @param {Event} e
8489
* @param {Number} pageX
8490
* @param {Number} pageY
8491
**/
8492
p._updatePointerPosition = function(id, e, pageX, pageY) {
8493
var rect = this._getElementRect(this.canvas);
8494
pageX -= rect.left;
8495
pageY -= rect.top;
8496
8497
var w = this.canvas.width;
8498
var h = this.canvas.height;
8499
pageX /= (rect.right-rect.left)/w;
8500
pageY /= (rect.bottom-rect.top)/h;
8501
var o = this._getPointerData(id);
8502
if (o.inBounds = (pageX >= 0 && pageY >= 0 && pageX <= w-1 && pageY <= h-1)) {
8503
o.x = pageX;
8504
o.y = pageY;
8505
} else if (this.mouseMoveOutside) {
8506
o.x = pageX < 0 ? 0 : (pageX > w-1 ? w-1 : pageX);
8507
o.y = pageY < 0 ? 0 : (pageY > h-1 ? h-1 : pageY);
8508
}
8509
8510
o.posEvtObj = e;
8511
o.rawX = pageX;
8512
o.rawY = pageY;
8513
8514
if (id === this._primaryPointerID || id === -1) {
8515
this.mouseX = o.x;
8516
this.mouseY = o.y;
8517
this.mouseInBounds = o.inBounds;
8518
}
8519
};
8520
8521
/**
8522
* @method _handleMouseUp
8523
* @protected
8524
* @param {MouseEvent} e
8525
**/
8526
p._handleMouseUp = function(e) {
8527
this._handlePointerUp(-1, e, false);
8528
};
8529
8530
/**
8531
* @method _handlePointerUp
8532
* @protected
8533
* @param {Number} id
8534
* @param {Event} e
8535
* @param {Boolean} clear
8536
* @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage.
8537
**/
8538
p._handlePointerUp = function(id, e, clear, owner) {
8539
var nextStage = this._nextStage, o = this._getPointerData(id);
8540
if (this._prevStage && owner === undefined) { return; } // redundant listener.
8541
8542
var target=null, oTarget = o.target;
8543
if (!owner && (oTarget || nextStage)) { target = this._getObjectsUnderPoint(o.x, o.y, null, true); }
8544
8545
if (o.down) { this._dispatchMouseEvent(this, "stagemouseup", false, id, o, e, target); o.down = false; }
8546
8547
if (target == oTarget) { this._dispatchMouseEvent(oTarget, "click", true, id, o, e); }
8548
this._dispatchMouseEvent(oTarget, "pressup", true, id, o, e);
8549
8550
if (clear) {
8551
if (id==this._primaryPointerID) { this._primaryPointerID = null; }
8552
delete(this._pointerData[id]);
8553
} else { o.target = null; }
8554
8555
nextStage&&nextStage._handlePointerUp(id, e, clear, owner || target && this);
8556
};
8557
8558
/**
8559
* @method _handleMouseDown
8560
* @protected
8561
* @param {MouseEvent} e
8562
**/
8563
p._handleMouseDown = function(e) {
8564
this._handlePointerDown(-1, e, e.pageX, e.pageY);
8565
};
8566
8567
/**
8568
* @method _handlePointerDown
8569
* @protected
8570
* @param {Number} id
8571
* @param {Event} e
8572
* @param {Number} pageX
8573
* @param {Number} pageY
8574
* @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage.
8575
**/
8576
p._handlePointerDown = function(id, e, pageX, pageY, owner) {
8577
if (this.preventSelection) { e.preventDefault(); }
8578
if (this._primaryPointerID == null || id === -1) { this._primaryPointerID = id; } // mouse always takes over.
8579
8580
if (pageY != null) { this._updatePointerPosition(id, e, pageX, pageY); }
8581
var target = null, nextStage = this._nextStage, o = this._getPointerData(id);
8582
if (!owner) { target = o.target = this._getObjectsUnderPoint(o.x, o.y, null, true); }
8583
8584
if (o.inBounds) { this._dispatchMouseEvent(this, "stagemousedown", false, id, o, e, target); o.down = true; }
8585
this._dispatchMouseEvent(target, "mousedown", true, id, o, e);
8586
8587
nextStage&&nextStage._handlePointerDown(id, e, pageX, pageY, owner || target && this);
8588
};
8589
8590
/**
8591
* @method _testMouseOver
8592
* @param {Boolean} clear If true, clears the mouseover / rollover (ie. no target)
8593
* @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage.
8594
* @param {Stage} eventTarget The stage that the cursor is actively over.
8595
* @protected
8596
**/
8597
p._testMouseOver = function(clear, owner, eventTarget) {
8598
if (this._prevStage && owner === undefined) { return; } // redundant listener.
8599
8600
var nextStage = this._nextStage;
8601
if (!this._mouseOverIntervalID) {
8602
// not enabled for mouseover, but should still relay the event.
8603
nextStage&&nextStage._testMouseOver(clear, owner, eventTarget);
8604
return;
8605
}
8606
var o = this._getPointerData(-1);
8607
// only update if the mouse position has changed. This provides a lot of optimization, but has some trade-offs.
8608
if (!o || (!clear && this.mouseX == this._mouseOverX && this.mouseY == this._mouseOverY && this.mouseInBounds)) { return; }
8609
8610
var e = o.posEvtObj;
8611
var isEventTarget = eventTarget || e&&(e.target == this.canvas);
8612
var target=null, common = -1, cursor="", t, i, l;
8613
8614
if (!owner && (clear || this.mouseInBounds && isEventTarget)) {
8615
target = this._getObjectsUnderPoint(this.mouseX, this.mouseY, null, true);
8616
this._mouseOverX = this.mouseX;
8617
this._mouseOverY = this.mouseY;
8618
}
8619
8620
var oldList = this._mouseOverTarget||[];
8621
var oldTarget = oldList[oldList.length-1];
8622
var list = this._mouseOverTarget = [];
8623
8624
// generate ancestor list and check for cursor:
8625
t = target;
8626
while (t) {
8627
list.unshift(t);
8628
if (!cursor) { cursor = t.cursor; }
8629
t = t.parent;
8630
}
8631
this.canvas.style.cursor = cursor;
8632
if (!owner && eventTarget) { eventTarget.canvas.style.cursor = cursor; }
8633
8634
// find common ancestor:
8635
for (i=0,l=list.length; i<l; i++) {
8636
if (list[i] != oldList[i]) { break; }
8637
common = i;
8638
}
8639
8640
if (oldTarget != target) {
8641
this._dispatchMouseEvent(oldTarget, "mouseout", true, -1, o, e, target);
8642
}
8643
8644
for (i=oldList.length-1; i>common; i--) {
8645
this._dispatchMouseEvent(oldList[i], "rollout", false, -1, o, e, target);
8646
}
8647
8648
for (i=list.length-1; i>common; i--) {
8649
this._dispatchMouseEvent(list[i], "rollover", false, -1, o, e, oldTarget);
8650
}
8651
8652
if (oldTarget != target) {
8653
this._dispatchMouseEvent(target, "mouseover", true, -1, o, e, oldTarget);
8654
}
8655
8656
nextStage&&nextStage._testMouseOver(clear, owner || target && this, eventTarget || isEventTarget && this);
8657
};
8658
8659
/**
8660
* @method _handleDoubleClick
8661
* @protected
8662
* @param {MouseEvent} e
8663
* @param {Stage} owner Indicates that the event has already been captured & handled by the indicated stage.
8664
**/
8665
p._handleDoubleClick = function(e, owner) {
8666
var target=null, nextStage=this._nextStage, o=this._getPointerData(-1);
8667
if (!owner) {
8668
target = this._getObjectsUnderPoint(o.x, o.y, null, true);
8669
this._dispatchMouseEvent(target, "dblclick", true, -1, o, e);
8670
}
8671
nextStage&&nextStage._handleDoubleClick(e, owner || target && this);
8672
};
8673
8674
/**
8675
* @method _dispatchMouseEvent
8676
* @protected
8677
* @param {DisplayObject} target
8678
* @param {String} type
8679
* @param {Boolean} bubbles
8680
* @param {Number} pointerId
8681
* @param {Object} o
8682
* @param {MouseEvent} [nativeEvent]
8683
* @param {DisplayObject} [relatedTarget]
8684
**/
8685
p._dispatchMouseEvent = function(target, type, bubbles, pointerId, o, nativeEvent, relatedTarget) {
8686
// TODO: might be worth either reusing MouseEvent instances, or adding a willTrigger method to avoid GC.
8687
if (!target || (!bubbles && !target.hasEventListener(type))) { return; }
8688
/*
8689
// TODO: account for stage transformations?
8690
this._mtx = this.getConcatenatedMatrix(this._mtx).invert();
8691
var pt = this._mtx.transformPoint(o.x, o.y);
8692
var evt = new createjs.MouseEvent(type, bubbles, false, pt.x, pt.y, nativeEvent, pointerId, pointerId==this._primaryPointerID || pointerId==-1, o.rawX, o.rawY);
8693
*/
8694
var evt = new createjs.MouseEvent(type, bubbles, false, o.x, o.y, nativeEvent, pointerId, pointerId === this._primaryPointerID || pointerId === -1, o.rawX, o.rawY, relatedTarget);
8695
target.dispatchEvent(evt);
8696
};
8697
8698
8699
createjs.Stage = createjs.promote(Stage, "Container");
8700
}());
8701
8702
//##############################################################################
8703
// Bitmap.js
8704
//##############################################################################
8705
8706
this.createjs = this.createjs||{};
8707
8708
(function() {
8709
8710
/**
8711
* A Bitmap represents an Image, Canvas, or Video in the display list. A Bitmap can be instantiated using an existing
8712
* HTML element, or a string.
8713
*
8714
* <h4>Example</h4>
8715
*
8716
* var bitmap = new createjs.Bitmap("imagePath.jpg");
8717
*
8718
* <strong>Notes:</strong>
8719
* <ol>
8720
* <li>When a string path or image tag that is not yet loaded is used, the stage may need to be redrawn before it
8721
* will be displayed.</li>
8722
* <li>Bitmaps with an SVG source currently will not respect an alpha value other than 0 or 1. To get around this,
8723
* the Bitmap can be cached.</li>
8724
* <li>Bitmaps with an SVG source will taint the canvas with cross-origin data, which prevents interactivity. This
8725
* happens in all browsers except recent Firefox builds.</li>
8726
* <li>Images loaded cross-origin will throw cross-origin security errors when interacted with using a mouse, using
8727
* methods such as `getObjectUnderPoint`, or using filters, or caching. You can get around this by setting
8728
* `crossOrigin` flags on your images before passing them to EaselJS, eg: `img.crossOrigin="Anonymous";`</li>
8729
* </ol>
8730
*
8731
* @class Bitmap
8732
* @extends DisplayObject
8733
* @constructor
8734
* @param {HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | String} imageOrUri The source object or URI to an image to
8735
* display. This can be either an Image, Canvas, or Video object, or a string URI to an image file to load and use.
8736
* If it is a URI, a new Image object will be constructed and assigned to the .image property.
8737
**/
8738
function Bitmap(imageOrUri) {
8739
this.DisplayObject_constructor();
8740
8741
8742
// public properties:
8743
/**
8744
* The image to render. This can be an Image, a Canvas, or a Video. Not all browsers (especially
8745
* mobile browsers) support drawing video to a canvas.
8746
* @property image
8747
* @type HTMLImageElement | HTMLCanvasElement | HTMLVideoElement
8748
**/
8749
if (typeof imageOrUri == "string") {
8750
this.image = document.createElement("img");
8751
this.image.src = imageOrUri;
8752
} else {
8753
this.image = imageOrUri;
8754
}
8755
8756
/**
8757
* Specifies an area of the source image to draw. If omitted, the whole image will be drawn.
8758
* Note that video sources must have a width / height set to work correctly with `sourceRect`.
8759
* @property sourceRect
8760
* @type Rectangle
8761
* @default null
8762
*/
8763
this.sourceRect = null;
8764
}
8765
var p = createjs.extend(Bitmap, createjs.DisplayObject);
8766
8767
8768
// public methods:
8769
/**
8770
* Constructor alias for backwards compatibility. This method will be removed in future versions.
8771
* Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}.
8772
* @method initialize
8773
* @deprecated in favour of `createjs.promote()`
8774
**/
8775
p.initialize = Bitmap; // TODO: deprecated.
8776
8777
/**
8778
* Returns true or false indicating whether the display object would be visible if drawn to a canvas.
8779
* This does not account for whether it would be visible within the boundaries of the stage.
8780
*
8781
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
8782
* @method isVisible
8783
* @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
8784
**/
8785
p.isVisible = function() {
8786
var image = this.image;
8787
var hasContent = this.cacheCanvas || (image && (image.naturalWidth || image.getContext || image.readyState >= 2));
8788
return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent);
8789
};
8790
8791
/**
8792
* Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
8793
* Returns true if the draw was handled (useful for overriding functionality).
8794
*
8795
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
8796
* @method draw
8797
* @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
8798
* @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache.
8799
* For example, used for drawing the cache (to prevent it from simply drawing an existing cache back
8800
* into itself).
8801
* @return {Boolean}
8802
**/
8803
p.draw = function(ctx, ignoreCache) {
8804
if (this.DisplayObject_draw(ctx, ignoreCache) || !this.image) { return true; }
8805
var img = this.image, rect = this.sourceRect;
8806
if (rect) {
8807
// some browsers choke on out of bound values, so we'll fix them:
8808
var x1 = rect.x, y1 = rect.y, x2 = x1 + rect.width, y2 = y1 + rect.height, x = 0, y = 0, w = img.width, h = img.height;
8809
if (x1 < 0) { x -= x1; x1 = 0; }
8810
if (x2 > w) { x2 = w; }
8811
if (y1 < 0) { y -= y1; y1 = 0; }
8812
if (y2 > h) { y2 = h; }
8813
ctx.drawImage(img, x1, y1, x2-x1, y2-y1, x, y, x2-x1, y2-y1);
8814
} else {
8815
ctx.drawImage(img, 0, 0);
8816
}
8817
return true;
8818
};
8819
8820
//Note, the doc sections below document using the specified APIs (from DisplayObject) from
8821
//Bitmap. This is why they have no method implementations.
8822
8823
/**
8824
* Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances.
8825
* You should <b>not</b> cache Bitmap instances as it can degrade performance.
8826
*
8827
* <strong>However: If you want to use a filter on a Bitmap, you <em>MUST</em> cache it, or it will not work.</strong>
8828
* To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}}
8829
* method.
8830
* @method cache
8831
**/
8832
8833
/**
8834
* Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances.
8835
* You should <b>not</b> cache Bitmap instances as it can degrade performance.
8836
*
8837
* <strong>However: If you want to use a filter on a Bitmap, you <em>MUST</em> cache it, or it will not work.</strong>
8838
* To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}}
8839
* method.
8840
* @method updateCache
8841
**/
8842
8843
/**
8844
* Because the content of a Bitmap is already in a simple format, cache is unnecessary for Bitmap instances.
8845
* You should <b>not</b> cache Bitmap instances as it can degrade performance.
8846
*
8847
* <strong>However: If you want to use a filter on a Bitmap, you <em>MUST</em> cache it, or it will not work.</strong>
8848
* To see the API for caching, please visit the DisplayObject {{#crossLink "DisplayObject/cache"}}{{/crossLink}}
8849
* method.
8850
* @method uncache
8851
**/
8852
8853
/**
8854
* Docced in superclass.
8855
*/
8856
p.getBounds = function() {
8857
var rect = this.DisplayObject_getBounds();
8858
if (rect) { return rect; }
8859
var image = this.image, o = this.sourceRect || image;
8860
var hasContent = (image && (image.naturalWidth || image.getContext || image.readyState >= 2));
8861
return hasContent ? this._rectangle.setValues(0, 0, o.width, o.height) : null;
8862
};
8863
8864
/**
8865
* Returns a clone of the Bitmap instance.
8866
* @method clone
8867
* @return {Bitmap} a clone of the Bitmap instance.
8868
**/
8869
p.clone = function() {
8870
var o = new Bitmap(this.image);
8871
if (this.sourceRect) { o.sourceRect = this.sourceRect.clone(); }
8872
this._cloneProps(o);
8873
return o;
8874
};
8875
8876
/**
8877
* Returns a string representation of this object.
8878
* @method toString
8879
* @return {String} a string representation of the instance.
8880
**/
8881
p.toString = function() {
8882
return "[Bitmap (name="+ this.name +")]";
8883
};
8884
8885
8886
createjs.Bitmap = createjs.promote(Bitmap, "DisplayObject");
8887
}());
8888
8889
//##############################################################################
8890
// Sprite.js
8891
//##############################################################################
8892
8893
this.createjs = this.createjs||{};
8894
8895
(function() {
8896
"use strict";
8897
8898
8899
// constructor:
8900
/**
8901
* Displays a frame or sequence of frames (ie. an animation) from a SpriteSheet instance. A sprite sheet is a series of
8902
* images (usually animation frames) combined into a single image. For example, an animation consisting of 8 100x100
8903
* images could be combined into a 400x200 sprite sheet (4 frames across by 2 high). You can display individual frames,
8904
* play frames as an animation, and even sequence animations together.
8905
*
8906
* See the {{#crossLink "SpriteSheet"}}{{/crossLink}} class for more information on setting up frames and animations.
8907
*
8908
* <h4>Example</h4>
8909
*
8910
* var instance = new createjs.Sprite(spriteSheet);
8911
* instance.gotoAndStop("frameName");
8912
*
8913
* Until {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} or {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}} is called,
8914
* only the first defined frame defined in the sprite sheet will be displayed.
8915
*
8916
* @class Sprite
8917
* @extends DisplayObject
8918
* @constructor
8919
* @param {SpriteSheet} spriteSheet The SpriteSheet instance to play back. This includes the source image(s), frame
8920
* dimensions, and frame data. See {{#crossLink "SpriteSheet"}}{{/crossLink}} for more information.
8921
* @param {String|Number} [frameOrAnimation] The frame number or animation to play initially.
8922
**/
8923
function Sprite(spriteSheet, frameOrAnimation) {
8924
this.DisplayObject_constructor();
8925
8926
8927
// public properties:
8928
/**
8929
* The frame index that will be drawn when draw is called. Note that with some {{#crossLink "SpriteSheet"}}{{/crossLink}}
8930
* definitions, this will advance non-sequentially. This will always be an integer value.
8931
* @property currentFrame
8932
* @type {Number}
8933
* @default 0
8934
* @readonly
8935
**/
8936
this.currentFrame = 0;
8937
8938
/**
8939
* Returns the name of the currently playing animation.
8940
* @property currentAnimation
8941
* @type {String}
8942
* @final
8943
* @readonly
8944
**/
8945
this.currentAnimation = null;
8946
8947
/**
8948
* Prevents the animation from advancing each tick automatically. For example, you could create a sprite
8949
* sheet of icons, set paused to true, and display the appropriate icon by setting <code>currentFrame</code>.
8950
* @property paused
8951
* @type {Boolean}
8952
* @default false
8953
**/
8954
this.paused = true;
8955
8956
/**
8957
* The SpriteSheet instance to play back. This includes the source image, frame dimensions, and frame
8958
* data. See {{#crossLink "SpriteSheet"}}{{/crossLink}} for more information.
8959
* @property spriteSheet
8960
* @type {SpriteSheet}
8961
* @readonly
8962
**/
8963
this.spriteSheet = spriteSheet;
8964
8965
/**
8966
* Specifies the current frame index within the currently playing animation. When playing normally, this will increase
8967
* from 0 to n-1, where n is the number of frames in the current animation.
8968
*
8969
* This could be a non-integer value if
8970
* using time-based playback (see {{#crossLink "Sprite/framerate"}}{{/crossLink}}, or if the animation's speed is
8971
* not an integer.
8972
* @property currentAnimationFrame
8973
* @type {Number}
8974
* @default 0
8975
**/
8976
this.currentAnimationFrame = 0;
8977
8978
/**
8979
* By default Sprite instances advance one frame per tick. Specifying a framerate for the Sprite (or its related
8980
* SpriteSheet) will cause it to advance based on elapsed time between ticks as appropriate to maintain the target
8981
* framerate.
8982
*
8983
* For example, if a Sprite with a framerate of 10 is placed on a Stage being updated at 40fps, then the Sprite will
8984
* advance roughly one frame every 4 ticks. This will not be exact, because the time between each tick will
8985
* vary slightly between frames.
8986
*
8987
* This feature is dependent on the tick event object (or an object with an appropriate "delta" property) being
8988
* passed into {{#crossLink "Stage/update"}}{{/crossLink}}.
8989
* @property framerate
8990
* @type {Number}
8991
* @default 0
8992
**/
8993
this.framerate = 0;
8994
8995
8996
// private properties:
8997
/**
8998
* Current animation object.
8999
* @property _animation
9000
* @protected
9001
* @type {Object}
9002
* @default null
9003
**/
9004
this._animation = null;
9005
9006
/**
9007
* Current frame index.
9008
* @property _currentFrame
9009
* @protected
9010
* @type {Number}
9011
* @default null
9012
**/
9013
this._currentFrame = null;
9014
9015
/**
9016
* Skips the next auto advance. Used by gotoAndPlay to avoid immediately jumping to the next frame
9017
* @property _skipAdvance
9018
* @protected
9019
* @type {Boolean}
9020
* @default false
9021
**/
9022
this._skipAdvance = false;
9023
9024
9025
if (frameOrAnimation != null) { this.gotoAndPlay(frameOrAnimation); }
9026
}
9027
var p = createjs.extend(Sprite, createjs.DisplayObject);
9028
9029
/**
9030
* Constructor alias for backwards compatibility. This method will be removed in future versions.
9031
* Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}.
9032
* @method initialize
9033
* @deprecated in favour of `createjs.promote()`
9034
**/
9035
p.initialize = Sprite; // TODO: Deprecated. This is for backwards support of FlashCC spritesheet export.
9036
9037
9038
// events:
9039
/**
9040
* Dispatched when an animation reaches its ends.
9041
* @event animationend
9042
* @param {Object} target The object that dispatched the event.
9043
* @param {String} type The event type.
9044
* @param {String} name The name of the animation that just ended.
9045
* @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.
9046
* @since 0.6.0
9047
*/
9048
9049
/**
9050
* Dispatched any time the current frame changes. For example, this could be due to automatic advancement on a tick,
9051
* or calling gotoAndPlay() or gotoAndStop().
9052
* @event change
9053
* @param {Object} target The object that dispatched the event.
9054
* @param {String} type The event type.
9055
*/
9056
9057
9058
// public methods:
9059
/**
9060
* Returns true or false indicating whether the display object would be visible if drawn to a canvas.
9061
* This does not account for whether it would be visible within the boundaries of the stage.
9062
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
9063
* @method isVisible
9064
* @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
9065
**/
9066
p.isVisible = function() {
9067
var hasContent = this.cacheCanvas || this.spriteSheet.complete;
9068
return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent);
9069
};
9070
9071
/**
9072
* Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
9073
* Returns true if the draw was handled (useful for overriding functionality).
9074
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
9075
* @method draw
9076
* @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
9077
* @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache.
9078
* For example, used for drawing the cache (to prevent it from simply drawing an existing cache back
9079
* into itself).
9080
**/
9081
p.draw = function(ctx, ignoreCache) {
9082
if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; }
9083
this._normalizeFrame();
9084
var o = this.spriteSheet.getFrame(this._currentFrame|0);
9085
if (!o) { return false; }
9086
var rect = o.rect;
9087
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); }
9088
return true;
9089
};
9090
9091
//Note, the doc sections below document using the specified APIs (from DisplayObject) from
9092
//Bitmap. This is why they have no method implementations.
9093
9094
/**
9095
* Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances.
9096
* You should not cache Sprite instances as it can degrade performance.
9097
* @method cache
9098
**/
9099
9100
/**
9101
* Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances.
9102
* You should not cache Sprite instances as it can degrade performance.
9103
* @method updateCache
9104
**/
9105
9106
/**
9107
* Because the content of a Sprite is already in a raster format, cache is unnecessary for Sprite instances.
9108
* You should not cache Sprite instances as it can degrade performance.
9109
* @method uncache
9110
**/
9111
9112
/**
9113
* Play (unpause) the current animation. The Sprite will be paused if either {{#crossLink "Sprite/stop"}}{{/crossLink}}
9114
* or {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} is called. Single frame animations will remain
9115
* unchanged.
9116
* @method play
9117
**/
9118
p.play = function() {
9119
this.paused = false;
9120
};
9121
9122
/**
9123
* Stop playing a running animation. The Sprite will be playing if {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}}
9124
* is called. Note that calling {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}} or {{#crossLink "Sprite/play"}}{{/crossLink}}
9125
* will resume playback.
9126
* @method stop
9127
**/
9128
p.stop = function() {
9129
this.paused = true;
9130
};
9131
9132
/**
9133
* Sets paused to false and plays the specified animation name, named frame, or frame number.
9134
* @method gotoAndPlay
9135
* @param {String|Number} frameOrAnimation The frame number or animation name that the playhead should move to
9136
* and begin playing.
9137
**/
9138
p.gotoAndPlay = function(frameOrAnimation) {
9139
this.paused = false;
9140
this._skipAdvance = true;
9141
this._goto(frameOrAnimation);
9142
};
9143
9144
/**
9145
* Sets paused to true and seeks to the specified animation name, named frame, or frame number.
9146
* @method gotoAndStop
9147
* @param {String|Number} frameOrAnimation The frame number or animation name that the playhead should move to
9148
* and stop.
9149
**/
9150
p.gotoAndStop = function(frameOrAnimation) {
9151
this.paused = true;
9152
this._goto(frameOrAnimation);
9153
};
9154
9155
/**
9156
* Advances the playhead. This occurs automatically each tick by default.
9157
* @param [time] {Number} The amount of time in ms to advance by. Only applicable if framerate is set on the Sprite
9158
* or its SpriteSheet.
9159
* @method advance
9160
*/
9161
p.advance = function(time) {
9162
var fps = this.framerate || this.spriteSheet.framerate;
9163
var t = (fps && time != null) ? time/(1000/fps) : 1;
9164
this._normalizeFrame(t);
9165
};
9166
9167
/**
9168
* Returns a {{#crossLink "Rectangle"}}{{/crossLink}} instance defining the bounds of the current frame relative to
9169
* the origin. For example, a 90 x 70 frame with <code>regX=50</code> and <code>regY=40</code> would return a
9170
* rectangle with [x=-50, y=-40, width=90, height=70]. This ignores transformations on the display object.
9171
*
9172
* Also see the SpriteSheet {{#crossLink "SpriteSheet/getFrameBounds"}}{{/crossLink}} method.
9173
* @method getBounds
9174
* @return {Rectangle} A Rectangle instance. Returns null if the frame does not exist, or the image is not fully
9175
* loaded.
9176
**/
9177
p.getBounds = function() {
9178
// TODO: should this normalizeFrame?
9179
return this.DisplayObject_getBounds() || this.spriteSheet.getFrameBounds(this.currentFrame, this._rectangle);
9180
};
9181
9182
/**
9183
* Returns a clone of the Sprite instance. Note that the same SpriteSheet is shared between cloned
9184
* instances.
9185
* @method clone
9186
* @return {Sprite} a clone of the Sprite instance.
9187
**/
9188
p.clone = function() {
9189
return this._cloneProps(new Sprite(this.spriteSheet));
9190
};
9191
9192
/**
9193
* Returns a string representation of this object.
9194
* @method toString
9195
* @return {String} a string representation of the instance.
9196
**/
9197
p.toString = function() {
9198
return "[Sprite (name="+ this.name +")]";
9199
};
9200
9201
// private methods:
9202
/**
9203
* @method _cloneProps
9204
* @param {Sprite} o
9205
* @return {Sprite} o
9206
* @protected
9207
**/
9208
p._cloneProps = function(o) {
9209
this.DisplayObject__cloneProps(o);
9210
o.currentFrame = this.currentFrame;
9211
o.currentAnimation = this.currentAnimation;
9212
o.paused = this.paused;
9213
o.currentAnimationFrame = this.currentAnimationFrame;
9214
o.framerate = this.framerate;
9215
9216
o._animation = this._animation;
9217
o._currentFrame = this._currentFrame;
9218
o._skipAdvance = this._skipAdvance;
9219
return o;
9220
};
9221
9222
/**
9223
* Advances the <code>currentFrame</code> if paused is not true. This is called automatically when the {{#crossLink "Stage"}}{{/crossLink}}
9224
* ticks.
9225
* @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.
9226
* @protected
9227
* @method _tick
9228
**/
9229
p._tick = function(evtObj) {
9230
if (!this.paused) {
9231
if (!this._skipAdvance) { this.advance(evtObj&&evtObj.delta); }
9232
this._skipAdvance = false;
9233
}
9234
this.DisplayObject__tick(evtObj);
9235
};
9236
9237
9238
/**
9239
* Normalizes the current frame, advancing animations and dispatching callbacks as appropriate.
9240
* @protected
9241
* @method _normalizeFrame
9242
**/
9243
p._normalizeFrame = function(frameDelta) {
9244
frameDelta = frameDelta || 0;
9245
var animation = this._animation;
9246
var paused = this.paused;
9247
var frame = this._currentFrame;
9248
var l;
9249
9250
if (animation) {
9251
var speed = animation.speed || 1;
9252
var animFrame = this.currentAnimationFrame;
9253
l = animation.frames.length;
9254
if (animFrame + frameDelta * speed >= l) {
9255
var next = animation.next;
9256
if (this._dispatchAnimationEnd(animation, frame, paused, next, l - 1)) {
9257
// something changed in the event stack, so we shouldn't make any more changes here.
9258
return;
9259
} else if (next) {
9260
// sequence. Automatically calls _normalizeFrame again with the remaining frames.
9261
return this._goto(next, frameDelta - (l - animFrame) / speed);
9262
} else {
9263
// end.
9264
this.paused = true;
9265
animFrame = animation.frames.length - 1;
9266
}
9267
} else {
9268
animFrame += frameDelta * speed;
9269
}
9270
this.currentAnimationFrame = animFrame;
9271
this._currentFrame = animation.frames[animFrame | 0]
9272
} else {
9273
frame = (this._currentFrame += frameDelta);
9274
l = this.spriteSheet.getNumFrames();
9275
if (frame >= l && l > 0) {
9276
if (!this._dispatchAnimationEnd(animation, frame, paused, l - 1)) {
9277
// looped.
9278
if ((this._currentFrame -= l) >= l) { return this._normalizeFrame(); }
9279
}
9280
}
9281
}
9282
frame = this._currentFrame | 0;
9283
if (this.currentFrame != frame) {
9284
this.currentFrame = frame;
9285
this.dispatchEvent("change");
9286
}
9287
};
9288
9289
/**
9290
* Dispatches the "animationend" event. Returns true if a handler changed the animation (ex. calling {{#crossLink "Sprite/stop"}}{{/crossLink}},
9291
* {{#crossLink "Sprite/gotoAndPlay"}}{{/crossLink}}, etc.)
9292
* @property _dispatchAnimationEnd
9293
* @private
9294
* @type {Function}
9295
**/
9296
p._dispatchAnimationEnd = function(animation, frame, paused, next, end) {
9297
var name = animation ? animation.name : null;
9298
if (this.hasEventListener("animationend")) {
9299
var evt = new createjs.Event("animationend");
9300
evt.name = name;
9301
evt.next = next;
9302
this.dispatchEvent(evt);
9303
}
9304
// did the animation get changed in the event stack?:
9305
var changed = (this._animation != animation || this._currentFrame != frame);
9306
// if the animation hasn't changed, but the sprite was paused, then we want to stick to the last frame:
9307
if (!changed && !paused && this.paused) { this.currentAnimationFrame = end; changed = true; }
9308
return changed;
9309
};
9310
9311
/**
9312
* Moves the playhead to the specified frame number or animation.
9313
* @method _goto
9314
* @param {String|Number} frameOrAnimation The frame number or animation that the playhead should move to.
9315
* @param {Boolean} [frame] The frame of the animation to go to. Defaults to 0.
9316
* @protected
9317
**/
9318
p._goto = function(frameOrAnimation, frame) {
9319
this.currentAnimationFrame = 0;
9320
if (isNaN(frameOrAnimation)) {
9321
var data = this.spriteSheet.getAnimation(frameOrAnimation);
9322
if (data) {
9323
this._animation = data;
9324
this.currentAnimation = frameOrAnimation;
9325
this._normalizeFrame(frame);
9326
}
9327
} else {
9328
this.currentAnimation = this._animation = null;
9329
this._currentFrame = frameOrAnimation;
9330
this._normalizeFrame();
9331
}
9332
};
9333
9334
9335
createjs.Sprite = createjs.promote(Sprite, "DisplayObject");
9336
}());
9337
9338
//##############################################################################
9339
// Shape.js
9340
//##############################################################################
9341
9342
this.createjs = this.createjs||{};
9343
9344
(function() {
9345
"use strict";
9346
9347
9348
// constructor:
9349
/**
9350
* A Shape allows you to display vector art in the display list. It composites a {{#crossLink "Graphics"}}{{/crossLink}}
9351
* instance which exposes all of the vector drawing methods. The Graphics instance can be shared between multiple Shape
9352
* instances to display the same vector graphics with different positions or transforms.
9353
*
9354
* If the vector art will not
9355
* change between draws, you may want to use the {{#crossLink "DisplayObject/cache"}}{{/crossLink}} method to reduce the
9356
* rendering cost.
9357
*
9358
* <h4>Example</h4>
9359
*
9360
* var graphics = new createjs.Graphics().beginFill("#ff0000").drawRect(0, 0, 100, 100);
9361
* var shape = new createjs.Shape(graphics);
9362
*
9363
* //Alternatively use can also use the graphics property of the Shape class to renderer the same as above.
9364
* var shape = new createjs.Shape();
9365
* shape.graphics.beginFill("#ff0000").drawRect(0, 0, 100, 100);
9366
*
9367
* @class Shape
9368
* @extends DisplayObject
9369
* @constructor
9370
* @param {Graphics} graphics Optional. The graphics instance to display. If null, a new Graphics instance will be created.
9371
**/
9372
function Shape(graphics) {
9373
this.DisplayObject_constructor();
9374
9375
9376
// public properties:
9377
/**
9378
* The graphics instance to display.
9379
* @property graphics
9380
* @type Graphics
9381
**/
9382
this.graphics = graphics ? graphics : new createjs.Graphics();
9383
}
9384
var p = createjs.extend(Shape, createjs.DisplayObject);
9385
9386
// TODO: deprecated
9387
// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
9388
9389
9390
// public methods:
9391
/**
9392
* Returns true or false indicating whether the Shape would be visible if drawn to a canvas.
9393
* This does not account for whether it would be visible within the boundaries of the stage.
9394
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
9395
* @method isVisible
9396
* @return {Boolean} Boolean indicating whether the Shape would be visible if drawn to a canvas
9397
**/
9398
p.isVisible = function() {
9399
var hasContent = this.cacheCanvas || (this.graphics && !this.graphics.isEmpty());
9400
return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent);
9401
};
9402
9403
/**
9404
* Draws the Shape into the specified context ignoring its visible, alpha, shadow, and transform. Returns true if
9405
* the draw was handled (useful for overriding functionality).
9406
*
9407
* <i>NOTE: This method is mainly for internal use, though it may be useful for advanced uses.</i>
9408
* @method draw
9409
* @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
9410
* @param {Boolean} [ignoreCache=false] Indicates whether the draw operation should ignore any current cache. For example,
9411
* used for drawing the cache (to prevent it from simply drawing an existing cache back into itself).
9412
* @return {Boolean}
9413
**/
9414
p.draw = function(ctx, ignoreCache) {
9415
if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; }
9416
this.graphics.draw(ctx, this);
9417
return true;
9418
};
9419
9420
/**
9421
* Returns a clone of this Shape. Some properties that are specific to this instance's current context are reverted to
9422
* their defaults (for example .parent).
9423
* @method clone
9424
* @param {Boolean} recursive If true, this Shape's {{#crossLink "Graphics"}}{{/crossLink}} instance will also be
9425
* cloned. If false, the Graphics instance will be shared with the new Shape.
9426
**/
9427
p.clone = function(recursive) {
9428
var g = (recursive && this.graphics) ? this.graphics.clone() : this.graphics;
9429
return this._cloneProps(new Shape(g));
9430
};
9431
9432
/**
9433
* Returns a string representation of this object.
9434
* @method toString
9435
* @return {String} a string representation of the instance.
9436
**/
9437
p.toString = function() {
9438
return "[Shape (name="+ this.name +")]";
9439
};
9440
9441
9442
createjs.Shape = createjs.promote(Shape, "DisplayObject");
9443
}());
9444
9445
//##############################################################################
9446
// Text.js
9447
//##############################################################################
9448
9449
this.createjs = this.createjs||{};
9450
9451
(function() {
9452
"use strict";
9453
9454
9455
// constructor:
9456
/**
9457
* Display one or more lines of dynamic text (not user editable) in the display list. Line wrapping support (using the
9458
* lineWidth) is very basic, wrapping on spaces and tabs only. Note that as an alternative to Text, you can position HTML
9459
* text above or below the canvas relative to items in the display list using the {{#crossLink "DisplayObject/localToGlobal"}}{{/crossLink}}
9460
* method, or using {{#crossLink "DOMElement"}}{{/crossLink}}.
9461
*
9462
* <b>Please note that Text does not support HTML text, and can only display one font style at a time.</b> To use
9463
* multiple font styles, you will need to create multiple text instances, and position them manually.
9464
*
9465
* <h4>Example</h4>
9466
*
9467
* var text = new createjs.Text("Hello World", "20px Arial", "#ff7700");
9468
* text.x = 100;
9469
* text.textBaseline = "alphabetic";
9470
*
9471
* CreateJS Text supports web fonts (the same rules as Canvas). The font must be loaded and supported by the browser
9472
* before it can be displayed.
9473
*
9474
* <strong>Note:</strong> Text can be expensive to generate, so cache instances where possible. Be aware that not all
9475
* browsers will render Text exactly the same.
9476
* @class Text
9477
* @extends DisplayObject
9478
* @constructor
9479
* @param {String} [text] The text to display.
9480
* @param {String} [font] The font style to use. Any valid value for the CSS font attribute is acceptable (ex. "bold
9481
* 36px Arial").
9482
* @param {String} [color] The color to draw the text in. Any valid value for the CSS color attribute is acceptable (ex.
9483
* "#F00", "red", or "#FF0000").
9484
**/
9485
function Text(text, font, color) {
9486
this.DisplayObject_constructor();
9487
9488
9489
// public properties:
9490
/**
9491
* The text to display.
9492
* @property text
9493
* @type String
9494
**/
9495
this.text = text;
9496
9497
/**
9498
* The font style to use. Any valid value for the CSS font attribute is acceptable (ex. "bold 36px Arial").
9499
* @property font
9500
* @type String
9501
**/
9502
this.font = font;
9503
9504
/**
9505
* The color to draw the text in. Any valid value for the CSS color attribute is acceptable (ex. "#F00"). Default is "#000".
9506
* It will also accept valid canvas fillStyle values.
9507
* @property color
9508
* @type String
9509
**/
9510
this.color = color;
9511
9512
/**
9513
* The horizontal text alignment. Any of "start", "end", "left", "right", and "center". For detailed
9514
* information view the
9515
* <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles">
9516
* whatwg spec</a>. Default is "left".
9517
* @property textAlign
9518
* @type String
9519
**/
9520
this.textAlign = "left";
9521
9522
/**
9523
* The vertical alignment point on the font. Any of "top", "hanging", "middle", "alphabetic", "ideographic", or
9524
* "bottom". For detailed information view the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles">
9525
* whatwg spec</a>. Default is "top".
9526
* @property textBaseline
9527
* @type String
9528
*/
9529
this.textBaseline = "top";
9530
9531
/**
9532
* The maximum width to draw the text. If maxWidth is specified (not null), the text will be condensed or
9533
* shrunk to make it fit in this width. For detailed information view the
9534
* <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles">
9535
* whatwg spec</a>.
9536
* @property maxWidth
9537
* @type Number
9538
*/
9539
this.maxWidth = null;
9540
9541
/**
9542
* If greater than 0, the text will be drawn as a stroke (outline) of the specified width.
9543
* @property outline
9544
* @type Number
9545
**/
9546
this.outline = 0;
9547
9548
/**
9549
* Indicates the line height (vertical distance between baselines) for multi-line text. If null or 0,
9550
* the value of getMeasuredLineHeight is used.
9551
* @property lineHeight
9552
* @type Number
9553
**/
9554
this.lineHeight = 0;
9555
9556
/**
9557
* Indicates the maximum width for a line of text before it is wrapped to multiple lines. If null,
9558
* the text will not be wrapped.
9559
* @property lineWidth
9560
* @type Number
9561
**/
9562
this.lineWidth = null;
9563
}
9564
var p = createjs.extend(Text, createjs.DisplayObject);
9565
9566
// TODO: deprecated
9567
// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
9568
9569
9570
// static properties:
9571
/**
9572
* @property _workingContext
9573
* @type CanvasRenderingContext2D
9574
* @private
9575
**/
9576
var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"));
9577
if (canvas.getContext) { Text._workingContext = canvas.getContext("2d"); canvas.width = canvas.height = 1; }
9578
9579
9580
// constants:
9581
/**
9582
* Lookup table for the ratio to offset bounds x calculations based on the textAlign property.
9583
* @property H_OFFSETS
9584
* @type Object
9585
* @protected
9586
* @static
9587
**/
9588
Text.H_OFFSETS = {start: 0, left: 0, center: -0.5, end: -1, right: -1};
9589
9590
/**
9591
* Lookup table for the ratio to offset bounds y calculations based on the textBaseline property.
9592
* @property H_OFFSETS
9593
* @type Object
9594
* @protected
9595
* @static
9596
**/
9597
Text.V_OFFSETS = {top: 0, hanging: -0.01, middle: -0.4, alphabetic: -0.8, ideographic: -0.85, bottom: -1};
9598
9599
9600
// public methods:
9601
/**
9602
* Returns true or false indicating whether the display object would be visible if drawn to a canvas.
9603
* This does not account for whether it would be visible within the boundaries of the stage.
9604
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
9605
* @method isVisible
9606
* @return {Boolean} Whether the display object would be visible if drawn to a canvas
9607
**/
9608
p.isVisible = function() {
9609
var hasContent = this.cacheCanvas || (this.text != null && this.text !== "");
9610
return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0 && hasContent);
9611
};
9612
9613
/**
9614
* Draws the Text into the specified context ignoring its visible, alpha, shadow, and transform.
9615
* Returns true if the draw was handled (useful for overriding functionality).
9616
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
9617
* @method draw
9618
* @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
9619
* @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache.
9620
* For example, used for drawing the cache (to prevent it from simply drawing an existing cache back
9621
* into itself).
9622
**/
9623
p.draw = function(ctx, ignoreCache) {
9624
if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; }
9625
9626
var col = this.color || "#000";
9627
if (this.outline) { ctx.strokeStyle = col; ctx.lineWidth = this.outline*1; }
9628
else { ctx.fillStyle = col; }
9629
9630
this._drawText(this._prepContext(ctx));
9631
return true;
9632
};
9633
9634
/**
9635
* Returns the measured, untransformed width of the text without wrapping. Use getBounds for a more robust value.
9636
* @method getMeasuredWidth
9637
* @return {Number} The measured, untransformed width of the text.
9638
**/
9639
p.getMeasuredWidth = function() {
9640
return this._getMeasuredWidth(this.text);
9641
};
9642
9643
/**
9644
* Returns an approximate line height of the text, ignoring the lineHeight property. This is based on the measured
9645
* width of a "M" character multiplied by 1.2, which provides an approximate line height for most fonts.
9646
* @method getMeasuredLineHeight
9647
* @return {Number} an approximate line height of the text, ignoring the lineHeight property. This is
9648
* based on the measured width of a "M" character multiplied by 1.2, which approximates em for most fonts.
9649
**/
9650
p.getMeasuredLineHeight = function() {
9651
return this._getMeasuredWidth("M")*1.2;
9652
};
9653
9654
/**
9655
* Returns the approximate height of multi-line text by multiplying the number of lines against either the
9656
* <code>lineHeight</code> (if specified) or {{#crossLink "Text/getMeasuredLineHeight"}}{{/crossLink}}. Note that
9657
* this operation requires the text flowing logic to run, which has an associated CPU cost.
9658
* @method getMeasuredHeight
9659
* @return {Number} The approximate height of the untransformed multi-line text.
9660
**/
9661
p.getMeasuredHeight = function() {
9662
return this._drawText(null,{}).height;
9663
};
9664
9665
/**
9666
* Docced in superclass.
9667
*/
9668
p.getBounds = function() {
9669
var rect = this.DisplayObject_getBounds();
9670
if (rect) { return rect; }
9671
if (this.text == null || this.text === "") { return null; }
9672
var o = this._drawText(null, {});
9673
var w = (this.maxWidth && this.maxWidth < o.width) ? this.maxWidth : o.width;
9674
var x = w * Text.H_OFFSETS[this.textAlign||"left"];
9675
var lineHeight = this.lineHeight||this.getMeasuredLineHeight();
9676
var y = lineHeight * Text.V_OFFSETS[this.textBaseline||"top"];
9677
return this._rectangle.setValues(x, y, w, o.height);
9678
};
9679
9680
/**
9681
* Returns an object with width, height, and lines properties. The width and height are the visual width and height
9682
* of the drawn text. The lines property contains an array of strings, one for
9683
* each line of text that will be drawn, accounting for line breaks and wrapping. These strings have trailing
9684
* whitespace removed.
9685
* @method getMetrics
9686
* @return {Object} An object with width, height, and lines properties.
9687
**/
9688
p.getMetrics = function() {
9689
var o = {lines:[]};
9690
o.lineHeight = this.lineHeight || this.getMeasuredLineHeight();
9691
o.vOffset = o.lineHeight * Text.V_OFFSETS[this.textBaseline||"top"];
9692
return this._drawText(null, o, o.lines);
9693
};
9694
9695
/**
9696
* Returns a clone of the Text instance.
9697
* @method clone
9698
* @return {Text} a clone of the Text instance.
9699
**/
9700
p.clone = function() {
9701
return this._cloneProps(new Text(this.text, this.font, this.color));
9702
};
9703
9704
/**
9705
* Returns a string representation of this object.
9706
* @method toString
9707
* @return {String} a string representation of the instance.
9708
**/
9709
p.toString = function() {
9710
return "[Text (text="+ (this.text.length > 20 ? this.text.substr(0, 17)+"..." : this.text) +")]";
9711
};
9712
9713
9714
// private methods:
9715
/**
9716
* @method _cloneProps
9717
* @param {Text} o
9718
* @protected
9719
* @return {Text} o
9720
**/
9721
p._cloneProps = function(o) {
9722
this.DisplayObject__cloneProps(o);
9723
o.textAlign = this.textAlign;
9724
o.textBaseline = this.textBaseline;
9725
o.maxWidth = this.maxWidth;
9726
o.outline = this.outline;
9727
o.lineHeight = this.lineHeight;
9728
o.lineWidth = this.lineWidth;
9729
return o;
9730
};
9731
9732
/**
9733
* @method _getWorkingContext
9734
* @param {CanvasRenderingContext2D} ctx
9735
* @return {CanvasRenderingContext2D}
9736
* @protected
9737
**/
9738
p._prepContext = function(ctx) {
9739
ctx.font = this.font||"10px sans-serif";
9740
ctx.textAlign = this.textAlign||"left";
9741
ctx.textBaseline = this.textBaseline||"top";
9742
return ctx;
9743
};
9744
9745
/**
9746
* Draws multiline text.
9747
* @method _drawText
9748
* @param {CanvasRenderingContext2D} ctx
9749
* @param {Object} o
9750
* @param {Array} lines
9751
* @return {Object}
9752
* @protected
9753
**/
9754
p._drawText = function(ctx, o, lines) {
9755
var paint = !!ctx;
9756
if (!paint) {
9757
ctx = Text._workingContext;
9758
ctx.save();
9759
this._prepContext(ctx);
9760
}
9761
var lineHeight = this.lineHeight||this.getMeasuredLineHeight();
9762
9763
var maxW = 0, count = 0;
9764
var hardLines = String(this.text).split(/(?:\r\n|\r|\n)/);
9765
for (var i=0, l=hardLines.length; i<l; i++) {
9766
var str = hardLines[i];
9767
var w = null;
9768
9769
if (this.lineWidth != null && (w = ctx.measureText(str).width) > this.lineWidth) {
9770
// text wrapping:
9771
var words = str.split(/(\s)/);
9772
str = words[0];
9773
w = ctx.measureText(str).width;
9774
9775
for (var j=1, jl=words.length; j<jl; j+=2) {
9776
// Line needs to wrap:
9777
var wordW = ctx.measureText(words[j] + words[j+1]).width;
9778
if (w + wordW > this.lineWidth) {
9779
if (paint) { this._drawTextLine(ctx, str, count*lineHeight); }
9780
if (lines) { lines.push(str); }
9781
if (w > maxW) { maxW = w; }
9782
str = words[j+1];
9783
w = ctx.measureText(str).width;
9784
count++;
9785
} else {
9786
str += words[j] + words[j+1];
9787
w += wordW;
9788
}
9789
}
9790
}
9791
9792
if (paint) { this._drawTextLine(ctx, str, count*lineHeight); }
9793
if (lines) { lines.push(str); }
9794
if (o && w == null) { w = ctx.measureText(str).width; }
9795
if (w > maxW) { maxW = w; }
9796
count++;
9797
}
9798
9799
if (o) {
9800
o.width = maxW;
9801
o.height = count*lineHeight;
9802
}
9803
if (!paint) { ctx.restore(); }
9804
return o;
9805
};
9806
9807
/**
9808
* @method _drawTextLine
9809
* @param {CanvasRenderingContext2D} ctx
9810
* @param {String} text
9811
* @param {Number} y
9812
* @protected
9813
**/
9814
p._drawTextLine = function(ctx, text, y) {
9815
// Chrome 17 will fail to draw the text if the last param is included but null, so we feed it a large value instead:
9816
if (this.outline) { ctx.strokeText(text, 0, y, this.maxWidth||0xFFFF); }
9817
else { ctx.fillText(text, 0, y, this.maxWidth||0xFFFF); }
9818
};
9819
9820
9821
/**
9822
* @method _getMeasuredWidth
9823
* @param {String} text
9824
* @protected
9825
**/
9826
p._getMeasuredWidth = function(text) {
9827
var ctx = Text._workingContext;
9828
ctx.save();
9829
var w = this._prepContext(ctx).measureText(text).width;
9830
ctx.restore();
9831
return w;
9832
};
9833
9834
9835
createjs.Text = createjs.promote(Text, "DisplayObject");
9836
}());
9837
9838
//##############################################################################
9839
// BitmapText.js
9840
//##############################################################################
9841
9842
this.createjs = this.createjs || {};
9843
9844
(function () {
9845
"use strict";
9846
9847
9848
// constructor:
9849
/**
9850
* Displays text using bitmap glyphs defined in a sprite sheet. Multi-line text is supported
9851
* using new line characters, but automatic wrapping is not supported. See the
9852
* {{#crossLink "BitmapText/spriteSheet:property"}}{{/crossLink}}
9853
* property for more information on defining glyphs.
9854
*
9855
* <strong>Important:</strong> BitmapText extends Container, but is not designed to be used as one.
9856
* As such, methods like addChild and removeChild are disabled.
9857
* @class BitmapText
9858
* @extends DisplayObject
9859
* @param {String} [text=""] The text to display.
9860
* @param {SpriteSheet} [spriteSheet=null] The spritesheet that defines the character glyphs.
9861
* @constructor
9862
**/
9863
function BitmapText(text, spriteSheet) {
9864
this.Container_constructor();
9865
9866
9867
// public properties:
9868
/**
9869
* The text to display.
9870
* @property text
9871
* @type String
9872
* @default ""
9873
**/
9874
this.text = text||"";
9875
9876
/**
9877
* A SpriteSheet instance that defines the glyphs for this bitmap text. Each glyph/character
9878
* should have a single frame animation defined in the sprite sheet named the same as
9879
* corresponding character. For example, the following animation definition:
9880
*
9881
* "A": {frames: [0]}
9882
*
9883
* would indicate that the frame at index 0 of the spritesheet should be drawn for the "A" character. The short form
9884
* is also acceptable:
9885
*
9886
* "A": 0
9887
*
9888
* Note that if a character in the text is not found in the sprite sheet, it will also
9889
* try to use the alternate case (upper or lower).
9890
*
9891
* See SpriteSheet for more information on defining sprite sheet data.
9892
* @property spriteSheet
9893
* @type SpriteSheet
9894
* @default null
9895
**/
9896
this.spriteSheet = spriteSheet;
9897
9898
/**
9899
* The height of each line of text. If 0, then it will use a line height calculated
9900
* by checking for the height of the "1", "T", or "L" character (in that order). If
9901
* those characters are not defined, it will use the height of the first frame of the
9902
* sprite sheet.
9903
* @property lineHeight
9904
* @type Number
9905
* @default 0
9906
**/
9907
this.lineHeight = 0;
9908
9909
/**
9910
* This spacing (in pixels) will be added after each character in the output.
9911
* @property letterSpacing
9912
* @type Number
9913
* @default 0
9914
**/
9915
this.letterSpacing = 0;
9916
9917
/**
9918
* If a space character is not defined in the sprite sheet, then empty pixels equal to
9919
* spaceWidth will be inserted instead. If 0, then it will use a value calculated
9920
* by checking for the width of the "1", "l", "E", or "A" character (in that order). If
9921
* those characters are not defined, it will use the width of the first frame of the
9922
* sprite sheet.
9923
* @property spaceWidth
9924
* @type Number
9925
* @default 0
9926
**/
9927
this.spaceWidth = 0;
9928
9929
9930
// private properties:
9931
/**
9932
* @property _oldProps
9933
* @type Object
9934
* @protected
9935
**/
9936
this._oldProps = {text:0,spriteSheet:0,lineHeight:0,letterSpacing:0,spaceWidth:0};
9937
}
9938
var p = createjs.extend(BitmapText, createjs.Container);
9939
9940
/**
9941
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
9942
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
9943
* for details.
9944
*
9945
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
9946
*
9947
* @method initialize
9948
* @protected
9949
* @deprecated
9950
*/
9951
// p.initialize = function() {}; // searchable for devs wondering where it is.
9952
9953
// static properties:
9954
/**
9955
* BitmapText uses Sprite instances to draw text. To reduce the creation and destruction of instances (and thus garbage collection), it maintains
9956
* an internal object pool of sprite instances to reuse. Increasing this value can cause more sprites to be
9957
* retained, slightly increasing memory use, but reducing instantiation.
9958
* @property maxPoolSize
9959
* @type Number
9960
* @static
9961
* @default 100
9962
**/
9963
BitmapText.maxPoolSize = 100;
9964
9965
/**
9966
* Sprite object pool.
9967
* @type {Array}
9968
* @static
9969
* @private
9970
*/
9971
BitmapText._spritePool = [];
9972
9973
9974
// public methods:
9975
/**
9976
* Docced in superclass.
9977
**/
9978
p.draw = function(ctx, ignoreCache) {
9979
if (this.DisplayObject_draw(ctx, ignoreCache)) { return; }
9980
this._updateText();
9981
this.Container_draw(ctx, ignoreCache);
9982
};
9983
9984
/**
9985
* Docced in superclass.
9986
**/
9987
p.getBounds = function() {
9988
this._updateText();
9989
return this.Container_getBounds();
9990
};
9991
9992
/**
9993
* Returns true or false indicating whether the display object would be visible if drawn to a canvas.
9994
* This does not account for whether it would be visible within the boundaries of the stage.
9995
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
9996
* @method isVisible
9997
* @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
9998
**/
9999
p.isVisible = function() {
10000
var hasContent = this.cacheCanvas || (this.spriteSheet && this.spriteSheet.complete && this.text);
10001
return !!(this.visible && this.alpha > 0 && this.scaleX !== 0 && this.scaleY !== 0 && hasContent);
10002
};
10003
10004
p.clone = function() {
10005
return this._cloneProps(new BitmapText(this.text, this.spriteSheet));
10006
};
10007
10008
/**
10009
* <strong>Disabled in BitmapText.</strong>
10010
* @method addChild
10011
**/
10012
/**
10013
* <strong>Disabled in BitmapText.</strong>
10014
* @method addChildAt
10015
**/
10016
/**
10017
* <strong>Disabled in BitmapText.</strong>
10018
* @method removeChild
10019
**/
10020
/**
10021
* <strong>Disabled in BitmapText.</strong>
10022
* @method removeChildAt
10023
**/
10024
/**
10025
* <strong>Disabled in BitmapText.</strong>
10026
* @method removeAllChildren
10027
**/
10028
p.addChild = p.addChildAt = p.removeChild = p.removeChildAt = p.removeAllChildren = function() {};
10029
10030
10031
// private methods:
10032
/**
10033
* @method _cloneProps
10034
* @param {BitmapText} o
10035
* @return {BitmapText} o
10036
* @protected
10037
**/
10038
p._cloneProps = function(o) {
10039
this.Container__cloneProps(o);
10040
o.lineHeight = this.lineHeight;
10041
o.letterSpacing = this.letterSpacing;
10042
o.spaceWidth = this.spaceWidth;
10043
return o;
10044
};
10045
10046
/**
10047
* @method _getFrameIndex
10048
* @param {String} character
10049
* @param {SpriteSheet} spriteSheet
10050
* @return {Number}
10051
* @protected
10052
**/
10053
p._getFrameIndex = function(character, spriteSheet) {
10054
var c, o = spriteSheet.getAnimation(character);
10055
if (!o) {
10056
(character != (c = character.toUpperCase())) || (character != (c = character.toLowerCase())) || (c=null);
10057
if (c) { o = spriteSheet.getAnimation(c); }
10058
}
10059
return o && o.frames[0];
10060
};
10061
10062
/**
10063
* @method _getFrame
10064
* @param {String} character
10065
* @param {SpriteSheet} spriteSheet
10066
* @return {Object}
10067
* @protected
10068
**/
10069
p._getFrame = function(character, spriteSheet) {
10070
var index = this._getFrameIndex(character, spriteSheet);
10071
return index == null ? index : spriteSheet.getFrame(index);
10072
};
10073
10074
/**
10075
* @method _getLineHeight
10076
* @param {SpriteSheet} ss
10077
* @return {Number}
10078
* @protected
10079
**/
10080
p._getLineHeight = function(ss) {
10081
var frame = this._getFrame("1",ss) || this._getFrame("T",ss) || this._getFrame("L",ss) || ss.getFrame(0);
10082
return frame ? frame.rect.height : 1;
10083
};
10084
/**
10085
* @method _getSpaceWidth
10086
* @param {SpriteSheet} ss
10087
* @return {Number}
10088
* @protected
10089
**/
10090
p._getSpaceWidth = function(ss) {
10091
var frame = this._getFrame("1",ss) || this._getFrame("l",ss) || this._getFrame("e",ss) || this._getFrame("a",ss) || ss.getFrame(0);
10092
return frame ? frame.rect.width : 1;
10093
};
10094
10095
/**
10096
* @method _drawText
10097
* @protected
10098
**/
10099
p._updateText = function() {
10100
var x=0, y=0, o=this._oldProps, change=false, spaceW=this.spaceWidth, lineH=this.lineHeight, ss=this.spriteSheet;
10101
var pool=BitmapText._spritePool, kids=this.children, childIndex=0, numKids=kids.length, sprite;
10102
10103
for (var n in o) {
10104
if (o[n] != this[n]) {
10105
o[n] = this[n];
10106
change = true;
10107
}
10108
}
10109
if (!change) { return; }
10110
10111
var hasSpace = !!this._getFrame(" ", ss);
10112
if (!hasSpace && !spaceW) { spaceW = this._getSpaceWidth(ss); }
10113
if (!lineH) { lineH = this._getLineHeight(ss); }
10114
10115
for(var i=0, l=this.text.length; i<l; i++) {
10116
var character = this.text.charAt(i);
10117
if (character == " " && !hasSpace) {
10118
x += spaceW;
10119
continue;
10120
} else if (character=="\n" || character=="\r") {
10121
if (character=="\r" && this.text.charAt(i+1) == "\n") { i++; } // crlf
10122
x = 0;
10123
y += lineH;
10124
continue;
10125
}
10126
10127
var index = this._getFrameIndex(character, ss);
10128
if (index == null) { continue; }
10129
10130
if (childIndex < numKids) {
10131
sprite = kids[childIndex];
10132
} else {
10133
kids.push(sprite = pool.length ? pool.pop() : new createjs.Sprite());
10134
sprite.parent = this;
10135
numKids++;
10136
}
10137
sprite.spriteSheet = ss;
10138
sprite.gotoAndStop(index);
10139
sprite.x = x;
10140
sprite.y = y;
10141
childIndex++;
10142
10143
x += sprite.getBounds().width + this.letterSpacing;
10144
}
10145
while (numKids > childIndex) {
10146
// faster than removeChild.
10147
pool.push(sprite = kids.pop());
10148
sprite.parent = null;
10149
numKids--;
10150
}
10151
if (pool.length > BitmapText.maxPoolSize) { pool.length = BitmapText.maxPoolSize; }
10152
};
10153
10154
10155
createjs.BitmapText = createjs.promote(BitmapText, "Container");
10156
}());
10157
10158
//##############################################################################
10159
// MovieClip.js
10160
//##############################################################################
10161
10162
this.createjs = this.createjs||{};
10163
10164
(function() {
10165
"use strict";
10166
10167
10168
// constructor:
10169
/**
10170
* The MovieClip class associates a TweenJS Timeline with an EaselJS {{#crossLink "Container"}}{{/crossLink}}. It allows
10171
* you to create objects which encapsulate timeline animations, state changes, and synched actions. Due to the
10172
* complexities inherent in correctly setting up a MovieClip, it is largely intended for tool output and is not included
10173
* in the main EaselJS library.
10174
*
10175
* Currently MovieClip only works properly if it is tick based (as opposed to time based) though some concessions have
10176
* been made to support time-based timelines in the future.
10177
*
10178
* <h4>Example</h4>
10179
* This example animates two shapes back and forth. The grey shape starts on the left, but we jump to a mid-point in
10180
* the animation using {{#crossLink "MovieClip/gotoAndPlay"}}{{/crossLink}}.
10181
*
10182
* var stage = new createjs.Stage("canvas");
10183
* createjs.Ticker.addEventListener("tick", stage);
10184
*
10185
* var mc = new createjs.MovieClip(null, 0, true, {start:20});
10186
* stage.addChild(mc);
10187
*
10188
* var child1 = new createjs.Shape(
10189
* new createjs.Graphics().beginFill("#999999")
10190
* .drawCircle(30,30,30));
10191
* var child2 = new createjs.Shape(
10192
* new createjs.Graphics().beginFill("#5a9cfb")
10193
* .drawCircle(30,30,30));
10194
*
10195
* mc.timeline.addTween(
10196
* createjs.Tween.get(child1)
10197
* .to({x:0}).to({x:60}, 50).to({x:0}, 50));
10198
* mc.timeline.addTween(
10199
* createjs.Tween.get(child2)
10200
* .to({x:60}).to({x:0}, 50).to({x:60}, 50));
10201
*
10202
* mc.gotoAndPlay("start");
10203
*
10204
* It is recommended to use <code>tween.to()</code> to animate and set properties (use no duration to have it set
10205
* immediately), and the <code>tween.wait()</code> method to create delays between animations. Note that using the
10206
* <code>tween.set()</code> method to affect properties will likely not provide the desired result.
10207
*
10208
* @class MovieClip
10209
* @main MovieClip
10210
* @extends Container
10211
* @constructor
10212
* @param {String} [mode=independent] Initial value for the mode property. One of {{#crossLink "MovieClip/INDEPENDENT:property"}}{{/crossLink}},
10213
* {{#crossLink "MovieClip/SINGLE_FRAME:property"}}{{/crossLink}}, or {{#crossLink "MovieClip/SYNCHED:property"}}{{/crossLink}}.
10214
* The default is {{#crossLink "MovieClip/INDEPENDENT:property"}}{{/crossLink}}.
10215
* @param {Number} [startPosition=0] Initial value for the {{#crossLink "MovieClip/startPosition:property"}}{{/crossLink}}
10216
* property.
10217
* @param {Boolean} [loop=true] Initial value for the {{#crossLink "MovieClip/loop:property"}}{{/crossLink}}
10218
* property. The default is `true`.
10219
* @param {Object} [labels=null] A hash of labels to pass to the {{#crossLink "MovieClip/timeline:property"}}{{/crossLink}}
10220
* instance associated with this MovieClip. Labels only need to be passed if they need to be used.
10221
**/
10222
function MovieClip(mode, startPosition, loop, labels) {
10223
this.Container_constructor();
10224
!MovieClip.inited&&MovieClip.init(); // static init
10225
10226
10227
// public properties:
10228
/**
10229
* Controls how this MovieClip advances its time. Must be one of 0 (INDEPENDENT), 1 (SINGLE_FRAME), or 2 (SYNCHED).
10230
* See each constant for a description of the behaviour.
10231
* @property mode
10232
* @type String
10233
* @default null
10234
**/
10235
this.mode = mode||MovieClip.INDEPENDENT;
10236
10237
/**
10238
* Specifies what the first frame to play in this movieclip, or the only frame to display if mode is SINGLE_FRAME.
10239
* @property startPosition
10240
* @type Number
10241
* @default 0
10242
*/
10243
this.startPosition = startPosition || 0;
10244
10245
/**
10246
* Indicates whether this MovieClip should loop when it reaches the end of its timeline.
10247
* @property loop
10248
* @type Boolean
10249
* @default true
10250
*/
10251
this.loop = loop;
10252
10253
/**
10254
* The current frame of the movieclip.
10255
* @property currentFrame
10256
* @type Number
10257
* @default 0
10258
* @readonly
10259
*/
10260
this.currentFrame = 0;
10261
10262
/**
10263
* The TweenJS Timeline that is associated with this MovieClip. This is created automatically when the MovieClip
10264
* instance is initialized. Animations are created by adding <a href="http://tweenjs.com">TweenJS</a> Tween
10265
* instances to the timeline.
10266
*
10267
* <h4>Example</h4>
10268
*
10269
* var tween = createjs.Tween.get(target).to({x:0}).to({x:100}, 30);
10270
* var mc = new createjs.MovieClip();
10271
* mc.timeline.addTween(tween);
10272
*
10273
* Elements can be added and removed from the timeline by toggling an "_off" property
10274
* using the <code>tweenInstance.to()</code> method. Note that using <code>Tween.set</code> is not recommended to
10275
* create MovieClip animations. The following example will toggle the target off on frame 0, and then back on for
10276
* frame 1. You can use the "visible" property to achieve the same effect.
10277
*
10278
* var tween = createjs.Tween.get(target).to({_off:false})
10279
* .wait(1).to({_off:true})
10280
* .wait(1).to({_off:false});
10281
*
10282
* @property timeline
10283
* @type Timeline
10284
* @default null
10285
*/
10286
this.timeline = new createjs.Timeline(null, labels, {paused:true, position:startPosition, useTicks:true});
10287
10288
/**
10289
* If true, the MovieClip's position will not advance when ticked.
10290
* @property paused
10291
* @type Boolean
10292
* @default false
10293
*/
10294
this.paused = false;
10295
10296
/**
10297
* If true, actions in this MovieClip's tweens will be run when the playhead advances.
10298
* @property actionsEnabled
10299
* @type Boolean
10300
* @default true
10301
*/
10302
this.actionsEnabled = true;
10303
10304
/**
10305
* If true, the MovieClip will automatically be reset to its first frame whenever the timeline adds
10306
* it back onto the display list. This only applies to MovieClip instances with mode=INDEPENDENT.
10307
* <br><br>
10308
* For example, if you had a character animation with a "body" child MovieClip instance
10309
* with different costumes on each frame, you could set body.autoReset = false, so that
10310
* you can manually change the frame it is on, without worrying that it will be reset
10311
* automatically.
10312
* @property autoReset
10313
* @type Boolean
10314
* @default true
10315
*/
10316
this.autoReset = true;
10317
10318
/**
10319
* An array of bounds for each frame in the MovieClip. This is mainly intended for tool output.
10320
* @property frameBounds
10321
* @type Array
10322
* @default null
10323
*/
10324
this.frameBounds = this.frameBounds||null; // TODO: Deprecated. This is for backwards support of FlashCC
10325
10326
/**
10327
* By default MovieClip instances advance one frame per tick. Specifying a framerate for the MovieClip
10328
* will cause it to advance based on elapsed time between ticks as appropriate to maintain the target
10329
* framerate.
10330
*
10331
* For example, if a MovieClip with a framerate of 10 is placed on a Stage being updated at 40fps, then the MovieClip will
10332
* advance roughly one frame every 4 ticks. This will not be exact, because the time between each tick will
10333
* vary slightly between frames.
10334
*
10335
* This feature is dependent on the tick event object (or an object with an appropriate "delta" property) being
10336
* passed into {{#crossLink "Stage/update"}}{{/crossLink}}.
10337
* @property framerate
10338
* @type {Number}
10339
* @default null
10340
**/
10341
this.framerate = null;
10342
10343
10344
// private properties:
10345
/**
10346
* @property _synchOffset
10347
* @type Number
10348
* @default 0
10349
* @private
10350
*/
10351
this._synchOffset = 0;
10352
10353
/**
10354
* @property _prevPos
10355
* @type Number
10356
* @default -1
10357
* @private
10358
*/
10359
this._prevPos = -1; // TODO: evaluate using a ._reset Boolean prop instead of -1.
10360
10361
/**
10362
* @property _prevPosition
10363
* @type Number
10364
* @default 0
10365
* @private
10366
*/
10367
this._prevPosition = 0;
10368
10369
/**
10370
* The time remaining from the previous tick, only applicable when .framerate is set.
10371
* @property _t
10372
* @type Number
10373
* @private
10374
*/
10375
this._t = 0;
10376
10377
/**
10378
* List of display objects that are actively being managed by the MovieClip.
10379
* @property _managed
10380
* @type Object
10381
* @private
10382
*/
10383
this._managed = {};
10384
}
10385
var p = createjs.extend(MovieClip, createjs.Container);
10386
10387
10388
// constants:
10389
/**
10390
* The MovieClip will advance independently of its parent, even if its parent is paused.
10391
* This is the default mode.
10392
* @property INDEPENDENT
10393
* @static
10394
* @type String
10395
* @default "independent"
10396
* @readonly
10397
**/
10398
MovieClip.INDEPENDENT = "independent";
10399
10400
/**
10401
* The MovieClip will only display a single frame (as determined by the startPosition property).
10402
* @property SINGLE_FRAME
10403
* @static
10404
* @type String
10405
* @default "single"
10406
* @readonly
10407
**/
10408
MovieClip.SINGLE_FRAME = "single";
10409
10410
/**
10411
* The MovieClip will be advanced only when its parent advances and will be synched to the position of
10412
* the parent MovieClip.
10413
* @property SYNCHED
10414
* @static
10415
* @type String
10416
* @default "synched"
10417
* @readonly
10418
**/
10419
MovieClip.SYNCHED = "synched";
10420
10421
10422
// static properties:
10423
MovieClip.inited = false;
10424
10425
10426
// static methods:
10427
MovieClip.init = function() {
10428
if (MovieClip.inited) { return; }
10429
// plugins introduce some overhead to Tween, so we only install this if an MC is instantiated.
10430
MovieClipPlugin.install();
10431
MovieClip.inited = true;
10432
};
10433
10434
10435
// getter / setters:
10436
/**
10437
* Use the {{#crossLink "MovieClip/labels:property"}}{{/crossLink}} property instead.
10438
* @method getLabels
10439
* @return {Array}
10440
* @deprecated
10441
**/
10442
p.getLabels = function() {
10443
return this.timeline.getLabels();
10444
};
10445
10446
/**
10447
* Use the {{#crossLink "MovieClip/currentLabel:property"}}{{/crossLink}} property instead.
10448
* @method getCurrentLabel
10449
* @return {String}
10450
* @deprecated
10451
**/
10452
p.getCurrentLabel = function() {
10453
this._updateTimeline();
10454
return this.timeline.getCurrentLabel();
10455
};
10456
10457
/**
10458
* Use the {{#crossLink "MovieClip/duration:property"}}{{/crossLink}} property instead.
10459
* @method getDuration
10460
* @return {Number}
10461
* @protected
10462
**/
10463
p.getDuration = function() {
10464
return this.timeline.duration;
10465
};
10466
10467
/**
10468
* Returns an array of objects with label and position (aka frame) properties, sorted by position.
10469
* Shortcut to TweenJS: Timeline.getLabels();
10470
* @property labels
10471
* @type {Array}
10472
* @readonly
10473
**/
10474
10475
/**
10476
* Returns the name of the label on or immediately before the current frame. See TweenJS: Timeline.getCurrentLabel()
10477
* for more information.
10478
* @property currentLabel
10479
* @type {String}
10480
* @readonly
10481
**/
10482
10483
/**
10484
* Returns the duration of this MovieClip in seconds or ticks. Identical to {{#crossLink "MovieClip/duration:property"}}{{/crossLink}}
10485
* and provided for Flash API compatibility.
10486
* @property totalFrames
10487
* @type {Number}
10488
* @readonly
10489
**/
10490
10491
/**
10492
* Returns the duration of this MovieClip in seconds or ticks.
10493
* @property duration
10494
* @type {Number}
10495
* @readonly
10496
**/
10497
try {
10498
Object.defineProperties(p, {
10499
labels: { get: p.getLabels },
10500
currentLabel: { get: p.getCurrentLabel },
10501
totalFrames: { get: p.getDuration },
10502
duration: { get: p.getDuration }
10503
});
10504
} catch (e) {}
10505
10506
10507
// public methods:
10508
/**
10509
* Constructor alias for backwards compatibility. This method will be removed in future versions.
10510
* Subclasses should be updated to use {{#crossLink "Utility Methods/extends"}}{{/crossLink}}.
10511
* @method initialize
10512
* @deprecated in favour of `createjs.promote()`
10513
**/
10514
p.initialize = MovieClip; // TODO: Deprecated. This is for backwards support of FlashCC
10515
10516
/**
10517
* Returns true or false indicating whether the display object would be visible if drawn to a canvas.
10518
* This does not account for whether it would be visible within the boundaries of the stage.
10519
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
10520
* @method isVisible
10521
* @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
10522
**/
10523
p.isVisible = function() {
10524
// children are placed in draw, so we can't determine if we have content.
10525
return !!(this.visible && this.alpha > 0 && this.scaleX != 0 && this.scaleY != 0);
10526
};
10527
10528
/**
10529
* Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
10530
* Returns true if the draw was handled (useful for overriding functionality).
10531
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
10532
* @method draw
10533
* @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
10534
* @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache.
10535
* For example, used for drawing the cache (to prevent it from simply drawing an existing cache back
10536
* into itself).
10537
**/
10538
p.draw = function(ctx, ignoreCache) {
10539
// draw to cache first:
10540
if (this.DisplayObject_draw(ctx, ignoreCache)) { return true; }
10541
this._updateTimeline();
10542
this.Container_draw(ctx, ignoreCache);
10543
return true;
10544
};
10545
10546
/**
10547
* Sets paused to false.
10548
* @method play
10549
**/
10550
p.play = function() {
10551
this.paused = false;
10552
};
10553
10554
/**
10555
* Sets paused to true.
10556
* @method stop
10557
**/
10558
p.stop = function() {
10559
this.paused = true;
10560
};
10561
10562
/**
10563
* Advances this movie clip to the specified position or label and sets paused to false.
10564
* @method gotoAndPlay
10565
* @param {String|Number} positionOrLabel The animation name or frame number to go to.
10566
**/
10567
p.gotoAndPlay = function(positionOrLabel) {
10568
this.paused = false;
10569
this._goto(positionOrLabel);
10570
};
10571
10572
/**
10573
* Advances this movie clip to the specified position or label and sets paused to true.
10574
* @method gotoAndStop
10575
* @param {String|Number} positionOrLabel The animation or frame name to go to.
10576
**/
10577
p.gotoAndStop = function(positionOrLabel) {
10578
this.paused = true;
10579
this._goto(positionOrLabel);
10580
};
10581
10582
/**
10583
* Advances the playhead. This occurs automatically each tick by default.
10584
* @param [time] {Number} The amount of time in ms to advance by. Only applicable if framerate is set.
10585
* @method advance
10586
*/
10587
p.advance = function(time) {
10588
// TODO: should we worry at all about clips who change their own modes via frame scripts?
10589
var independent = MovieClip.INDEPENDENT;
10590
if (this.mode != independent) { return; }
10591
10592
var o=this, fps = o.framerate;
10593
while ((o = o.parent) && fps == null) {
10594
if (o.mode == independent) { fps = o._framerate; }
10595
}
10596
this._framerate = fps;
10597
10598
var t = (fps != null && fps != -1 && time != null) ? time/(1000/fps) + this._t : 1;
10599
var frames = t|0;
10600
this._t = t-frames; // leftover time
10601
10602
while (!this.paused && frames--) {
10603
this._prevPosition = (this._prevPos < 0) ? 0 : this._prevPosition+1;
10604
this._updateTimeline();
10605
}
10606
};
10607
10608
/**
10609
* MovieClip instances cannot be cloned.
10610
* @method clone
10611
**/
10612
p.clone = function() {
10613
// TODO: add support for this? Need to clone the Timeline & retarget tweens - pretty complex.
10614
throw("MovieClip cannot be cloned.")
10615
};
10616
10617
/**
10618
* Returns a string representation of this object.
10619
* @method toString
10620
* @return {String} a string representation of the instance.
10621
**/
10622
p.toString = function() {
10623
return "[MovieClip (name="+ this.name +")]";
10624
};
10625
10626
10627
// private methods:
10628
/**
10629
* @method _tick
10630
* @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.
10631
* function.
10632
* @protected
10633
**/
10634
p._tick = function(evtObj) {
10635
this.advance(evtObj&&evtObj.delta);
10636
this.Container__tick(evtObj);
10637
};
10638
10639
/**
10640
* @method _goto
10641
* @param {String|Number} positionOrLabel The animation name or frame number to go to.
10642
* @protected
10643
**/
10644
p._goto = function(positionOrLabel) {
10645
var pos = this.timeline.resolve(positionOrLabel);
10646
if (pos == null) { return; }
10647
// prevent _updateTimeline from overwriting the new position because of a reset:
10648
if (this._prevPos == -1) { this._prevPos = NaN; }
10649
this._prevPosition = pos;
10650
this._t = 0;
10651
this._updateTimeline();
10652
};
10653
10654
/**
10655
* @method _reset
10656
* @private
10657
**/
10658
p._reset = function() {
10659
this._prevPos = -1;
10660
this._t = this.currentFrame = 0;
10661
this.paused = false;
10662
};
10663
10664
/**
10665
* @method _updateTimeline
10666
* @protected
10667
**/
10668
p._updateTimeline = function() {
10669
var tl = this.timeline;
10670
var synched = this.mode != MovieClip.INDEPENDENT;
10671
tl.loop = (this.loop==null) ? true : this.loop;
10672
10673
var pos = synched ? this.startPosition + (this.mode==MovieClip.SINGLE_FRAME?0:this._synchOffset) : (this._prevPos < 0 ? 0 : this._prevPosition);
10674
var mode = synched || !this.actionsEnabled ? createjs.Tween.NONE : null;
10675
10676
// pre-assign currentFrame so it is available to frame scripts:
10677
this.currentFrame = tl._calcPosition(pos);
10678
10679
// update timeline position, ignoring actions if this is a graphic.
10680
tl.setPosition(pos, mode);
10681
10682
this._prevPosition = tl._prevPosition;
10683
if (this._prevPos == tl._prevPos) { return; }
10684
this.currentFrame = this._prevPos = tl._prevPos;
10685
10686
for (var n in this._managed) { this._managed[n] = 1; }
10687
10688
var tweens = tl._tweens;
10689
for (var i=0, l=tweens.length; i<l; i++) {
10690
var tween = tweens[i];
10691
var target = tween._target;
10692
if (target == this || tween.passive) { continue; } // TODO: this assumes actions tween has this as the target. Valid?
10693
var offset = tween._stepPosition;
10694
10695
if (target instanceof createjs.DisplayObject) {
10696
// motion tween.
10697
this._addManagedChild(target, offset);
10698
} else {
10699
// state tween.
10700
this._setState(target.state, offset);
10701
}
10702
}
10703
10704
var kids = this.children;
10705
for (i=kids.length-1; i>=0; i--) {
10706
var id = kids[i].id;
10707
if (this._managed[id] == 1) {
10708
this.removeChildAt(i);
10709
delete(this._managed[id]);
10710
}
10711
}
10712
};
10713
10714
/**
10715
* @method _setState
10716
* @param {Array} state
10717
* @param {Number} offset
10718
* @protected
10719
**/
10720
p._setState = function(state, offset) {
10721
if (!state) { return; }
10722
for (var i=state.length-1;i>=0;i--) {
10723
var o = state[i];
10724
var target = o.t;
10725
var props = o.p;
10726
for (var n in props) { target[n] = props[n]; }
10727
this._addManagedChild(target, offset);
10728
}
10729
};
10730
10731
/**
10732
* Adds a child to the timeline, and sets it up as a managed child.
10733
* @method _addManagedChild
10734
* @param {MovieClip} child The child MovieClip to manage
10735
* @param {Number} offset
10736
* @private
10737
**/
10738
p._addManagedChild = function(child, offset) {
10739
if (child._off) { return; }
10740
this.addChildAt(child,0);
10741
10742
if (child instanceof MovieClip) {
10743
child._synchOffset = offset;
10744
// TODO: this does not precisely match Flash. Flash loses track of the clip if it is renamed or removed from the timeline, which causes it to reset.
10745
if (child.mode == MovieClip.INDEPENDENT && child.autoReset && !this._managed[child.id]) { child._reset(); }
10746
}
10747
this._managed[child.id] = 2;
10748
};
10749
10750
/**
10751
* @method _getBounds
10752
* @param {Matrix2D} matrix
10753
* @param {Boolean} ignoreTransform
10754
* @return {Rectangle}
10755
* @protected
10756
**/
10757
p._getBounds = function(matrix, ignoreTransform) {
10758
var bounds = this.DisplayObject_getBounds();
10759
if (!bounds) {
10760
this._updateTimeline();
10761
if (this.frameBounds) { bounds = this._rectangle.copy(this.frameBounds[this.currentFrame]); }
10762
}
10763
if (bounds) { return this._transformBounds(bounds, matrix, ignoreTransform); }
10764
return this.Container__getBounds(matrix, ignoreTransform);
10765
};
10766
10767
10768
createjs.MovieClip = createjs.promote(MovieClip, "Container");
10769
10770
10771
10772
// MovieClipPlugin for TweenJS:
10773
/**
10774
* This plugin works with <a href="http://tweenjs.com" target="_blank">TweenJS</a> to prevent the startPosition
10775
* property from tweening.
10776
* @private
10777
* @class MovieClipPlugin
10778
* @constructor
10779
**/
10780
function MovieClipPlugin() {
10781
throw("MovieClipPlugin cannot be instantiated.")
10782
}
10783
10784
/**
10785
* @method priority
10786
* @private
10787
**/
10788
MovieClipPlugin.priority = 100; // very high priority, should run first
10789
10790
/**
10791
* @method install
10792
* @private
10793
**/
10794
MovieClipPlugin.install = function() {
10795
createjs.Tween.installPlugin(MovieClipPlugin, ["startPosition"]);
10796
};
10797
10798
/**
10799
* @method init
10800
* @param {Tween} tween
10801
* @param {String} prop
10802
* @param {String|Number|Boolean} value
10803
* @private
10804
**/
10805
MovieClipPlugin.init = function(tween, prop, value) {
10806
return value;
10807
};
10808
10809
/**
10810
* @method step
10811
* @private
10812
**/
10813
MovieClipPlugin.step = function() {
10814
// unused.
10815
};
10816
10817
/**
10818
* @method tween
10819
* @param {Tween} tween
10820
* @param {String} prop
10821
* @param {String | Number | Boolean} value
10822
* @param {Array} startValues
10823
* @param {Array} endValues
10824
* @param {Number} ratio
10825
* @param {Object} wait
10826
* @param {Object} end
10827
* @return {*}
10828
*/
10829
MovieClipPlugin.tween = function(tween, prop, value, startValues, endValues, ratio, wait, end) {
10830
if (!(tween.target instanceof MovieClip)) { return value; }
10831
return (ratio == 1 ? endValues[prop] : startValues[prop]);
10832
};
10833
10834
}());
10835
10836
//##############################################################################
10837
// SpriteSheetUtils.js
10838
//##############################################################################
10839
10840
this.createjs = this.createjs||{};
10841
10842
(function() {
10843
"use strict";
10844
10845
10846
// constructor:
10847
/**
10848
* The SpriteSheetUtils class is a collection of static methods for working with {{#crossLink "SpriteSheet"}}{{/crossLink}}s.
10849
* A sprite sheet is a series of images (usually animation frames) combined into a single image on a regular grid. For
10850
* example, an animation consisting of 8 100x100 images could be combined into a 400x200 sprite sheet (4 frames across
10851
* by 2 high). The SpriteSheetUtils class uses a static interface and should not be instantiated.
10852
* @class SpriteSheetUtils
10853
* @static
10854
**/
10855
function SpriteSheetUtils() {
10856
throw "SpriteSheetUtils cannot be instantiated";
10857
}
10858
10859
10860
// private static properties:
10861
/**
10862
* @property _workingCanvas
10863
* @static
10864
* @type HTMLCanvasElement | Object
10865
* @protected
10866
*/
10867
/**
10868
* @property _workingContext
10869
* @static
10870
* @type CanvasRenderingContext2D
10871
* @protected
10872
*/
10873
var canvas = (createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"));
10874
if (canvas.getContext) {
10875
SpriteSheetUtils._workingCanvas = canvas;
10876
SpriteSheetUtils._workingContext = canvas.getContext("2d");
10877
canvas.width = canvas.height = 1;
10878
}
10879
10880
10881
// public static methods:
10882
/**
10883
* <b>This is an experimental method, and may be buggy. Please report issues.</b><br/><br/>
10884
* Extends the existing sprite sheet by flipping the original frames horizontally, vertically, or both,
10885
* and adding appropriate animation & frame data. The flipped animations will have a suffix added to their names
10886
* (_h, _v, _hv as appropriate). Make sure the sprite sheet images are fully loaded before using this method.
10887
* <br/><br/>
10888
* For example:<br/>
10889
* SpriteSheetUtils.addFlippedFrames(mySpriteSheet, true, true);
10890
* The above would add frames that are flipped horizontally AND frames that are flipped vertically.
10891
* <br/><br/>
10892
* Note that you can also flip any display object by setting its scaleX or scaleY to a negative value. On some
10893
* browsers (especially those without hardware accelerated canvas) this can result in slightly degraded performance,
10894
* which is why addFlippedFrames is available.
10895
* @method addFlippedFrames
10896
* @static
10897
* @param {SpriteSheet} spriteSheet
10898
* @param {Boolean} horizontal If true, horizontally flipped frames will be added.
10899
* @param {Boolean} vertical If true, vertically flipped frames will be added.
10900
* @param {Boolean} both If true, frames that are flipped both horizontally and vertically will be added.
10901
* @deprecated Modern browsers perform better when flipping via a transform (ex. scaleX=-1) rendering this obsolete.
10902
**/
10903
SpriteSheetUtils.addFlippedFrames = function(spriteSheet, horizontal, vertical, both) {
10904
if (!horizontal && !vertical && !both) { return; }
10905
10906
var count = 0;
10907
if (horizontal) { SpriteSheetUtils._flip(spriteSheet,++count,true,false); }
10908
if (vertical) { SpriteSheetUtils._flip(spriteSheet,++count,false,true); }
10909
if (both) { SpriteSheetUtils._flip(spriteSheet,++count,true,true); }
10910
};
10911
10912
/**
10913
* Returns a single frame of the specified sprite sheet as a new PNG image. An example of when this may be useful is
10914
* to use a spritesheet frame as the source for a bitmap fill.
10915
*
10916
* <strong>WARNING:</strong> In almost all cases it is better to display a single frame using a {{#crossLink "Sprite"}}{{/crossLink}}
10917
* with a {{#crossLink "Sprite/gotoAndStop"}}{{/crossLink}} call than it is to slice out a frame using this
10918
* method and display it with a Bitmap instance. You can also crop an image using the {{#crossLink "Bitmap/sourceRect"}}{{/crossLink}}
10919
* property of {{#crossLink "Bitmap"}}{{/crossLink}}.
10920
*
10921
* The extractFrame method may cause cross-domain warnings since it accesses pixels directly on the canvas.
10922
* @method extractFrame
10923
* @static
10924
* @param {SpriteSheet} spriteSheet The SpriteSheet instance to extract a frame from.
10925
* @param {Number|String} frameOrAnimation The frame number or animation name to extract. If an animation
10926
* name is specified, only the first frame of the animation will be extracted.
10927
* @return {HTMLImageElement} a single frame of the specified sprite sheet as a new PNG image.
10928
*/
10929
SpriteSheetUtils.extractFrame = function(spriteSheet, frameOrAnimation) {
10930
if (isNaN(frameOrAnimation)) {
10931
frameOrAnimation = spriteSheet.getAnimation(frameOrAnimation).frames[0];
10932
}
10933
var data = spriteSheet.getFrame(frameOrAnimation);
10934
if (!data) { return null; }
10935
var r = data.rect;
10936
var canvas = SpriteSheetUtils._workingCanvas;
10937
canvas.width = r.width;
10938
canvas.height = r.height;
10939
SpriteSheetUtils._workingContext.drawImage(data.image, r.x, r.y, r.width, r.height, 0, 0, r.width, r.height);
10940
var img = document.createElement("img");
10941
img.src = canvas.toDataURL("image/png");
10942
return img;
10943
};
10944
10945
/**
10946
* Merges the rgb channels of one image with the alpha channel of another. This can be used to combine a compressed
10947
* JPEG image containing color data with a PNG32 monochromatic image containing alpha data. With certain types of
10948
* images (those with detail that lend itself to JPEG compression) this can provide significant file size savings
10949
* versus a single RGBA PNG32. This method is very fast (generally on the order of 1-2 ms to run).
10950
* @method mergeAlpha
10951
* @static
10952
* @param {HTMLImageElement} rbgImage The image (or canvas) containing the RGB channels to use.
10953
* @param {HTMLImageElement} alphaImage The image (or canvas) containing the alpha channel to use.
10954
* @param {HTMLCanvasElement} canvas Optional. If specified, this canvas will be used and returned. If not, a new canvas will be created.
10955
* @return {HTMLCanvasElement} A canvas with the combined image data. This can be used as a source for Bitmap or SpriteSheet.
10956
* @deprecated Tools such as ImageAlpha generally provide better results. This will be moved to sandbox in the future.
10957
*/
10958
SpriteSheetUtils.mergeAlpha = function(rgbImage, alphaImage, canvas) {
10959
if (!canvas) { canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas"); }
10960
canvas.width = Math.max(alphaImage.width, rgbImage.width);
10961
canvas.height = Math.max(alphaImage.height, rgbImage.height);
10962
var ctx = canvas.getContext("2d");
10963
ctx.save();
10964
ctx.drawImage(rgbImage,0,0);
10965
ctx.globalCompositeOperation = "destination-in";
10966
ctx.drawImage(alphaImage,0,0);
10967
ctx.restore();
10968
return canvas;
10969
};
10970
10971
10972
// private static methods:
10973
SpriteSheetUtils._flip = function(spriteSheet, count, h, v) {
10974
var imgs = spriteSheet._images;
10975
var canvas = SpriteSheetUtils._workingCanvas;
10976
var ctx = SpriteSheetUtils._workingContext;
10977
var il = imgs.length/count;
10978
for (var i=0;i<il;i++) {
10979
var src = imgs[i];
10980
src.__tmp = i; // a bit hacky, but faster than doing indexOf below.
10981
ctx.setTransform(1,0,0,1,0,0);
10982
ctx.clearRect(0,0,canvas.width+1,canvas.height+1);
10983
canvas.width = src.width;
10984
canvas.height = src.height;
10985
ctx.setTransform(h?-1:1, 0, 0, v?-1:1, h?src.width:0, v?src.height:0);
10986
ctx.drawImage(src,0,0);
10987
var img = document.createElement("img");
10988
img.src = canvas.toDataURL("image/png");
10989
// work around a strange bug in Safari:
10990
img.width = src.width;
10991
img.height = src.height;
10992
imgs.push(img);
10993
}
10994
10995
var frames = spriteSheet._frames;
10996
var fl = frames.length/count;
10997
for (i=0;i<fl;i++) {
10998
src = frames[i];
10999
var rect = src.rect.clone();
11000
img = imgs[src.image.__tmp+il*count];
11001
11002
var frame = {image:img,rect:rect,regX:src.regX,regY:src.regY};
11003
if (h) {
11004
rect.x = img.width-rect.x-rect.width; // update rect
11005
frame.regX = rect.width-src.regX; // update registration point
11006
}
11007
if (v) {
11008
rect.y = img.height-rect.y-rect.height; // update rect
11009
frame.regY = rect.height-src.regY; // update registration point
11010
}
11011
frames.push(frame);
11012
}
11013
11014
var sfx = "_"+(h?"h":"")+(v?"v":"");
11015
var names = spriteSheet._animations;
11016
var data = spriteSheet._data;
11017
var al = names.length/count;
11018
for (i=0;i<al;i++) {
11019
var name = names[i];
11020
src = data[name];
11021
var anim = {name:name+sfx,speed:src.speed,next:src.next,frames:[]};
11022
if (src.next) { anim.next += sfx; }
11023
frames = src.frames;
11024
for (var j=0,l=frames.length;j<l;j++) {
11025
anim.frames.push(frames[j]+fl*count);
11026
}
11027
data[anim.name] = anim;
11028
names.push(anim.name);
11029
}
11030
};
11031
11032
11033
createjs.SpriteSheetUtils = SpriteSheetUtils;
11034
}());
11035
11036
//##############################################################################
11037
// SpriteSheetBuilder.js
11038
//##############################################################################
11039
11040
this.createjs = this.createjs||{};
11041
11042
(function() {
11043
"use strict";
11044
11045
11046
// constructor:
11047
/**
11048
* The SpriteSheetBuilder allows you to generate {{#crossLink "SpriteSheet"}}{{/crossLink}} instances at run time
11049
* from any display object. This can allow you to maintain your assets as vector graphics (for low file size), and
11050
* render them at run time as SpriteSheets for better performance.
11051
*
11052
* SpriteSheets can be built either synchronously, or asynchronously, so that large SpriteSheets can be generated
11053
* without locking the UI.
11054
*
11055
* Note that the "images" used in the generated SpriteSheet are actually canvas elements, and that they will be
11056
* sized to the nearest power of 2 up to the value of {{#crossLink "SpriteSheetBuilder/maxWidth:property"}}{{/crossLink}}
11057
* or {{#crossLink "SpriteSheetBuilder/maxHeight:property"}}{{/crossLink}}.
11058
* @class SpriteSheetBuilder
11059
* @param {Number} [framerate=0] The {{#crossLink "SpriteSheet/framerate:property"}}{{/crossLink}} of
11060
* {{#crossLink "SpriteSheet"}}{{/crossLink}} instances that are created.
11061
* @extends EventDispatcher
11062
* @constructor
11063
**/
11064
function SpriteSheetBuilder(framerate) {
11065
this.EventDispatcher_constructor();
11066
11067
// public properties:
11068
/**
11069
* The maximum width for the images (not individual frames) in the generated SpriteSheet. It is recommended to
11070
* use a power of 2 for this value (ex. 1024, 2048, 4096). If the frames cannot all fit within the max
11071
* dimensions, then additional images will be created as needed.
11072
* @property maxWidth
11073
* @type Number
11074
* @default 2048
11075
*/
11076
this.maxWidth = 2048;
11077
11078
/**
11079
* The maximum height for the images (not individual frames) in the generated SpriteSheet. It is recommended to
11080
* use a power of 2 for this value (ex. 1024, 2048, 4096). If the frames cannot all fit within the max
11081
* dimensions, then additional images will be created as needed.
11082
* @property maxHeight
11083
* @type Number
11084
* @default 2048
11085
**/
11086
this.maxHeight = 2048;
11087
11088
/**
11089
* The SpriteSheet that was generated. This will be null before a build is completed successfully.
11090
* @property spriteSheet
11091
* @type SpriteSheet
11092
**/
11093
this.spriteSheet = null;
11094
11095
/**
11096
* The scale to apply when drawing all frames to the SpriteSheet. This is multiplied against any scale specified
11097
* in the addFrame call. This can be used, for example, to generate a SpriteSheet at run time that is tailored
11098
* to the a specific device resolution (ex. tablet vs mobile).
11099
* @property scale
11100
* @type Number
11101
* @default 1
11102
**/
11103
this.scale = 1;
11104
11105
/**
11106
* The padding to use between frames. This is helpful to preserve antialiasing on drawn vector content.
11107
* @property padding
11108
* @type Number
11109
* @default 1
11110
**/
11111
this.padding = 1;
11112
11113
/**
11114
* A number from 0.01 to 0.99 that indicates what percentage of time the builder can use. This can be
11115
* thought of as the number of seconds per second the builder will use. For example, with a timeSlice value of 0.3,
11116
* the builder will run 20 times per second, using approximately 15ms per build (30% of available time, or 0.3s per second).
11117
* Defaults to 0.3.
11118
* @property timeSlice
11119
* @type Number
11120
* @default 0.3
11121
**/
11122
this.timeSlice = 0.3;
11123
11124
/**
11125
* A value between 0 and 1 that indicates the progress of a build, or -1 if a build has not
11126
* been initiated.
11127
* @property progress
11128
* @type Number
11129
* @default -1
11130
* @readonly
11131
*/
11132
this.progress = -1;
11133
11134
/**
11135
* A {{#crossLink "SpriteSheet/framerate:property"}}{{/crossLink}} value that will be passed to new {{#crossLink "SpriteSheet"}}{{/crossLink}} instances that are
11136
* created. If no framerate is specified (or it is 0), then SpriteSheets will use the {{#crossLink "Ticker"}}{{/crossLink}}
11137
* framerate.
11138
* @property framerate
11139
* @type Number
11140
* @default 0
11141
*/
11142
this.framerate = framerate || 0;
11143
11144
11145
// private properties:
11146
/**
11147
* @property _frames
11148
* @protected
11149
* @type Array
11150
**/
11151
this._frames = [];
11152
11153
/**
11154
* @property _animations
11155
* @protected
11156
* @type Array
11157
**/
11158
this._animations = {};
11159
11160
/**
11161
* @property _data
11162
* @protected
11163
* @type Array
11164
**/
11165
this._data = null;
11166
11167
/**
11168
* @property _nextFrameIndex
11169
* @protected
11170
* @type Number
11171
**/
11172
this._nextFrameIndex = 0;
11173
11174
/**
11175
* @property _index
11176
* @protected
11177
* @type Number
11178
**/
11179
this._index = 0;
11180
11181
/**
11182
* @property _timerID
11183
* @protected
11184
* @type Number
11185
**/
11186
this._timerID = null;
11187
11188
/**
11189
* @property _scale
11190
* @protected
11191
* @type Number
11192
**/
11193
this._scale = 1;
11194
}
11195
var p = createjs.extend(SpriteSheetBuilder, createjs.EventDispatcher);
11196
11197
/**
11198
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
11199
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
11200
* for details.
11201
*
11202
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
11203
*
11204
* @method initialize
11205
* @protected
11206
* @deprecated
11207
*/
11208
// p.initialize = function() {}; // searchable for devs wondering where it is.
11209
11210
11211
// constants:
11212
SpriteSheetBuilder.ERR_DIMENSIONS = "frame dimensions exceed max spritesheet dimensions";
11213
SpriteSheetBuilder.ERR_RUNNING = "a build is already running";
11214
11215
// events:
11216
/**
11217
* Dispatched when a build completes.
11218
* @event complete
11219
* @param {Object} target The object that dispatched the event.
11220
* @param {String} type The event type.
11221
* @since 0.6.0
11222
*/
11223
11224
/**
11225
* Dispatched when an asynchronous build has progress.
11226
* @event progress
11227
* @param {Object} target The object that dispatched the event.
11228
* @param {String} type The event type.
11229
* @param {Number} progress The current progress value (0-1).
11230
* @since 0.6.0
11231
*/
11232
11233
11234
// public methods:
11235
/**
11236
* Adds a frame to the {{#crossLink "SpriteSheet"}}{{/crossLink}}. Note that the frame will not be drawn until you
11237
* call {{#crossLink "SpriteSheetBuilder/build"}}{{/crossLink}} method. The optional setup params allow you to have
11238
* a function run immediately before the draw occurs. For example, this allows you to add a single source multiple
11239
* times, but manipulate it or its children to change it to generate different frames.
11240
*
11241
* Note that the source's transformations (x, y, scale, rotate, alpha) will be ignored, except for regX/Y. To apply
11242
* transforms to a source object and have them captured in the SpriteSheet, simply place it into a {{#crossLink "Container"}}{{/crossLink}}
11243
* and pass in the Container as the source.
11244
* @method addFrame
11245
* @param {DisplayObject} source The source {{#crossLink "DisplayObject"}}{{/crossLink}} to draw as the frame.
11246
* @param {Rectangle} [sourceRect] A {{#crossLink "Rectangle"}}{{/crossLink}} defining the portion of the
11247
* source to draw to the frame. If not specified, it will look for a `getBounds` method, bounds property, or
11248
* `nominalBounds` property on the source to use. If one is not found, the frame will be skipped.
11249
* @param {Number} [scale=1] Optional. The scale to draw this frame at. Default is 1.
11250
* @param {Function} [setupFunction] A function to call immediately before drawing this frame. It will be called with two parameters: the source, and setupData.
11251
* @param {Object} [setupData] Arbitrary setup data to pass to setupFunction as the second parameter.
11252
* @return {Number} The index of the frame that was just added, or null if a sourceRect could not be determined.
11253
**/
11254
p.addFrame = function(source, sourceRect, scale, setupFunction, setupData) {
11255
if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; }
11256
var rect = sourceRect||source.bounds||source.nominalBounds;
11257
if (!rect&&source.getBounds) { rect = source.getBounds(); }
11258
if (!rect) { return null; }
11259
scale = scale||1;
11260
return this._frames.push({source:source, sourceRect:rect, scale:scale, funct:setupFunction, data:setupData, index:this._frames.length, height:rect.height*scale})-1;
11261
};
11262
11263
/**
11264
* Adds an animation that will be included in the created {{#crossLink "SpriteSheet"}}{{/crossLink}}.
11265
* @method addAnimation
11266
* @param {String} name The name for the animation.
11267
* @param {Array} frames An array of frame indexes that comprise the animation. Ex. [3,6,5] would describe an animation
11268
* that played frame indexes 3, 6, and 5 in that order.
11269
* @param {String} [next] Specifies the name of the animation to continue to after this animation ends. You can
11270
* also pass false to have the animation stop when it ends. By default it will loop to the start of the same animation.
11271
* @param {Number} [speed] Specifies a frame advance speed for this animation. For example, a value of 0.5 would
11272
* cause the animation to advance every second tick. Note that earlier versions used `frequency` instead, which had
11273
* the opposite effect.
11274
**/
11275
p.addAnimation = function(name, frames, next, speed) {
11276
if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; }
11277
this._animations[name] = {frames:frames, next:next, speed:speed};
11278
};
11279
11280
/**
11281
* This will take a {{#crossLink "MovieClip"}}{{/crossLink}} instance, and add its frames and labels to this
11282
* builder. Labels will be added as an animation running from the label index to the next label. For example, if
11283
* there is a label named "foo" at frame 0 and a label named "bar" at frame 10, in a MovieClip with 15 frames, it
11284
* will add an animation named "foo" that runs from frame index 0 to 9, and an animation named "bar" that runs from
11285
* frame index 10 to 14.
11286
*
11287
* Note that this will iterate through the full MovieClip with {{#crossLink "MovieClip/actionsEnabled:property"}}{{/crossLink}}
11288
* set to `false`, ending on the last frame.
11289
* @method addMovieClip
11290
* @param {MovieClip} source The source MovieClip instance to add to the SpriteSheet.
11291
* @param {Rectangle} [sourceRect] A {{#crossLink "Rectangle"}}{{/crossLink}} defining the portion of the source to
11292
* draw to the frame. If not specified, it will look for a {{#crossLink "DisplayObject/getBounds"}}{{/crossLink}}
11293
* method, `frameBounds` Array, `bounds` property, or `nominalBounds` property on the source to use. If one is not
11294
* found, the MovieClip will be skipped.
11295
* @param {Number} [scale=1] The scale to draw the movie clip at.
11296
* @param {Function} [setupFunction] A function to call immediately before drawing each frame. It will be called
11297
* with three parameters: the source, setupData, and the frame index.
11298
* @param {Object} [setupData] Arbitrary setup data to pass to setupFunction as the second parameter.
11299
* @param {Function} [labelFunction] This method will be called for each MovieClip label that is added with four
11300
* parameters: the label name, the source MovieClip instance, the starting frame index (in the movieclip timeline)
11301
* and the end index. It must return a new name for the label/animation, or `false` to exclude the label.
11302
**/
11303
p.addMovieClip = function(source, sourceRect, scale, setupFunction, setupData, labelFunction) {
11304
if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; }
11305
var rects = source.frameBounds;
11306
var rect = sourceRect||source.bounds||source.nominalBounds;
11307
if (!rect&&source.getBounds) { rect = source.getBounds(); }
11308
if (!rect && !rects) { return; }
11309
11310
var i, l, baseFrameIndex = this._frames.length;
11311
var duration = source.timeline.duration;
11312
for (i=0; i<duration; i++) {
11313
var r = (rects&&rects[i]) ? rects[i] : rect;
11314
this.addFrame(source, r, scale, this._setupMovieClipFrame, {i:i, f:setupFunction, d:setupData});
11315
}
11316
var labels = source.timeline._labels;
11317
var lbls = [];
11318
for (var n in labels) {
11319
lbls.push({index:labels[n], label:n});
11320
}
11321
if (lbls.length) {
11322
lbls.sort(function(a,b){ return a.index-b.index; });
11323
for (i=0,l=lbls.length; i<l; i++) {
11324
var label = lbls[i].label;
11325
var start = baseFrameIndex+lbls[i].index;
11326
var end = baseFrameIndex+((i == l-1) ? duration : lbls[i+1].index);
11327
var frames = [];
11328
for (var j=start; j<end; j++) { frames.push(j); }
11329
if (labelFunction) {
11330
label = labelFunction(label, source, start, end);
11331
if (!label) { continue; }
11332
}
11333
this.addAnimation(label, frames, true); // for now, this loops all animations.
11334
}
11335
}
11336
};
11337
11338
/**
11339
* Builds a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance based on the current frames.
11340
* @method build
11341
* @return {SpriteSheet} The created SpriteSheet instance, or null if a build is already running or an error
11342
* occurred.
11343
**/
11344
p.build = function() {
11345
if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; }
11346
this._startBuild();
11347
while (this._drawNext()) {}
11348
this._endBuild();
11349
return this.spriteSheet;
11350
};
11351
11352
/**
11353
* Asynchronously builds a {{#crossLink "SpriteSheet"}}{{/crossLink}} instance based on the current frames. It will
11354
* run 20 times per second, using an amount of time defined by `timeSlice`. When it is complete it will call the
11355
* specified callback.
11356
* @method buildAsync
11357
* @param {Number} [timeSlice] Sets the timeSlice property on this instance.
11358
**/
11359
p.buildAsync = function(timeSlice) {
11360
if (this._data) { throw SpriteSheetBuilder.ERR_RUNNING; }
11361
this.timeSlice = timeSlice;
11362
this._startBuild();
11363
var _this = this;
11364
this._timerID = setTimeout(function() { _this._run(); }, 50-Math.max(0.01, Math.min(0.99, this.timeSlice||0.3))*50);
11365
};
11366
11367
/**
11368
* Stops the current asynchronous build.
11369
* @method stopAsync
11370
**/
11371
p.stopAsync = function() {
11372
clearTimeout(this._timerID);
11373
this._data = null;
11374
};
11375
11376
/**
11377
* SpriteSheetBuilder instances cannot be cloned.
11378
* @method clone
11379
**/
11380
p.clone = function() {
11381
throw("SpriteSheetBuilder cannot be cloned.");
11382
};
11383
11384
/**
11385
* Returns a string representation of this object.
11386
* @method toString
11387
* @return {String} a string representation of the instance.
11388
**/
11389
p.toString = function() {
11390
return "[SpriteSheetBuilder]";
11391
};
11392
11393
11394
// private methods:
11395
/**
11396
* @method _startBuild
11397
* @protected
11398
**/
11399
p._startBuild = function() {
11400
var pad = this.padding||0;
11401
this.progress = 0;
11402
this.spriteSheet = null;
11403
this._index = 0;
11404
this._scale = this.scale;
11405
var dataFrames = [];
11406
this._data = {
11407
images: [],
11408
frames: dataFrames,
11409
framerate: this.framerate,
11410
animations: this._animations // TODO: should we "clone" _animations in case someone adds more animations after a build?
11411
};
11412
11413
var frames = this._frames.slice();
11414
frames.sort(function(a,b) { return (a.height<=b.height) ? -1 : 1; });
11415
11416
if (frames[frames.length-1].height+pad*2 > this.maxHeight) { throw SpriteSheetBuilder.ERR_DIMENSIONS; }
11417
var y=0, x=0;
11418
var img = 0;
11419
while (frames.length) {
11420
var o = this._fillRow(frames, y, img, dataFrames, pad);
11421
if (o.w > x) { x = o.w; }
11422
y += o.h;
11423
if (!o.h || !frames.length) {
11424
var canvas = createjs.createCanvas?createjs.createCanvas():document.createElement("canvas");
11425
canvas.width = this._getSize(x,this.maxWidth);
11426
canvas.height = this._getSize(y,this.maxHeight);
11427
this._data.images[img] = canvas;
11428
if (!o.h) {
11429
x=y=0;
11430
img++;
11431
}
11432
}
11433
}
11434
};
11435
11436
/**
11437
* @method _setupMovieClipFrame
11438
* @protected
11439
* @return {Number} The width & height of the row.
11440
**/
11441
p._setupMovieClipFrame = function(source, data) {
11442
var ae = source.actionsEnabled;
11443
source.actionsEnabled = false;
11444
source.gotoAndStop(data.i);
11445
source.actionsEnabled = ae;
11446
data.f&&data.f(source, data.d, data.i);
11447
};
11448
11449
/**
11450
* @method _getSize
11451
* @protected
11452
* @return {Number} The width & height of the row.
11453
**/
11454
p._getSize = function(size,max) {
11455
var pow = 4;
11456
while (Math.pow(2,++pow) < size){}
11457
return Math.min(max,Math.pow(2,pow));
11458
};
11459
11460
/**
11461
* @method _fillRow
11462
* @param {Array} frames
11463
* @param {Number} y
11464
* @param {HTMLImageElement} img
11465
* @param {Object} dataFrames
11466
* @param {Number} pad
11467
* @protected
11468
* @return {Number} The width & height of the row.
11469
**/
11470
p._fillRow = function(frames, y, img, dataFrames, pad) {
11471
var w = this.maxWidth;
11472
var maxH = this.maxHeight;
11473
y += pad;
11474
var h = maxH-y;
11475
var x = pad;
11476
var height = 0;
11477
for (var i=frames.length-1; i>=0; i--) {
11478
var frame = frames[i];
11479
var sc = this._scale*frame.scale;
11480
var rect = frame.sourceRect;
11481
var source = frame.source;
11482
var rx = Math.floor(sc*rect.x-pad);
11483
var ry = Math.floor(sc*rect.y-pad);
11484
var rh = Math.ceil(sc*rect.height+pad*2);
11485
var rw = Math.ceil(sc*rect.width+pad*2);
11486
if (rw > w) { throw SpriteSheetBuilder.ERR_DIMENSIONS; }
11487
if (rh > h || x+rw > w) { continue; }
11488
frame.img = img;
11489
frame.rect = new createjs.Rectangle(x,y,rw,rh);
11490
height = height || rh;
11491
frames.splice(i,1);
11492
dataFrames[frame.index] = [x,y,rw,rh,img,Math.round(-rx+sc*source.regX-pad),Math.round(-ry+sc*source.regY-pad)];
11493
x += rw;
11494
}
11495
return {w:x, h:height};
11496
};
11497
11498
/**
11499
* @method _endBuild
11500
* @protected
11501
**/
11502
p._endBuild = function() {
11503
this.spriteSheet = new createjs.SpriteSheet(this._data);
11504
this._data = null;
11505
this.progress = 1;
11506
this.dispatchEvent("complete");
11507
};
11508
11509
/**
11510
* @method _run
11511
* @protected
11512
**/
11513
p._run = function() {
11514
var ts = Math.max(0.01, Math.min(0.99, this.timeSlice||0.3))*50;
11515
var t = (new Date()).getTime()+ts;
11516
var complete = false;
11517
while (t > (new Date()).getTime()) {
11518
if (!this._drawNext()) { complete = true; break; }
11519
}
11520
if (complete) {
11521
this._endBuild();
11522
} else {
11523
var _this = this;
11524
this._timerID = setTimeout(function() { _this._run(); }, 50-ts);
11525
}
11526
var p = this.progress = this._index/this._frames.length;
11527
if (this.hasEventListener("progress")) {
11528
var evt = new createjs.Event("progress");
11529
evt.progress = p;
11530
this.dispatchEvent(evt);
11531
}
11532
};
11533
11534
/**
11535
* @method _drawNext
11536
* @protected
11537
* @return Boolean Returns false if this is the last draw.
11538
**/
11539
p._drawNext = function() {
11540
var frame = this._frames[this._index];
11541
var sc = frame.scale*this._scale;
11542
var rect = frame.rect;
11543
var sourceRect = frame.sourceRect;
11544
var canvas = this._data.images[frame.img];
11545
var ctx = canvas.getContext("2d");
11546
frame.funct&&frame.funct(frame.source, frame.data);
11547
ctx.save();
11548
ctx.beginPath();
11549
ctx.rect(rect.x, rect.y, rect.width, rect.height);
11550
ctx.clip();
11551
ctx.translate(Math.ceil(rect.x-sourceRect.x*sc), Math.ceil(rect.y-sourceRect.y*sc));
11552
ctx.scale(sc,sc);
11553
frame.source.draw(ctx); // display object will draw itself.
11554
ctx.restore();
11555
return (++this._index) < this._frames.length;
11556
};
11557
11558
11559
createjs.SpriteSheetBuilder = createjs.promote(SpriteSheetBuilder, "EventDispatcher");
11560
}());
11561
11562
//##############################################################################
11563
// DOMElement.js
11564
//##############################################################################
11565
11566
this.createjs = this.createjs||{};
11567
11568
(function() {
11569
"use strict";
11570
11571
11572
// constructor:
11573
/**
11574
* <b>This class is still experimental, and more advanced use is likely to be buggy. Please report bugs.</b>
11575
*
11576
* A DOMElement allows you to associate a HTMLElement with the display list. It will be transformed
11577
* within the DOM as though it is child of the {{#crossLink "Container"}}{{/crossLink}} it is added to. However, it is
11578
* not rendered to canvas, and as such will retain whatever z-index it has relative to the canvas (ie. it will be
11579
* drawn in front of or behind the canvas).
11580
*
11581
* The position of a DOMElement is relative to their parent node in the DOM. It is recommended that
11582
* the DOM Object be added to a div that also contains the canvas so that they share the same position
11583
* on the page.
11584
*
11585
* DOMElement is useful for positioning HTML elements over top of canvas content, and for elements
11586
* that you want to display outside the bounds of the canvas. For example, a tooltip with rich HTML
11587
* content.
11588
*
11589
* <h4>Mouse Interaction</h4>
11590
*
11591
* DOMElement instances are not full EaselJS display objects, and do not participate in EaselJS mouse
11592
* events or support methods like hitTest. To get mouse events from a DOMElement, you must instead add handlers to
11593
* the htmlElement (note, this does not support EventDispatcher)
11594
*
11595
* var domElement = new createjs.DOMElement(htmlElement);
11596
* domElement.htmlElement.onclick = function() {
11597
* console.log("clicked");
11598
* }
11599
*
11600
* @class DOMElement
11601
* @extends DisplayObject
11602
* @constructor
11603
* @param {HTMLElement} htmlElement A reference or id for the DOM element to manage.
11604
*/
11605
function DOMElement(htmlElement) {
11606
this.DisplayObject_constructor();
11607
11608
if (typeof(htmlElement)=="string") { htmlElement = document.getElementById(htmlElement); }
11609
this.mouseEnabled = false;
11610
11611
var style = htmlElement.style;
11612
style.position = "absolute";
11613
style.transformOrigin = style.WebkitTransformOrigin = style.msTransformOrigin = style.MozTransformOrigin = style.OTransformOrigin = "0% 0%";
11614
11615
11616
// public properties:
11617
/**
11618
* The DOM object to manage.
11619
* @property htmlElement
11620
* @type HTMLElement
11621
*/
11622
this.htmlElement = htmlElement;
11623
11624
11625
// private properties:
11626
/**
11627
* @property _oldMtx
11628
* @type Matrix2D
11629
* @protected
11630
*/
11631
this._oldProps = null;
11632
}
11633
var p = createjs.extend(DOMElement, createjs.DisplayObject);
11634
11635
// TODO: deprecated
11636
// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
11637
11638
11639
// public methods:
11640
/**
11641
* Returns true or false indicating whether the display object would be visible if drawn to a canvas.
11642
* This does not account for whether it would be visible within the boundaries of the stage.
11643
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
11644
* @method isVisible
11645
* @return {Boolean} Boolean indicating whether the display object would be visible if drawn to a canvas
11646
*/
11647
p.isVisible = function() {
11648
return this.htmlElement != null;
11649
};
11650
11651
/**
11652
* Draws the display object into the specified context ignoring its visible, alpha, shadow, and transform.
11653
* Returns true if the draw was handled (useful for overriding functionality).
11654
* NOTE: This method is mainly for internal use, though it may be useful for advanced uses.
11655
* @method draw
11656
* @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
11657
* @param {Boolean} ignoreCache Indicates whether the draw operation should ignore any current cache.
11658
* For example, used for drawing the cache (to prevent it from simply drawing an existing cache back
11659
* into itself).
11660
* @return {Boolean}
11661
*/
11662
p.draw = function(ctx, ignoreCache) {
11663
// this relies on the _tick method because draw isn't called if the parent is not visible.
11664
// the actual update happens in _handleDrawEnd
11665
return true;
11666
};
11667
11668
/**
11669
* Not applicable to DOMElement.
11670
* @method cache
11671
*/
11672
p.cache = function() {};
11673
11674
/**
11675
* Not applicable to DOMElement.
11676
* @method uncache
11677
*/
11678
p.uncache = function() {};
11679
11680
/**
11681
* Not applicable to DOMElement.
11682
* @method updateCache
11683
*/
11684
p.updateCache = function() {};
11685
11686
/**
11687
* Not applicable to DOMElement.
11688
* @method hitTest
11689
*/
11690
p.hitTest = function() {};
11691
11692
/**
11693
* Not applicable to DOMElement.
11694
* @method localToGlobal
11695
*/
11696
p.localToGlobal = function() {};
11697
11698
/**
11699
* Not applicable to DOMElement.
11700
* @method globalToLocal
11701
*/
11702
p.globalToLocal = function() {};
11703
11704
/**
11705
* Not applicable to DOMElement.
11706
* @method localToLocal
11707
*/
11708
p.localToLocal = function() {};
11709
11710
/**
11711
* DOMElement cannot be cloned. Throws an error.
11712
* @method clone
11713
*/
11714
p.clone = function() {
11715
throw("DOMElement cannot be cloned.")
11716
};
11717
11718
/**
11719
* Returns a string representation of this object.
11720
* @method toString
11721
* @return {String} a string representation of the instance.
11722
*/
11723
p.toString = function() {
11724
return "[DOMElement (name="+ this.name +")]";
11725
};
11726
11727
/**
11728
* Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances
11729
* are not full EaselJS display objects and do not participate in EaselJS mouse events.
11730
* @event click
11731
*/
11732
11733
/**
11734
* Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances
11735
* are not full EaselJS display objects and do not participate in EaselJS mouse events.
11736
* @event dblClick
11737
*/
11738
11739
/**
11740
* Interaction events should be added to `htmlElement`, and not the DOMElement instance, since DOMElement instances
11741
* are not full EaselJS display objects and do not participate in EaselJS mouse events.
11742
* @event mousedown
11743
*/
11744
11745
/**
11746
* The HTMLElement can listen for the mouseover event, not the DOMElement instance.
11747
* Since DOMElement instances are not full EaselJS display objects and do not participate in EaselJS mouse events.
11748
* @event mouseover
11749
*/
11750
11751
/**
11752
* Not applicable to DOMElement.
11753
* @event tick
11754
*/
11755
11756
11757
// private methods:
11758
/**
11759
* @method _tick
11760
* @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.
11761
* function.
11762
* @protected
11763
*/
11764
p._tick = function(evtObj) {
11765
var stage = this.getStage();
11766
stage&&stage.on("drawend", this._handleDrawEnd, this, true);
11767
this.DisplayObject__tick(evtObj);
11768
};
11769
11770
/**
11771
* @method _handleDrawEnd
11772
* @param {Event} evt
11773
* @protected
11774
*/
11775
p._handleDrawEnd = function(evt) {
11776
var o = this.htmlElement;
11777
if (!o) { return; }
11778
var style = o.style;
11779
11780
var props = this.getConcatenatedDisplayProps(this._props), mtx = props.matrix;
11781
11782
var visibility = props.visible ? "visible" : "hidden";
11783
if (visibility != style.visibility) { style.visibility = visibility; }
11784
if (!props.visible) { return; }
11785
11786
var oldProps = this._oldProps, oldMtx = oldProps&&oldProps.matrix;
11787
var n = 10000; // precision
11788
11789
if (!oldMtx || !oldMtx.equals(mtx)) {
11790
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);
11791
style.transform = style.WebkitTransform = style.OTransform = style.msTransform = str +","+ (mtx.ty+0.5|0) +")";
11792
style.MozTransform = str +"px,"+ (mtx.ty+0.5|0) +"px)";
11793
if (!oldProps) { oldProps = this._oldProps = new createjs.DisplayProps(true, NaN); }
11794
oldProps.matrix.copy(mtx);
11795
}
11796
11797
if (oldProps.alpha != props.alpha) {
11798
style.opacity = ""+(props.alpha*n|0)/n;
11799
oldProps.alpha = props.alpha;
11800
}
11801
};
11802
11803
11804
createjs.DOMElement = createjs.promote(DOMElement, "DisplayObject");
11805
}());
11806
11807
//##############################################################################
11808
// Filter.js
11809
//##############################################################################
11810
11811
this.createjs = this.createjs||{};
11812
11813
(function() {
11814
"use strict";
11815
11816
11817
// constructor:
11818
/**
11819
* Base class that all filters should inherit from. Filters need to be applied to objects that have been cached using
11820
* the {{#crossLink "DisplayObject/cache"}}{{/crossLink}} method. If an object changes, please cache it again, or use
11821
* {{#crossLink "DisplayObject/updateCache"}}{{/crossLink}}. Note that the filters must be applied before caching.
11822
*
11823
* <h4>Example</h4>
11824
*
11825
* myInstance.filters = [
11826
* new createjs.ColorFilter(0, 0, 0, 1, 255, 0, 0),
11827
* new createjs.BlurFilter(5, 5, 10)
11828
* ];
11829
* myInstance.cache(0,0, 100, 100);
11830
*
11831
* Note that each filter can implement a {{#crossLink "Filter/getBounds"}}{{/crossLink}} method, which returns the
11832
* margins that need to be applied in order to fully display the filter. For example, the {{#crossLink "BlurFilter"}}{{/crossLink}}
11833
* will cause an object to feather outwards, resulting in a margin around the shape.
11834
*
11835
* <h4>EaselJS Filters</h4>
11836
* EaselJS comes with a number of pre-built filters:
11837
* <ul><li>{{#crossLink "AlphaMapFilter"}}{{/crossLink}} : Map a greyscale image to the alpha channel of a display object</li>
11838
* <li>{{#crossLink "AlphaMaskFilter"}}{{/crossLink}}: Map an image's alpha channel to the alpha channel of a display object</li>
11839
* <li>{{#crossLink "BlurFilter"}}{{/crossLink}}: Apply vertical and horizontal blur to a display object</li>
11840
* <li>{{#crossLink "ColorFilter"}}{{/crossLink}}: Color transform a display object</li>
11841
* <li>{{#crossLink "ColorMatrixFilter"}}{{/crossLink}}: Transform an image using a {{#crossLink "ColorMatrix"}}{{/crossLink}}</li>
11842
* </ul>
11843
*
11844
* @class Filter
11845
* @constructor
11846
**/
11847
function Filter() {}
11848
var p = Filter.prototype;
11849
11850
/**
11851
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
11852
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
11853
* for details.
11854
*
11855
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
11856
*
11857
* @method initialize
11858
* @protected
11859
* @deprecated
11860
*/
11861
// p.initialize = function() {}; // searchable for devs wondering where it is.
11862
11863
11864
// public methods:
11865
/**
11866
* Provides padding values for this filter. That is, how much the filter will extend the visual bounds of an object it is applied to.
11867
* @method getBounds
11868
* @param {Rectangle} [rect] If specified, the provided Rectangle instance will be expanded by the padding amounts and returned.
11869
* @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.
11870
**/
11871
p.getBounds = function(rect) {
11872
return rect;
11873
};
11874
11875
/**
11876
* Applies the filter to the specified context.
11877
* @method applyFilter
11878
* @param {CanvasRenderingContext2D} ctx The 2D context to use as the source.
11879
* @param {Number} x The x position to use for the source rect.
11880
* @param {Number} y The y position to use for the source rect.
11881
* @param {Number} width The width to use for the source rect.
11882
* @param {Number} height The height to use for the source rect.
11883
* @param {CanvasRenderingContext2D} [targetCtx] The 2D context to draw the result to. Defaults to the context passed to ctx.
11884
* @param {Number} [targetX] The x position to draw the result to. Defaults to the value passed to x.
11885
* @param {Number} [targetY] The y position to draw the result to. Defaults to the value passed to y.
11886
* @return {Boolean} If the filter was applied successfully.
11887
**/
11888
p.applyFilter = function(ctx, x, y, width, height, targetCtx, targetX, targetY) {
11889
// this is the default behaviour because most filters access pixel data. It is overridden when not needed.
11890
targetCtx = targetCtx || ctx;
11891
if (targetX == null) { targetX = x; }
11892
if (targetY == null) { targetY = y; }
11893
try {
11894
var imageData = ctx.getImageData(x, y, width, height);
11895
} catch (e) {
11896
return false;
11897
}
11898
if (this._applyFilter(imageData)) {
11899
targetCtx.putImageData(imageData, targetX, targetY);
11900
return true;
11901
}
11902
return false;
11903
};
11904
11905
/**
11906
* Returns a string representation of this object.
11907
* @method toString
11908
* @return {String} a string representation of the instance.
11909
**/
11910
p.toString = function() {
11911
return "[Filter]";
11912
};
11913
11914
/**
11915
* Returns a clone of this Filter instance.
11916
* @method clone
11917
* @return {Filter} A clone of the current Filter instance.
11918
**/
11919
p.clone = function() {
11920
return new Filter();
11921
};
11922
11923
// private methods:
11924
/**
11925
* @method _applyFilter
11926
* @param {ImageData} imageData Target ImageData instance.
11927
* @return {Boolean}
11928
**/
11929
p._applyFilter = function(imageData) { return true; };
11930
11931
11932
createjs.Filter = Filter;
11933
}());
11934
11935
//##############################################################################
11936
// BlurFilter.js
11937
//##############################################################################
11938
11939
this.createjs = this.createjs||{};
11940
11941
(function() {
11942
"use strict";
11943
11944
11945
// constructor:
11946
/**
11947
* Applies a box blur to DisplayObjects. Note that this filter is fairly CPU intensive, particularly if the quality is
11948
* set higher than 1.
11949
*
11950
* <h4>Example</h4>
11951
* This example creates a red circle, and then applies a 5 pixel blur to it. It uses the {{#crossLink "Filter/getBounds"}}{{/crossLink}}
11952
* method to account for the spread that the blur causes.
11953
*
11954
* var shape = new createjs.Shape().set({x:100,y:100});
11955
* shape.graphics.beginFill("#ff0000").drawCircle(0,0,50);
11956
*
11957
* var blurFilter = new createjs.BlurFilter(5, 5, 1);
11958
* shape.filters = [blurFilter];
11959
* var bounds = blurFilter.getBounds();
11960
*
11961
* shape.cache(-50+bounds.x, -50+bounds.y, 100+bounds.width, 100+bounds.height);
11962
*
11963
* See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters.
11964
* @class BlurFilter
11965
* @extends Filter
11966
* @constructor
11967
* @param {Number} [blurX=0] The horizontal blur radius in pixels.
11968
* @param {Number} [blurY=0] The vertical blur radius in pixels.
11969
* @param {Number} [quality=1] The number of blur iterations.
11970
**/
11971
function BlurFilter( blurX, blurY, quality) {
11972
if ( isNaN(blurX) || blurX < 0 ) blurX = 0;
11973
if ( isNaN(blurY) || blurY < 0 ) blurY = 0;
11974
if ( isNaN(quality) || quality < 1 ) quality = 1;
11975
11976
11977
// public properties:
11978
/**
11979
* Horizontal blur radius in pixels
11980
* @property blurX
11981
* @default 0
11982
* @type Number
11983
**/
11984
this.blurX = blurX | 0;
11985
11986
/**
11987
* Vertical blur radius in pixels
11988
* @property blurY
11989
* @default 0
11990
* @type Number
11991
**/
11992
this.blurY = blurY | 0;
11993
11994
/**
11995
* Number of blur iterations. For example, a value of 1 will produce a rough blur. A value of 2 will produce a
11996
* smoother blur, but take twice as long to run.
11997
* @property quality
11998
* @default 1
11999
* @type Number
12000
**/
12001
this.quality = quality | 0;
12002
}
12003
var p = createjs.extend(BlurFilter, createjs.Filter);
12004
12005
// TODO: deprecated
12006
// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
12007
12008
12009
// constants:
12010
/**
12011
* Array of multiply values for blur calculations.
12012
* @property MUL_TABLE
12013
* @type Array
12014
* @protected
12015
* @static
12016
**/
12017
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];
12018
12019
/**
12020
* Array of shift values for blur calculations.
12021
* @property SHG_TABLE
12022
* @type Array
12023
* @protected
12024
* @static
12025
**/
12026
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];
12027
12028
// public methods:
12029
/** docced in super class **/
12030
p.getBounds = function (rect) {
12031
var x = this.blurX|0, y = this.blurY| 0;
12032
if (x <= 0 && y <= 0) { return rect; }
12033
var q = Math.pow(this.quality, 0.2);
12034
return (rect || new createjs.Rectangle()).pad(x*q+1,y*q+1,x*q+1,y*q+1);
12035
};
12036
12037
/** docced in super class **/
12038
p.clone = function() {
12039
return new BlurFilter(this.blurX, this.blurY, this.quality);
12040
};
12041
12042
/** docced in super class **/
12043
p.toString = function() {
12044
return "[BlurFilter]";
12045
};
12046
12047
12048
// private methods:
12049
12050
/** docced in super class **/
12051
p._applyFilter = function (imageData) {
12052
12053
var radiusX = this.blurX >> 1;
12054
if (isNaN(radiusX) || radiusX < 0) return false;
12055
var radiusY = this.blurY >> 1;
12056
if (isNaN(radiusY) || radiusY < 0) return false;
12057
if (radiusX == 0 && radiusY == 0) return false;
12058
12059
var iterations = this.quality;
12060
if (isNaN(iterations) || iterations < 1) iterations = 1;
12061
iterations |= 0;
12062
if (iterations > 3) iterations = 3;
12063
if (iterations < 1) iterations = 1;
12064
12065
var px = imageData.data;
12066
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;
12067
12068
var divx = (radiusX + radiusX + 1) | 0;
12069
var divy = (radiusY + radiusY + 1) | 0;
12070
var w = imageData.width | 0;
12071
var h = imageData.height | 0;
12072
12073
var w1 = (w - 1) | 0;
12074
var h1 = (h - 1) | 0;
12075
var rxp1 = (radiusX + 1) | 0;
12076
var ryp1 = (radiusY + 1) | 0;
12077
12078
var ssx = {r:0,b:0,g:0,a:0};
12079
var sx = ssx;
12080
for ( i = 1; i < divx; i++ )
12081
{
12082
sx = sx.n = {r:0,b:0,g:0,a:0};
12083
}
12084
sx.n = ssx;
12085
12086
var ssy = {r:0,b:0,g:0,a:0};
12087
var sy = ssy;
12088
for ( i = 1; i < divy; i++ )
12089
{
12090
sy = sy.n = {r:0,b:0,g:0,a:0};
12091
}
12092
sy.n = ssy;
12093
12094
var si = null;
12095
12096
12097
var mtx = BlurFilter.MUL_TABLE[radiusX] | 0;
12098
var stx = BlurFilter.SHG_TABLE[radiusX] | 0;
12099
var mty = BlurFilter.MUL_TABLE[radiusY] | 0;
12100
var sty = BlurFilter.SHG_TABLE[radiusY] | 0;
12101
12102
while (iterations-- > 0) {
12103
12104
yw = yi = 0;
12105
var ms = mtx;
12106
var ss = stx;
12107
for (y = h; --y > -1;) {
12108
r = rxp1 * (pr = px[(yi) | 0]);
12109
g = rxp1 * (pg = px[(yi + 1) | 0]);
12110
b = rxp1 * (pb = px[(yi + 2) | 0]);
12111
a = rxp1 * (pa = px[(yi + 3) | 0]);
12112
12113
sx = ssx;
12114
12115
for( i = rxp1; --i > -1; )
12116
{
12117
sx.r = pr;
12118
sx.g = pg;
12119
sx.b = pb;
12120
sx.a = pa;
12121
sx = sx.n;
12122
}
12123
12124
for( i = 1; i < rxp1; i++ )
12125
{
12126
p = (yi + ((w1 < i ? w1 : i) << 2)) | 0;
12127
r += ( sx.r = px[p]);
12128
g += ( sx.g = px[p+1]);
12129
b += ( sx.b = px[p+2]);
12130
a += ( sx.a = px[p+3]);
12131
12132
sx = sx.n;
12133
}
12134
12135
si = ssx;
12136
for ( x = 0; x < w; x++ )
12137
{
12138
px[yi++] = (r * ms) >>> ss;
12139
px[yi++] = (g * ms) >>> ss;
12140
px[yi++] = (b * ms) >>> ss;
12141
px[yi++] = (a * ms) >>> ss;
12142
12143
p = ((yw + ((p = x + radiusX + 1) < w1 ? p : w1)) << 2);
12144
12145
r -= si.r - ( si.r = px[p]);
12146
g -= si.g - ( si.g = px[p+1]);
12147
b -= si.b - ( si.b = px[p+2]);
12148
a -= si.a - ( si.a = px[p+3]);
12149
12150
si = si.n;
12151
12152
}
12153
yw += w;
12154
}
12155
12156
ms = mty;
12157
ss = sty;
12158
for (x = 0; x < w; x++) {
12159
yi = (x << 2) | 0;
12160
12161
r = (ryp1 * (pr = px[yi])) | 0;
12162
g = (ryp1 * (pg = px[(yi + 1) | 0])) | 0;
12163
b = (ryp1 * (pb = px[(yi + 2) | 0])) | 0;
12164
a = (ryp1 * (pa = px[(yi + 3) | 0])) | 0;
12165
12166
sy = ssy;
12167
for( i = 0; i < ryp1; i++ )
12168
{
12169
sy.r = pr;
12170
sy.g = pg;
12171
sy.b = pb;
12172
sy.a = pa;
12173
sy = sy.n;
12174
}
12175
12176
yp = w;
12177
12178
for( i = 1; i <= radiusY; i++ )
12179
{
12180
yi = ( yp + x ) << 2;
12181
12182
r += ( sy.r = px[yi]);
12183
g += ( sy.g = px[yi+1]);
12184
b += ( sy.b = px[yi+2]);
12185
a += ( sy.a = px[yi+3]);
12186
12187
sy = sy.n;
12188
12189
if( i < h1 )
12190
{
12191
yp += w;
12192
}
12193
}
12194
12195
yi = x;
12196
si = ssy;
12197
if ( iterations > 0 )
12198
{
12199
for ( y = 0; y < h; y++ )
12200
{
12201
p = yi << 2;
12202
px[p+3] = pa =(a * ms) >>> ss;
12203
if ( pa > 0 )
12204
{
12205
px[p] = ((r * ms) >>> ss );
12206
px[p+1] = ((g * ms) >>> ss );
12207
px[p+2] = ((b * ms) >>> ss );
12208
} else {
12209
px[p] = px[p+1] = px[p+2] = 0
12210
}
12211
12212
p = ( x + (( ( p = y + ryp1) < h1 ? p : h1 ) * w )) << 2;
12213
12214
r -= si.r - ( si.r = px[p]);
12215
g -= si.g - ( si.g = px[p+1]);
12216
b -= si.b - ( si.b = px[p+2]);
12217
a -= si.a - ( si.a = px[p+3]);
12218
12219
si = si.n;
12220
12221
yi += w;
12222
}
12223
} else {
12224
for ( y = 0; y < h; y++ )
12225
{
12226
p = yi << 2;
12227
px[p+3] = pa =(a * ms) >>> ss;
12228
if ( pa > 0 )
12229
{
12230
pa = 255 / pa;
12231
px[p] = ((r * ms) >>> ss ) * pa;
12232
px[p+1] = ((g * ms) >>> ss ) * pa;
12233
px[p+2] = ((b * ms) >>> ss ) * pa;
12234
} else {
12235
px[p] = px[p+1] = px[p+2] = 0
12236
}
12237
12238
p = ( x + (( ( p = y + ryp1) < h1 ? p : h1 ) * w )) << 2;
12239
12240
r -= si.r - ( si.r = px[p]);
12241
g -= si.g - ( si.g = px[p+1]);
12242
b -= si.b - ( si.b = px[p+2]);
12243
a -= si.a - ( si.a = px[p+3]);
12244
12245
si = si.n;
12246
12247
yi += w;
12248
}
12249
}
12250
}
12251
12252
}
12253
return true;
12254
};
12255
12256
createjs.BlurFilter = createjs.promote(BlurFilter, "Filter");
12257
}());
12258
12259
//##############################################################################
12260
// AlphaMapFilter.js
12261
//##############################################################################
12262
12263
this.createjs = this.createjs || {};
12264
12265
(function () {
12266
"use strict";
12267
12268
12269
// constructor:
12270
/**
12271
* Applies a greyscale alpha map image (or canvas) to the target, such that the alpha channel of the result will
12272
* be copied from the red channel of the map, and the RGB channels will be copied from the target.
12273
*
12274
* Generally, it is recommended that you use {{#crossLink "AlphaMaskFilter"}}{{/crossLink}}, because it has much
12275
* better performance.
12276
*
12277
* <h4>Example</h4>
12278
* This example draws a red->blue box, caches it, and then uses the cache canvas as an alpha map on a 100x100 image.
12279
*
12280
* var box = new createjs.Shape();
12281
* box.graphics.beginLinearGradientFill(["#ff0000", "#0000ff"], [0, 1], 0, 0, 0, 100)
12282
* box.graphics.drawRect(0, 0, 100, 100);
12283
* box.cache(0, 0, 100, 100);
12284
*
12285
* var bmp = new createjs.Bitmap("path/to/image.jpg");
12286
* bmp.filters = [
12287
* new createjs.AlphaMapFilter(box.cacheCanvas)
12288
* ];
12289
* bmp.cache(0, 0, 100, 100);
12290
* stage.addChild(bmp);
12291
*
12292
* See {{#crossLink "Filter"}}{{/crossLink}} for more information on applying filters.
12293
* @class AlphaMapFilter
12294
* @extends Filter
12295
* @constructor
12296
* @param {HTMLImageElement|HTMLCanvasElement} alphaMap The greyscale image (or canvas) to use as the alpha value for the
12297
* result. This should be exactly the same dimensions as the target.
12298
**/
12299
function AlphaMapFilter(alphaMap) {
12300
12301
12302
// public properties:
12303
/**
12304
* The greyscale image (or canvas) to use as the alpha value for the result. This should be exactly the same
12305
* dimensions as the target.
12306
* @property alphaMap
12307
* @type HTMLImageElement|HTMLCanvasElement
12308
**/
12309
this.alphaMap = alphaMap;
12310
12311
12312
// private properties:
12313
/**
12314
* @property _alphaMap
12315
* @protected
12316
* @type HTMLImageElement|HTMLCanvasElement
12317
**/
12318
this._alphaMap = null;
12319
12320
/**
12321
* @property _mapData
12322
* @protected
12323
* @type Uint8ClampedArray
12324
**/
12325
this._mapData = null;
12326
}
12327
var p = createjs.extend(AlphaMapFilter, createjs.Filter);
12328
12329
// TODO: deprecated
12330
// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
12331
12332
12333
// public methods:
12334
/** docced in super class **/
12335
p.clone = function () {
12336
var o = new AlphaMapFilter(this.alphaMap);
12337
o._alphaMap = this._alphaMap;
12338
o._mapData = this._mapData;
12339
return o;
12340
};
12341
12342
/** docced in super class **/
12343
p.toString = function () {
12344
return "[AlphaMapFilter]";
12345
};
12346
12347
12348
// private methods:
12349
/** docced in super class **/
12350
p._applyFilter = function (imageData) {
12351
if (!this.alphaMap) { return true; }
12352
if (!this._prepAlphaMap()) { return false; }
12353
12354
// TODO: update to support scenarios where the target has different dimensions.
12355
var data = imageData.data;
12356
var map = this._mapData;
12357
for(var i=0, l=data.length; i<l; i += 4) { data[i + 3] = map[i] || 0; }
12358
12359
return true;
12360
};
12361
12362
/**
12363
* @method _prepAlphaMap
12364
* @protected
12365
**/
12366
p._prepAlphaMap = function () {
12367
if (!this.alphaMap) { return false; }
12368
if (this.alphaMap == this._alphaMap && this._mapData) { return true; }
12369
12370
this._mapData = null;
12371
var map = this._alphaMap = this.alphaMap;
12372
var canvas = map;
12373
var ctx;
12374
if (map instanceof HTMLCanvasElement) {
12375
ctx = canvas.getContext("2d");
12376
} else {
12377
canvas = createjs.createCanvas ? createjs.createCanvas() : document.createElement("canvas");
12378
canvas.width = map.width;
12379
canvas.height = map.height;
12380
ctx = canvas.getContext("2d");
12381
ctx.drawImage(map, 0, 0);
12382
}
12383
12384
try {
12385
var imgData = ctx.getImageData(0, 0, map.width, map.height);
12386
} catch (e) {
12387
//if (!this.suppressCrossDomainErrors) throw new Error("unable to access local image data: " + e);
12388
return false;
12389
}
12390
12391
this._mapData = imgData.data;
12392
return true;
12393
};
12394
12395
12396
createjs.AlphaMapFilter = createjs.promote(AlphaMapFilter, "Filter");
12397
}());
12398
12399
//##############################################################################
12400
// AlphaMaskFilter.js
12401
//##############################################################################
12402
12403
this.createjs = this.createjs || {};
12404
12405
(function () {
12406
"use strict";
12407
12408
12409
// constructor:
12410
/**
12411
* Applies the alpha from the mask image (or canvas) to the target, such that the alpha channel of the result will
12412
* be derived from the mask, and the RGB channels will be copied from the target. This can be used, for example, to
12413
* apply an alpha mask to a display object. This can also be used to combine a JPG compressed RGB image with a PNG32
12414
* alpha mask, which can result in a much smaller file size than a single PNG32 containing ARGB.
12415
*
12416
* <b>IMPORTANT NOTE: This filter currently does not support the targetCtx, or targetX/Y parameters correctly.</b>
12417
*
12418
* <h4>Example</h4>
12419
* This example draws a gradient box, then caches it and uses the "cacheCanvas" as the alpha mask on a 100x100 image.
12420
*
12421
* var box = new createjs.Shape();
12422
* box.graphics.beginLinearGradientFill(["#000000", "rgba(0, 0, 0, 0)"], [0, 1], 0, 0, 100, 100)
12423
* box.graphics.drawRect(0, 0, 100, 100);
12424
* box.cache(0, 0, 100, 100);
12425
*
12426
* var bmp = new createjs.Bitmap("path/to/image.jpg");
12427
* bmp.filters = [
12428
* new createjs.AlphaMaskFilter(box.cacheCanvas)
12429
* ];
12430
* bmp.cache(0, 0, 100, 100);
12431
*
12432
* See {{#crossLink "Filter"}}{{/crossLink}} for more information on applying filters.
12433
* @class AlphaMaskFilter
12434
* @extends Filter
12435
* @constructor
12436
* @param {HTMLImageElement|HTMLCanvasElement} mask
12437
**/
12438
function AlphaMaskFilter(mask) {
12439
12440
12441
// public properties:
12442
/**
12443
* The image (or canvas) to use as the mask.
12444
* @property mask
12445
* @type HTMLImageElement|HTMLCanvasElement
12446
**/
12447
this.mask = mask;
12448
}
12449
var p = createjs.extend(AlphaMaskFilter, createjs.Filter);
12450
12451
// TODO: deprecated
12452
// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
12453
12454
12455
// public methods:
12456
/**
12457
* Applies the filter to the specified context.
12458
*
12459
* <strong>IMPORTANT NOTE: This filter currently does not support the targetCtx, or targetX/Y parameters
12460
* correctly.</strong>
12461
* @method applyFilter
12462
* @param {CanvasRenderingContext2D} ctx The 2D context to use as the source.
12463
* @param {Number} x The x position to use for the source rect.
12464
* @param {Number} y The y position to use for the source rect.
12465
* @param {Number} width The width to use for the source rect.
12466
* @param {Number} height The height to use for the source rect.
12467
* @param {CanvasRenderingContext2D} [targetCtx] NOT SUPPORTED IN THIS FILTER. The 2D context to draw the result to. Defaults to the context passed to ctx.
12468
* @param {Number} [targetX] NOT SUPPORTED IN THIS FILTER. The x position to draw the result to. Defaults to the value passed to x.
12469
* @param {Number} [targetY] NOT SUPPORTED IN THIS FILTER. The y position to draw the result to. Defaults to the value passed to y.
12470
* @return {Boolean} If the filter was applied successfully.
12471
**/
12472
p.applyFilter = function (ctx, x, y, width, height, targetCtx, targetX, targetY) {
12473
if (!this.mask) { return true; }
12474
targetCtx = targetCtx || ctx;
12475
if (targetX == null) { targetX = x; }
12476
if (targetY == null) { targetY = y; }
12477
12478
targetCtx.save();
12479
if (ctx != targetCtx) {
12480
// TODO: support targetCtx and targetX/Y
12481
// clearRect, then draw the ctx in?
12482
return false;
12483
}
12484
12485
targetCtx.globalCompositeOperation = "destination-in";
12486
targetCtx.drawImage(this.mask, targetX, targetY);
12487
targetCtx.restore();
12488
return true;
12489
};
12490
12491
/** docced in super class **/
12492
p.clone = function () {
12493
return new AlphaMaskFilter(this.mask);
12494
};
12495
12496
/** docced in super class **/
12497
p.toString = function () {
12498
return "[AlphaMaskFilter]";
12499
};
12500
12501
12502
createjs.AlphaMaskFilter = createjs.promote(AlphaMaskFilter, "Filter");
12503
}());
12504
12505
//##############################################################################
12506
// ColorFilter.js
12507
//##############################################################################
12508
12509
this.createjs = this.createjs||{};
12510
12511
(function() {
12512
"use strict";
12513
12514
12515
// constructor:
12516
/**
12517
* Applies a color transform to DisplayObjects.
12518
*
12519
* <h4>Example</h4>
12520
* This example draws a red circle, and then transforms it to Blue. This is accomplished by multiplying all the channels
12521
* to 0 (except alpha, which is set to 1), and then adding 255 to the blue channel.
12522
*
12523
* var shape = new createjs.Shape().set({x:100,y:100});
12524
* shape.graphics.beginFill("#ff0000").drawCircle(0,0,50);
12525
*
12526
* shape.filters = [
12527
* new createjs.ColorFilter(0,0,0,1, 0,0,255,0)
12528
* ];
12529
* shape.cache(-50, -50, 100, 100);
12530
*
12531
* See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters.
12532
* @class ColorFilter
12533
* @param {Number} [redMultiplier=1] The amount to multiply against the red channel. This is a range between 0 and 1.
12534
* @param {Number} [greenMultiplier=1] The amount to multiply against the green channel. This is a range between 0 and 1.
12535
* @param {Number} [blueMultiplier=1] The amount to multiply against the blue channel. This is a range between 0 and 1.
12536
* @param {Number} [alphaMultiplier=1] The amount to multiply against the alpha channel. This is a range between 0 and 1.
12537
* @param {Number} [redOffset=0] The amount to add to the red channel after it has been multiplied. This is a range
12538
* between -255 and 255.
12539
* @param {Number} [greenOffset=0] The amount to add to the green channel after it has been multiplied. This is a range
12540
* between -255 and 255.
12541
* @param {Number} [blueOffset=0] The amount to add to the blue channel after it has been multiplied. This is a range
12542
* between -255 and 255.
12543
* @param {Number} [alphaOffset=0] The amount to add to the alpha channel after it has been multiplied. This is a range
12544
* between -255 and 255.
12545
* @constructor
12546
* @extends Filter
12547
**/
12548
function ColorFilter(redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier, redOffset, greenOffset, blueOffset, alphaOffset) {
12549
12550
12551
// public properties:
12552
/**
12553
* Red channel multiplier.
12554
* @property redMultiplier
12555
* @type Number
12556
**/
12557
this.redMultiplier = redMultiplier != null ? redMultiplier : 1;
12558
12559
/**
12560
* Green channel multiplier.
12561
* @property greenMultiplier
12562
* @type Number
12563
**/
12564
this.greenMultiplier = greenMultiplier != null ? greenMultiplier : 1;
12565
12566
/**
12567
* Blue channel multiplier.
12568
* @property blueMultiplier
12569
* @type Number
12570
**/
12571
this.blueMultiplier = blueMultiplier != null ? blueMultiplier : 1;
12572
12573
/**
12574
* Alpha channel multiplier.
12575
* @property alphaMultiplier
12576
* @type Number
12577
**/
12578
this.alphaMultiplier = alphaMultiplier != null ? alphaMultiplier : 1;
12579
12580
/**
12581
* Red channel offset (added to value).
12582
* @property redOffset
12583
* @type Number
12584
**/
12585
this.redOffset = redOffset || 0;
12586
12587
/**
12588
* Green channel offset (added to value).
12589
* @property greenOffset
12590
* @type Number
12591
**/
12592
this.greenOffset = greenOffset || 0;
12593
12594
/**
12595
* Blue channel offset (added to value).
12596
* @property blueOffset
12597
* @type Number
12598
**/
12599
this.blueOffset = blueOffset || 0;
12600
12601
/**
12602
* Alpha channel offset (added to value).
12603
* @property alphaOffset
12604
* @type Number
12605
**/
12606
this.alphaOffset = alphaOffset || 0;
12607
}
12608
var p = createjs.extend(ColorFilter, createjs.Filter);
12609
12610
// TODO: deprecated
12611
// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
12612
12613
12614
// public methods:
12615
/** docced in super class **/
12616
p.toString = function() {
12617
return "[ColorFilter]";
12618
};
12619
12620
/** docced in super class **/
12621
p.clone = function() {
12622
return new ColorFilter(this.redMultiplier, this.greenMultiplier, this.blueMultiplier, this.alphaMultiplier, this.redOffset, this.greenOffset, this.blueOffset, this.alphaOffset);
12623
};
12624
12625
12626
// private methods:
12627
/** docced in super class **/
12628
p._applyFilter = function(imageData) {
12629
var data = imageData.data;
12630
var l = data.length;
12631
for (var i=0; i<l; i+=4) {
12632
data[i] = data[i]*this.redMultiplier+this.redOffset;
12633
data[i+1] = data[i+1]*this.greenMultiplier+this.greenOffset;
12634
data[i+2] = data[i+2]*this.blueMultiplier+this.blueOffset;
12635
data[i+3] = data[i+3]*this.alphaMultiplier+this.alphaOffset;
12636
}
12637
return true;
12638
};
12639
12640
12641
createjs.ColorFilter = createjs.promote(ColorFilter, "Filter");
12642
}());
12643
12644
//##############################################################################
12645
// ColorMatrix.js
12646
//##############################################################################
12647
12648
this.createjs = this.createjs||{};
12649
12650
(function() {
12651
"use strict";
12652
12653
12654
// constructor:
12655
/**
12656
* Provides helper functions for assembling a matrix for use with the {{#crossLink "ColorMatrixFilter"}}{{/crossLink}}.
12657
* Most methods return the instance to facilitate chained calls.
12658
*
12659
* <h4>Example</h4>
12660
*
12661
* myColorMatrix.adjustHue(20).adjustBrightness(50);
12662
*
12663
* See {{#crossLink "Filter"}}{{/crossLink}} for an example of how to apply filters, or {{#crossLink "ColorMatrixFilter"}}{{/crossLink}}
12664
* for an example of how to use ColorMatrix to change a DisplayObject's color.
12665
* @class ColorMatrix
12666
* @param {Number} brightness
12667
* @param {Number} contrast
12668
* @param {Number} saturation
12669
* @param {Number} hue
12670
* @constructor
12671
**/
12672
function ColorMatrix(brightness, contrast, saturation, hue) {
12673
this.setColor(brightness, contrast, saturation, hue);
12674
}
12675
var p = ColorMatrix.prototype;
12676
12677
/**
12678
* <strong>REMOVED</strong>. Removed in favor of using `MySuperClass_constructor`.
12679
* See {{#crossLink "Utility Methods/extend"}}{{/crossLink}} and {{#crossLink "Utility Methods/promote"}}{{/crossLink}}
12680
* for details.
12681
*
12682
* There is an inheritance tutorial distributed with EaselJS in /tutorials/Inheritance.
12683
*
12684
* @method initialize
12685
* @protected
12686
* @deprecated
12687
*/
12688
// p.initialize = function() {}; // searchable for devs wondering where it is.
12689
12690
12691
// constants:
12692
/**
12693
* Array of delta values for contrast calculations.
12694
* @property DELTA_INDEX
12695
* @type Array
12696
* @protected
12697
* @static
12698
**/
12699
ColorMatrix.DELTA_INDEX = [
12700
0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11,
12701
0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24,
12702
0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42,
12703
0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68,
12704
0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98,
12705
1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54,
12706
1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25,
12707
2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8,
12708
4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0,
12709
7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8,
12710
10.0
12711
];
12712
12713
/**
12714
* Identity matrix values.
12715
* @property IDENTITY_MATRIX
12716
* @type Array
12717
* @protected
12718
* @static
12719
**/
12720
ColorMatrix.IDENTITY_MATRIX = [
12721
1,0,0,0,0,
12722
0,1,0,0,0,
12723
0,0,1,0,0,
12724
0,0,0,1,0,
12725
0,0,0,0,1
12726
];
12727
12728
/**
12729
* The constant length of a color matrix.
12730
* @property LENGTH
12731
* @type Number
12732
* @protected
12733
* @static
12734
**/
12735
ColorMatrix.LENGTH = ColorMatrix.IDENTITY_MATRIX.length;
12736
12737
12738
// public methods:
12739
/**
12740
* Resets the instance with the specified values.
12741
* @method setColor
12742
* @param {Number} brightness
12743
* @param {Number} contrast
12744
* @param {Number} saturation
12745
* @param {Number} hue
12746
* @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
12747
* @chainable
12748
*/
12749
p.setColor = function(brightness,contrast,saturation,hue) {
12750
return this.reset().adjustColor(brightness,contrast,saturation,hue);
12751
};
12752
12753
/**
12754
* Resets the matrix to identity values.
12755
* @method reset
12756
* @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
12757
* @chainable
12758
*/
12759
p.reset = function() {
12760
return this.copy(ColorMatrix.IDENTITY_MATRIX);
12761
};
12762
12763
/**
12764
* Shortcut method to adjust brightness, contrast, saturation and hue.
12765
* Equivalent to calling adjustHue(hue), adjustContrast(contrast),
12766
* adjustBrightness(brightness), adjustSaturation(saturation), in that order.
12767
* @method adjustColor
12768
* @param {Number} brightness
12769
* @param {Number} contrast
12770
* @param {Number} saturation
12771
* @param {Number} hue
12772
* @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
12773
* @chainable
12774
**/
12775
p.adjustColor = function(brightness,contrast,saturation,hue) {
12776
this.adjustHue(hue);
12777
this.adjustContrast(contrast);
12778
this.adjustBrightness(brightness);
12779
return this.adjustSaturation(saturation);
12780
};
12781
12782
/**
12783
* Adjusts the brightness of pixel color by adding the specified value to the red, green and blue channels.
12784
* Positive values will make the image brighter, negative values will make it darker.
12785
* @method adjustBrightness
12786
* @param {Number} value A value between -255 & 255 that will be added to the RGB channels.
12787
* @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
12788
* @chainable
12789
**/
12790
p.adjustBrightness = function(value) {
12791
if (value == 0 || isNaN(value)) { return this; }
12792
value = this._cleanValue(value,255);
12793
this._multiplyMatrix([
12794
1,0,0,0,value,
12795
0,1,0,0,value,
12796
0,0,1,0,value,
12797
0,0,0,1,0,
12798
0,0,0,0,1
12799
]);
12800
return this;
12801
};
12802
12803
/**
12804
* Adjusts the contrast of pixel color.
12805
* Positive values will increase contrast, negative values will decrease contrast.
12806
* @method adjustContrast
12807
* @param {Number} value A value between -100 & 100.
12808
* @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
12809
* @chainable
12810
**/
12811
p.adjustContrast = function(value) {
12812
if (value == 0 || isNaN(value)) { return this; }
12813
value = this._cleanValue(value,100);
12814
var x;
12815
if (value<0) {
12816
x = 127+value/100*127;
12817
} else {
12818
x = value%1;
12819
if (x == 0) {
12820
x = ColorMatrix.DELTA_INDEX[value];
12821
} else {
12822
x = ColorMatrix.DELTA_INDEX[(value<<0)]*(1-x)+ColorMatrix.DELTA_INDEX[(value<<0)+1]*x; // use linear interpolation for more granularity.
12823
}
12824
x = x*127+127;
12825
}
12826
this._multiplyMatrix([
12827
x/127,0,0,0,0.5*(127-x),
12828
0,x/127,0,0,0.5*(127-x),
12829
0,0,x/127,0,0.5*(127-x),
12830
0,0,0,1,0,
12831
0,0,0,0,1
12832
]);
12833
return this;
12834
};
12835
12836
/**
12837
* Adjusts the color saturation of the pixel.
12838
* Positive values will increase saturation, negative values will decrease saturation (trend towards greyscale).
12839
* @method adjustSaturation
12840
* @param {Number} value A value between -100 & 100.
12841
* @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
12842
* @chainable
12843
**/
12844
p.adjustSaturation = function(value) {
12845
if (value == 0 || isNaN(value)) { return this; }
12846
value = this._cleanValue(value,100);
12847
var x = 1+((value > 0) ? 3*value/100 : value/100);
12848
var lumR = 0.3086;
12849
var lumG = 0.6094;
12850
var lumB = 0.0820;
12851
this._multiplyMatrix([
12852
lumR*(1-x)+x,lumG*(1-x),lumB*(1-x),0,0,
12853
lumR*(1-x),lumG*(1-x)+x,lumB*(1-x),0,0,
12854
lumR*(1-x),lumG*(1-x),lumB*(1-x)+x,0,0,
12855
0,0,0,1,0,
12856
0,0,0,0,1
12857
]);
12858
return this;
12859
};
12860
12861
12862
/**
12863
* Adjusts the hue of the pixel color.
12864
* @method adjustHue
12865
* @param {Number} value A value between -180 & 180.
12866
* @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
12867
* @chainable
12868
**/
12869
p.adjustHue = function(value) {
12870
if (value == 0 || isNaN(value)) { return this; }
12871
value = this._cleanValue(value,180)/180*Math.PI;
12872
var cosVal = Math.cos(value);
12873
var sinVal = Math.sin(value);
12874
var lumR = 0.213;
12875
var lumG = 0.715;
12876
var lumB = 0.072;
12877
this._multiplyMatrix([
12878
lumR+cosVal*(1-lumR)+sinVal*(-lumR),lumG+cosVal*(-lumG)+sinVal*(-lumG),lumB+cosVal*(-lumB)+sinVal*(1-lumB),0,0,
12879
lumR+cosVal*(-lumR)+sinVal*(0.143),lumG+cosVal*(1-lumG)+sinVal*(0.140),lumB+cosVal*(-lumB)+sinVal*(-0.283),0,0,
12880
lumR+cosVal*(-lumR)+sinVal*(-(1-lumR)),lumG+cosVal*(-lumG)+sinVal*(lumG),lumB+cosVal*(1-lumB)+sinVal*(lumB),0,0,
12881
0,0,0,1,0,
12882
0,0,0,0,1
12883
]);
12884
return this;
12885
};
12886
12887
/**
12888
* Concatenates (multiplies) the specified matrix with this one.
12889
* @method concat
12890
* @param {Array} matrix An array or ColorMatrix instance.
12891
* @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
12892
* @chainable
12893
**/
12894
p.concat = function(matrix) {
12895
matrix = this._fixMatrix(matrix);
12896
if (matrix.length != ColorMatrix.LENGTH) { return this; }
12897
this._multiplyMatrix(matrix);
12898
return this;
12899
};
12900
12901
/**
12902
* Returns a clone of this ColorMatrix.
12903
* @method clone
12904
* @return {ColorMatrix} A clone of this ColorMatrix.
12905
**/
12906
p.clone = function() {
12907
return (new ColorMatrix()).copy(this);
12908
};
12909
12910
/**
12911
* Return a length 25 (5x5) array instance containing this matrix's values.
12912
* @method toArray
12913
* @return {Array} An array holding this matrix's values.
12914
**/
12915
p.toArray = function() {
12916
var arr = [];
12917
for (var i= 0, l=ColorMatrix.LENGTH; i<l; i++) {
12918
arr[i] = this[i];
12919
}
12920
return arr;
12921
};
12922
12923
/**
12924
* Copy the specified matrix's values to this matrix.
12925
* @method copy
12926
* @param {Array} matrix An array or ColorMatrix instance.
12927
* @return {ColorMatrix} The ColorMatrix instance the method is called on (useful for chaining calls.)
12928
* @chainable
12929
**/
12930
p.copy = function(matrix) {
12931
var l = ColorMatrix.LENGTH;
12932
for (var i=0;i<l;i++) {
12933
this[i] = matrix[i];
12934
}
12935
return this;
12936
};
12937
12938
/**
12939
* Returns a string representation of this object.
12940
* @method toString
12941
* @return {String} a string representation of the instance.
12942
**/
12943
p.toString = function() {
12944
return "[ColorMatrix]";
12945
};
12946
12947
12948
// private methods:
12949
/**
12950
* @method _multiplyMatrix
12951
* @param {Array} matrix
12952
* @protected
12953
**/
12954
p._multiplyMatrix = function(matrix) {
12955
var i, j, k, col = [];
12956
12957
for (i=0;i<5;i++) {
12958
for (j=0;j<5;j++) {
12959
col[j] = this[j+i*5];
12960
}
12961
for (j=0;j<5;j++) {
12962
var val=0;
12963
for (k=0;k<5;k++) {
12964
val += matrix[j+k*5]*col[k];
12965
}
12966
this[j+i*5] = val;
12967
}
12968
}
12969
};
12970
12971
/**
12972
* Make sure values are within the specified range, hue has a limit of 180, brightness is 255, others are 100.
12973
* @method _cleanValue
12974
* @param {Number} value The raw number
12975
* @param {Number} limit The maximum that the number can be. The minimum is the limit * -1.
12976
* @protected
12977
**/
12978
p._cleanValue = function(value, limit) {
12979
return Math.min(limit,Math.max(-limit,value));
12980
};
12981
12982
/**
12983
* Makes sure matrixes are 5x5 (25 long).
12984
* @method _fixMatrix
12985
* @param {Array} matrix
12986
* @protected
12987
**/
12988
p._fixMatrix = function(matrix) {
12989
if (matrix instanceof ColorMatrix) { matrix = matrix.toArray(); }
12990
if (matrix.length < ColorMatrix.LENGTH) {
12991
matrix = matrix.slice(0,matrix.length).concat(ColorMatrix.IDENTITY_MATRIX.slice(matrix.length,ColorMatrix.LENGTH));
12992
} else if (matrix.length > ColorMatrix.LENGTH) {
12993
matrix = matrix.slice(0,ColorMatrix.LENGTH);
12994
}
12995
return matrix;
12996
};
12997
12998
12999
createjs.ColorMatrix = ColorMatrix;
13000
}());
13001
13002
//##############################################################################
13003
// ColorMatrixFilter.js
13004
//##############################################################################
13005
13006
this.createjs = this.createjs||{};
13007
13008
(function() {
13009
"use strict";
13010
13011
13012
// constructor:
13013
/**
13014
* Allows you to carry out complex color operations such as modifying saturation, brightness, or inverting. See the
13015
* {{#crossLink "ColorMatrix"}}{{/crossLink}} for more information on changing colors. For an easier color transform,
13016
* consider the {{#crossLink "ColorFilter"}}{{/crossLink}}.
13017
*
13018
* <h4>Example</h4>
13019
* This example creates a red circle, inverts its hue, and then saturates it to brighten it up.
13020
*
13021
* var shape = new createjs.Shape().set({x:100,y:100});
13022
* shape.graphics.beginFill("#ff0000").drawCircle(0,0,50);
13023
*
13024
* var matrix = new createjs.ColorMatrix().adjustHue(180).adjustSaturation(100);
13025
* shape.filters = [
13026
* new createjs.ColorMatrixFilter(matrix)
13027
* ];
13028
*
13029
* shape.cache(-50, -50, 100, 100);
13030
*
13031
* See {{#crossLink "Filter"}}{{/crossLink}} for an more information on applying filters.
13032
* @class ColorMatrixFilter
13033
* @constructor
13034
* @extends Filter
13035
* @param {Array | ColorMatrix} matrix A 4x5 matrix describing the color operation to perform. See also the {{#crossLink "ColorMatrix"}}{{/crossLink}}
13036
* class.
13037
**/
13038
function ColorMatrixFilter(matrix) {
13039
13040
13041
// public properties:
13042
/**
13043
* A 4x5 matrix describing the color operation to perform. See also the {{#crossLink "ColorMatrix"}}{{/crossLink}}
13044
* @property matrix
13045
* @type Array | ColorMatrix
13046
**/
13047
this.matrix = matrix;
13048
}
13049
var p = createjs.extend(ColorMatrixFilter, createjs.Filter);
13050
13051
// TODO: deprecated
13052
// p.initialize = function() {}; // searchable for devs wondering where it is. REMOVED. See docs for details.
13053
13054
13055
// public methods:
13056
/** docced in super class **/
13057
p.toString = function() {
13058
return "[ColorMatrixFilter]";
13059
};
13060
13061
/** docced in super class **/
13062
p.clone = function() {
13063
return new ColorMatrixFilter(this.matrix);
13064
};
13065
13066
// private methods:
13067
/** docced in super class **/
13068
p._applyFilter = function(imageData) {
13069
var data = imageData.data;
13070
var l = data.length;
13071
var r,g,b,a;
13072
var mtx = this.matrix;
13073
var m0 = mtx[0], m1 = mtx[1], m2 = mtx[2], m3 = mtx[3], m4 = mtx[4];
13074
var m5 = mtx[5], m6 = mtx[6], m7 = mtx[7], m8 = mtx[8], m9 = mtx[9];
13075
var m10 = mtx[10], m11 = mtx[11], m12 = mtx[12], m13 = mtx[13], m14 = mtx[14];
13076
var m15 = mtx[15], m16 = mtx[16], m17 = mtx[17], m18 = mtx[18], m19 = mtx[19];
13077
13078
for (var i=0; i<l; i+=4) {
13079
r = data[i];
13080
g = data[i+1];
13081
b = data[i+2];
13082
a = data[i+3];
13083
data[i] = r*m0+g*m1+b*m2+a*m3+m4; // red
13084
data[i+1] = r*m5+g*m6+b*m7+a*m8+m9; // green
13085
data[i+2] = r*m10+g*m11+b*m12+a*m13+m14; // blue
13086
data[i+3] = r*m15+g*m16+b*m17+a*m18+m19; // alpha
13087
}
13088
return true;
13089
};
13090
13091
13092
createjs.ColorMatrixFilter = createjs.promote(ColorMatrixFilter, "Filter");
13093
}());
13094
13095
//##############################################################################
13096
// Touch.js
13097
//##############################################################################
13098
13099
this.createjs = this.createjs||{};
13100
13101
(function() {
13102
"use strict";
13103
13104
13105
// constructor:
13106
/**
13107
* Global utility for working with multi-touch enabled devices in EaselJS. Currently supports W3C Touch API (iOS and
13108
* modern Android browser) and the Pointer API (IE), including ms-prefixed events in IE10, and unprefixed in IE11.
13109
*
13110
* Ensure that you {{#crossLink "Touch/disable"}}{{/crossLink}} touch when cleaning up your application. You do not have
13111
* to check if touch is supported to enable it, as it will fail gracefully if it is not supported.
13112
*
13113
* <h4>Example</h4>
13114
*
13115
* var stage = new createjs.Stage("canvasId");
13116
* createjs.Touch.enable(stage);
13117
*
13118
* <strong>Note:</strong> It is important to disable Touch on a stage that you are no longer using:
13119
*
13120
* createjs.Touch.disable(stage);
13121
*
13122
* @class Touch
13123
* @static
13124
**/
13125
function Touch() {
13126
throw "Touch cannot be instantiated";
13127
}
13128
13129
13130
// public static methods:
13131
/**
13132
* Returns `true` if touch is supported in the current browser.
13133
* @method isSupported
13134
* @return {Boolean} Indicates whether touch is supported in the current browser.
13135
* @static
13136
**/
13137
Touch.isSupported = function() {
13138
return !!(('ontouchstart' in window) // iOS & Android
13139
|| (window.navigator['msPointerEnabled'] && window.navigator['msMaxTouchPoints'] > 0) // IE10
13140
|| (window.navigator['pointerEnabled'] && window.navigator['maxTouchPoints'] > 0)); // IE11+
13141
};
13142
13143
/**
13144
* Enables touch interaction for the specified EaselJS {{#crossLink "Stage"}}{{/crossLink}}. Currently supports iOS
13145
* (and compatible browsers, such as modern Android browsers), and IE10/11. Supports both single touch and
13146
* multi-touch modes. Extends the EaselJS {{#crossLink "MouseEvent"}}{{/crossLink}} model, but without support for
13147
* double click or over/out events. See the MouseEvent {{#crossLink "MouseEvent/pointerId:property"}}{{/crossLink}}
13148
* for more information.
13149
* @method enable
13150
* @param {Stage} stage The {{#crossLink "Stage"}}{{/crossLink}} to enable touch on.
13151
* @param {Boolean} [singleTouch=false] If `true`, only a single touch will be active at a time.
13152
* @param {Boolean} [allowDefault=false] If `true`, then default gesture actions (ex. scrolling, zooming) will be
13153
* allowed when the user is interacting with the target canvas.
13154
* @return {Boolean} Returns `true` if touch was successfully enabled on the target stage.
13155
* @static
13156
**/
13157
Touch.enable = function(stage, singleTouch, allowDefault) {
13158
if (!stage || !stage.canvas || !Touch.isSupported()) { return false; }
13159
if (stage.__touch) { return true; }
13160
13161
// inject required properties on stage:
13162
stage.__touch = {pointers:{}, multitouch:!singleTouch, preventDefault:!allowDefault, count:0};
13163
13164
// note that in the future we may need to disable the standard mouse event model before adding
13165
// these to prevent duplicate calls. It doesn't seem to be an issue with iOS devices though.
13166
if ('ontouchstart' in window) { Touch._IOS_enable(stage); }
13167
else if (window.navigator['msPointerEnabled'] || window.navigator["pointerEnabled"]) { Touch._IE_enable(stage); }
13168
return true;
13169
};
13170
13171
/**
13172
* Removes all listeners that were set up when calling `Touch.enable()` on a stage.
13173
* @method disable
13174
* @param {Stage} stage The {{#crossLink "Stage"}}{{/crossLink}} to disable touch on.
13175
* @static
13176
**/
13177
Touch.disable = function(stage) {
13178
if (!stage) { return; }
13179
if ('ontouchstart' in window) { Touch._IOS_disable(stage); }
13180
else if (window.navigator['msPointerEnabled'] || window.navigator["pointerEnabled"]) { Touch._IE_disable(stage); }
13181
13182
delete stage.__touch;
13183
};
13184
13185
13186
// Private static methods:
13187
/**
13188
* @method _IOS_enable
13189
* @protected
13190
* @param {Stage} stage
13191
* @static
13192
**/
13193
Touch._IOS_enable = function(stage) {
13194
var canvas = stage.canvas;
13195
var f = stage.__touch.f = function(e) { Touch._IOS_handleEvent(stage,e); };
13196
canvas.addEventListener("touchstart", f, false);
13197
canvas.addEventListener("touchmove", f, false);
13198
canvas.addEventListener("touchend", f, false);
13199
canvas.addEventListener("touchcancel", f, false);
13200
};
13201
13202
/**
13203
* @method _IOS_disable
13204
* @protected
13205
* @param {Stage} stage
13206
* @static
13207
**/
13208
Touch._IOS_disable = function(stage) {
13209
var canvas = stage.canvas;
13210
if (!canvas) { return; }
13211
var f = stage.__touch.f;
13212
canvas.removeEventListener("touchstart", f, false);
13213
canvas.removeEventListener("touchmove", f, false);
13214
canvas.removeEventListener("touchend", f, false);
13215
canvas.removeEventListener("touchcancel", f, false);
13216
};
13217
13218
/**
13219
* @method _IOS_handleEvent
13220
* @param {Stage} stage
13221
* @param {Object} e The event to handle
13222
* @protected
13223
* @static
13224
**/
13225
Touch._IOS_handleEvent = function(stage, e) {
13226
if (!stage) { return; }
13227
if (stage.__touch.preventDefault) { e.preventDefault&&e.preventDefault(); }
13228
var touches = e.changedTouches;
13229
var type = e.type;
13230
for (var i= 0,l=touches.length; i<l; i++) {
13231
var touch = touches[i];
13232
var id = touch.identifier;
13233
if (touch.target != stage.canvas) { continue; }
13234
13235
if (type == "touchstart") {
13236
this._handleStart(stage, id, e, touch.pageX, touch.pageY);
13237
} else if (type == "touchmove") {
13238
this._handleMove(stage, id, e, touch.pageX, touch.pageY);
13239
} else if (type == "touchend" || type == "touchcancel") {
13240
this._handleEnd(stage, id, e);
13241
}
13242
}
13243
};
13244
13245
/**
13246
* @method _IE_enable
13247
* @protected
13248
* @param {Stage} stage
13249
* @static
13250
**/
13251
Touch._IE_enable = function(stage) {
13252
var canvas = stage.canvas;
13253
var f = stage.__touch.f = function(e) { Touch._IE_handleEvent(stage,e); };
13254
13255
if (window.navigator["pointerEnabled"] === undefined) {
13256
canvas.addEventListener("MSPointerDown", f, false);
13257
window.addEventListener("MSPointerMove", f, false);
13258
window.addEventListener("MSPointerUp", f, false);
13259
window.addEventListener("MSPointerCancel", f, false);
13260
if (stage.__touch.preventDefault) { canvas.style.msTouchAction = "none"; }
13261
} else {
13262
canvas.addEventListener("pointerdown", f, false);
13263
window.addEventListener("pointermove", f, false);
13264
window.addEventListener("pointerup", f, false);
13265
window.addEventListener("pointercancel", f, false);
13266
if (stage.__touch.preventDefault) { canvas.style.touchAction = "none"; }
13267
13268
}
13269
stage.__touch.activeIDs = {};
13270
};
13271
13272
/**
13273
* @method _IE_disable
13274
* @protected
13275
* @param {Stage} stage
13276
* @static
13277
**/
13278
Touch._IE_disable = function(stage) {
13279
var f = stage.__touch.f;
13280
13281
if (window.navigator["pointerEnabled"] === undefined) {
13282
window.removeEventListener("MSPointerMove", f, false);
13283
window.removeEventListener("MSPointerUp", f, false);
13284
window.removeEventListener("MSPointerCancel", f, false);
13285
if (stage.canvas) {
13286
stage.canvas.removeEventListener("MSPointerDown", f, false);
13287
}
13288
} else {
13289
window.removeEventListener("pointermove", f, false);
13290
window.removeEventListener("pointerup", f, false);
13291
window.removeEventListener("pointercancel", f, false);
13292
if (stage.canvas) {
13293
stage.canvas.removeEventListener("pointerdown", f, false);
13294
}
13295
}
13296
};
13297
13298
/**
13299
* @method _IE_handleEvent
13300
* @param {Stage} stage
13301
* @param {Object} e The event to handle.
13302
* @protected
13303
* @static
13304
**/
13305
Touch._IE_handleEvent = function(stage, e) {
13306
if (!stage) { return; }
13307
if (stage.__touch.preventDefault) { e.preventDefault && e.preventDefault(); }
13308
var type = e.type;
13309
var id = e.pointerId;
13310
var ids = stage.__touch.activeIDs;
13311
13312
if (type == "MSPointerDown" || type == "pointerdown") {
13313
if (e.srcElement != stage.canvas) { return; }
13314
ids[id] = true;
13315
this._handleStart(stage, id, e, e.pageX, e.pageY);
13316
} else if (ids[id]) { // it's an id we're watching
13317
if (type == "MSPointerMove" || type == "pointermove") {
13318
this._handleMove(stage, id, e, e.pageX, e.pageY);
13319
} else if (type == "MSPointerUp" || type == "MSPointerCancel"
13320
|| type == "pointerup" || type == "pointercancel") {
13321
delete(ids[id]);
13322
this._handleEnd(stage, id, e);
13323
}
13324
}
13325
};
13326
13327
/**
13328
* @method _handleStart
13329
* @param {Stage} stage
13330
* @param {String|Number} id
13331
* @param {Object} e
13332
* @param {Number} x
13333
* @param {Number} y
13334
* @protected
13335
**/
13336
Touch._handleStart = function(stage, id, e, x, y) {
13337
var props = stage.__touch;
13338
if (!props.multitouch && props.count) { return; }
13339
var ids = props.pointers;
13340
if (ids[id]) { return; }
13341
ids[id] = true;
13342
props.count++;
13343
stage._handlePointerDown(id, e, x, y);
13344
};
13345
13346
/**
13347
* @method _handleMove
13348
* @param {Stage} stage
13349
* @param {String|Number} id
13350
* @param {Object} e
13351
* @param {Number} x
13352
* @param {Number} y
13353
* @protected
13354
**/
13355
Touch._handleMove = function(stage, id, e, x, y) {
13356
if (!stage.__touch.pointers[id]) { return; }
13357
stage._handlePointerMove(id, e, x, y);
13358
};
13359
13360
/**
13361
* @method _handleEnd
13362
* @param {Stage} stage
13363
* @param {String|Number} id
13364
* @param {Object} e
13365
* @protected
13366
**/
13367
Touch._handleEnd = function(stage, id, e) {
13368
// TODO: cancel should be handled differently for proper UI (ex. an up would trigger a click, a cancel would more closely resemble an out).
13369
var props = stage.__touch;
13370
var ids = props.pointers;
13371
if (!ids[id]) { return; }
13372
props.count--;
13373
stage._handlePointerUp(id, e, true);
13374
delete(ids[id]);
13375
};
13376
13377
13378
createjs.Touch = Touch;
13379
}());
13380
13381
//##############################################################################
13382
// version.js
13383
//##############################################################################
13384
13385
this.createjs = this.createjs || {};
13386
13387
(function() {
13388
"use strict";
13389
13390
/**
13391
* Static class holding library specific information such as the version and buildDate of
13392
* the library.
13393
* @class EaselJS
13394
**/
13395
var s = createjs.EaselJS = createjs.EaselJS || {};
13396
13397
/**
13398
* The version string for this release.
13399
* @property version
13400
* @type String
13401
* @static
13402
**/
13403
s.version = /*=version*/"0.8.2"; // injected by build process
13404
13405
/**
13406
* The build date for this release in UTC format.
13407
* @property buildDate
13408
* @type String
13409
* @static
13410
**/
13411
s.buildDate = /*=date*/"Thu, 26 Nov 2015 20:44:34 GMT"; // injected by build process
13412
13413
})();
13414