2014-11-18 18:26:26 -05:00
//##############################################################################
// extend.js
//##############################################################################
this . createjs = this . createjs || { } ;
/ * *
* @ class Utility Methods
* /
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Sets up the prototype chain and constructor property for a new class .
2014-01-03 13:32:13 -05:00
*
2014-11-18 18:26:26 -05:00
* This should be called right after creating the class constructor .
*
* function MySubClass ( ) { }
* createjs . extend ( MySubClass , MySuperClass ) ;
* ClassB . prototype . doSomething = function ( ) { }
2014-01-03 13:32:13 -05:00
*
2014-11-18 18:26:26 -05:00
* var foo = new MySubClass ( ) ;
* console . log ( foo instanceof MySuperClass ) ; // true
* console . log ( foo . prototype . constructor === MySubClass ) ; // true
*
* @ method extends
* @ param { Function } subclass The subclass .
* @ param { Function } superclass The superclass to extend .
* @ return { Function } Returns the subclass ' s new prototype .
2014-01-03 13:32:13 -05:00
* /
2014-11-18 18:26:26 -05:00
createjs . extend = function ( subclass , superclass ) {
2014-01-03 13:32:13 -05:00
"use strict" ;
2014-11-18 18:26:26 -05:00
function o ( ) { this . constructor = subclass ; }
o . prototype = superclass . prototype ;
return ( subclass . prototype = new o ( ) ) ;
2014-01-03 13:32:13 -05:00
} ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// promote.js
//##############################################################################
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
this . createjs = this . createjs || { } ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
/ * *
* @ class Utility Methods
* /
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
/ * *
* Promotes any methods on the super class that were overridden , by creating an alias in the format ` prefix_methodName ` .
* It is recommended to use the super class ' s name as the prefix .
* An alias to the super class ' s constructor is always added in the format ` prefix_constructor ` .
* This allows the subclass to call super class methods without using ` function.call ` , providing better performance .
*
* For example , if ` MySubClass ` extends ` MySuperClass ` , and both define a ` draw ` method , then calling ` promote(MySubClass, "MySuperClass") `
* would add a ` MySuperClass_constructor ` method to MySubClass and promote the ` draw ` method on ` MySuperClass ` to the
* prototype of ` MySubClass ` as ` MySuperClass_draw ` .
*
* This should be called after the class ' s prototype is fully defined .
*
* function ClassA ( name ) {
* this . name = name ;
* }
* ClassA . prototype . greet = function ( ) {
* return "Hello " + this . name ;
* }
*
* function ClassB ( name , punctuation ) {
* this . ClassA _constructor ( name ) ;
* this . punctuation = punctuation ;
* }
* createjs . extend ( ClassB , ClassA ) ;
* ClassB . prototype . greet = function ( ) {
* return this . ClassA _greet ( ) + this . punctuation ;
* }
* createjs . promote ( ClassB , "ClassA" ) ;
*
* var foo = new ClassB ( "World" , "!?!" ) ;
* console . log ( foo . greet ( ) ) ; // Hello World!?!
*
* @ method promote
* @ param { Function } subclass The class to promote super class methods on .
* @ param { String } prefix The prefix to add to the promoted method names . Usually the name of the superclass .
* @ return { Function } Returns the subclass .
* /
createjs . promote = function ( subclass , prefix ) {
"use strict" ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
var subP = subclass . prototype , supP = ( Object . getPrototypeOf && Object . getPrototypeOf ( subP ) ) || subP . _ _proto _ _ ;
if ( supP ) {
subP [ ( prefix += "_" ) + "constructor" ] = supP . constructor ; // constructor is not always innumerable
for ( var n in supP ) {
if ( subP . hasOwnProperty ( n ) && ( typeof supP [ n ] == "function" ) ) { subP [ prefix + n ] = supP [ n ] ; }
}
}
return subclass ;
} ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
//##############################################################################
// indexOf.js
//##############################################################################
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
this . createjs = this . createjs || { } ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
/ * *
* @ class Utility Methods
* /
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
/ * *
* Finds the first occurrence of a specified value searchElement in the passed in array , and returns the index of
* that value . Returns - 1 if value is not found .
*
* var i = createjs . indexOf ( myArray , myElementToFind ) ;
*
* @ method indexOf
* @ param { Array } array Array to search for searchElement
* @ param searchElement Element to find in array .
* @ return { Number } The first index of searchElement in array .
* /
createjs . indexOf = function ( array , searchElement ) {
"use strict" ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
for ( var i = 0 , l = array . length ; i < l ; i ++ ) {
if ( searchElement === array [ i ] ) {
return i ;
}
}
return - 1 ;
} ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
//##############################################################################
// Event.js
//##############################################################################
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-01-03 13:32:13 -05:00
// constructor:
/ * *
2014-11-18 18:26:26 -05:00
* Contains properties and methods shared by all events for use with
* { { # crossLink "EventDispatcher" } } { { / c r o s s L i n k } } .
*
* Note that Event objects are often reused , so you should never
* rely on an event object ' s state outside of the call stack it was received in .
* @ class Event
2014-01-03 13:32:13 -05:00
* @ param { String } type The event type .
* @ param { Boolean } bubbles Indicates whether the event will bubble through the display list .
* @ param { Boolean } cancelable Indicates whether the default behaviour of this event can be cancelled .
2014-11-18 18:26:26 -05:00
* @ constructor
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
function Event ( type , bubbles , cancelable ) {
// public properties:
/ * *
* The type of event .
* @ property type
* @ type String
* * /
2014-01-03 13:32:13 -05:00
this . type = type ;
2014-11-18 18:26:26 -05:00
/ * *
* The object that generated an event .
* @ property target
* @ type Object
* @ default null
* @ readonly
* /
this . target = null ;
/ * *
* The current target that a bubbling event is being dispatched from . For non - bubbling events , this will
* always be the same as target . For example , if childObj . parent = parentObj , and a bubbling event
* is generated from childObj , then a listener on parentObj would receive the event with
* target = childObj ( the original target ) and currentTarget = parentObj ( where the listener was added ) .
* @ property currentTarget
* @ type Object
* @ default null
* @ readonly
* /
this . currentTarget = null ;
/ * *
* For bubbling events , this indicates the current event phase : < OL >
* < LI > capture phase : starting from the top parent to the target < / L I >
* < LI > at target phase : currently being dispatched from the target < / L I >
* < LI > bubbling phase : from the target to the top parent < / L I >
* < / O L >
* @ property eventPhase
* @ type Number
* @ default 0
* @ readonly
* /
this . eventPhase = 0 ;
/ * *
* Indicates whether the event will bubble through the display list .
* @ property bubbles
* @ type Boolean
* @ default false
* @ readonly
* /
this . bubbles = ! ! bubbles ;
/ * *
* Indicates whether the default behaviour of this event can be cancelled via
* { { # crossLink "Event/preventDefault" } } { { / c r o s s L i n k } } . T h i s i s s e t v i a t h e E v e n t c o n s t r u c t o r .
* @ property cancelable
* @ type Boolean
* @ default false
* @ readonly
* /
this . cancelable = ! ! cancelable ;
/ * *
* The epoch time at which this event was created .
* @ property timeStamp
* @ type Number
* @ default 0
* @ readonly
* /
2014-01-03 13:32:13 -05:00
this . timeStamp = ( new Date ( ) ) . getTime ( ) ;
2014-11-18 18:26:26 -05:00
/ * *
* Indicates if { { # crossLink "Event/preventDefault" } } { { / c r o s s L i n k } } h a s b e e n c a l l e d
* on this event .
* @ property defaultPrevented
* @ type Boolean
* @ default false
* @ readonly
* /
this . defaultPrevented = false ;
/ * *
* Indicates if { { # crossLink "Event/stopPropagation" } } { { / c r o s s L i n k } } o r
* { { # crossLink "Event/stopImmediatePropagation" } } { { / c r o s s L i n k } } h a s b e e n c a l l e d o n t h i s e v e n t .
* @ property propagationStopped
* @ type Boolean
* @ default false
* @ readonly
* /
this . propagationStopped = false ;
/ * *
* Indicates if { { # crossLink "Event/stopImmediatePropagation" } } { { / c r o s s L i n k } } h a s b e e n c a l l e d
* on this event .
* @ property immediatePropagationStopped
* @ type Boolean
* @ default false
* @ readonly
* /
this . immediatePropagationStopped = false ;
/ * *
* Indicates if { { # crossLink "Event/remove" } } { { / c r o s s L i n k } } h a s b e e n c a l l e d o n t h i s e v e n t .
* @ property removed
* @ type Boolean
* @ default false
* @ readonly
* /
this . removed = false ;
}
var p = Event . prototype ;
2014-01-03 13:32:13 -05:00
// public methods:
/ * *
* Sets { { # crossLink "Event/defaultPrevented" } } { { / c r o s s L i n k } } t o t r u e .
* Mirrors the DOM event standard .
* @ method preventDefault
* * /
p . preventDefault = function ( ) {
2014-11-18 18:26:26 -05:00
this . defaultPrevented = this . cancelable && true ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Sets { { # crossLink "Event/propagationStopped" } } { { / c r o s s L i n k } } t o t r u e .
* Mirrors the DOM event standard .
* @ method stopPropagation
* * /
p . stopPropagation = function ( ) {
this . propagationStopped = true ;
} ;
/ * *
* Sets { { # crossLink "Event/propagationStopped" } } { { / c r o s s L i n k } } a n d
* { { # crossLink "Event/immediatePropagationStopped" } } { { / c r o s s L i n k } } t o t r u e .
* Mirrors the DOM event standard .
* @ method stopImmediatePropagation
* * /
p . stopImmediatePropagation = function ( ) {
this . immediatePropagationStopped = this . propagationStopped = true ;
} ;
/ * *
* Causes the active listener to be removed via removeEventListener ( ) ;
*
* myBtn . addEventListener ( "click" , function ( evt ) {
* // do stuff...
* evt . remove ( ) ; // removes this listener.
* } ) ;
*
* @ method remove
* * /
p . remove = function ( ) {
this . removed = true ;
} ;
/ * *
* Returns a clone of the Event instance .
* @ method clone
* @ return { Event } a clone of the Event instance .
* * /
p . clone = function ( ) {
return new Event ( this . type , this . bubbles , this . cancelable ) ;
} ;
2014-11-18 18:26:26 -05:00
/ * *
* Provides a chainable shortcut method for setting a number of properties on the instance .
*
* @ method set
* @ param { Object } props A generic object containing properties to copy to the instance .
* @ return { Event } Returns the instance the method is called on ( useful for chaining calls . )
* /
p . set = function ( props ) {
for ( var n in props ) { this [ n ] = props [ n ] ; }
return this ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Event (type=" + this . type + ")]" ;
} ;
2014-11-18 18:26:26 -05:00
createjs . Event = Event ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// EventDispatcher.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
/ * *
* EventDispatcher provides methods for managing queues of event listeners and dispatching events .
*
* You can either extend EventDispatcher or mix its methods into an existing prototype or instance by using the
* EventDispatcher { { # crossLink "EventDispatcher/initialize" } } { { / c r o s s L i n k } } m e t h o d .
*
* Together with the CreateJS Event class , EventDispatcher provides an extended event model that is based on the
* DOM Level 2 event model , including addEventListener , removeEventListener , and dispatchEvent . It supports
* bubbling / capture , preventDefault , stopPropagation , stopImmediatePropagation , and handleEvent .
*
* EventDispatcher also exposes a { { # crossLink "EventDispatcher/on" } } { { / c r o s s L i n k } } m e t h o d , w h i c h m a k e s i t e a s i e r
* to create scoped listeners , listeners that only run once , and listeners with associated arbitrary data . The
* { { # crossLink "EventDispatcher/off" } } { { / c r o s s L i n k } } m e t h o d i s m e r e l y a n a l i a s t o
* { { # crossLink "EventDispatcher/removeEventListener" } } { { / c r o s s L i n k } } .
*
* Another addition to the DOM Level 2 model is the { { # crossLink "EventDispatcher/removeAllEventListeners" } } { { / c r o s s L i n k } }
* method , which can be used to listeners for all events , or listeners for a specific event . The Event object also
* includes a { { # crossLink "Event/remove" } } { { / c r o s s L i n k } } m e t h o d w h i c h r e m o v e s t h e a c t i v e l i s t e n e r .
*
* < h4 > Example < / h 4 >
* Add EventDispatcher capabilities to the "MyClass" class .
*
* EventDispatcher . initialize ( MyClass . prototype ) ;
*
* Add an event ( see { { # crossLink "EventDispatcher/addEventListener" } } { { / c r o s s L i n k } } ) .
*
* instance . addEventListener ( "eventName" , handlerMethod ) ;
* function handlerMethod ( event ) {
* console . log ( event . target + " Was Clicked" ) ;
* }
*
* < b > Maintaining proper scope < /b><br / >
* Scope ( ie . "this" ) can be be a challenge with events . Using the { { # crossLink "EventDispatcher/on" } } { { / c r o s s L i n k } }
* method to subscribe to events simplifies this .
*
* instance . addEventListener ( "click" , function ( event ) {
* console . log ( instance == this ) ; // false, scope is ambiguous.
* } ) ;
*
* instance . on ( "click" , function ( event ) {
* console . log ( instance == this ) ; // true, "on" uses dispatcher scope by default.
* } ) ;
*
* If you want to use addEventListener instead , you may want to use function . bind ( ) or a similar proxy to manage scope .
*
*
* @ class EventDispatcher
* @ constructor
* * /
function EventDispatcher ( ) {
// private properties:
/ * *
* @ protected
* @ property _listeners
* @ type Object
* * /
this . _listeners = null ;
/ * *
* @ protected
* @ property _captureListeners
* @ type Object
* * /
this . _captureListeners = null ;
}
var p = EventDispatcher . prototype ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// static public methods:
2014-01-03 13:32:13 -05:00
/ * *
* Static initializer to mix EventDispatcher methods into a target object or prototype .
*
* EventDispatcher . initialize ( MyClass . prototype ) ; // add to the prototype of the class
* EventDispatcher . initialize ( myObject ) ; // add to a specific instance
*
* @ method initialize
* @ static
* @ param { Object } target The target object to inject EventDispatcher methods into . This can be an instance or a
* prototype .
* * /
EventDispatcher . initialize = function ( target ) {
target . addEventListener = p . addEventListener ;
target . on = p . on ;
target . removeEventListener = target . off = p . removeEventListener ;
target . removeAllEventListeners = p . removeAllEventListeners ;
target . hasEventListener = p . hasEventListener ;
target . dispatchEvent = p . dispatchEvent ;
target . _dispatchEvent = p . _dispatchEvent ;
2014-02-02 19:31:06 -05:00
target . willTrigger = p . willTrigger ;
2014-01-03 13:32:13 -05:00
} ;
// public methods:
/ * *
* Adds the specified event listener . Note that adding multiple listeners to the same function will result in
* multiple callbacks getting fired .
*
* < h4 > Example < / h 4 >
*
* displayObject . addEventListener ( "click" , handleClick ) ;
* function handleClick ( event ) {
* // Click happened.
* }
*
* @ method addEventListener
* @ param { String } type The string type of the event .
* @ param { Function | Object } listener An object with a handleEvent method , or a function that will be called when
* the event is dispatched .
* @ param { Boolean } [ useCapture ] For events that bubble , indicates whether to listen for the event in the capture or bubbling / target phase .
* @ return { Function | Object } Returns the listener for chaining or assignment .
* * /
p . addEventListener = function ( type , listener , useCapture ) {
var listeners ;
if ( useCapture ) {
listeners = this . _captureListeners = this . _captureListeners || { } ;
} else {
listeners = this . _listeners = this . _listeners || { } ;
}
var arr = listeners [ type ] ;
if ( arr ) { this . removeEventListener ( type , listener , useCapture ) ; }
arr = listeners [ type ] ; // remove may have deleted the array
if ( ! arr ) { listeners [ type ] = [ listener ] ; }
else { arr . push ( listener ) ; }
return listener ;
} ;
/ * *
* A shortcut method for using addEventListener that makes it easier to specify an execution scope , have a listener
* only run once , associate arbitrary data with the listener , and remove the listener .
*
* This method works by creating an anonymous wrapper function and subscribing it with addEventListener .
* The created anonymous function is returned for use with . removeEventListener ( or . off ) .
*
* < h4 > Example < / h 4 >
*
* var listener = myBtn . on ( "click" , handleClick , null , false , { count : 3 } ) ;
* function handleClick ( evt , data ) {
* data . count -= 1 ;
* console . log ( this == myBtn ) ; // true - scope defaults to the dispatcher
* if ( data . count == 0 ) {
* alert ( "clicked 3 times!" ) ;
* myBtn . off ( "click" , listener ) ;
* // alternately: evt.remove();
* }
* }
*
* @ method on
* @ param { String } type The string type of the event .
* @ param { Function | Object } listener An object with a handleEvent method , or a function that will be called when
* the event is dispatched .
* @ param { Object } [ scope ] The scope to execute the listener in . Defaults to the dispatcher / currentTarget for function listeners , and to the listener itself for object listeners ( ie . using handleEvent ) .
* @ param { Boolean } [ once = false ] If true , the listener will remove itself after the first time it is triggered .
* @ param { * } [ data ] Arbitrary data that will be included as the second parameter when the listener is called .
* @ param { Boolean } [ useCapture = false ] For events that bubble , indicates whether to listen for the event in the capture or bubbling / target phase .
* @ return { Function } Returns the anonymous function that was created and assigned as the listener . This is needed to remove the listener later using . removeEventListener .
* * /
p . on = function ( type , listener , scope , once , data , useCapture ) {
if ( listener . handleEvent ) {
scope = scope || listener ;
listener = listener . handleEvent ;
}
scope = scope || this ;
return this . addEventListener ( type , function ( evt ) {
listener . call ( scope , evt , data ) ;
once && evt . remove ( ) ;
} , useCapture ) ;
} ;
/ * *
* Removes the specified event listener .
*
* < b > Important Note : < / b > t h a t y o u m u s t p a s s t h e e x a c t f u n c t i o n r e f e r e n c e u s e d w h e n t h e e v e n t w a s a d d e d . I f a p r o x y
* function , or function closure is used as the callback , the proxy / closure reference must be used - a new proxy or
* closure will not work .
*
* < h4 > Example < / h 4 >
*
* displayObject . removeEventListener ( "click" , handleClick ) ;
*
* @ method removeEventListener
* @ param { String } type The string type of the event .
* @ param { Function | Object } listener The listener function or object .
* @ param { Boolean } [ useCapture ] For events that bubble , indicates whether to listen for the event in the capture or bubbling / target phase .
* * /
p . removeEventListener = function ( type , listener , useCapture ) {
var listeners = useCapture ? this . _captureListeners : this . _listeners ;
if ( ! listeners ) { return ; }
var arr = listeners [ type ] ;
if ( ! arr ) { return ; }
for ( var i = 0 , l = arr . length ; i < l ; i ++ ) {
if ( arr [ i ] == listener ) {
if ( l == 1 ) { delete ( listeners [ type ] ) ; } // allows for faster checks.
else { arr . splice ( i , 1 ) ; }
break ;
}
}
} ;
/ * *
* A shortcut to the removeEventListener method , with the same parameters and return value . This is a companion to the
* . on method .
*
* @ method off
* @ param { String } type The string type of the event .
* @ param { Function | Object } listener The listener function or object .
* @ param { Boolean } [ useCapture ] For events that bubble , indicates whether to listen for the event in the capture or bubbling / target phase .
* * /
p . off = p . removeEventListener ;
/ * *
* Removes all listeners for the specified type , or all listeners of all types .
*
* < h4 > Example < / h 4 >
*
* // Remove all listeners
* displayObject . removeAllEventListeners ( ) ;
*
* // Remove all click listeners
* displayObject . removeAllEventListeners ( "click" ) ;
*
* @ method removeAllEventListeners
* @ param { String } [ type ] The string type of the event . If omitted , all listeners for all types will be removed .
* * /
p . removeAllEventListeners = function ( type ) {
if ( ! type ) { this . _listeners = this . _captureListeners = null ; }
else {
if ( this . _listeners ) { delete ( this . _listeners [ type ] ) ; }
if ( this . _captureListeners ) { delete ( this . _captureListeners [ type ] ) ; }
}
} ;
/ * *
* Dispatches the specified event to all listeners .
*
* < h4 > Example < / h 4 >
*
* // Use a string event
* this . dispatchEvent ( "complete" ) ;
*
* // Use an Event instance
* var event = new createjs . Event ( "progress" ) ;
* this . dispatchEvent ( event ) ;
*
* @ method dispatchEvent
* @ param { Object | String | Event } eventObj An object with a "type" property , or a string type .
* While a generic object will work , it is recommended to use a CreateJS Event instance . If a string is used ,
* dispatchEvent will construct an Event instance with the specified type .
* @ return { Boolean } Returns the value of eventObj . defaultPrevented .
* * /
2014-11-18 18:26:26 -05:00
p . dispatchEvent = function ( eventObj ) {
2014-01-03 13:32:13 -05:00
if ( typeof eventObj == "string" ) {
// won't bubble, so skip everything if there's no listeners:
var listeners = this . _listeners ;
if ( ! listeners || ! listeners [ eventObj ] ) { return false ; }
eventObj = new createjs . Event ( eventObj ) ;
2014-11-18 18:26:26 -05:00
} else if ( eventObj . target && eventObj . clone ) {
// redispatching an active event object, so clone it:
eventObj = eventObj . clone ( ) ;
2014-01-03 13:32:13 -05:00
}
2014-11-18 18:26:26 -05:00
try { eventObj . target = this ; } catch ( e ) { } // try/catch allows redispatching of native events
2014-01-03 13:32:13 -05:00
if ( ! eventObj . bubbles || ! this . parent ) {
this . _dispatchEvent ( eventObj , 2 ) ;
} else {
var top = this , list = [ top ] ;
while ( top . parent ) { list . push ( top = top . parent ) ; }
var i , l = list . length ;
// capture & atTarget
for ( i = l - 1 ; i >= 0 && ! eventObj . propagationStopped ; i -- ) {
list [ i ] . _dispatchEvent ( eventObj , 1 + ( i == 0 ) ) ;
}
// bubbling
for ( i = 1 ; i < l && ! eventObj . propagationStopped ; i ++ ) {
list [ i ] . _dispatchEvent ( eventObj , 3 ) ;
}
}
return eventObj . defaultPrevented ;
} ;
/ * *
2014-02-02 19:31:06 -05:00
* Indicates whether there is at least one listener for the specified event type .
2014-01-03 13:32:13 -05:00
* @ method hasEventListener
* @ param { String } type The string type of the event .
* @ return { Boolean } Returns true if there is at least one listener for the specified event .
* * /
p . hasEventListener = function ( type ) {
var listeners = this . _listeners , captureListeners = this . _captureListeners ;
return ! ! ( ( listeners && listeners [ type ] ) || ( captureListeners && captureListeners [ type ] ) ) ;
} ;
2014-02-02 19:31:06 -05:00
/ * *
* Indicates whether there is at least one listener for the specified event type on this object or any of its
* ancestors ( parent , parent ' s parent , etc ) . A return value of true indicates that if a bubbling event of the
* specified type is dispatched from this object , it will trigger at least one listener .
*
* This is similar to { { # crossLink "EventDispatcher/hasEventListener" } } { { / c r o s s L i n k } } , b u t i t s e a r c h e s t h e e n t i r e
* event flow for a listener , not just this object .
* @ method willTrigger
* @ param { String } type The string type of the event .
* @ return { Boolean } Returns ` true ` if there is at least one listener for the specified event .
* * /
p . willTrigger = function ( type ) {
var o = this ;
while ( o ) {
if ( o . hasEventListener ( type ) ) { return true ; }
o = o . parent ;
}
return false ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[EventDispatcher]" ;
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
// private methods:
/ * *
* @ method _dispatchEvent
* @ param { Object | String | Event } eventObj
* @ param { Object } eventPhase
* @ protected
* * /
p . _dispatchEvent = function ( eventObj , eventPhase ) {
var l , listeners = ( eventPhase == 1 ) ? this . _captureListeners : this . _listeners ;
if ( eventObj && listeners ) {
var arr = listeners [ eventObj . type ] ;
if ( ! arr || ! ( l = arr . length ) ) { return ; }
2014-02-02 19:31:06 -05:00
try { eventObj . currentTarget = this ; } catch ( e ) { }
try { eventObj . eventPhase = eventPhase ; } catch ( e ) { }
2014-01-03 13:32:13 -05:00
eventObj . removed = false ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
arr = arr . slice ( ) ; // to avoid issues with items being removed or added during the dispatch
for ( var i = 0 ; i < l && ! eventObj . immediatePropagationStopped ; i ++ ) {
var o = arr [ i ] ;
if ( o . handleEvent ) { o . handleEvent ( eventObj ) ; }
else { o ( eventObj ) ; }
if ( eventObj . removed ) {
this . off ( eventObj . type , o , eventPhase == 1 ) ;
eventObj . removed = false ;
}
}
}
} ;
2014-11-18 18:26:26 -05:00
createjs . EventDispatcher = EventDispatcher ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// Ticker.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* The Ticker provides a centralized tick or heartbeat broadcast at a set interval . Listeners can subscribe to the tick
* event to be notified when a set time interval has elapsed .
2014-01-03 13:32:13 -05:00
*
2014-11-18 18:26:26 -05:00
* Note that the interval that the tick event is called is a target interval , and may be broadcast at a slower interval
* during times of high CPU load . The Ticker class uses a static interface ( ex . < code > Ticker . getPaused ( ) < / c o d e > ) a n d
* should not be instantiated .
2014-01-03 13:32:13 -05:00
*
2014-11-18 18:26:26 -05:00
* < h4 > Example < / h 4 >
*
* createjs . Ticker . addEventListener ( "tick" , handleTick ) ;
* function handleTick ( event ) {
* // Actions carried out each frame
* if ( ! event . paused ) {
* // Actions carried out when the Ticker is not paused.
* }
* }
*
* To update a stage every tick , the { { # crossLink "Stage" } } { { / c r o s s L i n k } } i n s t a n c e c a n a l s o b e u s e d a s a l i s t e n e r , a s
* it will automatically update when it receives a tick event :
*
* createjs . Ticker . addEventListener ( "tick" , stage ) ;
*
* @ class Ticker
* @ uses EventDispatcher
* @ static
* * /
function Ticker ( ) {
throw "Ticker cannot be instantiated." ;
2014-01-03 13:32:13 -05:00
}
2014-11-18 18:26:26 -05:00
// constants:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* In this mode , Ticker uses the requestAnimationFrame API , but attempts to synch the ticks to target framerate . It
* uses a simple heuristic that compares the time of the RAF return to the target time for the current frame and
* dispatches the tick when the time is within a certain threshold .
*
* This mode has a higher variance for time between frames than TIMEOUT , but does not require that content be time
* based as with RAF while gaining the benefits of that API ( screen synch , background throttling ) .
*
* Variance is usually lowest for framerates that are a divisor of the RAF frequency . This is usually 60 , so
* framerates of 10 , 12 , 15 , 20 , and 30 work well .
*
* Falls back on TIMEOUT if the requestAnimationFrame API is not supported .
* @ property RAF _SYNCHED
* @ static
* @ type { String }
* @ default "synched"
* @ readonly
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
Ticker . RAF _SYNCHED = "synched" ;
2014-01-03 13:32:13 -05:00
/ * *
* In this mode , Ticker passes through the requestAnimationFrame heartbeat , ignoring the target framerate completely .
* Because requestAnimationFrame frequency is not deterministic , any content using this mode should be time based .
* You can leverage { { # crossLink "Ticker/getTime" } } { { / c r o s s L i n k } } a n d t h e t i c k e v e n t o b j e c t ' s " d e l t a " p r o p e r t i e s
* to make this easier .
*
* Falls back on TIMEOUT if the requestAnimationFrame API is not supported .
* @ property RAF
* @ static
* @ type { String }
* @ default "raf"
* @ readonly
* * /
Ticker . RAF = "raf" ;
/ * *
* In this mode , Ticker uses the setTimeout API . This provides predictable , adaptive frame timing , but does not
* provide the benefits of requestAnimationFrame ( screen synch , background throttling ) .
* @ property TIMEOUT
* @ static
* @ type { String }
* @ default "timer"
* @ readonly
* * /
Ticker . TIMEOUT = "timeout" ;
2014-11-18 18:26:26 -05:00
// static events:
2014-01-03 13:32:13 -05:00
/ * *
* Dispatched each tick . The event will be dispatched to each listener even when the Ticker has been paused using
* { { # crossLink "Ticker/setPaused" } } { { / c r o s s L i n k } } .
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* createjs . Ticker . addEventListener ( "tick" , handleTick ) ;
* function handleTick ( event ) {
* console . log ( "Paused:" , event . paused , event . delta ) ;
* }
*
* @ event tick
* @ param { Object } target The object that dispatched the event .
* @ param { String } type The event type .
* @ param { Boolean } paused Indicates whether the ticker is currently paused .
* @ param { Number } delta The time elapsed in ms since the last tick .
* @ param { Number } time The total time in ms since Ticker was initialized .
* @ param { Number } runTime The total time in ms that Ticker was not paused since it was initialized . For example ,
* you could determine the amount of time that the Ticker has been paused since initialization with time - runTime .
* @ since 0.6 . 0
* /
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
// public static properties:
/ * *
* Deprecated in favour of { { # crossLink "Ticker/timingMode" } } { { / c r o s s L i n k } } , a n d w i l l b e r e m o v e d i n a f u t u r e v e r s i o n . I f t r u e , t i m i n g M o d e w i l l
* use { { # crossLink "Ticker/RAF_SYNCHED" } } { { / c r o s s L i n k } } b y d e f a u l t .
* @ deprecated Deprecated in favour of { { # crossLink "Ticker/timingMode" } } { { / c r o s s L i n k } } .
* @ property useRAF
* @ static
* @ type { Boolean }
* @ default false
* * /
Ticker . useRAF = false ;
/ * *
* Specifies the timing api ( setTimeout or requestAnimationFrame ) and mode to use . See
* { { # crossLink "Ticker/TIMEOUT" } } { { / c r o s s L i n k } } , { { # c r o s s L i n k " T i c k e r / R A F " } } { { / c r o s s L i n k } } , a n d
* { { # crossLink "Ticker/RAF_SYNCHED" } } { { / c r o s s L i n k } } f o r m o d e d e t a i l s .
* @ property timingMode
* @ static
* @ type { String }
* @ default Ticker . TIMEOUT
* * /
Ticker . timingMode = null ;
/ * *
* Specifies a maximum value for the delta property in the tick event object . This is useful when building time
* based animations and systems to prevent issues caused by large time gaps caused by background tabs , system sleep ,
* alert dialogs , or other blocking routines . Double the expected frame duration is often an effective value
* ( ex . maxDelta = 50 when running at 40 fps ) .
*
* This does not impact any other values ( ex . time , runTime , etc ) , so you may experience issues if you enable maxDelta
* when using both delta and other values .
*
* If 0 , there is no maximum .
* @ property maxDelta
* @ static
* @ type { number }
* @ default 0
* /
Ticker . maxDelta = 0 ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
// mix-ins:
// EventDispatcher methods:
Ticker . removeEventListener = null ;
Ticker . removeAllEventListeners = null ;
Ticker . dispatchEvent = null ;
Ticker . hasEventListener = null ;
Ticker . _listeners = null ;
createjs . EventDispatcher . initialize ( Ticker ) ; // inject EventDispatcher methods.
Ticker . _addEventListener = Ticker . addEventListener ;
Ticker . addEventListener = function ( ) {
! Ticker . _inited && Ticker . init ( ) ;
return Ticker . _addEventListener . apply ( Ticker , arguments ) ;
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
// private static properties:
/ * *
* @ property _paused
* @ type { Boolean }
* @ protected
* * /
Ticker . _paused = false ;
/ * *
* @ property _inited
* @ type { Boolean }
* @ protected
* * /
Ticker . _inited = false ;
/ * *
* @ property _startTime
* @ type { Number }
* @ protected
* * /
Ticker . _startTime = 0 ;
/ * *
* @ property _pausedTime
* @ type { Number }
* @ protected
* * /
Ticker . _pausedTime = 0 ;
/ * *
* The number of ticks that have passed
* @ property _ticks
* @ type { Number }
* @ protected
* * /
Ticker . _ticks = 0 ;
/ * *
* The number of ticks that have passed while Ticker has been paused
* @ property _pausedTicks
* @ type { Number }
* @ protected
* * /
Ticker . _pausedTicks = 0 ;
/ * *
* @ property _interval
* @ type { Number }
* @ protected
* * /
Ticker . _interval = 50 ;
/ * *
* @ property _lastTime
* @ type { Number }
* @ protected
* * /
Ticker . _lastTime = 0 ;
/ * *
* @ property _times
* @ type { Array }
* @ protected
* * /
Ticker . _times = null ;
/ * *
* @ property _tickTimes
* @ type { Array }
* @ protected
* * /
Ticker . _tickTimes = null ;
/ * *
* Stores the timeout or requestAnimationFrame id .
* @ property _timerId
* @ type { Number }
* @ protected
* * /
Ticker . _timerId = null ;
/ * *
* True if currently using requestAnimationFrame , false if using setTimeout .
* @ property _raf
* @ type { Boolean }
* @ protected
* * /
Ticker . _raf = true ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
// public static methods:
/ * *
* Starts the tick . This is called automatically when the first listener is added .
* @ method init
* @ static
* * /
Ticker . init = function ( ) {
if ( Ticker . _inited ) { return ; }
Ticker . _inited = true ;
Ticker . _times = [ ] ;
Ticker . _tickTimes = [ ] ;
Ticker . _startTime = Ticker . _getTime ( ) ;
Ticker . _times . push ( Ticker . _lastTime = 0 ) ;
Ticker . setInterval ( Ticker . _interval ) ;
} ;
/ * *
* Stops the Ticker and removes all listeners . Use init ( ) to restart the Ticker .
* @ method reset
* @ static
* * /
Ticker . reset = function ( ) {
if ( Ticker . _raf ) {
var f = window . cancelAnimationFrame || window . webkitCancelAnimationFrame || window . mozCancelAnimationFrame || window . oCancelAnimationFrame || window . msCancelAnimationFrame ;
f && f ( Ticker . _timerId ) ;
} else {
clearTimeout ( Ticker . _timerId ) ;
}
Ticker . removeAllEventListeners ( "tick" ) ;
2014-11-18 18:26:26 -05:00
Ticker . _timerId = null ;
Ticker . _inited = false ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Sets the target time ( in milliseconds ) between ticks . Default is 50 ( 20 FPS ) .
*
* Note actual time between ticks may be more than requested depending on CPU load .
* @ method setInterval
* @ static
* @ param { Number } interval Time in milliseconds between ticks . Default value is 50.
* * /
Ticker . setInterval = function ( interval ) {
Ticker . _interval = interval ;
if ( ! Ticker . _inited ) { return ; }
Ticker . _setupTick ( ) ;
} ;
/ * *
* Returns the current target time between ticks , as set with { { # crossLink "Ticker/setInterval" } } { { / c r o s s L i n k } } .
* @ method getInterval
* @ static
* @ return { Number } The current target interval in milliseconds between tick events .
* * /
Ticker . getInterval = function ( ) {
return Ticker . _interval ;
} ;
/ * *
* Sets the target frame rate in frames per second ( FPS ) . For example , with an interval of 40 , < code > getFPS ( ) < / c o d e >
* will return 25 ( 1000 ms per second divided by 40 ms per tick = 25 fps ) .
* @ method setFPS
* @ static
* @ param { Number } value Target number of ticks broadcast per second .
* * /
Ticker . setFPS = function ( value ) {
Ticker . setInterval ( 1000 / value ) ;
} ;
/ * *
* Returns the target frame rate in frames per second ( FPS ) . For example , with an interval of 40 , < code > getFPS ( ) < / c o d e >
* will return 25 ( 1000 ms per second divided by 40 ms per tick = 25 fps ) .
* @ method getFPS
* @ static
* @ return { Number } The current target number of frames / ticks broadcast per second .
* * /
Ticker . getFPS = function ( ) {
return 1000 / Ticker . _interval ;
} ;
/ * *
* Returns the average time spent within a tick . This can vary significantly from the value provided by getMeasuredFPS
* because it only measures the time spent within the tick execution stack .
*
* Example 1 : With a target FPS of 20 , getMeasuredFPS ( ) returns 20 fps , which indicates an average of 50 ms between
* the end of one tick and the end of the next . However , getMeasuredTickTime ( ) returns 15 ms . This indicates that
* there may be up to 35 ms of "idle" time between the end of one tick and the start of the next .
*
* Example 2 : With a target FPS of 30 , getFPS ( ) returns 10 fps , which indicates an average of 100 ms between the end of
* one tick and the end of the next . However , getMeasuredTickTime ( ) returns 20 ms . This would indicate that something
* other than the tick is using ~ 80 ms ( another script , DOM rendering , etc ) .
* @ method getMeasuredTickTime
* @ static
* @ param { Number } [ ticks ] The number of previous ticks over which to measure the average time spent in a tick .
* Defaults to the number of ticks per second . To get only the last tick ' s time , pass in 1.
* @ return { Number } The average time spent in a tick in milliseconds .
* * /
Ticker . getMeasuredTickTime = function ( ticks ) {
var ttl = 0 , times = Ticker . _tickTimes ;
2014-11-18 18:26:26 -05:00
if ( ! times || times . length < 1 ) { return - 1 ; }
2014-01-03 13:32:13 -05:00
// by default, calculate average for the past ~1 second:
ticks = Math . min ( times . length , ticks || ( Ticker . getFPS ( ) | 0 ) ) ;
for ( var i = 0 ; i < ticks ; i ++ ) { ttl += times [ i ] ; }
return ttl / ticks ;
} ;
/ * *
* Returns the actual frames / ticks per second .
* @ method getMeasuredFPS
* @ static
* @ param { Number } [ ticks ] The number of previous ticks over which to measure the actual frames / ticks per second .
* Defaults to the number of ticks per second .
* @ return { Number } The actual frames / ticks per second . Depending on performance , this may differ
* from the target frames per second .
* * /
Ticker . getMeasuredFPS = function ( ticks ) {
var times = Ticker . _times ;
2014-11-18 18:26:26 -05:00
if ( ! times || times . length < 2 ) { return - 1 ; }
2014-01-03 13:32:13 -05:00
// by default, calculate fps for the past ~1 second:
ticks = Math . min ( times . length - 1 , ticks || ( Ticker . getFPS ( ) | 0 ) ) ;
return 1000 / ( ( times [ 0 ] - times [ ticks ] ) / ticks ) ;
} ;
/ * *
* Changes the "paused" state of the Ticker , which can be retrieved by the { { # crossLink "Ticker/getPaused" } } { { / c r o s s L i n k } }
* method , and is passed as the "paused" property of the < code > tick < / c o d e > e v e n t . W h e n t h e t i c k e r i s p a u s e d , a l l
* listeners will still receive a tick event , but the < code > paused < / c o d e > p r o p e r t y w i l l b e f a l s e .
*
* Note that in EaselJS v0 . 5.0 and earlier , "pauseable" listeners would < strong > not < / s t r o n g > r e c e i v e t h e t i c k
* callback when Ticker was paused . This is no longer the case .
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* createjs . Ticker . addEventListener ( "tick" , handleTick ) ;
* createjs . Ticker . setPaused ( true ) ;
* function handleTick ( event ) {
* console . log ( "Paused:" , event . paused , createjs . Ticker . getPaused ( ) ) ;
* }
*
* @ method setPaused
* @ static
* @ param { Boolean } value Indicates whether to pause ( true ) or unpause ( false ) Ticker .
* * /
Ticker . setPaused = function ( value ) {
Ticker . _paused = value ;
} ;
/ * *
* Returns a boolean indicating whether Ticker is currently paused , as set with { { # crossLink "Ticker/setPaused" } } { { / c r o s s L i n k } } .
* When the ticker is paused , all listeners will still receive a tick event , but this value will be false .
*
* Note that in EaselJS v0 . 5.0 and earlier , "pauseable" listeners would < strong > not < / s t r o n g > r e c e i v e t h e t i c k
* callback when Ticker was paused . This is no longer the case .
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* createjs . Ticker . addEventListener ( "tick" , handleTick ) ;
* createjs . Ticker . setPaused ( true ) ;
* function handleTick ( event ) {
* console . log ( "Paused:" , createjs . Ticker . getPaused ( ) ) ;
* }
*
* @ method getPaused
* @ static
* @ return { Boolean } Whether the Ticker is currently paused .
* * /
Ticker . getPaused = function ( ) {
return Ticker . _paused ;
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Returns the number of milliseconds that have elapsed since Ticker was initialized via { { # crossLink "Ticker/init" } } .
* Returns - 1 if Ticker has not been initialized . For example , you could use
2014-01-03 13:32:13 -05:00
* this in a time synchronized animation to determine the exact amount of time that has elapsed .
* @ method getTime
* @ static
* @ param { Boolean } [ runTime = false ] If true only time elapsed while Ticker was not paused will be returned .
* If false , the value returned will be total time elapsed since the first tick event listener was added .
2014-11-18 18:26:26 -05:00
* @ return { Number } Number of milliseconds that have elapsed since Ticker was initialized or - 1.
2014-01-03 13:32:13 -05:00
* * /
Ticker . getTime = function ( runTime ) {
2014-11-18 18:26:26 -05:00
return Ticker . _startTime ? Ticker . _getTime ( ) - Ticker . _startTime - ( runTime ? Ticker . _pausedTime : 0 ) : - 1 ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Similar to getTime ( ) , but returns the time included with the current ( or most recent ) tick event object .
* @ method getEventTime
* @ param runTime { Boolean } [ runTime = false ] If true , the runTime property will be returned instead of time .
2014-11-18 18:26:26 -05:00
* @ returns { number } The time or runTime property from the most recent tick event or - 1.
2014-01-03 13:32:13 -05:00
* /
Ticker . getEventTime = function ( runTime ) {
2014-11-18 18:26:26 -05:00
return Ticker . _startTime ? ( Ticker . _lastTime || Ticker . _startTime ) - ( runTime ? Ticker . _pausedTime : 0 ) : - 1 ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns the number of ticks that have been broadcast by Ticker .
* @ method getTicks
* @ static
* @ param { Boolean } pauseable Indicates whether to include ticks that would have been broadcast
* while Ticker was paused . If true only tick events broadcast while Ticker is not paused will be returned .
* If false , tick events that would have been broadcast while Ticker was paused will be included in the return
* value . The default value is false .
* @ return { Number } of ticks that have been broadcast .
* * /
Ticker . getTicks = function ( pauseable ) {
return Ticker . _ticks - ( pauseable ? Ticker . _pausedTicks : 0 ) ;
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
// private static methods:
/ * *
* @ method _handleSynch
* @ static
* @ protected
* * /
Ticker . _handleSynch = function ( ) {
Ticker . _timerId = null ;
Ticker . _setupTick ( ) ;
// run if enough time has elapsed, with a little bit of flexibility to be early:
2014-11-18 18:26:26 -05:00
if ( Ticker . _getTime ( ) - Ticker . _lastTime >= ( Ticker . _interval - 1 ) * 0.97 ) {
2014-01-03 13:32:13 -05:00
Ticker . _tick ( ) ;
}
} ;
/ * *
* @ method _handleRAF
* @ static
* @ protected
* * /
Ticker . _handleRAF = function ( ) {
Ticker . _timerId = null ;
Ticker . _setupTick ( ) ;
Ticker . _tick ( ) ;
} ;
/ * *
* @ method _handleTimeout
* @ static
* @ protected
* * /
Ticker . _handleTimeout = function ( ) {
Ticker . _timerId = null ;
Ticker . _setupTick ( ) ;
Ticker . _tick ( ) ;
} ;
/ * *
* @ method _setupTick
* @ static
* @ protected
* * /
Ticker . _setupTick = function ( ) {
if ( Ticker . _timerId != null ) { return ; } // avoid duplicates
var mode = Ticker . timingMode || ( Ticker . useRAF && Ticker . RAF _SYNCHED ) ;
if ( mode == Ticker . RAF _SYNCHED || mode == Ticker . RAF ) {
var f = window . requestAnimationFrame || window . webkitRequestAnimationFrame || window . mozRequestAnimationFrame || window . oRequestAnimationFrame || window . msRequestAnimationFrame ;
if ( f ) {
Ticker . _timerId = f ( mode == Ticker . RAF ? Ticker . _handleRAF : Ticker . _handleSynch ) ;
Ticker . _raf = true ;
return ;
}
}
Ticker . _raf = false ;
Ticker . _timerId = setTimeout ( Ticker . _handleTimeout , Ticker . _interval ) ;
} ;
/ * *
* @ method _tick
* @ static
* @ protected
* * /
Ticker . _tick = function ( ) {
2014-11-18 18:26:26 -05:00
var time = Ticker . _getTime ( ) ;
var adjTime = time - Ticker . _startTime ;
2014-01-03 13:32:13 -05:00
var elapsedTime = time - Ticker . _lastTime ;
var paused = Ticker . _paused ;
Ticker . _ticks ++ ;
if ( paused ) {
Ticker . _pausedTicks ++ ;
Ticker . _pausedTime += elapsedTime ;
}
Ticker . _lastTime = time ;
if ( Ticker . hasEventListener ( "tick" ) ) {
var event = new createjs . Event ( "tick" ) ;
var maxDelta = Ticker . maxDelta ;
event . delta = ( maxDelta && elapsedTime > maxDelta ) ? maxDelta : elapsedTime ;
event . paused = paused ;
2014-11-18 18:26:26 -05:00
event . time = adjTime ;
event . runTime = adjTime - Ticker . _pausedTime ;
2014-01-03 13:32:13 -05:00
Ticker . dispatchEvent ( event ) ;
}
Ticker . _tickTimes . unshift ( Ticker . _getTime ( ) - time ) ;
while ( Ticker . _tickTimes . length > 100 ) { Ticker . _tickTimes . pop ( ) ; }
2014-11-18 18:26:26 -05:00
Ticker . _times . unshift ( adjTime ) ;
2014-01-03 13:32:13 -05:00
while ( Ticker . _times . length > 100 ) { Ticker . _times . pop ( ) ; }
} ;
/ * *
* @ method _getTime
* @ static
* @ protected
* * /
var now = window . performance && ( performance . now || performance . mozNow || performance . msNow || performance . oNow || performance . webkitNow ) ;
Ticker . _getTime = function ( ) {
return ( now && now . call ( performance ) ) || ( new Date ( ) . getTime ( ) ) ;
} ;
2014-11-18 18:26:26 -05:00
createjs . Ticker = Ticker ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// UID.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Global utility for generating sequential unique ID numbers . The UID class uses a static interface ( ex . < code > UID . get ( ) < / c o d e > )
* and should not be instantiated .
* @ class UID
* @ static
* * /
function UID ( ) {
throw "UID cannot be instantiated" ;
}
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// private static properties:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* @ property _nextID
2014-01-03 13:32:13 -05:00
* @ type Number
2014-11-18 18:26:26 -05:00
* @ protected
* * /
UID . _nextID = 0 ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// public static methods:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Returns the next unique id .
* @ method get
* @ return { Number } The next unique id
* @ static
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
UID . get = function ( ) {
return UID . _nextID ++ ;
} ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
createjs . UID = UID ;
} ( ) ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
//##############################################################################
// MouseEvent.js
//##############################################################################
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
this . createjs = this . createjs || { } ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
( function ( ) {
"use strict" ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Passed as the parameter to all mouse / pointer / touch related events . For a listing of mouse events and their properties ,
* see the { { # crossLink "DisplayObject" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " S t a g e " } } { { / c r o s s L i n k } } e v e n t l i s t i n g s .
* @ class MouseEvent
* @ param { String } type The event type .
* @ param { Boolean } bubbles Indicates whether the event will bubble through the display list .
* @ param { Boolean } cancelable Indicates whether the default behaviour of this event can be cancelled .
* @ param { Number } stageX The normalized x position relative to the stage .
* @ param { Number } stageY The normalized y position relative to the stage .
* @ param { MouseEvent } nativeEvent The native DOM event related to this mouse event .
* @ param { Number } pointerID The unique id for the pointer .
* @ param { Boolean } primary Indicates whether this is the primary pointer in a multitouch environment .
* @ param { Number } rawX The raw x position relative to the stage .
* @ param { Number } rawY The raw y position relative to the stage .
* @ extends Event
* @ constructor
* * /
function MouseEvent ( type , bubbles , cancelable , stageX , stageY , nativeEvent , pointerID , primary , rawX , rawY ) {
this . Event _constructor ( type , bubbles , cancelable ) ;
// public properties:
/ * *
* The normalized x position on the stage . This will always be within the range 0 to stage width .
* @ property stageX
* @ type Number
* /
this . stageX = stageX ;
/ * *
* The normalized y position on the stage . This will always be within the range 0 to stage height .
* @ property stageY
* @ type Number
* * /
this . stageY = stageY ;
/ * *
* The raw x position relative to the stage . Normally this will be the same as the stageX value , unless
* stage . mouseMoveOutside is true and the pointer is outside of the stage bounds .
* @ property rawX
* @ type Number
* /
this . rawX = ( rawX == null ) ? stageX : rawX ;
/ * *
* The raw y position relative to the stage . Normally this will be the same as the stageY value , unless
* stage . mouseMoveOutside is true and the pointer is outside of the stage bounds .
* @ property rawY
* @ type Number
* /
this . rawY = ( rawY == null ) ? stageY : rawY ;
/ * *
* The native MouseEvent generated by the browser . The properties and API for this
* event may differ between browsers . This property will be null if the
* EaselJS property was not directly generated from a native MouseEvent .
* @ property nativeEvent
* @ type HtmlMouseEvent
* @ default null
* * /
this . nativeEvent = nativeEvent ;
/ * *
* The unique id for the pointer ( touch point or cursor ) . This will be either - 1 for the mouse , or the system
* supplied id value .
* @ property pointerID
* @ type { Number }
* /
this . pointerID = pointerID ;
/ * *
* Indicates whether this is the primary pointer in a multitouch environment . This will always be true for the mouse .
* For touch pointers , the first pointer in the current stack will be considered the primary pointer .
* @ property primary
* @ type { Boolean }
* /
this . primary = ! ! primary ;
}
var p = createjs . extend ( MouseEvent , createjs . Event ) ;
2014-01-03 13:32:13 -05:00
// getter / setters:
/ * *
* Returns the x position of the mouse in the local coordinate system of the current target ( ie . the dispatcher ) .
* @ property localX
* @ type { Number }
* @ readonly
* /
p . _get _localX = function ( ) {
return this . currentTarget . globalToLocal ( this . rawX , this . rawY ) . x ;
} ;
/ * *
* Returns the y position of the mouse in the local coordinate system of the current target ( ie . the dispatcher ) .
* @ property localY
* @ type { Number }
* @ readonly
* /
p . _get _localY = function ( ) {
return this . currentTarget . globalToLocal ( this . rawX , this . rawY ) . y ;
} ;
try {
Object . defineProperties ( p , {
localX : { get : p . _get _localX } ,
localY : { get : p . _get _localY }
} ) ;
} catch ( e ) { } // TODO: use Log
// public methods:
/ * *
* Returns a clone of the MouseEvent instance .
* @ method clone
* @ return { MouseEvent } a clone of the MouseEvent instance .
* * /
p . clone = function ( ) {
2014-11-18 18:26:26 -05:00
return new MouseEvent ( this . type , this . bubbles , this . cancelable , this . stageX , this . stageY , this . nativeEvent , this . pointerID , this . primary , this . rawX , this . rawY ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[MouseEvent (type=" + this . type + " stageX=" + this . stageX + " stageY=" + this . stageY + ")]" ;
} ;
2014-11-18 18:26:26 -05:00
createjs . MouseEvent = createjs . promote ( MouseEvent , "Event" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// Matrix2D.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Represents an affine transformation matrix , and provides tools for constructing and concatenating matrixes .
* @ class Matrix2D
* @ param { Number } [ a = 1 ] Specifies the a property for the new matrix .
* @ param { Number } [ b = 0 ] Specifies the b property for the new matrix .
* @ param { Number } [ c = 0 ] Specifies the c property for the new matrix .
* @ param { Number } [ d = 1 ] Specifies the d property for the new matrix .
* @ param { Number } [ tx = 0 ] Specifies the tx property for the new matrix .
* @ param { Number } [ ty = 0 ] Specifies the ty property for the new matrix .
* @ constructor
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
function Matrix2D ( a , b , c , d , tx , ty ) {
this . setValues ( a , b , c , d , tx , ty ) ;
// public properties:
// assigned in the setValues method.
/ * *
* Position ( 0 , 0 ) in a 3 x3 affine transformation matrix .
* @ property a
* @ type Number
* * /
/ * *
* Position ( 0 , 1 ) in a 3 x3 affine transformation matrix .
* @ property b
* @ type Number
* * /
/ * *
* Position ( 1 , 0 ) in a 3 x3 affine transformation matrix .
* @ property c
* @ type Number
* * /
/ * *
* Position ( 1 , 1 ) in a 3 x3 affine transformation matrix .
* @ property d
* @ type Number
* * /
/ * *
* Position ( 2 , 0 ) in a 3 x3 affine transformation matrix .
* @ property tx
* @ type Number
* * /
/ * *
* Position ( 2 , 1 ) in a 3 x3 affine transformation matrix .
* @ property ty
* @ type Number
* * /
}
var p = Matrix2D . prototype ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// constants:
2014-01-03 13:32:13 -05:00
/ * *
* Multiplier for converting degrees to radians . Used internally by Matrix2D .
* @ property DEG _TO _RAD
* @ static
* @ final
* @ type Number
* @ readonly
* * /
Matrix2D . DEG _TO _RAD = Math . PI / 180 ;
2014-11-18 18:26:26 -05:00
// static public properties:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* An identity matrix , representing a null transformation .
* @ property identity
* @ static
* @ type Matrix2D
* @ readonly
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
Matrix2D . identity = null ; // set at bottom of class definition.
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// public methods:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Sets the specified values on this instance .
* @ method setValues
* @ param { Number } [ a = 1 ] Specifies the a property for the new matrix .
* @ param { Number } [ b = 0 ] Specifies the b property for the new matrix .
* @ param { Number } [ c = 0 ] Specifies the c property for the new matrix .
* @ param { Number } [ d = 1 ] Specifies the d property for the new matrix .
* @ param { Number } [ tx = 0 ] Specifies the tx property for the new matrix .
* @ param { Number } [ ty = 0 ] Specifies the ty property for the new matrix .
* @ return { Matrix2D } This instance . Useful for chaining method calls .
* /
p . setValues = function ( a , b , c , d , tx , ty ) {
// don't forget to update docs in the constructor if these change:
this . a = ( a == null ) ? 1 : a ;
this . b = b || 0 ;
this . c = c || 0 ;
this . d = ( d == null ) ? 1 : d ;
this . tx = tx || 0 ;
this . ty = ty || 0 ;
return this ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Appends the specified matrix properties to this matrix . All parameters are required .
* This is the equivalent of multiplying ` (this matrix) * (specified matrix) ` .
* @ method append
* @ param { Number } a
* @ param { Number } b
* @ param { Number } c
* @ param { Number } d
* @ param { Number } tx
* @ param { Number } ty
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . append = function ( a , b , c , d , tx , ty ) {
2014-01-03 13:32:13 -05:00
var tx1 = this . tx ;
if ( a != 1 || b != 0 || c != 0 || d != 1 ) {
var a1 = this . a ;
var c1 = this . c ;
this . a = a1 * a + this . b * c ;
this . b = a1 * b + this . b * d ;
this . c = c1 * a + this . d * c ;
this . d = c1 * b + this . d * d ;
}
this . tx = tx1 * a + this . ty * c + tx ;
this . ty = tx1 * b + this . ty * d + ty ;
return this ;
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Prepends the specified matrix properties to this matrix .
* This is the equivalent of multiplying ` (specified matrix) * (this matrix) ` .
* All parameters are required .
* @ method prepend
2014-01-03 13:32:13 -05:00
* @ param { Number } a
* @ param { Number } b
* @ param { Number } c
* @ param { Number } d
* @ param { Number } tx
* @ param { Number } ty
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* * /
2014-11-18 18:26:26 -05:00
p . prepend = function ( a , b , c , d , tx , ty ) {
2014-01-03 13:32:13 -05:00
var a1 = this . a ;
var b1 = this . b ;
var c1 = this . c ;
var d1 = this . d ;
this . a = a * a1 + b * c1 ;
this . b = a * b1 + b * d1 ;
this . c = c * a1 + d * c1 ;
this . d = c * b1 + d * d1 ;
this . tx = tx * a1 + ty * c1 + this . tx ;
this . ty = tx * b1 + ty * d1 + this . ty ;
return this ;
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Appends the specified matrix to this matrix .
* This is the equivalent of multiplying ` (this matrix) * (specified matrix) ` .
* For example , you could calculate the combined transformation for a child object using :
* var o = myDisplayObject ;
* var mtx = o . getMatrix ( ) ;
* while ( o = o . parent ) {
* // append each parent's transformation in turn:
* o . appendMatrix ( o . getMatrix ( ) ) ;
* }
* @ method appendMatrix
2014-01-03 13:32:13 -05:00
* @ param { Matrix2D } matrix
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* * /
2014-11-18 18:26:26 -05:00
p . appendMatrix = function ( matrix ) {
return this . append ( matrix . a , matrix . b , matrix . c , matrix . d , matrix . tx , matrix . ty ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Prepends the specified matrix to this matrix .
* This is the equivalent of multiplying ` (specified matrix) * (this matrix) ` .
* @ method prependMatrix
2014-01-03 13:32:13 -05:00
* @ param { Matrix2D } matrix
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* * /
2014-11-18 18:26:26 -05:00
p . prependMatrix = function ( matrix ) {
return this . prepend ( matrix . a , matrix . b , matrix . c , matrix . d , matrix . tx , matrix . ty ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Generates matrix properties from the specified display object transform properties , and appends them to this matrix .
* For example , you can use this to generate a matrix from a display object :
*
* var mtx = new Matrix2D ( ) ;
* mtx . appendTransform ( o . x , o . y , o . scaleX , o . scaleY , o . rotation ) ;
* @ method appendTransform
2014-01-03 13:32:13 -05:00
* @ param { Number } x
* @ param { Number } y
* @ param { Number } scaleX
* @ param { Number } scaleY
* @ param { Number } rotation
* @ param { Number } skewX
* @ param { Number } skewY
* @ param { Number } regX Optional .
* @ param { Number } regY Optional .
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* * /
2014-11-18 18:26:26 -05:00
p . appendTransform = function ( x , y , scaleX , scaleY , rotation , skewX , skewY , regX , regY ) {
2014-01-03 13:32:13 -05:00
if ( rotation % 360 ) {
var r = rotation * Matrix2D . DEG _TO _RAD ;
var cos = Math . cos ( r ) ;
var sin = Math . sin ( r ) ;
} else {
cos = 1 ;
sin = 0 ;
}
if ( regX || regY ) {
// append the registration offset:
this . tx -= regX ; this . ty -= regY ;
}
if ( skewX || skewY ) {
// TODO: can this be combined into a single prepend operation?
skewX *= Matrix2D . DEG _TO _RAD ;
skewY *= Matrix2D . DEG _TO _RAD ;
2014-11-18 18:26:26 -05:00
this . append ( cos * scaleX , sin * scaleX , - sin * scaleY , cos * scaleY , 0 , 0 ) ;
this . append ( Math . cos ( skewY ) , Math . sin ( skewY ) , - Math . sin ( skewX ) , Math . cos ( skewX ) , x , y ) ;
2014-01-03 13:32:13 -05:00
} else {
2014-11-18 18:26:26 -05:00
this . append ( cos * scaleX , sin * scaleX , - sin * scaleY , cos * scaleY , x , y ) ;
2014-01-03 13:32:13 -05:00
}
return this ;
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Generates matrix properties from the specified display object transform properties , and prepends them to this matrix .
* For example , you can use this to generate a matrix from a display object :
*
* var mtx = new Matrix2D ( ) ;
* mtx . prependTransform ( o . x , o . y , o . scaleX , o . scaleY , o . rotation ) ;
* @ method prependTransform
2014-01-03 13:32:13 -05:00
* @ param { Number } x
* @ param { Number } y
* @ param { Number } scaleX
* @ param { Number } scaleY
* @ param { Number } rotation
* @ param { Number } skewX
* @ param { Number } skewY
* @ param { Number } regX Optional .
* @ param { Number } regY Optional .
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* * /
2014-11-18 18:26:26 -05:00
p . prependTransform = function ( x , y , scaleX , scaleY , rotation , skewX , skewY , regX , regY ) {
2014-01-03 13:32:13 -05:00
if ( rotation % 360 ) {
var r = rotation * Matrix2D . DEG _TO _RAD ;
var cos = Math . cos ( r ) ;
var sin = Math . sin ( r ) ;
} else {
cos = 1 ;
sin = 0 ;
}
if ( skewX || skewY ) {
// TODO: can this be combined into a single append?
skewX *= Matrix2D . DEG _TO _RAD ;
skewY *= Matrix2D . DEG _TO _RAD ;
2014-11-18 18:26:26 -05:00
this . prepend ( Math . cos ( skewY ) , Math . sin ( skewY ) , - Math . sin ( skewX ) , Math . cos ( skewX ) , x , y ) ;
this . prepend ( cos * scaleX , sin * scaleX , - sin * scaleY , cos * scaleY , 0 , 0 ) ;
2014-01-03 13:32:13 -05:00
} else {
2014-11-18 18:26:26 -05:00
this . prepend ( cos * scaleX , sin * scaleX , - sin * scaleY , cos * scaleY , x , y ) ;
2014-01-03 13:32:13 -05:00
}
if ( regX || regY ) {
// prepend the registration offset:
this . tx -= regX * this . a + regY * this . c ;
this . ty -= regX * this . b + regY * this . d ;
}
return this ;
} ;
/ * *
* Applies a rotation transformation to the matrix .
* @ method rotate
2014-11-18 18:26:26 -05:00
* @ param { Number } angle The angle in radians . To use degrees , multiply by ` Math.PI/180 ` .
2014-01-03 13:32:13 -05:00
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* * /
p . rotate = function ( angle ) {
var cos = Math . cos ( angle ) ;
var sin = Math . sin ( angle ) ;
var a1 = this . a ;
var c1 = this . c ;
var tx1 = this . tx ;
this . a = a1 * cos - this . b * sin ;
this . b = a1 * sin + this . b * cos ;
this . c = c1 * cos - this . d * sin ;
this . d = c1 * sin + this . d * cos ;
this . tx = tx1 * cos - this . ty * sin ;
this . ty = tx1 * sin + this . ty * cos ;
return this ;
} ;
/ * *
* Applies a skew transformation to the matrix .
* @ method skew
* @ param { Number } skewX The amount to skew horizontally in degrees .
* @ param { Number } skewY The amount to skew vertically in degrees .
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* /
p . skew = function ( skewX , skewY ) {
skewX = skewX * Matrix2D . DEG _TO _RAD ;
skewY = skewY * Matrix2D . DEG _TO _RAD ;
2014-11-18 18:26:26 -05:00
this . prepend ( Math . cos ( skewY ) , Math . sin ( skewY ) , - Math . sin ( skewX ) , Math . cos ( skewX ) , 0 , 0 ) ;
2014-01-03 13:32:13 -05:00
return this ;
} ;
/ * *
* Applies a scale transformation to the matrix .
* @ method scale
* @ param { Number } x The amount to scale horizontally
* @ param { Number } y The amount to scale vertically
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* * /
p . scale = function ( x , y ) {
this . a *= x ;
this . d *= y ;
this . c *= x ;
this . b *= y ;
this . tx *= x ;
this . ty *= y ;
return this ;
} ;
/ * *
* Translates the matrix on the x and y axes .
* @ method translate
* @ param { Number } x
* @ param { Number } y
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* * /
p . translate = function ( x , y ) {
this . tx += x ;
this . ty += y ;
return this ;
} ;
/ * *
* Sets the properties of the matrix to those of an identity matrix ( one that applies a null transformation ) .
* @ method identity
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* * /
p . identity = function ( ) {
2014-11-18 18:26:26 -05:00
this . a = this . d = 1 ;
2014-01-03 13:32:13 -05:00
this . b = this . c = this . tx = this . ty = 0 ;
return this ;
} ;
/ * *
* Inverts the matrix , causing it to perform the opposite transformation .
* @ method invert
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* * /
p . invert = function ( ) {
var a1 = this . a ;
var b1 = this . b ;
var c1 = this . c ;
var d1 = this . d ;
var tx1 = this . tx ;
var n = a1 * d1 - b1 * c1 ;
this . a = d1 / n ;
this . b = - b1 / n ;
this . c = - c1 / n ;
this . d = a1 / n ;
this . tx = ( c1 * this . ty - d1 * tx1 ) / n ;
this . ty = - ( a1 * this . ty - b1 * tx1 ) / n ;
return this ;
} ;
/ * *
* Returns true if the matrix is an identity matrix .
* @ method isIdentity
* @ return { Boolean }
* * /
p . isIdentity = function ( ) {
2014-11-18 18:26:26 -05:00
return this . tx === 0 && this . ty === 0 && this . a === 1 && this . b === 0 && this . c === 0 && this . d === 1 ;
} ;
/ * *
* Returns true if this matrix is equal to the specified matrix ( all property values are equal ) .
* @ method equals
* @ param { Matrix2D } matrix The matrix to compare .
* @ return { Boolean }
* * /
p . equals = function ( matrix ) {
return this . tx === matrix . tx && this . ty === matrix . ty && this . a === matrix . a && this . b === matrix . b && this . c === matrix . c && this . d === matrix . d ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Transforms a point according to this matrix .
* @ method transformPoint
* @ param { Number } x The x component of the point to transform .
* @ param { Number } y The y component of the point to transform .
* @ param { Point | Object } [ pt ] An object to copy the result into . If omitted a generic object with x / y properties will be returned .
* @ return { Point } This matrix . Useful for chaining method calls .
* * /
p . transformPoint = function ( x , y , pt ) {
pt = pt || { } ;
pt . x = x * this . a + y * this . c + this . tx ;
pt . y = x * this . b + y * this . d + this . ty ;
return pt ;
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Decomposes the matrix into transform properties ( x , y , scaleX , scaleY , and rotation ) . Note that these values
2014-01-03 13:32:13 -05:00
* may not match the transform properties you used to generate the matrix , though they will produce the same visual
* results .
* @ method decompose
* @ param { Object } target The object to apply the transform properties to . If null , then a new object will be returned .
2014-11-18 18:26:26 -05:00
* @ return { Object } The target , or a new generic object with the transform properties applied .
2014-01-03 13:32:13 -05:00
* /
p . decompose = function ( target ) {
2014-11-18 18:26:26 -05:00
// 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
2014-01-03 13:32:13 -05:00
if ( target == null ) { target = { } ; }
target . x = this . tx ;
target . y = this . ty ;
target . scaleX = Math . sqrt ( this . a * this . a + this . b * this . b ) ;
target . scaleY = Math . sqrt ( this . c * this . c + this . d * this . d ) ;
var skewX = Math . atan2 ( - this . c , this . d ) ;
var skewY = Math . atan2 ( this . b , this . a ) ;
2014-11-18 18:26:26 -05:00
var delta = Math . abs ( 1 - skewX / skewY ) ;
if ( delta < 0.00001 ) { // effectively identical, can use rotation:
2014-01-03 13:32:13 -05:00
target . rotation = skewY / Matrix2D . DEG _TO _RAD ;
if ( this . a < 0 && this . d >= 0 ) {
target . rotation += ( target . rotation <= 0 ) ? 180 : - 180 ;
}
target . skewX = target . skewY = 0 ;
} else {
target . skewX = skewX / Matrix2D . DEG _TO _RAD ;
target . skewY = skewY / Matrix2D . DEG _TO _RAD ;
}
return target ;
} ;
/ * *
* Copies all properties from the specified matrix to this matrix .
* @ method copy
* @ param { Matrix2D } matrix The matrix to copy properties from .
* @ return { Matrix2D } This matrix . Useful for chaining method calls .
* /
p . copy = function ( matrix ) {
2014-11-18 18:26:26 -05:00
return this . setValues ( matrix . a , matrix . b , matrix . c , matrix . d , matrix . tx , matrix . ty ) ;
} ;
/ * *
* Returns a clone of the Matrix2D instance .
* @ method clone
* @ return { Matrix2D } a clone of the Matrix2D instance .
* * /
p . clone = function ( ) {
return new Matrix2D ( this . a , this . b , this . c , this . d , this . tx , this . ty ) ;
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Matrix2D (a=" + this . a + " b=" + this . b + " c=" + this . c + " d=" + this . d + " tx=" + this . tx + " ty=" + this . ty + ")]" ;
} ;
// this has to be populated after the class is defined:
Matrix2D . identity = new Matrix2D ( ) ;
createjs . Matrix2D = Matrix2D ;
} ( ) ) ;
//##############################################################################
// DisplayProps.js
//##############################################################################
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
/ * *
* Used for calculating and encapsulating display related properties .
* @ class DisplayProps
* @ param { Number } [ visible = true ] Visible value .
* @ param { Number } [ alpha = 0 ] Alpha value .
* @ param { Number } [ shadow = null ] A Shadow instance or null .
* @ param { Number } [ compositeOperation = null ] A compositeOperation value or null .
* @ param { Number } [ matrix ] A transformation matrix . Defaults to a new identity matrix .
* @ constructor
* * /
function DisplayProps ( visible , alpha , shadow , compositeOperation , matrix ) {
this . setValues ( visible , alpha , shadow , compositeOperation , matrix ) ;
// public properties:
// assigned in the setValues method.
/ * *
* Property representing the alpha that will be applied to a display object .
* @ property alpha
* @ type Number
* * /
/ * *
* Property representing the shadow that will be applied to a display object .
* @ property shadow
* @ type Shadow
* * /
/ * *
* Property representing the compositeOperation that will be applied to a display object .
* You can find a list of valid composite operations at :
* < a href = "https://developer.mozilla.org/en/Canvas_tutorial/Compositing" > https : //developer.mozilla.org/en/Canvas_tutorial/Compositing</a>
* @ property compositeOperation
* @ type String
* * /
/ * *
* Property representing the value for visible that will be applied to a display object .
* @ property visible
* @ type Boolean
* * /
/ * *
* The transformation matrix that will be applied to a display object .
* @ property matrix
* @ type Matrix2D
* * /
}
var p = DisplayProps . prototype ;
// initialization:
/ * *
* Reinitializes the instance with the specified values .
* @ method setValues
* @ param { Number } [ visible = true ] Visible value .
* @ param { Number } [ alpha = 1 ] Alpha value .
* @ param { Number } [ shadow = null ] A Shadow instance or null .
* @ param { Number } [ compositeOperation = null ] A compositeOperation value or null .
* @ param { Number } [ matrix ] A transformation matrix . Defaults to an identity matrix .
* @ return { DisplayProps } This instance . Useful for chaining method calls .
* /
p . setValues = function ( visible , alpha , shadow , compositeOperation , matrix ) {
this . visible = visible == null ? true : ! ! visible ;
this . alpha = alpha == null ? 1 : alpha ;
this . shadow = shadow ;
this . compositeOperation = shadow ;
this . matrix = matrix || ( this . matrix && this . matrix . identity ( ) ) || new createjs . Matrix2D ( ) ;
return this ;
2014-01-03 13:32:13 -05:00
} ;
2014-11-18 18:26:26 -05:00
// public methods:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Prepends the specified display properties . This is generally used to apply a parent 's properties to a child' s .
* For example , to get the combined display properties that would be applied to a child , you could use :
* var o = myDisplayObject ;
* var props = new createjs . DisplayProps ( ) ;
* do {
* // append each parent's props in turn:
* props . append ( o . visible , o . alpha , o . shadow , o . compositeOperation , o . getMatrix ( ) ) ;
* o = o . parent ;
* } while ( o ) ;
* @ method prepend
* @ param { Boolean } visible desired visible value
2014-01-03 13:32:13 -05:00
* @ param { Number } alpha desired alpha value
* @ param { Shadow } shadow desired shadow value
* @ param { String } compositeOperation desired composite operation value
2014-11-18 18:26:26 -05:00
* @ param { Matrix2D } [ matrix ] a Matrix2D instance
* @ return { DisplayProps } This instance . Useful for chaining method calls .
2014-01-03 13:32:13 -05:00
* /
2014-11-18 18:26:26 -05:00
p . prepend = function ( visible , alpha , shadow , compositeOperation , matrix ) {
2014-01-03 13:32:13 -05:00
this . alpha *= alpha ;
this . shadow = shadow || this . shadow ;
this . compositeOperation = compositeOperation || this . compositeOperation ;
2014-02-02 19:31:06 -05:00
this . visible = this . visible && visible ;
2014-11-18 18:26:26 -05:00
matrix && this . matrix . prependMatrix ( matrix ) ;
2014-01-03 13:32:13 -05:00
return this ;
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Appends the specified display properties . This is generally used to apply a child 's properties its parent' s .
* @ method append
* @ param { Boolean } visible desired visible value
2014-01-03 13:32:13 -05:00
* @ param { Number } alpha desired alpha value
* @ param { Shadow } shadow desired shadow value
* @ param { String } compositeOperation desired composite operation value
2014-11-18 18:26:26 -05:00
* @ param { Matrix2D } [ matrix ] a Matrix2D instance
* @ return { DisplayProps } This instance . Useful for chaining method calls .
2014-01-03 13:32:13 -05:00
* /
2014-11-18 18:26:26 -05:00
p . append = function ( visible , alpha , shadow , compositeOperation , matrix ) {
2014-01-03 13:32:13 -05:00
this . alpha *= alpha ;
this . shadow = this . shadow || shadow ;
this . compositeOperation = this . compositeOperation || compositeOperation ;
2014-02-02 19:31:06 -05:00
this . visible = this . visible && visible ;
2014-11-18 18:26:26 -05:00
matrix && this . matrix . appendMatrix ( matrix ) ;
2014-01-03 13:32:13 -05:00
return this ;
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Resets this instance and its matrix to default values .
* @ method identity
* @ return { DisplayProps } This instance . Useful for chaining method calls .
* /
p . identity = function ( ) {
this . visible = true ;
this . alpha = 1 ;
this . shadow = this . compositeOperation = null ;
this . matrix . identity ( ) ;
return this ;
2014-01-03 13:32:13 -05:00
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Returns a clone of the DisplayProps instance . Clones the associated matrix .
* @ method clone
* @ return { DisplayProps } a clone of the DisplayProps instance .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . clone = function ( ) {
return new DisplayProps ( this . alpha , this . shadow , this . compositeOperation , this . visible , this . matrix . clone ( ) ) ;
2014-01-03 13:32:13 -05:00
} ;
2014-11-18 18:26:26 -05:00
// private methods:
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
createjs . DisplayProps = DisplayProps ;
} ) ( ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
//##############################################################################
// Point.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Represents a point on a 2 dimensional x / y coordinate system .
*
* < h4 > Example < / h 4 >
*
* var point = new createjs . Point ( 0 , 100 ) ;
*
* @ class Point
* @ param { Number } [ x = 0 ] X position .
* @ param { Number } [ y = 0 ] Y position .
* @ constructor
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
function Point ( x , y ) {
this . setValues ( x , y ) ;
// public properties:
// assigned in the setValues method.
/ * *
* X position .
* @ property x
* @ type Number
* * /
/ * *
* Y position .
* @ property y
* @ type Number
* * /
}
var p = Point . prototype ;
// public methods:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Sets the specified values on this instance .
* @ method setValues
2014-01-03 13:32:13 -05:00
* @ param { Number } [ x = 0 ] X position .
* @ param { Number } [ y = 0 ] Y position .
* @ return { Point } This instance . Useful for chaining method calls .
* /
2014-11-18 18:26:26 -05:00
p . setValues = function ( x , y ) {
this . x = x || 0 ;
this . y = y || 0 ;
2014-01-03 13:32:13 -05:00
return this ;
} ;
/ * *
* Copies all properties from the specified point to this point .
* @ method copy
* @ param { Point } point The point to copy properties from .
* @ return { Point } This point . Useful for chaining method calls .
* /
p . copy = function ( point ) {
2014-11-18 18:26:26 -05:00
this . x = point . x ;
this . y = point . y ;
return this ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns a clone of the Point instance .
* @ method clone
* @ return { Point } a clone of the Point instance .
* * /
p . clone = function ( ) {
return new Point ( this . x , this . y ) ;
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Point (x=" + this . x + " y=" + this . y + ")]" ;
} ;
2014-11-18 18:26:26 -05:00
createjs . Point = Point ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// Rectangle.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Represents a rectangle as defined by the points ( x , y ) and ( x + width , y + height ) .
*
* < h4 > Example < / h 4 >
*
* var rect = new createjs . Rectangle ( 0 , 0 , 100 , 100 ) ;
*
* @ class Rectangle
* @ param { Number } [ x = 0 ] X position .
* @ param { Number } [ y = 0 ] Y position .
* @ param { Number } [ width = 0 ] The width of the Rectangle .
* @ param { Number } [ height = 0 ] The height of the Rectangle .
* @ constructor
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
function Rectangle ( x , y , width , height ) {
this . setValues ( x , y , width , height ) ;
// public properties:
// assigned in the setValues method.
/ * *
* X position .
* @ property x
* @ type Number
* * /
/ * *
* Y position .
* @ property y
* @ type Number
* * /
/ * *
* Width .
* @ property width
* @ type Number
* * /
/ * *
* Height .
* @ property height
* @ type Number
* * /
}
var p = Rectangle . prototype ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// public methods:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Sets the specified values on this instance .
* @ method setValues
2014-01-03 13:32:13 -05:00
* @ param { Number } [ x = 0 ] X position .
* @ param { Number } [ y = 0 ] Y position .
* @ param { Number } [ width = 0 ] The width of the Rectangle .
* @ param { Number } [ height = 0 ] The height of the Rectangle .
* @ return { Rectangle } This instance . Useful for chaining method calls .
* /
2014-11-18 18:26:26 -05:00
p . setValues = function ( x , y , width , height ) {
// don't forget to update docs in the constructor if these change:
2014-01-03 13:32:13 -05:00
this . x = x || 0 ;
this . y = y || 0 ;
this . width = width || 0 ;
this . height = height || 0 ;
return this ;
} ;
2014-11-18 18:26:26 -05:00
/ * *
* Extends the rectangle ' s bounds to include the described point or rectangle .
* @ method extend
* @ param { Number } x X position of the point or rectangle .
* @ param { Number } y Y position of the point or rectangle .
* @ param { Number } [ width = 0 ] The width of the rectangle .
* @ param { Number } [ height = 0 ] The height of the rectangle .
* @ return { Rectangle } This instance . Useful for chaining method calls .
* /
p . extend = function ( x , y , width , height ) {
width = width || 0 ;
height = height || 0 ;
if ( x + width > this . x + this . width ) { this . width = x + width - this . x ; }
if ( y + height > this . y + this . height ) { this . height = y + height - this . y ; }
if ( x < this . x ) { this . width += this . x - x ; this . x = x ; }
if ( y < this . y ) { this . height += this . y - y ; this . y = y ; }
return this ;
} ;
/ * *
* Returns true if this rectangle fully encloses the described point or rectangle .
* @ method contains
* @ param { Number } x X position of the point or rectangle .
* @ param { Number } y Y position of the point or rectangle .
* @ param { Number } [ width = 0 ] The width of the rectangle .
* @ param { Number } [ height = 0 ] The height of the rectangle .
* @ return { Boolean } True if the described point or rectangle is contained within this rectangle .
* /
p . contains = function ( x , y , width , height ) {
width = width || 0 ;
height = height || 0 ;
return ( x >= this . x && x + width <= this . x + this . width && y >= this . y && y + height <= this . y + this . height ) ;
} ;
/ * *
* Returns a new rectangle which contains this rectangle and the specified rectangle .
* @ method union
* @ param { Rectangle } rect The rectangle to calculate a union with .
* @ return { Rectangle } A new rectangle describing the union .
* /
p . union = function ( rect ) {
return this . clone ( ) . extend ( rect . x , rect . y , rect . width , rect . height ) ;
} ;
/ * *
* Returns a new rectangle which describes the intersection ( overlap ) of this rectangle and the specified rectangle ,
* or null if they do not intersect .
* @ method intersection
* @ param { Rectangle } rect The rectangle to calculate an intersection with .
* @ return { Rectangle } A new rectangle describing the intersection or null .
* /
p . intersection = function ( rect ) {
var x1 = rect . x , y1 = rect . y , x2 = x1 + rect . width , y2 = y1 + rect . height ;
if ( this . x > x1 ) { x1 = this . x ; }
if ( this . y > y1 ) { y1 = this . y ; }
if ( this . x + this . width < x2 ) { x2 = this . x + this . width ; }
if ( this . y + this . height < y2 ) { y2 = this . y + this . height ; }
return ( x2 <= x1 || y2 <= y1 ) ? null : new Rectangle ( x1 , y1 , x2 - x1 , y2 - y1 ) ;
} ;
/ * *
* Returns true if the specified rectangle intersects ( has any overlap ) with this rectangle .
* @ method intersects
* @ param { Rectangle } rect The rectangle to compare .
* @ return { Boolean } True if the rectangles intersect .
* /
p . intersects = function ( rect ) {
return ( rect . x <= this . x + this . width && this . x <= rect . x + rect . width && rect . y <= this . y + this . height && this . y <= rect . y + rect . height ) ;
} ;
/ * *
* Returns true if the width or height are equal or less than 0.
* @ method isEmpty
* @ return { Boolean } True if the rectangle is empty .
* /
p . isEmpty = function ( ) {
return this . width <= 0 || this . height <= 0 ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
* Copies all properties from the specified rectangle to this rectangle .
* @ method copy
* @ param { Rectangle } rectangle The rectangle to copy properties from .
* @ return { Rectangle } This rectangle . Useful for chaining method calls .
* /
p . copy = function ( rectangle ) {
2014-11-18 18:26:26 -05:00
return this . setValues ( rectangle . x , rectangle . y , rectangle . width , rectangle . height ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns a clone of the Rectangle instance .
* @ method clone
* @ return { Rectangle } a clone of the Rectangle instance .
* * /
p . clone = function ( ) {
return new Rectangle ( this . x , this . y , this . width , this . height ) ;
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Rectangle (x=" + this . x + " y=" + this . y + " width=" + this . width + " height=" + this . height + ")]" ;
} ;
2014-11-18 18:26:26 -05:00
createjs . Rectangle = Rectangle ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// ButtonHelper.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* The ButtonHelper is a helper class to create interactive buttons from { { # crossLink "MovieClip" } } { { / c r o s s L i n k } } o r
* { { # crossLink "Sprite" } } { { / c r o s s L i n k } } i n s t a n c e s . T h i s c l a s s w i l l i n t e r c e p t m o u s e e v e n t s f r o m a n o b j e c t , a n d
* automatically call { { # crossLink "Sprite/gotoAndStop" } } { { / c r o s s L i n k } } o r { { # c r o s s L i n k " S p r i t e / g o t o A n d P l a y " } } { { / c r o s s L i n k } } ,
* to the respective animation labels , add a pointer cursor , and allows the user to define a hit state frame .
*
* The ButtonHelper instance does not need to be added to the stage , but a reference should be maintained to prevent
* garbage collection .
*
* Note that over states will not work unless you call { { # crossLink "Stage/enableMouseOver" } } { { / c r o s s L i n k } } .
*
* < h4 > Example < / h 4 >
*
* var helper = new createjs . ButtonHelper ( myInstance , "out" , "over" , "down" , false , myInstance , "hit" ) ;
* myInstance . addEventListener ( "click" , handleClick ) ;
* function handleClick ( event ) {
* // Click Happened.
* }
*
* @ class ButtonHelper
* @ param { Sprite | MovieClip } target The instance to manage .
* @ param { String } [ outLabel = "out" ] The label or animation to go to when the user rolls out of the button .
* @ param { String } [ overLabel = "over" ] The label or animation to go to when the user rolls over the button .
* @ param { String } [ downLabel = "down" ] The label or animation to go to when the user presses the button .
* @ param { Boolean } [ play = false ] If the helper should call "gotoAndPlay" or "gotoAndStop" on the button when changing
* states .
* @ param { DisplayObject } [ hitArea ] An optional item to use as the hit state for the button . If this is not defined ,
* then the button ' s visible states will be used instead . Note that the same instance as the "target" argument can be
* used for the hitState .
* @ param { String } [ hitLabel ] The label or animation on the hitArea instance that defines the hitArea bounds . If this is
* null , then the default state of the hitArea will be used . *
* @ constructor
* /
function ButtonHelper ( target , outLabel , overLabel , downLabel , play , hitArea , hitLabel ) {
if ( ! target . addEventListener ) { return ; }
// public properties:
/ * *
* The target for this button helper .
* @ property target
* @ type MovieClip | Sprite
* @ readonly
* * /
this . target = target ;
/ * *
* The label name or frame number to display when the user mouses out of the target . Defaults to "over" .
* @ property overLabel
* @ type String | Number
* * /
this . overLabel = overLabel == null ? "over" : overLabel ;
/ * *
* The label name or frame number to display when the user mouses over the target . Defaults to "out" .
* @ property outLabel
* @ type String | Number
* * /
this . outLabel = outLabel == null ? "out" : outLabel ;
/ * *
* The label name or frame number to display when the user presses on the target . Defaults to "down" .
* @ property downLabel
* @ type String | Number
* * /
this . downLabel = downLabel == null ? "down" : downLabel ;
/ * *
* If true , then ButtonHelper will call gotoAndPlay , if false , it will use gotoAndStop . Default is false .
* @ property play
* @ default false
* @ type Boolean
* * /
this . play = play ;
// private properties
/ * *
* @ property _isPressed
* @ type Boolean
* @ protected
* * /
this . _isPressed = false ;
/ * *
* @ property _isOver
* @ type Boolean
* @ protected
* * /
this . _isOver = false ;
/ * *
* @ property _enabled
* @ type Boolean
* @ protected
* * /
this . _enabled = false ;
// setup:
target . mouseChildren = false ; // prevents issues when children are removed from the display list when state changes.
this . enabled = true ;
this . handleEvent ( { } ) ;
if ( hitArea ) {
if ( hitLabel ) {
hitArea . actionsEnabled = false ;
hitArea . gotoAndStop && hitArea . gotoAndStop ( hitLabel ) ;
}
target . hitArea = hitArea ;
}
}
var p = ButtonHelper . prototype ;
2014-01-03 13:32:13 -05:00
2014-02-02 19:31:06 -05:00
// getter / setters:
/ * *
* Enables or disables the button functionality on the target .
* @ property enabled
* @ type { Boolean }
* * /
/ * *
* Enables or disables the button functionality on the target .
* @ deprecated in favour of the enabled property .
* @ method setEnabled
* @ param { Boolean } value
* * /
p . setEnabled = function ( value ) { // TODO: deprecated.
2014-11-18 18:26:26 -05:00
if ( value == this . _enabled ) { return ; }
2014-02-02 19:31:06 -05:00
var o = this . target ;
this . _enabled = value ;
if ( value ) {
o . cursor = "pointer" ;
o . addEventListener ( "rollover" , this ) ;
o . addEventListener ( "rollout" , this ) ;
o . addEventListener ( "mousedown" , this ) ;
o . addEventListener ( "pressup" , this ) ;
} else {
o . cursor = null ;
o . removeEventListener ( "rollover" , this ) ;
o . removeEventListener ( "rollout" , this ) ;
o . removeEventListener ( "mousedown" , this ) ;
o . removeEventListener ( "pressup" , this ) ;
}
} ;
/ * *
* Returns enabled state of this instance .
* @ deprecated in favour of the enabled property .
* @ method getEnabled
* @ return { Boolean } The last value passed to setEnabled ( ) .
* * /
p . getEnabled = function ( ) {
return this . _enabled ;
} ;
try {
Object . defineProperties ( p , {
enabled : { get : p . getEnabled , set : p . setEnabled }
} ) ;
} catch ( e ) { } // TODO: use Log
2014-01-03 13:32:13 -05:00
// public methods:
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[ButtonHelper]" ;
} ;
2014-11-18 18:26:26 -05:00
// private methods:
2014-01-03 13:32:13 -05:00
/ * *
* @ method handleEvent
* @ param { Object } evt The mouse event to handle .
* @ protected
* * /
p . handleEvent = function ( evt ) {
var label , t = this . target , type = evt . type ;
if ( type == "mousedown" ) {
this . _isPressed = true ;
label = this . downLabel ;
} else if ( type == "pressup" ) {
this . _isPressed = false ;
label = this . _isOver ? this . overLabel : this . outLabel ;
} else if ( type == "rollover" ) {
this . _isOver = true ;
label = this . _isPressed ? this . downLabel : this . overLabel ;
} else { // rollout and default
this . _isOver = false ;
label = this . _isPressed ? this . overLabel : this . outLabel ;
}
if ( this . play ) {
t . gotoAndPlay && t . gotoAndPlay ( label ) ;
} else {
t . gotoAndStop && t . gotoAndStop ( label ) ;
}
} ;
2014-11-18 18:26:26 -05:00
createjs . ButtonHelper = ButtonHelper ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// Shadow.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
/ * *
* This class encapsulates the properties required to define a shadow to apply to a { { # crossLink "DisplayObject" } } { { / c r o s s L i n k } }
* via its < code > shadow < / c o d e > p r o p e r t y .
*
* < h4 > Example < / h 4 >
*
* myImage . shadow = new createjs . Shadow ( "#000000" , 5 , 5 , 10 ) ;
*
* @ class Shadow
* @ constructor
* @ param { String } color The color of the shadow .
* @ param { Number } offsetX The x offset of the shadow in pixels .
* @ param { Number } offsetY The y offset of the shadow in pixels .
* @ param { Number } blur The size of the blurring effect .
* * /
function Shadow ( color , offsetX , offsetY , blur ) {
// public properties:
/ * * T h e c o l o r o f t h e s h a d o w .
* property color
* @ type String
* @ default null
* /
this . color = color || "black" ;
/ * * T h e x o f f s e t o f t h e s h a d o w .
* property offsetX
* @ type Number
* @ default 0
* /
this . offsetX = offsetX || 0 ;
/ * * T h e y o f f s e t o f t h e s h a d o w .
* property offsetY
* @ type Number
* @ default 0
* /
this . offsetY = offsetY || 0 ;
/ * * T h e b l u r o f t h e s h a d o w .
* property blur
* @ type Number
* @ default 0
* /
this . blur = blur || 0 ;
}
var p = Shadow . prototype ;
2014-01-03 13:32:13 -05:00
// static public properties:
/ * *
* An identity shadow object ( all properties are set to 0 ) .
* @ property identity
* @ type Shadow
* @ static
* @ final
* @ readonly
* * /
2014-11-18 18:26:26 -05:00
Shadow . identity = new Shadow ( "transparent" , 0 , 0 , 0 ) ;
2014-01-03 13:32:13 -05:00
// public methods:
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Shadow]" ;
} ;
/ * *
* Returns a clone of this Shadow instance .
* @ method clone
* @ return { Shadow } A clone of the current Shadow instance .
* * /
p . clone = function ( ) {
return new Shadow ( this . color , this . offsetX , this . offsetY , this . blur ) ;
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
createjs . Shadow = Shadow ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// SpriteSheet.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
/ * *
* Encapsulates the properties and methods associated with a sprite sheet . A sprite sheet is a series of images ( usually
* animation frames ) combined into a larger image ( or images ) . For example , an animation consisting of eight 100 x100
* images could be combined into a single 400 x200 sprite sheet ( 4 frames across by 2 high ) .
*
* The data passed to the SpriteSheet constructor defines : < ol >
* < li > The source image or images to use . < / l i >
* < li > The positions of individual image frames . < / l i >
* < li > Sequences of frames that form named animations . Optional . < / l i >
* < li > The target playback framerate . Optional . < / l i >
* < / O L >
*
* < h3 > SpriteSheet Format < / h 3 >
*
* SpriteSheets are an object with two required properties ( ` images ` and ` frames ` ) , and two optional properties
* ( ` framerate ` and ` animations ` ) . This makes them easy to define in javascript code , or in JSON .
*
* < h4 > images < / h 4 >
* An array of source images . Images can be either an HTMLImage
* instance , or a uri to an image . The former is recommended to control preloading .
*
* images : [ image1 , "path/to/image2.png" ] ,
*
* < h4 > frames < / h 4 >
* Defines the individual frames . There are two supported formats for frame data : < OL >
* < LI > when all of the frames are the same size ( in a grid ) , use an object with ` width ` , ` height ` , ` regX ` , ` regY ` , and ` count ` properties .
* ` width ` & ` height ` are required and specify the dimensions of the frames .
* ` regX ` & ` regY ` indicate the registration point or "origin" of the frames .
* ` count ` allows you to specify the total number of frames in the spritesheet ; if omitted , this will be calculated
* based on the dimensions of the source images and the frames . Frames will be assigned indexes based on their position
* in the source images ( left to right , top to bottom ) .
*
* frames : { width : 64 , height : 64 , count : 20 , regX : 32 , regY : 64 }
*
* < LI > if the frames are of different sizes , use an array of frame definitions . Each definition is itself an array
* with 4 required and 3 optional entries , in the order : ` x ` , ` y ` , ` width ` , ` height ` , ` imageIndex ` , ` regX ` , ` regY ` . The first
* four entries are required and define the frame rectangle . The fifth specifies the index of the source image ( defaults to 0 ) . The
* last two specify the registration point of the frame .
*
* frames : [
* // x, y, width, height, imageIndex*, regX*, regY*
* [ 64 , 0 , 96 , 64 ] ,
* [ 0 , 0 , 64 , 64 , 1 , 32 , 32 ]
* // etc.
* ]
*
* < / O L >
*
* < h4 > animations < / h 4 >
* Optional . An object defining sequences of frames to play as named animations . Each property corresponds to an
* animation of the same name . Each animation must specify the frames to play , and may
* also include a relative playback ` speed ` ( ex . 2 would playback at double speed , 0.5 at half ) , and
* the name of the ` next ` animation to sequence to after it completes .
*
* There are three formats supported for defining the frames in an animation , which can be mixed and matched as appropriate : < OL >
* < LI > for a single frame animation , you can simply specify the frame index
*
* animations : {
* sit : 7
* }
*
* < LI > for an animation of consecutive frames , you can use an array with two required , and two optional entries
* in the order : ` start ` , ` end ` , ` next ` , and ` speed ` . This will play the frames from start to end inclusive .
*
* animations : {
* // start, end, next*, speed*
* run : [ 0 , 8 ] ,
* jump : [ 9 , 12 , "run" , 2 ]
* }
*
* < LI > for non - consecutive frames , you can use an object with a ` frames ` property defining an array of frame indexes to
* play in order . The object can also specify ` next ` and ` speed ` properties .
*
* animations : {
* walk : {
* frames : [ 1 , 2 , 3 , 3 , 2 , 1 ]
* } ,
* shoot : {
* frames : [ 1 , 4 , 5 , 6 ] ,
* next : "walk" ,
* speed : 0.5
* }
* }
*
* < / O L >
* < strong > Note : < / s t r o n g > t h e ` s p e e d ` p r o p e r t y w a s a d d e d i n E a s e l J S 0 . 7 . 0 . E a r l i e r v e r s i o n s h a d a ` f r e q u e n c y `
* property instead , which was the inverse of ` speed ` . For example , a value of "4" would be 1 / 4 normal speed in earlier
* versions , but is 4 x normal speed in 0.7 . 0 + .
*
* < h4 > framerate < / h 4 >
* Optional . Indicates the default framerate to play this spritesheet at in frames per second .
* See { { # crossLink "SpriteSheet/framerate:property" } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
*
* framerate : 20
*
* < h4 > Example < / h 4 >
* To define a simple sprite sheet , with a single image "sprites.jpg" arranged in a regular 50 x50 grid with three
* animations : "stand" showing the first frame , "run" looping frame 1 - 5 inclusive , and "jump" playing frame 6 - 8 and sequencing back to run .
*
* var data = {
* images : [ "sprites.jpg" ] ,
* frames : { width : 50 , height : 50 } ,
* animations : {
* stand : 0 ,
* run : [ 1 , 5 ] ,
* jump : [ 6 , 8 , "run" ]
* }
* } ;
* var spriteSheet = new createjs . SpriteSheet ( data ) ;
* var animation = new createjs . Sprite ( spriteSheet , "run" ) ;
*
*
* < strong > Warning : < / s t r o n g > I m a g e s l o a d e d c r o s s - o r i g i n w i l l t h r o w c r o s s - o r i g i n s e c u r i t y e r r o r s w h e n i n t e r a c t e d w i t h
* using a mouse , using methods such as ` getObjectUnderPoint ` , using filters , or caching . You can get around this by
* setting ` crossOrigin ` flags on your images before passing them to EaselJS , eg : ` img.crossOrigin="Anonymous"; `
*
* @ class SpriteSheet
* @ constructor
* @ param { Object } data An object describing the SpriteSheet data .
* @ extends EventDispatcher
* * /
function SpriteSheet ( data ) {
this . EventDispatcher _constructor ( ) ;
// public properties:
/ * *
* Indicates whether all images are finished loading .
* @ property complete
* @ type Boolean
* @ readonly
* * /
this . complete = true ;
/ * *
* Specifies the framerate to use by default for Sprite instances using the SpriteSheet . See
* Sprite . framerate for more information .
* @ property framerate
* @ type Number
* * /
this . framerate = 0 ;
// private properties:
/ * *
* @ property _animations
* @ protected
* * /
this . _animations = null ;
/ * *
* @ property _frames
* @ protected
* * /
this . _frames = null ;
/ * *
* @ property _images
* @ protected
* * /
this . _images = null ;
/ * *
* @ property _data
* @ protected
* * /
this . _data = null ;
/ * *
* @ property _loadCount
* @ protected
* * /
this . _loadCount = 0 ;
// only used for simple frame defs:
/ * *
* @ property _frameHeight
* @ protected
* * /
this . _frameHeight = 0 ;
/ * *
* @ property _frameWidth
* @ protected
* * /
this . _frameWidth = 0 ;
/ * *
* @ property _numFrames
* @ protected
* * /
this . _numFrames = 0 ;
/ * *
* @ property _regX
* @ protected
* * /
this . _regX = 0 ;
/ * *
* @ property _regY
* @ protected
* * /
this . _regY = 0 ;
// setup:
this . _parseData ( data ) ;
}
var p = createjs . extend ( SpriteSheet , createjs . EventDispatcher ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// events:
2014-01-03 13:32:13 -05:00
/ * *
* Dispatched when all images are loaded . Note that this only fires if the images
* were not fully loaded when the sprite sheet was initialized . You should check the complete property
* to prior to adding a listener . Ex .
2014-11-18 18:26:26 -05:00
*
* var sheet = new SpriteSheet ( data ) ;
* if ( ! sheet . complete ) {
* // not preloaded, listen for the complete event:
* sheet . addEventListener ( "complete" , handler ) ;
* }
*
2014-01-03 13:32:13 -05:00
* @ event complete
* @ param { Object } target The object that dispatched the event .
* @ param { String } type The event type .
* @ since 0.6 . 0
* /
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// public methods:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Returns the total number of frames in the specified animation , or in the whole sprite
* sheet if the animation param is omitted . Returns 0 if the spritesheet relies on calculated frame counts , and
* the images have not been fully loaded .
* @ method getNumFrames
* @ param { String } animation The name of the animation to get a frame count for .
* @ return { Number } The number of frames in the animation , or in the entire sprite sheet if the animation param is omitted .
* /
p . getNumFrames = function ( animation ) {
if ( animation == null ) {
return this . _frames ? this . _frames . length : this . _numFrames || 0 ;
} else {
var data = this . _data [ animation ] ;
if ( data == null ) { return 0 ; }
else { return data . frames . length ; }
}
} ;
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Returns an array of all available animation names as strings .
* @ method getAnimations
* @ return { Array } an array of animation names available on this sprite sheet .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . getAnimations = function ( ) {
return this . _animations . slice ( 0 ) ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Returns an object defining the specified animation . The returned object contains : < UL >
* < LI > frames : an array of the frame ids in the animation < / L I >
* < LI > speed : the playback speed for this animation < / L I >
* < LI > name : the name of the animation < / L I >
* < LI > next : the default animation to play next . If the animation loops , the name and next property will be the
* same . < / L I >
* < / U L >
* @ method getAnimation
* @ param { String } name The name of the animation to get .
* @ return { Object } a generic object with frames , speed , name , and next properties .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . getAnimation = function ( name ) {
return this . _data [ name ] ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Returns an object specifying the image and source rect of the specified frame . The returned object has : < UL >
* < LI > an image property holding a reference to the image object in which the frame is found < / L I >
* < LI > a rect property containing a Rectangle instance which defines the boundaries for the frame within that
* image . < / L I >
* < LI > A regX and regY property corresponding to the regX / Y values for the frame .
* < / U L >
* @ method getFrame
* @ param { Number } frameIndex The index of the frame .
* @ return { Object } a generic object with image and rect properties . Returns null if the frame does not exist .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . getFrame = function ( frameIndex ) {
var frame ;
if ( this . _frames && ( frame = this . _frames [ frameIndex ] ) ) { return frame ; }
return null ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Returns a { { # crossLink "Rectangle" } } { { / c r o s s L i n k } } i n s t a n c e d e f i n i n g t h e b o u n d s o f t h e s p e c i f i e d f r a m e r e l a t i v e
* to the origin . For example , a 90 x 70 frame with a regX of 50 and a regY of 40 would return :
*
* [ x = - 50 , y = - 40 , width = 90 , height = 70 ]
*
* @ method getFrameBounds
* @ param { Number } frameIndex The index of the frame .
* @ param { Rectangle } [ rectangle ] A Rectangle instance to copy the values into . By default a new instance is created .
* @ return { Rectangle } A Rectangle instance . Returns null if the frame does not exist , or the image is not fully loaded .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . getFrameBounds = function ( frameIndex , rectangle ) {
var frame = this . getFrame ( frameIndex ) ;
return frame ? ( rectangle || new createjs . Rectangle ( ) ) . setValues ( - frame . regX , - frame . regY , frame . rect . width , frame . rect . height ) : null ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . toString = function ( ) {
return "[SpriteSheet]" ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* SpriteSheet cannot be cloned . A SpriteSheet can be shared by multiple Sprite instances without cloning it .
* @ method clone
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . clone = function ( ) {
throw ( "SpriteSheet cannot be cloned." )
} ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// private methods:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* @ method _parseData
2014-01-03 13:32:13 -05:00
* @ param { Object } data An object describing the SpriteSheet data .
* @ protected
* * /
2014-11-18 18:26:26 -05:00
p . _parseData = function ( data ) {
2014-01-03 13:32:13 -05:00
var i , l , o , a ;
if ( data == null ) { return ; }
this . framerate = data . framerate || 0 ;
// parse images:
if ( data . images && ( l = data . images . length ) > 0 ) {
a = this . _images = [ ] ;
for ( i = 0 ; i < l ; i ++ ) {
var img = data . images [ i ] ;
if ( typeof img == "string" ) {
var src = img ;
img = document . createElement ( "img" ) ;
img . src = src ;
}
a . push ( img ) ;
if ( ! img . getContext && ! img . complete ) {
this . _loadCount ++ ;
this . complete = false ;
( function ( o ) { img . onload = function ( ) { o . _handleImageLoad ( ) ; } } ) ( this ) ;
}
}
}
// parse frames:
if ( data . frames == null ) { // nothing
} else if ( data . frames instanceof Array ) {
this . _frames = [ ] ;
a = data . frames ;
for ( i = 0 , l = a . length ; i < l ; i ++ ) {
var arr = a [ i ] ;
this . _frames . push ( { image : this . _images [ arr [ 4 ] ? arr [ 4 ] : 0 ] , rect : new createjs . Rectangle ( arr [ 0 ] , arr [ 1 ] , arr [ 2 ] , arr [ 3 ] ) , regX : arr [ 5 ] || 0 , regY : arr [ 6 ] || 0 } ) ;
}
} else {
o = data . frames ;
this . _frameWidth = o . width ;
this . _frameHeight = o . height ;
this . _regX = o . regX || 0 ;
this . _regY = o . regY || 0 ;
this . _numFrames = o . count ;
if ( this . _loadCount == 0 ) { this . _calculateFrames ( ) ; }
}
// parse animations:
this . _animations = [ ] ;
if ( ( o = data . animations ) != null ) {
this . _data = { } ;
var name ;
for ( name in o ) {
var anim = { name : name } ;
var obj = o [ name ] ;
if ( typeof obj == "number" ) { // single frame
a = anim . frames = [ obj ] ;
} else if ( obj instanceof Array ) { // simple
if ( obj . length == 1 ) { anim . frames = [ obj [ 0 ] ] ; }
else {
anim . speed = obj [ 3 ] ;
anim . next = obj [ 2 ] ;
a = anim . frames = [ ] ;
for ( i = obj [ 0 ] ; i <= obj [ 1 ] ; i ++ ) {
a . push ( i ) ;
}
}
} else { // complex
anim . speed = obj . speed ;
anim . next = obj . next ;
var frames = obj . frames ;
a = anim . frames = ( typeof frames == "number" ) ? [ frames ] : frames . slice ( 0 ) ;
}
if ( anim . next === true || anim . next === undefined ) { anim . next = name ; } // loop
if ( anim . next === false || ( a . length < 2 && anim . next == name ) ) { anim . next = null ; } // stop
if ( ! anim . speed ) { anim . speed = 1 ; }
this . _animations . push ( name ) ;
this . _data [ name ] = anim ;
}
}
} ;
/ * *
* @ method _handleImageLoad
* @ protected
* * /
p . _handleImageLoad = function ( ) {
if ( -- this . _loadCount == 0 ) {
this . _calculateFrames ( ) ;
this . complete = true ;
this . dispatchEvent ( "complete" ) ;
}
} ;
/ * *
* @ method _calculateFrames
* @ protected
* * /
p . _calculateFrames = function ( ) {
if ( this . _frames || this . _frameWidth == 0 ) { return ; }
this . _frames = [ ] ;
var ttlFrames = 0 ;
var fw = this . _frameWidth ;
var fh = this . _frameHeight ;
for ( var i = 0 , imgs = this . _images ; i < imgs . length ; i ++ ) {
var img = imgs [ i ] ;
var cols = img . width / fw | 0 ;
var rows = img . height / fh | 0 ;
var ttl = this . _numFrames > 0 ? Math . min ( this . _numFrames - ttlFrames , cols * rows ) : cols * rows ;
for ( var j = 0 ; j < ttl ; j ++ ) {
this . _frames . push ( { image : img , rect : new createjs . Rectangle ( j % cols * fw , ( j / cols | 0 ) * fh , fw , fh ) , regX : this . _regX , regY : this . _regY } ) ;
}
ttlFrames += ttl ;
}
this . _numFrames = ttlFrames ;
} ;
2014-11-18 18:26:26 -05:00
createjs . SpriteSheet = createjs . promote ( SpriteSheet , "EventDispatcher" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// Graphics.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
/ * *
* The Graphics class exposes an easy to use API for generating vector drawing instructions and drawing them to a
* specified context . Note that you can use Graphics without any dependency on the Easel framework by calling { { # crossLink "Graphics/draw" } } { { / c r o s s L i n k } }
* directly , or it can be used with the { { # crossLink "Shape" } } { { / c r o s s L i n k } } o b j e c t t o d r a w v e c t o r g r a p h i c s w i t h i n t h e
* context of an EaselJS display list .
*
* There are two approaches to working with Graphics object : calling methods on a Graphics instance ( the "Graphics API" ) , or
* instantiating Graphics command objects and adding them to the graphics queue via { { # crossLink "Graphics/append" } } { { / c r o s s L i n k } } .
* The former abstracts the latter , simplifying beginning and ending paths , fills , and strokes .
*
* var g = new createjs . Graphics ( ) ;
* g . setStrokeStyle ( 1 ) ;
* g . beginStroke ( "#000000" ) ;
* g . beginFill ( "red" ) ;
* g . drawCircle ( 0 , 0 , 30 ) ;
*
* All drawing methods in Graphics return the Graphics instance , so they can be chained together . For example ,
* the following line of code would generate the instructions to draw a rectangle with a red stroke and blue fill :
*
* myGraphics . beginStroke ( "red" ) . beginFill ( "blue" ) . drawRect ( 20 , 20 , 100 , 50 ) ;
*
* Each graphics API call generates a command object ( see below ) . The last command to be created can be accessed via
* { { # crossLink "Graphics/command:property" } } { { / c r o s s L i n k } } :
*
* var fillCommand = myGraphics . beginFill ( "red" ) . command ;
* // ... later, update the fill style/color:
* fillCommand . style = "blue" ;
* // or change it to a bitmap fill:
* fillCommand . bitmap ( myImage ) ;
*
* For more direct control of rendering , you can instantiate and append command objects to the graphics queue directly . In this case , you
* need to manage path creation manually , and ensure that fill / stroke is applied to a defined path :
*
* // start a new path. Graphics.beginPath is a reusable BeginPath instance:
* myGraphics . append ( Graphics . beginPath ) ;
* // we need to define the path before applying the fill:
* var circle = new Graphics . Circle ( 0 , 0 , 30 ) ;
* myGraphics . append ( circle ) ;
* // fill the path we just defined:
* var fill = new Graphics . Fill ( "red" ) ;
* myGraphics . append ( fill ) ;
*
* These approaches can be used together , for example to insert a custom command :
*
* myGraphics . beginFill ( "red" ) ;
* var customCommand = new CustomSpiralCommand ( etc ) ;
* myGraphics . append ( customCommand ) ;
* myGraphics . beginFill ( "blue" ) ;
* myGraphics . drawCircle ( 0 , 0 , 30 ) ;
*
* See { { # crossLink "Graphics/append" } } { { / c r o s s L i n k } } f o r m o r e i n f o o n c r e a t i n g c u s t o m c o m m a n d s .
*
* < h4 > Tiny API < / h 4 >
* The Graphics class also includes a "tiny API" , which is one or two - letter methods that are shortcuts for all of the
* Graphics methods . These methods are great for creating compact instructions , and is used by the Toolkit for CreateJS
* to generate readable code . All tiny methods are marked as protected , so you can view them by enabling protected
* descriptions in the docs .
*
* < table >
* < tr > < td > < b > Tiny < / b > < / t d > < t d > < b > M e t h o d < / b > < / t d > < t d > < b > T i n y < / b > < / t d > < t d > < b > M e t h o d < / b > < / t d > < / t r >
* < tr > < td > mt < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / m o v e T o " } } { { / c r o s s L i n k } } < / t d >
* < td > lt < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / l i n e T o " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > a / at < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / a r c " } } { { / c r o s s L i n k } } / { { # c r o s s L i n k " G r a p h i c s / a r c T o " } } { { / c r o s s L i n k } } < / t d >
* < td > bt < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / b e z i e r C u r v e T o " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > qt < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / q u a d r a t i c C u r v e T o " } } { { / c r o s s L i n k } } ( a l s o c u r v e T o ) < / t d >
* < td > r < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / r e c t " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > cp < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / c l o s e P a t h " } } { { / c r o s s L i n k } } < / t d >
* < td > c < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / c l e a r " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > f < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / b e g i n F i l l " } } { { / c r o s s L i n k } } < / t d >
* < td > lf < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / b e g i n L i n e a r G r a d i e n t F i l l " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > rf < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / b e g i n R a d i a l G r a d i e n t F i l l " } } { { / c r o s s L i n k } } < / t d >
* < td > bf < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / b e g i n B i t m a p F i l l " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > ef < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / e n d F i l l " } } { { / c r o s s L i n k } } < / t d >
* < td > ss < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / s e t S t r o k e S t y l e " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > s < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / b e g i n S t r o k e " } } { { / c r o s s L i n k } } < / t d >
* < td > ls < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / b e g i n L i n e a r G r a d i e n t S t r o k e " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > rs < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / b e g i n R a d i a l G r a d i e n t S t r o k e " } } { { / c r o s s L i n k } } < / t d >
* < td > bs < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / b e g i n B i t m a p S t r o k e " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > es < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / e n d S t r o k e " } } { { / c r o s s L i n k } } < / t d >
* < td > dr < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / d r a w R e c t " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > rr < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / d r a w R o u n d R e c t " } } { { / c r o s s L i n k } } < / t d >
* < td > rc < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / d r a w R o u n d R e c t C o m p l e x " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > dc < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / d r a w C i r c l e " } } { { / c r o s s L i n k } } < / t d >
* < td > de < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / d r a w E l l i p s e " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < tr > < td > dp < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / d r a w P o l y S t a r " } } { { / c r o s s L i n k } } < / t d >
* < td > p < / t d > < t d > { { # c r o s s L i n k " G r a p h i c s / d e c o d e P a t h " } } { { / c r o s s L i n k } } < / t d > < / t r >
* < / t a b l e >
*
* Here is the above example , using the tiny API instead .
*
* myGraphics . s ( "red" ) . f ( "blue" ) . r ( 20 , 20 , 100 , 50 ) ;
*
* @ class Graphics
* @ constructor
* * /
function Graphics ( ) {
// public properties
/ * *
* Holds a reference to the last command that was created or appended . For example , you could retain a reference
* to a Fill command in order to dynamically update the color later by using :
* myFill = myGraphics . beginFill ( "red" ) . command ;
* // update color later:
* myFill . style = "yellow" ;
* @ property command
* @ type Object
* * /
this . command = null ;
// private properties
/ * *
* @ property _stroke
* @ protected
* @ type { Array }
* * /
this . _stroke = null ;
/ * *
* @ property _strokeStyle
* @ protected
* @ type { Array }
* * /
this . _strokeStyle = null ;
/ * *
* @ property _strokeIgnoreScale
* @ protected
* @ type Boolean
* * /
this . _strokeIgnoreScale = false ;
/ * *
* @ property _fill
* @ protected
* @ type { Array }
* * /
this . _fill = null ;
/ * *
* @ property _instructions
* @ protected
* @ type { Array }
* * /
this . _instructions = [ ] ;
/ * *
* Indicates the last instruction index that was committed .
* @ property _commitIndex
* @ protected
* @ type { Number }
* * /
this . _commitIndex = 0 ;
/ * *
* Uncommitted instructions .
* @ property _activeInstructions
* @ protected
* @ type { Array }
* * /
this . _activeInstructions = [ ] ;
/ * *
* This indicates that there have been changes to the activeInstruction list since the last updateInstructions call .
* @ property _dirty
* @ protected
* @ type { Boolean }
* @ default false
* * /
this . _dirty = false ;
/ * *
* Index to draw from if a store operation has happened .
* @ property _storeIndex
* @ protected
* @ type { Number }
* @ default 0
* * /
this . _storeIndex = 0 ;
// setup:
this . clear ( ) ;
}
var p = Graphics . prototype ;
var G = Graphics ; // shortcut
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// static public methods:
2014-01-03 13:32:13 -05:00
/ * *
* Returns a CSS compatible color string based on the specified RGB numeric color values in the format
* "rgba(255,255,255,1.0)" , or if alpha is null then in the format "rgb(255,255,255)" . For example ,
*
* createjs . Graphics . getRGB ( 50 , 100 , 150 , 0.5 ) ;
* // Returns "rgba(50,100,150,0.5)"
*
* It also supports passing a single hex color value as the first param , and an optional alpha value as the second
* param . For example ,
*
* createjs . Graphics . getRGB ( 0xFF00FF , 0.2 ) ;
* // Returns "rgba(255,0,255,0.2)"
*
* @ method getRGB
* @ static
* @ param { Number } r The red component for the color , between 0 and 0xFF ( 255 ) .
* @ param { Number } g The green component for the color , between 0 and 0xFF ( 255 ) .
* @ param { Number } b The blue component for the color , between 0 and 0xFF ( 255 ) .
* @ param { Number } [ alpha ] The alpha component for the color where 0 is fully transparent and 1 is fully opaque .
* @ return { String } A CSS compatible color string based on the specified RGB numeric color values in the format
* "rgba(255,255,255,1.0)" , or if alpha is null then in the format "rgb(255,255,255)" .
* * /
Graphics . getRGB = function ( r , g , b , alpha ) {
if ( r != null && b == null ) {
alpha = g ;
b = r & 0xFF ;
g = r >> 8 & 0xFF ;
r = r >> 16 & 0xFF ;
}
if ( alpha == null ) {
return "rgb(" + r + "," + g + "," + b + ")" ;
} else {
return "rgba(" + r + "," + g + "," + b + "," + alpha + ")" ;
}
} ;
/ * *
* Returns a CSS compatible color string based on the specified HSL numeric color values in the format "hsla(360,100,100,1.0)" ,
* or if alpha is null then in the format "hsl(360,100,100)" .
*
* createjs . Graphics . getHSL ( 150 , 100 , 70 ) ;
* // Returns "hsl(150,100,70)"
*
* @ method getHSL
* @ static
* @ param { Number } hue The hue component for the color , between 0 and 360.
* @ param { Number } saturation The saturation component for the color , between 0 and 100.
* @ param { Number } lightness The lightness component for the color , between 0 and 100.
* @ param { Number } [ alpha ] The alpha component for the color where 0 is fully transparent and 1 is fully opaque .
* @ return { String } A CSS compatible color string based on the specified HSL numeric color values in the format
* "hsla(360,100,100,1.0)" , or if alpha is null then in the format "hsl(360,100,100)" .
* * /
Graphics . getHSL = function ( hue , saturation , lightness , alpha ) {
if ( alpha == null ) {
return "hsl(" + ( hue % 360 ) + "," + saturation + "%," + lightness + "%)" ;
} else {
return "hsla(" + ( hue % 360 ) + "," + saturation + "%," + lightness + "%," + alpha + ")" ;
}
} ;
2014-11-18 18:26:26 -05:00
// static properties:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* A reusable instance of { { # crossLink "Graphics/BeginPath" } } { { / c r o s s L i n k } } t o a v o i d
* unnecessary instantiation .
* @ property beginCmd
* @ type { Graphics . BeginPath }
2014-01-03 13:32:13 -05:00
* @ static
* * /
2014-11-18 18:26:26 -05:00
// defined at the bottom of this file.
2014-01-03 13:32:13 -05:00
/ * *
* Map of Base64 characters to values . Used by { { # crossLink "Graphics/decodePath" } } { { / c r o s s L i n k } } .
* @ property BASE _64
* @ static
* @ final
* @ readonly
* @ type { Object }
* * /
Graphics . BASE _64 = { "A" : 0 , "B" : 1 , "C" : 2 , "D" : 3 , "E" : 4 , "F" : 5 , "G" : 6 , "H" : 7 , "I" : 8 , "J" : 9 , "K" : 10 , "L" : 11 , "M" : 12 , "N" : 13 , "O" : 14 , "P" : 15 , "Q" : 16 , "R" : 17 , "S" : 18 , "T" : 19 , "U" : 20 , "V" : 21 , "W" : 22 , "X" : 23 , "Y" : 24 , "Z" : 25 , "a" : 26 , "b" : 27 , "c" : 28 , "d" : 29 , "e" : 30 , "f" : 31 , "g" : 32 , "h" : 33 , "i" : 34 , "j" : 35 , "k" : 36 , "l" : 37 , "m" : 38 , "n" : 39 , "o" : 40 , "p" : 41 , "q" : 42 , "r" : 43 , "s" : 44 , "t" : 45 , "u" : 46 , "v" : 47 , "w" : 48 , "x" : 49 , "y" : 50 , "z" : 51 , "0" : 52 , "1" : 53 , "2" : 54 , "3" : 55 , "4" : 56 , "5" : 57 , "6" : 58 , "7" : 59 , "8" : 60 , "9" : 61 , "+" : 62 , "/" : 63 } ;
/ * *
* Maps numeric values for the caps parameter of { { # crossLink "Graphics/setStrokeStyle" } } { { / c r o s s L i n k } } t o
* corresponding string values . This is primarily for use with the tiny API . The mappings are as follows : 0 to
* "butt" , 1 to "round" , and 2 to "square" .
* For example , to set the line caps to "square" :
*
* myGraphics . ss ( 16 , 2 ) ;
*
* @ property STROKE _CAPS _MAP
* @ static
* @ final
* @ readonly
* @ type { Array }
* * /
Graphics . STROKE _CAPS _MAP = [ "butt" , "round" , "square" ] ;
/ * *
* Maps numeric values for the joints parameter of { { # crossLink "Graphics/setStrokeStyle" } } { { / c r o s s L i n k } } t o
* corresponding string values . This is primarily for use with the tiny API . The mappings are as follows : 0 to
* "miter" , 1 to "round" , and 2 to "bevel" .
* For example , to set the line joints to "bevel" :
*
* myGraphics . ss ( 16 , 0 , 2 ) ;
*
* @ property STROKE _JOINTS _MAP
* @ static
* @ final
* @ readonly
* @ type { Array }
* * /
Graphics . STROKE _JOINTS _MAP = [ "miter" , "round" , "bevel" ] ;
/ * *
* @ property _ctx
* @ static
* @ protected
* @ type { CanvasRenderingContext2D }
* * /
var canvas = ( createjs . createCanvas ? createjs . createCanvas ( ) : document . createElement ( "canvas" ) ) ;
if ( canvas . getContext ) {
2014-11-18 18:26:26 -05:00
Graphics . _ctx = canvas . getContext ( "2d" ) ;
2014-01-03 13:32:13 -05:00
canvas . width = canvas . height = 1 ;
}
2014-11-18 18:26:26 -05:00
// public methods:
2014-01-03 13:32:13 -05:00
/ * *
* Returns true if this Graphics instance has no drawing commands .
* @ method isEmpty
* @ return { Boolean } Returns true if this Graphics instance has no drawing commands .
* * /
p . isEmpty = function ( ) {
2014-11-18 18:26:26 -05:00
return ! ( this . _instructions . length || this . _activeInstructions . length ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Draws the display object into the specified context ignoring its visible , alpha , shadow , and transform .
* Returns true if the draw was handled ( useful for overriding functionality ) .
*
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method draw
* @ param { CanvasRenderingContext2D } ctx The canvas 2 D context object to draw into .
2014-11-18 18:26:26 -05:00
* @ 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 .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . draw = function ( ctx , data ) {
this . _updateInstructions ( ) ;
2014-01-03 13:32:13 -05:00
var instr = this . _instructions ;
2014-11-18 18:26:26 -05:00
for ( var i = this . _storeIndex , l = instr . length ; i < l ; i ++ ) {
instr [ i ] . exec ( ctx , data ) ;
2014-01-03 13:32:13 -05:00
}
} ;
/ * *
* Draws only the path described for this Graphics instance , skipping any non - path instructions , including fill and
2014-11-18 18:26:26 -05:00
* stroke descriptions . Used for < code > DisplayObject . mask < / c o d e > t o d r a w t h e c l i p p i n g p a t h , f o r e x a m p l e .
2014-01-03 13:32:13 -05:00
* @ method drawAsPath
* @ param { CanvasRenderingContext2D } ctx The canvas 2 D context object to draw into .
* * /
p . drawAsPath = function ( ctx ) {
2014-11-18 18:26:26 -05:00
this . _updateInstructions ( ) ;
2014-01-03 13:32:13 -05:00
var instr , instrs = this . _instructions ;
for ( var i = 0 , l = instrs . length ; i < l ; i ++ ) {
// the first command is always a beginPath command.
2014-11-18 18:26:26 -05:00
if ( ( instr = instrs [ i ] ) . path !== false ) { instr . exec ( ctx ) ; }
2014-01-03 13:32:13 -05:00
}
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
// public methods that map directly to context 2D calls:
/ * *
* Moves the drawing point to the specified position . A tiny API method "mt" also exists .
* @ method moveTo
* @ param { Number } x The x coordinate the drawing point should move to .
* @ param { Number } y The y coordinate the drawing point should move to .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls ) .
* * /
p . moveTo = function ( x , y ) {
2014-11-18 18:26:26 -05:00
return this . append ( new G . MoveTo ( x , y ) , true ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Draws a line from the current drawing point to the specified position , which become the new current drawing
* point . A tiny API method "lt" also exists .
*
* For detailed information , read the
* < a href = "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#complex-shapes-(paths)" >
* whatwg spec < / a > .
* @ method lineTo
* @ param { Number } x The x coordinate the drawing point should draw to .
* @ param { Number } y The y coordinate the drawing point should draw to .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . lineTo = function ( x , y ) {
2014-11-18 18:26:26 -05:00
return this . append ( new G . LineTo ( x , y ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Draws an arc with the specified control points and radius . For detailed information , read the
* < a href = "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arcto" >
* whatwg spec < / a > . A t i n y A P I m e t h o d " a t " a l s o e x i s t s .
* @ method arcTo
* @ param { Number } x1
* @ param { Number } y1
* @ param { Number } x2
* @ param { Number } y2
* @ param { Number } radius
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . arcTo = function ( x1 , y1 , x2 , y2 , radius ) {
2014-11-18 18:26:26 -05:00
return this . append ( new G . ArcTo ( x1 , y1 , x2 , y2 , radius ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Draws an arc defined by the radius , startAngle and endAngle arguments , centered at the position ( x , y ) . For
* example , to draw a full circle with a radius of 20 centered at ( 100 , 100 ) :
*
* arc ( 100 , 100 , 20 , 0 , Math . PI * 2 ) ;
*
* For detailed information , read the
* < a href = "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-arc" > whatwg spec < / a > .
* A tiny API method "a" also exists .
* @ method arc
* @ param { Number } x
* @ param { Number } y
* @ param { Number } radius
* @ param { Number } startAngle Measured in radians .
* @ param { Number } endAngle Measured in radians .
* @ param { Boolean } anticlockwise
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . arc = function ( x , y , radius , startAngle , endAngle , anticlockwise ) {
2014-11-18 18:26:26 -05:00
return this . append ( new G . Arc ( x , y , radius , startAngle , endAngle , anticlockwise ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Draws a quadratic curve from the current drawing point to ( x , y ) using the control point ( cpx , cpy ) . For detailed
* information , read the < a href = "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-quadraticcurveto" >
* whatwg spec < / a > . A t i n y A P I m e t h o d " q t " a l s o e x i s t s .
* @ method quadraticCurveTo
* @ param { Number } cpx
* @ param { Number } cpy
* @ param { Number } x
* @ param { Number } y
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . quadraticCurveTo = function ( cpx , cpy , x , y ) {
2014-11-18 18:26:26 -05:00
return this . append ( new G . QuadraticCurveTo ( cpx , cpy , x , y ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Draws a bezier curve from the current drawing point to ( x , y ) using the control points ( cp1x , cp1y ) and ( cp2x ,
* cp2y ) . For detailed information , read the
* < a href = "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-beziercurveto" >
* whatwg spec < / a > . A t i n y A P I m e t h o d " b t " a l s o e x i s t s .
* @ method bezierCurveTo
* @ param { Number } cp1x
* @ param { Number } cp1y
* @ param { Number } cp2x
* @ param { Number } cp2y
* @ param { Number } x
* @ param { Number } y
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . bezierCurveTo = function ( cp1x , cp1y , cp2x , cp2y , x , y ) {
2014-11-18 18:26:26 -05:00
return this . append ( new G . BezierCurveTo ( cp1x , cp1y , cp2x , cp2y , x , y ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Draws a rectangle at ( x , y ) with the specified width and height using the current fill and / or stroke .
* For detailed information , read the
* < a href = "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-rect" >
* whatwg spec < / a > . A t i n y A P I m e t h o d " r " a l s o e x i s t s .
* @ method rect
* @ param { Number } x
* @ param { Number } y
* @ param { Number } w Width of the rectangle
* @ param { Number } h Height of the rectangle
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . rect = function ( x , y , w , h ) {
2014-11-18 18:26:26 -05:00
return this . append ( new G . Rect ( x , y , w , h ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Closes the current path , effectively drawing a line from the current drawing point to the first drawing point specified
* since the fill or stroke was last set . A tiny API method "cp" also exists .
* @ method closePath
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . closePath = function ( ) {
2014-11-18 18:26:26 -05:00
return this . _activeInstructions . length ? this . append ( new G . ClosePath ( ) ) : this ;
2014-01-03 13:32:13 -05:00
} ;
// public methods that roughly map to Flash graphics APIs:
/ * *
* Clears all drawing instructions , effectively resetting this Graphics instance . Any line and fill styles will need
* to be redefined to draw shapes following a clear call . A tiny API method "c" also exists .
* @ method clear
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . clear = function ( ) {
2014-11-18 18:26:26 -05:00
this . _instructions . length = this . _activeInstructions . length = this . _commitIndex = 0 ;
this . _strokeStyle = this . _stroke = this . _fill = null ;
this . _dirty = this . _strokeIgnoreScale = false ;
2014-01-03 13:32:13 -05:00
return this ;
} ;
/ * *
* Begins a fill with the specified color . This ends the current sub - path . A tiny API method "f" also exists .
* @ method beginFill
* @ param { String } color A CSS compatible color value ( ex . "red" , "#FF0000" , or "rgba(255,0,0,0.5)" ) . Setting to
* null will result in no fill .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . beginFill = function ( color ) {
2014-11-18 18:26:26 -05:00
return this . _setFill ( color ? new G . Fill ( color ) : null ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Begins a linear gradient fill defined by the line ( x0 , y0 ) to ( x1 , y1 ) . This ends the current sub - path . For
* example , the following code defines a black to white vertical gradient ranging from 20 px to 120 px , and draws a
* square to display it :
*
* myGraphics . beginLinearGradientFill ( [ "#000" , "#FFF" ] , [ 0 , 1 ] , 0 , 20 , 0 , 120 ) . drawRect ( 20 , 20 , 120 , 120 ) ;
*
* A tiny API method "lf" also exists .
* @ method beginLinearGradientFill
* @ param { Array } colors An array of CSS compatible color values . For example , [ "#F00" , "#00F" ] would define a gradient
* drawing from red to blue .
* @ param { Array } ratios An array of gradient positions which correspond to the colors . For example , [ 0.1 , 0.9 ] would draw
* the first color to 10 % then interpolating to the second color at 90 % .
* @ param { Number } x0 The position of the first point defining the line that defines the gradient direction and size .
* @ param { Number } y0 The position of the first point defining the line that defines the gradient direction and size .
* @ param { Number } x1 The position of the second point defining the line that defines the gradient direction and size .
* @ param { Number } y1 The position of the second point defining the line that defines the gradient direction and size .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . beginLinearGradientFill = function ( colors , ratios , x0 , y0 , x1 , y1 ) {
2014-11-18 18:26:26 -05:00
return this . _setFill ( new G . Fill ( ) . linearGradient ( colors , ratios , x0 , y0 , x1 , y1 ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Begins a radial gradient fill . This ends the current sub - path . For example , the following code defines a red to
* blue radial gradient centered at ( 100 , 100 ) , with a radius of 50 , and draws a circle to display it :
*
* myGraphics . beginRadialGradientFill ( [ "#F00" , "#00F" ] , [ 0 , 1 ] , 100 , 100 , 0 , 100 , 100 , 50 ) . drawCircle ( 100 , 100 , 50 ) ;
*
* A tiny API method "rf" also exists .
* @ method beginRadialGradientFill
* @ param { Array } colors An array of CSS compatible color values . For example , [ "#F00" , "#00F" ] would define
* a gradient drawing from red to blue .
* @ param { Array } ratios An array of gradient positions which correspond to the colors . For example , [ 0.1 ,
* 0.9 ] would draw the first color to 10 % then interpolating to the second color at 90 % .
* @ param { Number } x0 Center position of the inner circle that defines the gradient .
* @ param { Number } y0 Center position of the inner circle that defines the gradient .
* @ param { Number } r0 Radius of the inner circle that defines the gradient .
* @ param { Number } x1 Center position of the outer circle that defines the gradient .
* @ param { Number } y1 Center position of the outer circle that defines the gradient .
* @ param { Number } r1 Radius of the outer circle that defines the gradient .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . beginRadialGradientFill = function ( colors , ratios , x0 , y0 , r0 , x1 , y1 , r1 ) {
2014-11-18 18:26:26 -05:00
return this . _setFill ( new G . Fill ( ) . radialGradient ( colors , ratios , x0 , y0 , r0 , x1 , y1 , r1 ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Begins a pattern fill using the specified image . This ends the current sub - path . A tiny API method "bf" also
* exists .
* @ method beginBitmapFill
* @ param { HTMLImageElement | HTMLCanvasElement | HTMLVideoElement } image The Image , Canvas , or Video object to use
* as the pattern .
* @ param { String } repetition Optional . Indicates whether to repeat the image in the fill area . One of "repeat" ,
* "repeat-x" , "repeat-y" , or "no-repeat" . Defaults to "repeat" . Note that Firefox does not support "repeat-x" or
* "repeat-y" ( latest tests were in FF 20.0 ) , and will default to "repeat" .
* @ param { Matrix2D } matrix Optional . Specifies a transformation matrix for the bitmap fill . This transformation
* will be applied relative to the parent transform .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . beginBitmapFill = function ( image , repetition , matrix ) {
2014-11-18 18:26:26 -05:00
return this . _setFill ( new G . Fill ( null , matrix ) . bitmap ( image , repetition ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Ends the current sub - path , and begins a new one with no fill . Functionally identical to < code > beginFill ( null ) < / c o d e > .
* A tiny API method "ef" also exists .
* @ method endFill
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . endFill = function ( ) {
return this . beginFill ( ) ;
} ;
/ * *
* Sets the stroke style for the current sub - path . Like all drawing methods , this can be chained , so you can define
* the stroke style and color in a single line of code like so :
*
* myGraphics . setStrokeStyle ( 8 , "round" ) . beginStroke ( "#F00" ) ;
*
* A tiny API method "ss" also exists .
* @ method setStrokeStyle
* @ param { Number } thickness The width of the stroke .
* @ param { String | Number } [ caps = 0 ] Indicates the type of caps to use at the end of lines . One of butt ,
* round , or square . Defaults to "butt" . Also accepts the values 0 ( butt ) , 1 ( round ) , and 2 ( square ) for use with
* the tiny API .
* @ param { String | Number } [ joints = 0 ] Specifies the type of joints that should be used where two lines meet .
* One of bevel , round , or miter . Defaults to "miter" . Also accepts the values 0 ( miter ) , 1 ( round ) , and 2 ( bevel )
* for use with the tiny API .
* @ param { Number } [ miterLimit = 10 ] If joints is set to "miter" , then you can specify a miter limit ratio which
* controls at what point a mitered joint will be clipped .
* @ param { Boolean } [ ignoreScale = false ] If true , the stroke will be drawn at the specified thickness regardless
* of active transformations .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . setStrokeStyle = function ( thickness , caps , joints , miterLimit , ignoreScale ) {
2014-11-18 18:26:26 -05:00
this . _updateInstructions ( true ) ;
this . _strokeStyle = this . command = new G . StrokeStyle ( thickness , caps , joints , miterLimit , ignoreScale ) ;
// ignoreScale lives on Stroke, not StrokeStyle, so we do a little trickery:
if ( this . _stroke ) { this . _stroke . ignoreScale = ignoreScale ; }
2014-01-03 13:32:13 -05:00
this . _strokeIgnoreScale = ignoreScale ;
return this ;
} ;
/ * *
* Begins a stroke with the specified color . This ends the current sub - path . A tiny API method "s" also exists .
* @ method beginStroke
* @ param { String } color A CSS compatible color value ( ex . "#FF0000" , "red" , or "rgba(255,0,0,0.5)" ) . Setting to
* null will result in no stroke .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . beginStroke = function ( color ) {
2014-11-18 18:26:26 -05:00
return this . _setStroke ( color ? new G . Stroke ( color ) : null ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Begins a linear gradient stroke defined by the line ( x0 , y0 ) to ( x1 , y1 ) . This ends the current sub - path . For
* example , the following code defines a black to white vertical gradient ranging from 20 px to 120 px , and draws a
* square to display it :
*
* myGraphics . setStrokeStyle ( 10 ) .
* beginLinearGradientStroke ( [ "#000" , "#FFF" ] , [ 0 , 1 ] , 0 , 20 , 0 , 120 ) . drawRect ( 20 , 20 , 120 , 120 ) ;
*
* A tiny API method "ls" also exists .
* @ method beginLinearGradientStroke
* @ param { Array } colors An array of CSS compatible color values . For example , [ "#F00" , "#00F" ] would define
* a gradient drawing from red to blue .
* @ param { Array } ratios An array of gradient positions which correspond to the colors . For example , [ 0.1 ,
* 0.9 ] would draw the first color to 10 % then interpolating to the second color at 90 % .
* @ param { Number } x0 The position of the first point defining the line that defines the gradient direction and size .
* @ param { Number } y0 The position of the first point defining the line that defines the gradient direction and size .
* @ param { Number } x1 The position of the second point defining the line that defines the gradient direction and size .
* @ param { Number } y1 The position of the second point defining the line that defines the gradient direction and size .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . beginLinearGradientStroke = function ( colors , ratios , x0 , y0 , x1 , y1 ) {
2014-11-18 18:26:26 -05:00
return this . _setStroke ( new G . Stroke ( ) . linearGradient ( colors , ratios , x0 , y0 , x1 , y1 ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Begins a radial gradient stroke . This ends the current sub - path . For example , the following code defines a red to
* blue radial gradient centered at ( 100 , 100 ) , with a radius of 50 , and draws a rectangle to display it :
*
* myGraphics . setStrokeStyle ( 10 )
* . beginRadialGradientStroke ( [ "#F00" , "#00F" ] , [ 0 , 1 ] , 100 , 100 , 0 , 100 , 100 , 50 )
* . drawRect ( 50 , 90 , 150 , 110 ) ;
*
* A tiny API method "rs" also exists .
* @ method beginRadialGradientStroke
* @ param { Array } colors An array of CSS compatible color values . For example , [ "#F00" , "#00F" ] would define
* a gradient drawing from red to blue .
* @ param { Array } ratios An array of gradient positions which correspond to the colors . For example , [ 0.1 ,
* 0.9 ] would draw the first color to 10 % then interpolating to the second color at 90 % , then draw the second color
* to 100 % .
* @ param { Number } x0 Center position of the inner circle that defines the gradient .
* @ param { Number } y0 Center position of the inner circle that defines the gradient .
* @ param { Number } r0 Radius of the inner circle that defines the gradient .
* @ param { Number } x1 Center position of the outer circle that defines the gradient .
* @ param { Number } y1 Center position of the outer circle that defines the gradient .
* @ param { Number } r1 Radius of the outer circle that defines the gradient .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . beginRadialGradientStroke = function ( colors , ratios , x0 , y0 , r0 , x1 , y1 , r1 ) {
2014-11-18 18:26:26 -05:00
return this . _setStroke ( new G . Stroke ( ) . radialGradient ( colors , ratios , x0 , y0 , r0 , x1 , y1 , r1 ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Begins a pattern fill using the specified image . This ends the current sub - path . Note that unlike bitmap fills ,
* strokes do not currently support a matrix parameter due to limitations in the canvas API . A tiny API method "bs"
* also exists .
* @ method beginBitmapStroke
* @ param { HTMLImageElement | HTMLCanvasElement | HTMLVideoElement } image The Image , Canvas , or Video object to use
* as the pattern .
* @ param { String } [ repetition = repeat ] Optional . Indicates whether to repeat the image in the fill area . One of
* "repeat" , "repeat-x" , "repeat-y" , or "no-repeat" . Defaults to "repeat" .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . beginBitmapStroke = function ( image , repetition ) {
// NOTE: matrix is not supported for stroke because transforms on strokes also affect the drawn stroke width.
2014-11-18 18:26:26 -05:00
return this . _setStroke ( new G . Stroke ( ) . bitmap ( image , repetition ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Ends the current sub - path , and begins a new one with no stroke . Functionally identical to < code > beginStroke ( null ) < / c o d e > .
* A tiny API method "es" also exists .
* @ method endStroke
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . endStroke = function ( ) {
2014-11-18 18:26:26 -05:00
return this . beginStroke ( ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Maps the familiar ActionScript < code > curveTo ( ) < / c o d e > m e t h o d t o t h e f u n c t i o n a l l y s i m i l a r { { # c r o s s L i n k " G r a p h i c s / q u a d r a t i c C u r v e T o " } } { { / c r o s s L i n k } }
* method .
* @ method curveTo
* @ type { Function }
* * /
p . curveTo = p . quadraticCurveTo ;
/ * *
* Maps the familiar ActionScript < code > drawRect ( ) < / c o d e > m e t h o d t o t h e f u n c t i o n a l l y s i m i l a r { { # c r o s s L i n k " G r a p h i c s / r e c t " } } { { / c r o s s L i n k } }
* method .
* @ method drawRect
* @ type { Function }
* * /
p . drawRect = p . rect ;
/ * *
* Draws a rounded rectangle with all corners with the specified radius .
* @ method drawRoundRect
* @ param { Number } x
* @ param { Number } y
* @ param { Number } w
* @ param { Number } h
* @ param { Number } radius Corner radius .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . drawRoundRect = function ( x , y , w , h , radius ) {
2014-11-18 18:26:26 -05:00
return this . drawRoundRectComplex ( x , y , w , h , radius , radius , radius , radius ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Draws a rounded rectangle with different corner radii . Supports positive and negative corner radii . A tiny API
* method "rc" also exists .
* @ method drawRoundRectComplex
* @ param { Number } x The horizontal coordinate to draw the round rect .
* @ param { Number } y The vertical coordinate to draw the round rect .
* @ param { Number } w The width of the round rect .
* @ param { Number } h The height of the round rect .
* @ param { Number } radiusTL Top left corner radius .
* @ param { Number } radiusTR Top right corner radius .
* @ param { Number } radiusBR Bottom right corner radius .
* @ param { Number } radiusBL Bottom left corner radius .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . drawRoundRectComplex = function ( x , y , w , h , radiusTL , radiusTR , radiusBR , radiusBL ) {
2014-11-18 18:26:26 -05:00
return this . append ( new G . RoundRect ( x , y , w , h , radiusTL , radiusTR , radiusBR , radiusBL ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Draws a circle with the specified radius at ( x , y ) .
*
* var g = new createjs . Graphics ( ) ;
* g . setStrokeStyle ( 1 ) ;
* g . beginStroke ( createjs . Graphics . getRGB ( 0 , 0 , 0 ) ) ;
* g . beginFill ( createjs . Graphics . getRGB ( 255 , 0 , 0 ) ) ;
* g . drawCircle ( 0 , 0 , 3 ) ;
*
* var s = new createjs . Shape ( g ) ;
* s . x = 100 ;
* s . y = 100 ;
*
* stage . addChild ( s ) ;
* stage . update ( ) ;
*
* A tiny API method "dc" also exists .
* @ method drawCircle
* @ param { Number } x x coordinate center point of circle .
* @ param { Number } y y coordinate center point of circle .
* @ param { Number } radius Radius of circle .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . drawCircle = function ( x , y , radius ) {
2014-11-18 18:26:26 -05:00
return this . append ( new G . Circle ( x , y , radius ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Draws an ellipse ( oval ) with a specified width ( w ) and height ( h ) . Similar to { { # crossLink "Graphics/drawCircle" } } { { / c r o s s L i n k } } ,
* except the width and height can be different . A tiny API method "de" also exists .
* @ method drawEllipse
* @ param { Number } x The left coordinate point of the ellipse . Note that this is different from { { # crossLink "Graphics/drawCircle" } } { { / c r o s s L i n k } }
* which draws from center .
* @ param { Number } y The top coordinate point of the ellipse . Note that this is different from { { # crossLink "Graphics/drawCircle" } } { { / c r o s s L i n k } }
* which draws from the center .
* @ param { Number } w The height ( horizontal diameter ) of the ellipse . The horizontal radius will be half of this
* number .
* @ param { Number } h The width ( vertical diameter ) of the ellipse . The vertical radius will be half of this number .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . drawEllipse = function ( x , y , w , h ) {
2014-11-18 18:26:26 -05:00
return this . append ( new G . Ellipse ( x , y , w , h ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Draws a star if pointSize is greater than 0 , or a regular polygon if pointSize is 0 with the specified number of
* points . For example , the following code will draw a familiar 5 pointed star shape centered at 100 , 100 and with a
* radius of 50 :
*
* myGraphics . beginFill ( "#FF0" ) . drawPolyStar ( 100 , 100 , 50 , 5 , 0.6 , - 90 ) ;
* // Note: -90 makes the first point vertical
*
* A tiny API method "dp" also exists .
*
* @ method drawPolyStar
* @ param { Number } x Position of the center of the shape .
* @ param { Number } y Position of the center of the shape .
* @ param { Number } radius The outer radius of the shape .
* @ param { Number } sides The number of points on the star or sides on the polygon .
* @ param { Number } pointSize The depth or "pointy-ness" of the star points . A pointSize of 0 will draw a regular
* polygon ( no points ) , a pointSize of 1 will draw nothing because the points are infinitely pointy .
* @ param { Number } angle The angle of the first point / corner . For example a value of 0 will draw the first point
* directly to the right of the center .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . drawPolyStar = function ( x , y , radius , sides , pointSize , angle ) {
2014-11-18 18:26:26 -05:00
return this . append ( new G . PolyStar ( x , y , radius , sides , pointSize , angle ) ) ;
} ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
/ * *
* Removed in favour of using custom command objects with { { # crossLink "Graphics/append" } } { { / c r o s s L i n k } } .
* @ method inject
* @ deprecated
* * /
/ * *
* Appends a graphics command object to the graphics queue . Command objects expose an "exec" method
* that accepts two parameters : the Context2D to operate on , and an arbitrary data object passed into
* { { # crossLink "Graphics/draw" } } { { / c r o s s L i n k } } . T h e l a t t e r w i l l u s u a l l y b e t h e S h a p e i n s t a n c e t h a t c a l l e d d r a w .
*
* This method is used internally by Graphics methods , such as drawCircle , but can also be used directly to insert
* built - in or custom graphics commands . For example :
*
* // attach data to our shape, so we can access it during the draw:
* myShape . color = "red" ;
*
* // append a Circle command object:
* myShape . graphics . append ( new Graphics . Circle ( 50 , 50 , 30 ) ) ;
*
* // append a custom command object with an exec method that sets the fill style
* // based on the shape's data, and then fills the circle.
* myShape . graphics . append ( { exec : function ( ctx , shape ) {
* ctx . fillStyle = shape . color ;
* ctx . fill ( ) ;
* } } ) ;
*
* @ method append
* @ param { Object } command A graphics command object exposing an "exec" method .
* @ param { boolean } clean The clean param is primarily for internal use . A value of true indicates that a command does not generate a path that should be stroked or filled .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . append = function ( command , clean ) {
this . _activeInstructions . push ( command ) ;
this . command = command ;
if ( ! clean ) { this . _dirty = true ; }
2014-01-03 13:32:13 -05:00
return this ;
} ;
/ * *
* Decodes a compact encoded path string into a series of draw instructions .
* This format is not intended to be human readable , and is meant for use by authoring tools .
* The format uses a base64 character set , with each character representing 6 bits , to define a series of draw
* commands .
*
* Each command is comprised of a single "header" character followed by a variable number of alternating x and y
* position values . Reading the header bits from left to right ( most to least significant ) : bits 1 to 3 specify the
* type of operation ( 0 - moveTo , 1 - lineTo , 2 - quadraticCurveTo , 3 - bezierCurveTo , 4 - closePath , 5 - 7 unused ) . Bit 4
* indicates whether position values use 12 bits ( 2 characters ) or 18 bits ( 3 characters ) , with a one indicating the
* latter . Bits 5 and 6 are currently unused .
*
* Following the header is a series of 0 ( closePath ) , 2 ( moveTo , lineTo ) , 4 ( quadraticCurveTo ) , or 6 ( bezierCurveTo )
* parameters . These parameters are alternating x / y positions represented by 2 or 3 characters ( as indicated by the
* 4 th bit in the command char ) . These characters consist of a 1 bit sign ( 1 is negative , 0 is positive ) , followed
* by an 11 ( 2 char ) or 17 ( 3 char ) bit integer value . All position values are in tenths of a pixel . Except in the
* case of move operations which are absolute , this value is a delta from the previous x or y position ( as
* appropriate ) .
*
* For example , the string "A3cAAMAu4AAA" represents a line starting at - 150 , 0 and ending at 150 , 0.
* < br / > A - bits 000000. First 3 bits ( 000 ) indicate a moveTo operation . 4 th bit ( 0 ) indicates 2 chars per
* parameter .
* < br / > n0 - 110111011100. Absolute x position of - 150.0 px . First bit indicates a negative value , remaining bits
* indicate 1500 tenths of a pixel .
* < br / > AA - 000000000000. Absolute y position of 0.
* < br / > I - 001100. First 3 bits ( 001 ) indicate a lineTo operation . 4 th bit ( 1 ) indicates 3 chars per parameter .
* < br / > Au4 - 000000101110111000. An x delta of 300.0 px , which is added to the previous x value of - 150.0 px to
* provide an absolute position of + 150.0 px .
* < br / > AAA - 000000000000000000. A y delta value of 0.
*
* A tiny API method "p" also exists .
* @ method decodePath
* @ param { String } str The path string to decode .
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . decodePath = function ( str ) {
var instructions = [ this . moveTo , this . lineTo , this . quadraticCurveTo , this . bezierCurveTo , this . closePath ] ;
var paramCount = [ 2 , 2 , 4 , 6 , 0 ] ;
var i = 0 , l = str . length ;
var params = [ ] ;
var x = 0 , y = 0 ;
var base64 = Graphics . BASE _64 ;
while ( i < l ) {
var c = str . charAt ( i ) ;
var n = base64 [ c ] ;
var fi = n >> 3 ; // highest order bits 1-3 code for operation.
var f = instructions [ fi ] ;
// check that we have a valid instruction & that the unused bits are empty:
if ( ! f || ( n & 3 ) ) { throw ( "bad path data (@" + i + "): " + c ) ; }
var pl = paramCount [ fi ] ;
if ( ! fi ) { x = y = 0 ; } // move operations reset the position.
params . length = 0 ;
i ++ ;
var charCount = ( n >> 2 & 1 ) + 2 ; // 4th header bit indicates number size for this operation.
for ( var p = 0 ; p < pl ; p ++ ) {
var num = base64 [ str . charAt ( i ) ] ;
var sign = ( num >> 5 ) ? - 1 : 1 ;
num = ( ( num & 31 ) << 6 ) | ( base64 [ str . charAt ( i + 1 ) ] ) ;
if ( charCount == 3 ) { num = ( num << 6 ) | ( base64 [ str . charAt ( i + 2 ) ] ) ; }
num = sign * num / 10 ;
if ( p % 2 ) { x = ( num += x ) ; }
else { y = ( num += y ) ; }
params [ p ] = num ;
i += charCount ;
}
f . apply ( this , params ) ;
}
return this ;
} ;
2014-11-18 18:26:26 -05:00
/ * *
* Stores all graphics commands so they won ' t be executed in future draws . Calling store ( ) a second time adds to
* the existing store .
*
* This is useful in cases where you are creating vector graphics in an iterative manner , so that only new
* graphics need to be drawn ( which can provide huge performance benefits ) , but you wish to retain all of
* the vector instructions for later use ( ex . scaling , modifying , or exporting ) .
*
* Note that calling store ( ) will force the active path ( if any ) to be ended in a manner similar to changing
* the fill or stroke .
*
* For example , consider a application where the user draws lines with the mouse . As each line segment ( or collection of
* segments ) are added to a Shape , it can be rasterized using { { # crossLink "DisplayObject/updateCache" } } { { / c r o s s L i n k } } ,
* and then stored , so that it can be redrawn at a different scale when the application is resized , or exported to SVG .
*
* // set up cache:
* myShape . cache ( 0 , 0 , 500 , 500 , scale ) ;
*
* // when the user drags, draw a new line:
* myShape . graphics . moveTo ( oldX , oldY ) . lineTo ( newX , newY ) ;
* // then draw it into the existing cache:
* myShape . updateCache ( "source-over" ) ;
* // store the new line, so it isn't redrawn next time:
* myShape . store ( ) ;
*
* // then, when the window resizes, we can re-render at a different scale:
* // first, unstore all our lines:
* myShape . unstore ( ) ;
* // then cache using the new scale:
* myShape . cache ( 0 , 0 , 500 , 500 , newScale ) ;
* // finally, store the existing commands again:
* myShape . store ( ) ;
*
* @ method store
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . store = function ( ) {
this . _updateInstructions ( true ) ;
this . _storeIndex = this . _instructions . length ;
return this ;
} ;
/ * *
* Unstores any graphics commands that were previously stored using { { # crossLink "Graphics/store" } } { { / c r o s s L i n k } }
* so that they will be executed in subsequent draw calls .
*
* @ method unstore
* @ return { Graphics } The Graphics instance the method is called on ( useful for chaining calls . )
* * /
p . unstore = function ( ) {
this . _storeIndex = 0 ;
return this ;
} ;
/ * *
* Returns the graphics instructions array . Each entry is a graphics command object ( ex . Graphics . Fill , Graphics . Rect )
* Modifying the array directly is very likely to result in unexpected behaviour .
*
* This method is mainly intended for introspection of the instructions ( ex . for graphics export ) .
* @ method getInstructions
* @ return { Array } The graphics instructions array .
* * /
p . getInstructions = function ( ) {
this . _updateInstructions ( ) ;
return this . _instructions ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Returns a clone of this Graphics instance . Note that the individual command objects are not cloned .
2014-01-03 13:32:13 -05:00
* @ method clone
* @ return { Graphics } A clone of the current Graphics instance .
* * /
p . clone = function ( ) {
var o = new Graphics ( ) ;
2014-11-18 18:26:26 -05:00
o . command = this . command ;
o . _stroke = this . _stroke ;
o . _strokeStyle = this . _strokeStyle ;
o . _strokeIgnoreScale = this . _strokeIgnoreScale ;
o . _fill = this . _fill ;
2014-01-03 13:32:13 -05:00
o . _instructions = this . _instructions . slice ( ) ;
2014-11-18 18:26:26 -05:00
o . _commitIndex = this . _commitIndex ;
2014-01-03 13:32:13 -05:00
o . _activeInstructions = this . _activeInstructions . slice ( ) ;
o . _dirty = this . _dirty ;
2014-11-18 18:26:26 -05:00
o . _storeIndex = this . _storeIndex ;
2014-01-03 13:32:13 -05:00
return o ;
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Graphics]" ;
} ;
// tiny API:
/ * * S h o r t c u t t o m o v e T o .
* @ method mt
* @ protected
* @ type { Function }
* * /
p . mt = p . moveTo ;
/ * * S h o r t c u t t o l i n e T o .
* @ method lt
* @ protected
* @ type { Function }
* * /
p . lt = p . lineTo ;
/ * * S h o r t c u t t o a r c T o .
* @ method at
* @ protected
* @ type { Function }
* * /
p . at = p . arcTo ;
/ * * S h o r t c u t t o b e z i e r C u r v e T o .
* @ method bt
* @ protected
* @ type { Function }
* * /
p . bt = p . bezierCurveTo ;
/** Shortcut to quadraticCurveTo / curveTo .
* @ method qt
* @ protected
* @ type { Function }
* * /
p . qt = p . quadraticCurveTo ;
/ * * S h o r t c u t t o a r c .
* @ method a
* @ protected
* @ type { Function }
* * /
p . a = p . arc ;
/ * * S h o r t c u t t o r e c t .
* @ method r
* @ protected
* @ type { Function }
* * /
p . r = p . rect ;
/ * * S h o r t c u t t o c l o s e P a t h .
* @ method cp
* @ protected
* @ type { Function }
* * /
p . cp = p . closePath ;
/ * * S h o r t c u t t o c l e a r .
* @ method c
* @ protected
* @ type { Function }
* * /
p . c = p . clear ;
/ * * S h o r t c u t t o b e g i n F i l l .
* @ method f
* @ protected
* @ type { Function }
* * /
p . f = p . beginFill ;
/ * * S h o r t c u t t o b e g i n L i n e a r G r a d i e n t F i l l .
* @ method lf
* @ protected
* @ type { Function }
* * /
p . lf = p . beginLinearGradientFill ;
/ * * S h o r t c u t t o b e g i n R a d i a l G r a d i e n t F i l l .
* @ method rf
* @ protected
* @ type { Function }
* * /
p . rf = p . beginRadialGradientFill ;
/ * * S h o r t c u t t o b e g i n B i t m a p F i l l .
* @ method bf
* @ protected
* @ type { Function }
* * /
p . bf = p . beginBitmapFill ;
/ * * S h o r t c u t t o e n d F i l l .
* @ method ef
* @ protected
* @ type { Function }
* * /
p . ef = p . endFill ;
/ * * S h o r t c u t t o s e t S t r o k e S t y l e .
* @ method ss
* @ protected
* @ type { Function }
* * /
p . ss = p . setStrokeStyle ;
/ * * S h o r t c u t t o b e g i n S t r o k e .
* @ method s
* @ protected
* @ type { Function }
* * /
p . s = p . beginStroke ;
/ * * S h o r t c u t t o b e g i n L i n e a r G r a d i e n t S t r o k e .
* @ method ls
* @ protected
* @ type { Function }
* * /
p . ls = p . beginLinearGradientStroke ;
/ * * S h o r t c u t t o b e g i n R a d i a l G r a d i e n t S t r o k e .
* @ method rs
* @ protected
* @ type { Function }
* * /
p . rs = p . beginRadialGradientStroke ;
/ * * S h o r t c u t t o b e g i n B i t m a p S t r o k e .
* @ method bs
* @ protected
* @ type { Function }
* * /
p . bs = p . beginBitmapStroke ;
/ * * S h o r t c u t t o e n d S t r o k e .
* @ method es
* @ protected
* @ type { Function }
* * /
p . es = p . endStroke ;
/ * * S h o r t c u t t o d r a w R e c t .
* @ method dr
* @ protected
* @ type { Function }
* * /
p . dr = p . drawRect ;
/ * * S h o r t c u t t o d r a w R o u n d R e c t .
* @ method rr
* @ protected
* @ type { Function }
* * /
p . rr = p . drawRoundRect ;
/ * * S h o r t c u t t o d r a w R o u n d R e c t C o m p l e x .
* @ method rc
* @ protected
* @ type { Function }
* * /
p . rc = p . drawRoundRectComplex ;
/ * * S h o r t c u t t o d r a w C i r c l e .
* @ method dc
* @ protected
* @ type { Function }
* * /
p . dc = p . drawCircle ;
/ * * S h o r t c u t t o d r a w E l l i p s e .
* @ method de
* @ protected
* @ type { Function }
* * /
p . de = p . drawEllipse ;
/ * * S h o r t c u t t o d r a w P o l y S t a r .
* @ method dp
* @ protected
* @ type { Function }
* * /
p . dp = p . drawPolyStar ;
/ * * S h o r t c u t t o d e c o d e P a t h .
* @ method p
* @ protected
* @ type Function
* * /
p . p = p . decodePath ;
// private methods:
/ * *
* @ method _updateInstructions
* @ protected
* * /
2014-11-18 18:26:26 -05:00
p . _updateInstructions = function ( commit ) {
var instr = this . _instructions , active = this . _activeInstructions , commitIndex = this . _commitIndex ;
if ( this . _dirty && active . length ) {
instr . length = commitIndex ; // remove old, uncommitted commands
instr . push ( Graphics . beginCmd ) ;
instr . push . apply ( instr , active ) ;
if ( this . _fill ) { instr . push ( this . _fill ) ; }
if ( this . _stroke && this . _strokeStyle ) { instr . push ( this . _strokeStyle ) ; }
if ( this . _stroke ) { instr . push ( this . _stroke ) ; }
this . _dirty = false ;
2014-01-03 13:32:13 -05:00
}
2014-11-18 18:26:26 -05:00
if ( commit ) {
active . length = 0 ;
this . _commitIndex = instr . length ;
2014-01-03 13:32:13 -05:00
}
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* @ method _setFill
2014-01-03 13:32:13 -05:00
* @ protected
* * /
2014-11-18 18:26:26 -05:00
p . _setFill = function ( fill ) {
this . _updateInstructions ( true ) ;
if ( this . _fill = fill ) { this . command = fill ; }
return this ;
2014-01-03 13:32:13 -05:00
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* @ method _setStroke
2014-01-03 13:32:13 -05:00
* @ protected
* * /
2014-11-18 18:26:26 -05:00
p . _setStroke = function ( stroke ) {
this . _updateInstructions ( true ) ;
if ( this . _stroke = stroke ) {
this . command = stroke ;
stroke . ignoreScale = this . _strokeIgnoreScale ;
2014-01-03 13:32:13 -05:00
}
2014-11-18 18:26:26 -05:00
return this ;
2014-01-03 13:32:13 -05:00
} ;
2014-11-18 18:26:26 -05:00
// Command Objects:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* @ namespace Graphics
* /
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n . S e e { { # c r o s s L i n k " G r a p h i c s " } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class MoveTo
* @ constructor
* @ param { Number } x
* @ param { Number } y
2014-01-03 13:32:13 -05:00
* * /
/ * *
2014-11-18 18:26:26 -05:00
* @ property x
* @ type Number
* /
/ * *
* @ property y
* @ type Number
* /
( G . LineTo = function ( x , y ) {
this . x = x ; this . y = y ;
} ) . prototype . exec = function ( ctx ) { ctx . lineTo ( this . x , this . y ) ; } ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class LineTo
* @ constructor
* @ param { Number } x
* @ param { Number } y
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
/ * *
* @ property x
* @ type Number
* /
/ * *
* @ property y
* @ type Number
* /
( G . MoveTo = function ( x , y ) {
this . x = x ; this . y = y ;
} ) . prototype . exec = function ( ctx ) { ctx . moveTo ( this . x , this . y ) ; } ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class ArcTo
* @ constructor
* @ param { Number } x1
* @ param { Number } y1
* @ param { Number } x2
* @ param { Number } y2
* @ param { Number } radius
* * /
/ * *
* @ property x1
* @ type Number
* /
/ * *
* @ property y1
* @ type Number
* /
/ * *
* @ property x2
* @ type Number
* /
/ * *
* @ property y2
* @ type Number
* /
/ * *
* @ property radius
* @ type Number
* /
( G . ArcTo = function ( x1 , y1 , x2 , y2 , radius ) {
this . x1 = x1 ; this . y1 = y1 ;
this . x2 = x2 ; this . y2 = y2 ;
this . radius = radius ;
} ) . prototype . exec = function ( ctx ) { ctx . arcTo ( this . x1 , this . y1 , this . x2 , this . y2 , this . radius ) ; } ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class Arc
* @ constructor
* @ param { Number } x
* @ param { Number } y
* @ param { Number } radius
* @ param { Number } startAngle
* @ param { Number } endAngle
* @ param { Number } anticlockwise
* * /
/ * *
* @ property x
* @ type Number
* /
/ * *
* @ property y
* @ type Number
* /
/ * *
* @ property radius
* @ type Number
* /
/ * *
* @ property startAngle
* @ type Number
* /
/ * *
* @ property endAngle
* @ type Number
* /
/ * *
* @ property anticlockwise
* @ type Number
* /
( G . Arc = function ( x , y , radius , startAngle , endAngle , anticlockwise ) {
this . x = x ; this . y = y ;
this . radius = radius ;
this . startAngle = startAngle ; this . endAngle = endAngle ;
this . anticlockwise = ! ! anticlockwise ;
} ) . prototype . exec = function ( ctx ) { ctx . arc ( this . x , this . y , this . radius , this . startAngle , this . endAngle , this . anticlockwise ) ; } ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class QuadraticCurveTo
* @ constructor
* @ param { Number } cpx
* @ param { Number } cpy
* @ param { Number } x
* @ param { Number } y
* * /
/ * *
* @ property cpx
* @ type Number
* /
/ * *
* @ property cpy
* @ type Number
* /
/ * *
* @ property x
* @ type Number
* /
/ * *
* @ property y
* @ type Number
* /
( G . QuadraticCurveTo = function ( cpx , cpy , x , y ) {
this . cpx = cpx ; this . cpy = cpy ;
this . x = x ; this . y = y ;
} ) . prototype . exec = function ( ctx ) { ctx . quadraticCurveTo ( this . cpx , this . cpy , this . x , this . y ) ; } ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class BezierCurveTo
* @ constructor
* @ param { Number } cp1x
* @ param { Number } cp1y
* @ param { Number } cp2x
* @ param { Number } cp2y
* @ param { Number } x
* @ param { Number } y
* * /
/ * *
* @ property cp1x
* @ type Number
* /
/ * *
* @ property cp1y
* @ type Number
* /
/ * *
* @ property cp2x
* @ type Number
* /
/ * *
* @ property cp2y
* @ type Number
* /
/ * *
* @ property x
* @ type Number
* /
/ * *
* @ property y
* @ type Number
* /
( G . BezierCurveTo = function ( cp1x , cp1y , cp2x , cp2y , x , y ) {
this . cp1x = cp1x ; this . cp1y = cp1y ;
this . cp2x = cp2x ; this . cp2y = cp2y ;
this . x = x ; this . y = y ;
} ) . prototype . exec = function ( ctx ) { ctx . bezierCurveTo ( this . cp1x , this . cp1y , this . cp2x , this . cp2y , this . x , this . y ) ; } ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class Rect
* @ constructor
* @ param { Number } x
* @ param { Number } y
* @ param { Number } w
* @ param { Number } h
* * /
/ * *
* @ property x
* @ type Number
* /
/ * *
* @ property y
* @ type Number
* /
/ * *
* @ property w
* @ type Number
* /
/ * *
* @ property h
* @ type Number
* /
( G . Rect = function ( x , y , w , h ) {
this . x = x ; this . y = y ;
this . w = w ; this . h = h ;
} ) . prototype . exec = function ( ctx ) { ctx . rect ( this . x , this . y , this . w , this . h ) ; } ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class ClosePath
* @ constructor
* * /
( G . ClosePath = function ( ) {
} ) . prototype . exec = function ( ctx ) { ctx . closePath ( ) ; } ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class BeginPath
* @ constructor
* * /
( G . BeginPath = function ( ) {
} ) . prototype . exec = function ( ctx ) { ctx . beginPath ( ) ; } ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class Fill
* @ constructor
* @ param { Object } style A valid Context2D fillStyle .
* @ param { Matrix2D } matrix
* * /
/ * *
* A valid Context2D fillStyle .
* @ property style
* @ type Object
* /
/ * *
* @ property matrix
* @ type Matrix2D
* /
p = ( G . Fill = function ( style , matrix ) {
this . style = style ;
this . matrix = matrix ;
} ) . prototype ;
p . exec = function ( ctx ) {
if ( ! this . style ) { return ; }
ctx . fillStyle = this . style ;
var mtx = this . matrix ;
if ( mtx ) { ctx . save ( ) ; ctx . transform ( mtx . a , mtx . b , mtx . c , mtx . d , mtx . tx , mtx . ty ) ; }
ctx . fill ( ) ;
if ( mtx ) { ctx . restore ( ) ; }
} ;
/ * *
* Creates a linear gradient style and assigns it to { { # crossLink "Fill/style:property" } } { { / c r o s s L i n k } } .
* @ method linearGradient
* @ param { Array } colors
* @ param { Array } ratios
* @ param { Number } x0
* @ param { Number } y0
* @ param { Number } x1
* @ param { Number } y1
* @ return { Fill } Returns this Fill object for chaining or assignment .
* /
p . linearGradient = function ( colors , ratios , x0 , y0 , x1 , y1 ) {
var o = this . style = Graphics . _ctx . createLinearGradient ( x0 , y0 , x1 , y1 ) ;
for ( var i = 0 , l = colors . length ; i < l ; i ++ ) { o . addColorStop ( ratios [ i ] , colors [ i ] ) ; }
o . props = { colors : colors , ratios : ratios , x0 : x0 , y0 : y0 , x1 : x1 , y1 : y1 , type : "linear" } ;
return this ;
} ;
/ * *
* Creates a radial gradient style and assigns it to { { # crossLink "Fill/style:property" } } { { / c r o s s L i n k } } .
* @ method radialGradient
* @ param { Array } colors
* @ param { Array } ratios
* @ param { Number } x0
* @ param { Number } y0
* @ param { Number } r0
* @ param { Number } x1
* @ param { Number } y1
* @ param { Number } r1
* @ return { Fill } Returns this Fill object for chaining or assignment .
* /
p . radialGradient = function ( colors , ratios , x0 , y0 , r0 , x1 , y1 , r1 ) {
var o = this . style = Graphics . _ctx . createRadialGradient ( x0 , y0 , r0 , x1 , y1 , r1 ) ;
for ( var i = 0 , l = colors . length ; i < l ; i ++ ) { o . addColorStop ( ratios [ i ] , colors [ i ] ) ; }
o . props = { colors : colors , ratios : ratios , x0 : x0 , y0 : y0 , r0 : r0 , x1 : x1 , y1 : y1 , r1 : r1 , type : "radial" } ;
return this ;
} ;
/ * *
* Creates a bitmap fill style and assigns it to { { # crossLink "Fill/style:property" } } { { / c r o s s L i n k } } .
* @ method bitmap
* @ param { Image } image
* @ param { String } [ repetition ] One of : repeat , repeat - x , repeat - y , or no - repeat .
* @ return { Fill } Returns this Fill object for chaining or assignment .
* /
p . bitmap = function ( image , repetition ) {
var o = this . style = Graphics . _ctx . createPattern ( image , repetition || "" ) ;
o . props = { image : image , repetition : repetition , type : "bitmap" } ;
return this ;
} ;
p . path = false ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class Stroke
* @ constructor
* @ param { Object } style A valid Context2D fillStyle .
* @ param { Boolean } ignoreScale
* * /
/ * *
* A valid Context2D strokeStyle .
* @ property style
* @ type Object
* /
/ * *
* @ property ignoreScale
* @ type Boolean
* /
p = ( G . Stroke = function ( style , ignoreScale ) {
this . style = style ;
this . ignoreScale = ignoreScale ;
} ) . prototype ;
p . exec = function ( ctx ) {
if ( ! this . style ) { return ; }
ctx . strokeStyle = this . style ;
if ( this . ignoreScale ) { ctx . save ( ) ; ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ; }
ctx . stroke ( ) ;
if ( this . ignoreScale ) { ctx . restore ( ) ; }
} ;
/ * *
* Creates a linear gradient style and assigns it to { { # crossLink "Stroke/style:property" } } { { / c r o s s L i n k } } .
* @ method linearGradient
* @ param { Array } colors
* @ param { Array } ratios
* @ param { Number } x0
* @ param { Number } y0
* @ param { Number } x1
* @ param { Number } y1
* @ return { Fill } Returns this Stroke object for chaining or assignment .
* /
p . linearGradient = G . Fill . prototype . linearGradient ;
/ * *
* Creates a radial gradient style and assigns it to { { # crossLink "Stroke/style:property" } } { { / c r o s s L i n k } } .
* @ method radialGradient
* @ param { Array } colors
* @ param { Array } ratios
* @ param { Number } x0
* @ param { Number } y0
* @ param { Number } r0
* @ param { Number } x1
* @ param { Number } y1
* @ param { Number } r1
* @ return { Fill } Returns this Stroke object for chaining or assignment .
* /
p . radialGradient = G . Fill . prototype . radialGradient ;
/ * *
* Creates a bitmap fill style and assigns it to { { # crossLink "Stroke/style:property" } } { { / c r o s s L i n k } } .
* @ method bitmap
* @ param { Image } image
* @ param { String } [ repetition ] One of : repeat , repeat - x , repeat - y , or no - repeat .
* @ return { Fill } Returns this Stroke object for chaining or assignment .
* /
p . bitmap = G . Fill . prototype . bitmap ;
p . path = false ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class StrokeStyle
* @ constructor
* @ param { Number } width
* @ param { String } caps
* @ param { String } joints
* @ param { Number } miterLimit
* * /
/ * *
* @ property width
* @ type Number
* /
/ * *
* One of : butt , round , square
* @ property caps
* @ type String
* /
/ * *
* One of : round , bevel , miter
* @ property joints
* @ type String
* /
/ * *
* @ property miterLimit
* @ type Number
* /
p = ( G . StrokeStyle = function ( width , caps , joints , miterLimit ) {
this . width = width ;
this . caps = caps ;
this . joints = joints ;
this . miterLimit = miterLimit ;
} ) . prototype ;
p . exec = function ( ctx ) {
ctx . lineWidth = ( this . width == null ? "1" : this . width ) ;
ctx . lineCap = ( this . caps == null ? "butt" : this . caps ) ;
ctx . lineJoin = ( this . joints == null ? "miter" : this . joints ) ;
ctx . miterLimit = ( this . miterLimit == null ? "10" : this . miterLimit ) ;
} ;
p . path = false ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class RoundRect
* @ constructor
* @ param { Number } x
* @ param { Number } y
* @ param { Number } w
* @ param { Number } h
* @ param { Number } radiusTL
* @ param { Number } radiusTR
* @ param { Number } radiusBR
* @ param { Number } radiusBL
* * /
/ * *
* @ property x
* @ type Number
* /
/ * *
* @ property y
* @ type Number
* /
/ * *
* @ property w
* @ type Number
* /
/ * *
* @ property h
* @ type Number
* /
/ * *
* @ property radiusTL
* @ type Number
* /
/ * *
* @ property radiusTR
* @ type Number
* /
/ * *
* @ property radiusBR
* @ type Number
* /
/ * *
* @ property radiusBL
* @ type Number
* /
( G . RoundRect = function ( x , y , w , h , radiusTL , radiusTR , radiusBR , radiusBL ) {
this . x = x ; this . y = y ;
this . w = w ; this . h = h ;
this . radiusTL = radiusTL ; this . radiusTR = radiusTR ;
this . radiusBR = radiusBR ; this . radiusBL = radiusBL ;
} ) . prototype . exec = function ( ctx ) {
var max = ( w < h ? w : h ) / 2 ;
var mTL = 0 , mTR = 0 , mBR = 0 , mBL = 0 ;
var x = this . x , y = this . y , w = this . w , h = this . h ;
var rTL = this . radiusTL , rTR = this . radiusTR , rBR = this . radiusBR , rBL = this . radiusBL ;
if ( rTL < 0 ) { rTL *= ( mTL = - 1 ) ; }
if ( rTL > max ) { rTL = max ; }
if ( rTR < 0 ) { rTR *= ( mTR = - 1 ) ; }
if ( rTR > max ) { rTR = max ; }
if ( rBR < 0 ) { rBR *= ( mBR = - 1 ) ; }
if ( rBR > max ) { rBR = max ; }
if ( rBL < 0 ) { rBL *= ( mBL = - 1 ) ; }
if ( rBL > max ) { rBL = max ; }
ctx . moveTo ( x + w - rTR , y ) ;
ctx . arcTo ( x + w + rTR * mTR , y - rTR * mTR , x + w , y + rTR , rTR ) ;
ctx . lineTo ( x + w , y + h - rBR ) ;
ctx . arcTo ( x + w + rBR * mBR , y + h + rBR * mBR , x + w - rBR , y + h , rBR ) ;
ctx . lineTo ( x + rBL , y + h ) ;
ctx . arcTo ( x - rBL * mBL , y + h + rBL * mBL , x , y + h - rBL , rBL ) ;
ctx . lineTo ( x , y + rTL ) ;
ctx . arcTo ( x - rTL * mTL , y - rTL * mTL , x + rTL , y , rTL ) ;
ctx . closePath ( ) ;
} ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class Circle
* @ constructor
* @ param { Number } x
* @ param { Number } y
* @ param { Number } radius
* * /
/ * *
* @ property x
* @ type Number
* /
/ * *
* @ property y
* @ type Number
* /
/ * *
* @ property radius
* @ type Number
* /
( G . Circle = function ( x , y , radius ) {
this . x = x ; this . y = y ;
this . radius = radius ;
} ) . prototype . exec = function ( ctx ) { ctx . arc ( this . x , this . y , this . radius , 0 , Math . PI * 2 ) ; } ;
( G . Ellipse = function ( x , y , w , h ) {
this . x = x ; this . y = y ;
this . w = w ; this . h = h ;
} ) . prototype . exec = function ( ctx ) {
var x = this . x , y = this . y ;
var w = this . w , h = this . h ;
var k = 0.5522848 ;
var ox = ( w / 2 ) * k ;
var oy = ( h / 2 ) * k ;
var xe = x + w ;
var ye = y + h ;
var xm = x + w / 2 ;
var ym = y + h / 2 ;
ctx . moveTo ( x , ym ) ;
ctx . bezierCurveTo ( x , ym - oy , xm - ox , y , xm , y ) ;
ctx . bezierCurveTo ( xm + ox , y , xe , ym - oy , xe , ym ) ;
ctx . bezierCurveTo ( xe , ym + oy , xm + ox , ye , xm , ye ) ;
ctx . bezierCurveTo ( xm - ox , ye , x , ym + oy , x , ym ) ;
} ;
/ * *
* Graphics command object . See { { # crossLink "Graphics" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " G r a p h i c s / a p p e n d " } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ class PolyStar
* @ constructor
* @ param { Number } x
* @ param { Number } y
* @ param { Number } radius
* @ param { Number } sides
* @ param { Number } pointSize
* @ param { Number } angle
* * /
/ * *
* @ property x
* @ type Number
* /
/ * *
* @ property y
* @ type Number
* /
/ * *
* @ property radius
* @ type Number
* /
/ * *
* @ property sides
* @ type Number
* /
/ * *
* @ property pointSize
* @ type Number
* /
/ * *
* @ property angle
* @ type Number
* /
( G . PolyStar = function ( x , y , radius , sides , pointSize , angle ) {
this . x = x ; this . y = y ;
this . radius = radius ;
this . sides = sides ;
this . pointSize = pointSize ;
this . angle = angle ;
} ) . prototype . exec = function ( ctx ) {
var x = this . x , y = this . y ;
var radius = this . radius ;
var angle = ( this . angle || 0 ) / 180 * Math . PI ;
var sides = this . sides ;
var ps = 1 - ( this . pointSize || 0 ) ;
var a = Math . PI / sides ;
ctx . moveTo ( x + Math . cos ( angle ) * radius , y + Math . sin ( angle ) * radius ) ;
for ( var i = 0 ; i < sides ; i ++ ) {
angle += a ;
if ( ps != 1 ) {
ctx . lineTo ( x + Math . cos ( angle ) * radius * ps , y + Math . sin ( angle ) * radius * ps ) ;
}
angle += a ;
ctx . lineTo ( x + Math . cos ( angle ) * radius , y + Math . sin ( angle ) * radius ) ;
}
ctx . closePath ( ) ;
} ;
// docced above.
Graphics . beginCmd = new G . BeginPath ( ) ; // so we don't have to instantiate multiple instances.
createjs . Graphics = Graphics ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// DisplayObject.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
2014-11-18 18:26:26 -05:00
"use strict" ;
// constructor:
/ * *
* DisplayObject is an abstract class that should not be constructed directly . Instead construct subclasses such as
* { { # crossLink "Container" } } { { / c r o s s L i n k } } , { { # c r o s s L i n k " B i t m a p " } } { { / c r o s s L i n k } } , a n d { { # c r o s s L i n k " S h a p e " } } { { / c r o s s L i n k } } .
* DisplayObject is the base class for all display classes in the EaselJS library . It defines the core properties and
* methods that are shared between all display objects , such as transformation properties ( x , y , scaleX , scaleY , etc ) ,
* caching , and mouse handlers .
* @ class DisplayObject
* @ extends EventDispatcher
* @ constructor
* * /
function DisplayObject ( ) {
this . EventDispatcher _constructor ( ) ;
// public properties:
/ * *
* The alpha ( transparency ) for this display object . 0 is fully transparent , 1 is fully opaque .
* @ property alpha
* @ type { Number }
* @ default 1
* * /
this . alpha = 1 ;
/ * *
* If a cache is active , this returns the canvas that holds the cached version of this display object . See { { # crossLink "cache" } } { { / c r o s s L i n k } }
* for more information .
* @ property cacheCanvas
* @ type { HTMLCanvasElement | Object }
* @ default null
* @ readonly
* * /
this . cacheCanvas = null ;
/ * *
* Returns an ID number that uniquely identifies the current cache for this display object . This can be used to
* determine if the cache has changed since a previous check .
* @ property cacheID
* @ type { Number }
* @ default 0
* /
this . cacheID = 0 ;
/ * *
* Unique ID for this display object . Makes display objects easier for some uses .
* @ property id
* @ type { Number }
* @ default - 1
* * /
this . id = createjs . UID . get ( ) ;
/ * *
* Indicates whether to include this object when running mouse interactions . Setting this to ` false ` for children
* of a { { # crossLink "Container" } } { { / c r o s s L i n k } } w i l l c a u s e e v e n t s o n t h e C o n t a i n e r t o n o t f i r e w h e n t h a t c h i l d i s
* clicked . Setting this property to ` false ` does not prevent the { { # crossLink "Container/getObjectsUnderPoint" } } { { / c r o s s L i n k } }
* method from returning the child .
*
* < strong > Note : < / s t r o n g > I n E a s e l J S 0 . 7 . 0 , t h e m o u s e E n a b l e d p r o p e r t y w i l l n o t w o r k p r o p e r l y w i t h n e s t e d C o n t a i n e r s . P l e a s e
* check out the latest NEXT version in < a href = "https://github.com/CreateJS/EaselJS/tree/master/lib" > GitHub < / a > f o r a n u p d a t e d v e r s i o n w i t h t h i s i s s u e r e s o l v e d . T h e f i x w i l l b e
* provided in the next release of EaselJS .
* @ property mouseEnabled
* @ type { Boolean }
* @ default true
* * /
this . mouseEnabled = true ;
/ * *
* If false , the tick will not run on this display object ( or its children ) . This can provide some performance benefits .
* In addition to preventing the "tick" event from being dispatched , it will also prevent tick related updates
* on some display objects ( ex . Sprite & MovieClip frame advancing , DOMElement visibility handling ) .
* @ property tickEnabled
* @ type Boolean
* @ default true
* * /
this . tickEnabled = true ;
/ * *
* An optional name for this display object . Included in { { # crossLink "DisplayObject/toString" } } { { / c r o s s L i n k } } . U s e f u l f o r
* debugging .
* @ property name
* @ type { String }
* @ default null
* * /
this . name = null ;
/ * *
* A reference to the { { # crossLink "Container" } } { { / c r o s s L i n k } } o r { { # c r o s s L i n k " S t a g e " } } { { / c r o s s L i n k } } o b j e c t t h a t
* contains this display object , or null if it has not been added
* to one .
* @ property parent
* @ final
* @ type { Container }
* @ default null
* @ readonly
* * /
this . parent = null ;
/ * *
* The left offset for this display object ' s registration point . For example , to make a 100 x100px Bitmap rotate
* around its center , you would set regX and { { # crossLink "DisplayObject/regY:property" } } { { / c r o s s L i n k } } t o 5 0 .
* @ property regX
* @ type { Number }
* @ default 0
* * /
this . regX = 0 ;
/ * *
* The y offset for this display object ' s registration point . For example , to make a 100 x100px Bitmap rotate around
* its center , you would set { { # crossLink "DisplayObject/regX:property" } } { { / c r o s s L i n k } } a n d r e g Y t o 5 0 .
* @ property regY
* @ type { Number }
* @ default 0
* * /
this . regY = 0 ;
/ * *
* The rotation in degrees for this display object .
* @ property rotation
* @ type { Number }
* @ default 0
* * /
this . rotation = 0 ;
/ * *
* The factor to stretch this display object horizontally . For example , setting scaleX to 2 will stretch the display
* object to twice its nominal width . To horizontally flip an object , set the scale to a negative number .
* @ property scaleX
* @ type { Number }
* @ default 1
* * /
this . scaleX = 1 ;
/ * *
* The factor to stretch this display object vertically . For example , setting scaleY to 0.5 will stretch the display
* object to half its nominal height . To vertically flip an object , set the scale to a negative number .
* @ property scaleY
* @ type { Number }
* @ default 1
* * /
this . scaleY = 1 ;
/ * *
* The factor to skew this display object horizontally .
* @ property skewX
* @ type { Number }
* @ default 0
* * /
this . skewX = 0 ;
/ * *
* The factor to skew this display object vertically .
* @ property skewY
* @ type { Number }
* @ default 0
* * /
this . skewY = 0 ;
/ * *
* A shadow object that defines the shadow to render on this display object . Set to ` null ` to remove a shadow . If
* null , this property is inherited from the parent container .
* @ property shadow
* @ type { Shadow }
* @ default null
* * /
this . shadow = null ;
/ * *
* Indicates whether this display object should be rendered to the canvas and included when running the Stage
* { { # crossLink "Stage/getObjectsUnderPoint" } } { { / c r o s s L i n k } } m e t h o d .
* @ property visible
* @ type { Boolean }
* @ default true
* * /
this . visible = true ;
/ * *
* The x ( horizontal ) position of the display object , relative to its parent .
* @ property x
* @ type { Number }
* @ default 0
* * /
this . x = 0 ;
/ * * T h e y ( v e r t i c a l ) p o s i t i o n o f t h e d i s p l a y o b j e c t , r e l a t i v e t o i t s p a r e n t .
* @ property y
* @ type { Number }
* @ default 0
* * /
this . y = 0 ;
/ * *
* If set , defines the transformation for this display object , overriding all other transformation properties
* ( x , y , rotation , scale , skew ) .
* @ property transformMatrix
* @ type { Matrix2D }
* @ default null
* * /
this . transformMatrix = null ;
/ * *
* The composite operation indicates how the pixels of this display object will be composited with the elements
* behind it . If ` null ` , this property is inherited from the parent container . For more information , read the
* < a href = "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#compositing" >
* whatwg spec on compositing < / a > .
* @ property compositeOperation
* @ type { String }
* @ default null
* * /
this . compositeOperation = null ;
/ * *
* Indicates whether the display object should be drawn to a whole pixel when
* { { # crossLink "Stage/snapToPixelEnabled" } } { { / c r o s s L i n k } } i s t r u e . T o e n a b l e / d i s a b l e s n a p p i n g o n w h o l e
* categories of display objects , set this value on the prototype ( Ex . Text . prototype . snapToPixel = true ) .
* @ property snapToPixel
* @ type { Boolean }
* @ default true
* * /
this . snapToPixel = true ;
/ * *
* An array of Filter objects to apply to this display object . Filters are only applied / updated when { { # crossLink "cache" } } { { / c r o s s L i n k } }
* or { { # crossLink "updateCache" } } { { / c r o s s L i n k } } i s c a l l e d o n t h e d i s p l a y o b j e c t , a n d o n l y a p p l y t o t h e a r e a t h a t i s
* cached .
* @ property filters
* @ type { Array }
* @ default null
* * /
this . filters = null ;
/ * *
* A Shape instance that defines a vector mask ( clipping path ) for this display object . The shape ' s transformation
* will be applied relative to the display object ' s parent coordinates ( as if it were a child of the parent ) .
* @ property mask
* @ type { Shape }
* @ default null
* /
this . mask = null ;
/ * *
* A display object that will be tested when checking mouse interactions or testing { { # crossLink "Container/getObjectsUnderPoint" } } { { / c r o s s L i n k } } .
* The hit area will have its transformation applied relative to this display object ' s coordinate space ( as though
* the hit test object were a child of this display object and relative to its regX / Y ) . The hitArea will be tested
* using only its own ` alpha ` value regardless of the alpha value on the target display object , or the target ' s
* ancestors ( parents ) .
*
* If set on a { { # crossLink "Container" } } { { / c r o s s L i n k } } , c h i l d r e n o f t h e C o n t a i n e r w i l l n o t r e c e i v e m o u s e e v e n t s .
* This is similar to setting { { # crossLink "mouseChildren" } } { { / c r o s s L i n k } } t o f a l s e .
*
* Note that hitArea is NOT currently used by the ` hitTest() ` method , nor is it supported for { { # crossLink "Stage" } } { { / c r o s s L i n k } } .
* @ property hitArea
* @ type { DisplayObject }
* @ default null
* /
this . hitArea = null ;
/ * *
* A CSS cursor ( ex . "pointer" , "help" , "text" , etc ) that will be displayed when the user hovers over this display
* object . You must enable mouseover events using the { { # crossLink "Stage/enableMouseOver" } } { { / c r o s s L i n k } } m e t h o d t o
* use this property . Setting a non - null cursor on a Container will override the cursor set on its descendants .
* @ property cursor
* @ type { String }
* @ default null
* /
this . cursor = null ;
// private properties:
/ * *
* @ property _cacheOffsetX
* @ protected
* @ type { Number }
* @ default 0
* * /
this . _cacheOffsetX = 0 ;
/ * *
* @ property _cacheOffsetY
* @ protected
* @ type { Number }
* @ default 0
* * /
this . _cacheOffsetY = 0 ;
/ * *
* @ property _cacheScale
* @ protected
* @ type { Number }
* @ default 1
* * /
this . _cacheScale = 1 ;
/ * *
* @ property _cacheDataURLID
* @ protected
* @ type { Number }
* @ default 0
* /
this . _cacheDataURLID = 0 ;
/ * *
* @ property _cacheDataURL
* @ protected
* @ type { String }
* @ default null
* /
this . _cacheDataURL = null ;
/ * *
* @ property _props
* @ protected
* @ type { DisplayObject }
* @ default null
* * /
this . _props = new createjs . DisplayProps ( ) ;
/ * *
* @ property _rectangle
* @ protected
* @ type { Rectangle }
* @ default null
* * /
this . _rectangle = new createjs . Rectangle ( ) ;
/ * *
* @ property _bounds
* @ protected
* @ type { Rectangle }
* @ default null
* * /
this . _bounds = null ;
}
var p = createjs . extend ( DisplayObject , createjs . EventDispatcher ) ;
2014-02-02 19:31:06 -05:00
// static properties:
/ * *
* Listing of mouse event names . Used in _hasMouseEventListener .
* @ property _MOUSE _EVENTS
* @ protected
* @ static
* @ type { Array }
* * /
DisplayObject . _MOUSE _EVENTS = [ "click" , "dblclick" , "mousedown" , "mouseout" , "mouseover" , "pressmove" , "pressup" , "rollout" , "rollover" ] ;
2014-01-03 13:32:13 -05:00
/ * *
* Suppresses errors generated when using features like hitTest , mouse events , and { { # crossLink "getObjectsUnderPoint" } } { { / c r o s s L i n k } }
* with cross domain content .
* @ property suppressCrossDomainErrors
* @ static
* @ type { Boolean }
* @ default false
* * /
DisplayObject . suppressCrossDomainErrors = false ;
2014-02-02 19:31:06 -05:00
/ * *
* @ property _snapToPixelEnabled
* @ protected
* @ static
* @ type { Boolean }
* @ default false
* * /
DisplayObject . _snapToPixelEnabled = false ; // stage.snapToPixelEnabled is temporarily copied here during a draw to provide global access.
2014-01-03 13:32:13 -05:00
/ * *
* @ property _hitTestCanvas
* @ type { HTMLCanvasElement | Object }
* @ static
* @ protected
* * /
/ * *
* @ property _hitTestContext
* @ type { CanvasRenderingContext2D }
* @ static
* @ protected
* * /
var canvas = createjs . createCanvas ? createjs . createCanvas ( ) : document . createElement ( "canvas" ) ; // prevent errors on load in browsers without canvas.
if ( canvas . getContext ) {
DisplayObject . _hitTestCanvas = canvas ;
DisplayObject . _hitTestContext = canvas . getContext ( "2d" ) ;
canvas . width = canvas . height = 1 ;
}
/ * *
* @ property _nextCacheID
* @ type { Number }
* @ static
* @ protected
* * /
DisplayObject . _nextCacheID = 1 ;
2014-11-18 18:26:26 -05:00
// events:
2014-01-03 13:32:13 -05:00
/ * *
* Dispatched when the user presses their left mouse button over the display object . See the
* { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } } c l a s s f o r a l i s t i n g o f e v e n t p r o p e r t i e s .
* @ event mousedown
* @ since 0.6 . 0
* /
/ * *
* Dispatched when the user presses their left mouse button and then releases it while over the display object .
* See the { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } } c l a s s f o r a l i s t i n g o f e v e n t p r o p e r t i e s .
* @ event click
* @ since 0.6 . 0
* /
/ * *
* Dispatched when the user double clicks their left mouse button over this display object .
* See the { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } } c l a s s f o r a l i s t i n g o f e v e n t p r o p e r t i e s .
* @ event dblclick
* @ since 0.6 . 0
* /
/ * *
* Dispatched when the user ' s mouse enters this display object . This event must be enabled using
* { { # crossLink "Stage/enableMouseOver" } } { { / c r o s s L i n k } } . S e e a l s o { { # c r o s s L i n k " D i s p l a y O b j e c t / r o l l o v e r : e v e n t " } } { { / c r o s s L i n k } } .
* See the { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } } c l a s s f o r a l i s t i n g o f e v e n t p r o p e r t i e s .
* @ event mouseover
* @ since 0.6 . 0
* /
/ * *
* Dispatched when the user ' s mouse leaves this display object . This event must be enabled using
* { { # crossLink "Stage/enableMouseOver" } } { { / c r o s s L i n k } } . S e e a l s o { { # c r o s s L i n k " D i s p l a y O b j e c t / r o l l o u t : e v e n t " } } { { / c r o s s L i n k } } .
* See the { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } } c l a s s f o r a l i s t i n g o f e v e n t p r o p e r t i e s .
* @ event mouseout
* @ since 0.6 . 0
* /
/ * *
* This event is similar to { { # crossLink "DisplayObject/mouseover:event" } } { { / c r o s s L i n k } } , w i t h t h e f o l l o w i n g
* differences : it does not bubble , and it considers { { # crossLink "Container" } } { { / c r o s s L i n k } } i n s t a n c e s a s a n
* aggregate of their content .
*
* For example , myContainer contains two overlapping children : shapeA and shapeB . The user moves their mouse over
* shapeA and then directly on to shapeB . With a listener for { { # crossLink "mouseover:event" } } { { / c r o s s L i n k } } o n
* myContainer , two events would be received , each targeting a child element : < OL >
* < LI > when the mouse enters shapeA ( target = shapeA ) < / L I >
* < LI > when the mouse enters shapeB ( target = shapeB ) < / L I >
* < / O L >
* However , with a listener for "rollover" instead , only a single event is received when the mouse first enters
* the aggregate myContainer content ( target = myContainer ) .
*
* This event must be enabled using { { # crossLink "Stage/enableMouseOver" } } { { / c r o s s L i n k } } .
* See the { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } } c l a s s f o r a l i s t i n g o f e v e n t p r o p e r t i e s .
* @ event rollover
* @ since 0.7 . 0
* /
/ * *
* This event is similar to { { # crossLink "DisplayObject/mouseout:event" } } { { / c r o s s L i n k } } , w i t h t h e f o l l o w i n g
* differences : it does not bubble , and it considers { { # crossLink "Container" } } { { / c r o s s L i n k } } i n s t a n c e s a s a n
* aggregate of their content .
*
* For example , myContainer contains two overlapping children : shapeA and shapeB . The user moves their mouse over
* shapeA , then directly on to shapeB , then off both . With a listener for { { # crossLink "mouseout:event" } } { { / c r o s s L i n k } }
* on myContainer , two events would be received , each targeting a child element : < OL >
* < LI > when the mouse leaves shapeA ( target = shapeA ) < / L I >
* < LI > when the mouse leaves shapeB ( target = shapeB ) < / L I >
* < / O L >
* However , with a listener for "rollout" instead , only a single event is received when the mouse leaves
* the aggregate myContainer content ( target = myContainer ) .
*
* This event must be enabled using { { # crossLink "Stage/enableMouseOver" } } { { / c r o s s L i n k } } .
* See the { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } } c l a s s f o r a l i s t i n g o f e v e n t p r o p e r t i e s .
* @ event rollout
* @ since 0.7 . 0
* /
/ * *
* After a { { # crossLink "DisplayObject/mousedown:event" } } { { / c r o s s L i n k } } o c c u r s o n a d i s p l a y o b j e c t , a p r e s s m o v e
* event will be generated on that object whenever the mouse moves until the mouse press is released . This can be
* useful for dragging and similar operations .
* @ event pressmove
* @ since 0.7 . 0
* /
/ * *
* After a { { # crossLink "DisplayObject/mousedown:event" } } { { / c r o s s L i n k } } o c c u r s o n a d i s p l a y o b j e c t , a p r e s s u p e v e n t
* will be generated on that object when that mouse press is released . This can be useful for dragging and similar
* operations .
* @ event pressup
* @ since 0.7 . 0
* /
/ * *
2014-11-18 18:26:26 -05:00
* Dispatched when the display object is added to a parent container .
* @ event added
2014-01-03 13:32:13 -05:00
* /
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Dispatched when the display object is removed from its parent container .
* @ event removed
2014-01-03 13:32:13 -05:00
* /
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Dispatched on each display object on a stage whenever the stage updates . This occurs immediately before the
* rendering ( draw ) pass . When { { # crossLink "Stage/update" } } { { / c r o s s L i n k } } i s c a l l e d , f i r s t a l l d i s p l a y o b j e c t s o n
* the stage dispatch the tick event , then all of the display objects are drawn to stage . Children will have their
* { { # crossLink "tick:event" } } { { / c r o s s L i n k } } e v e n t d i s p a t c h e d i n o r d e r o f t h e i r d e p t h p r i o r t o t h e e v e n t b e i n g
* dispatched on their parent .
* @ event tick
* @ param { Object } target The object that dispatched the event .
* @ param { String } type The event type .
* @ param { Array } params An array containing any arguments that were passed to the Stage . update ( ) method . For
* example if you called stage . update ( "hello" ) , then the params would be [ "hello" ] .
* @ since 0.6 . 0
* /
2014-01-03 13:32:13 -05:00
// public methods:
/ * *
* Returns true or false indicating whether the display object would be visible if drawn to a canvas .
* This does not account for whether it would be visible within the boundaries of the stage .
*
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method isVisible
* @ return { Boolean } Boolean indicating whether the display object would be visible if drawn to a canvas
* * /
p . isVisible = function ( ) {
return ! ! ( this . visible && this . alpha > 0 && this . scaleX != 0 && this . scaleY != 0 ) ;
} ;
/ * *
* Draws the display object into the specified context ignoring its visible , alpha , shadow , and transform .
* Returns < code > true < / c o d e > i f t h e d r a w w a s h a n d l e d ( u s e f u l f o r o v e r r i d i n g f u n c t i o n a l i t y ) .
*
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method draw
* @ param { CanvasRenderingContext2D } ctx The canvas 2 D context object to draw into .
* @ param { Boolean } [ ignoreCache = false ] Indicates whether the draw operation should ignore any current cache . For example ,
* used for drawing the cache ( to prevent it from simply drawing an existing cache back into itself ) .
* @ return { Boolean }
* * /
p . draw = function ( ctx , ignoreCache ) {
var cacheCanvas = this . cacheCanvas ;
if ( ignoreCache || ! cacheCanvas ) { return false ; }
var scale = this . _cacheScale , offX = this . _cacheOffsetX , offY = this . _cacheOffsetY , fBounds ;
if ( fBounds = this . _applyFilterBounds ( offX , offY , 0 , 0 ) ) {
offX = fBounds . x ;
offY = fBounds . y ;
}
ctx . drawImage ( cacheCanvas , offX , offY , cacheCanvas . width / scale , cacheCanvas . height / scale ) ;
return true ;
} ;
/ * *
* Applies this display object ' s transformation , alpha , globalCompositeOperation , clipping path ( mask ) , and shadow
* to the specified context . This is typically called prior to { { # crossLink "DisplayObject/draw" } } { { / c r o s s L i n k } } .
* @ method updateContext
* @ param { CanvasRenderingContext2D } ctx The canvas 2 D to update .
* * /
p . updateContext = function ( ctx ) {
2014-11-18 18:26:26 -05:00
var o = this , mask = o . mask , mtx = o . _props . matrix ;
2014-01-03 13:32:13 -05:00
if ( mask && mask . graphics && ! mask . graphics . isEmpty ( ) ) {
2014-11-18 18:26:26 -05:00
mask . getMatrix ( mtx ) ;
2014-01-03 13:32:13 -05:00
ctx . transform ( mtx . a , mtx . b , mtx . c , mtx . d , mtx . tx , mtx . ty ) ;
mask . graphics . drawAsPath ( ctx ) ;
ctx . clip ( ) ;
mtx . invert ( ) ;
ctx . transform ( mtx . a , mtx . b , mtx . c , mtx . d , mtx . tx , mtx . ty ) ;
}
2014-11-18 18:26:26 -05:00
this . getMatrix ( mtx ) ;
2014-02-02 19:31:06 -05:00
var tx = mtx . tx , ty = mtx . ty ;
if ( DisplayObject . _snapToPixelEnabled && o . snapToPixel ) {
tx = tx + ( tx < 0 ? - 0.5 : 0.5 ) | 0 ;
ty = ty + ( ty < 0 ? - 0.5 : 0.5 ) | 0 ;
}
ctx . transform ( mtx . a , mtx . b , mtx . c , mtx . d , tx , ty ) ;
2014-01-03 13:32:13 -05:00
ctx . globalAlpha *= o . alpha ;
if ( o . compositeOperation ) { ctx . globalCompositeOperation = o . compositeOperation ; }
if ( o . shadow ) { this . _applyShadow ( ctx , o . shadow ) ; }
} ;
/ * *
* Draws the display object into a new canvas , which is then used for subsequent draws . For complex content
* that does not change frequently ( ex . a Container with many children that do not move , or a complex vector Shape ) ,
* this can provide for much faster rendering because the content does not need to be re - rendered each tick . The
* cached display object can be moved , rotated , faded , etc freely , however if its content changes , you must
* manually update the cache by calling < code > updateCache ( ) < / c o d e > o r < c o d e > c a c h e ( ) < / c o d e > a g a i n . Y o u m u s t s p e c i f y
* the cache area via the x , y , w , and h parameters . This defines the rectangle that will be rendered and cached
* using this display object ' s coordinates .
*
* < h4 > Example < / h 4 >
* For example if you defined a Shape that drew a circle at 0 , 0 with a radius of 25 :
*
* var shape = new createjs . Shape ( ) ;
* shape . graphics . beginFill ( "#ff0000" ) . drawCircle ( 0 , 0 , 25 ) ;
* myShape . cache ( - 25 , - 25 , 50 , 50 ) ;
*
* Note that filters need to be defined < em > before < / e m > t h e c a c h e i s a p p l i e d . C h e c k o u t t h e { { # c r o s s L i n k " F i l t e r " } } { { / c r o s s L i n k } }
* class for more information . Some filters ( ex . BlurFilter ) will not work as expected in conjunction with the scale param .
*
* Usually , the resulting cacheCanvas will have the dimensions width * scale by height * scale , however some filters ( ex . BlurFilter )
* will add padding to the canvas dimensions .
*
* @ method cache
* @ param { Number } x The x coordinate origin for the cache region .
* @ param { Number } y The y coordinate origin for the cache region .
* @ param { Number } width The width of the cache region .
* @ param { Number } height The height of the cache region .
* @ param { Number } [ scale = 1 ] The scale at which the cache will be created . For example , if you cache a vector shape using
* myShape . cache ( 0 , 0 , 100 , 100 , 2 ) then the resulting cacheCanvas will be 200 x200 px . This lets you scale and rotate
* cached elements with greater fidelity . Default is 1.
* * /
p . cache = function ( x , y , width , height , scale ) {
// draw to canvas.
scale = scale || 1 ;
if ( ! this . cacheCanvas ) { this . cacheCanvas = createjs . createCanvas ? createjs . createCanvas ( ) : document . createElement ( "canvas" ) ; }
this . _cacheWidth = width ;
this . _cacheHeight = height ;
this . _cacheOffsetX = x ;
this . _cacheOffsetY = y ;
this . _cacheScale = scale ;
this . updateCache ( ) ;
} ;
/ * *
* Redraws the display object to its cache . Calling updateCache without an active cache will throw an error .
* If compositeOperation is null the current cache will be cleared prior to drawing . Otherwise the display object
* will be drawn over the existing cache using the specified compositeOperation .
*
* < h4 > Example < / h 4 >
* Clear the current graphics of a cached shape , draw some new instructions , and then update the cache . The new line
* will be drawn on top of the old one .
*
* // Not shown: Creating the shape, and caching it.
* shapeInstance . clear ( ) ;
* shapeInstance . setStrokeStyle ( 3 ) . beginStroke ( "#ff0000" ) . moveTo ( 100 , 100 ) . lineTo ( 200 , 200 ) ;
* shapeInstance . updateCache ( ) ;
*
* @ method updateCache
* @ param { String } compositeOperation The compositeOperation to use , or null to clear the cache and redraw it .
* < a href = "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#compositing" >
* whatwg spec on compositing < / a > .
* * /
p . updateCache = function ( compositeOperation ) {
var cacheCanvas = this . cacheCanvas , scale = this . _cacheScale , offX = this . _cacheOffsetX * scale , offY = this . _cacheOffsetY * scale ;
var w = this . _cacheWidth , h = this . _cacheHeight , fBounds ;
if ( ! cacheCanvas ) { throw "cache() must be called before updateCache()" ; }
var ctx = cacheCanvas . getContext ( "2d" ) ;
// update bounds based on filters:
if ( fBounds = this . _applyFilterBounds ( offX , offY , w , h ) ) {
offX = fBounds . x ;
offY = fBounds . y ;
w = fBounds . width ;
h = fBounds . height ;
}
w = Math . ceil ( w * scale ) ;
h = Math . ceil ( h * scale ) ;
if ( w != cacheCanvas . width || h != cacheCanvas . height ) {
// TODO: it would be nice to preserve the content if there is a compositeOperation.
cacheCanvas . width = w ;
cacheCanvas . height = h ;
} else if ( ! compositeOperation ) {
ctx . clearRect ( 0 , 0 , w + 1 , h + 1 ) ;
}
ctx . save ( ) ;
ctx . globalCompositeOperation = compositeOperation ;
ctx . setTransform ( scale , 0 , 0 , scale , - offX , - offY ) ;
this . draw ( ctx , true ) ;
// TODO: filters and cache scale don't play well together at present.
this . _applyFilters ( ) ;
ctx . restore ( ) ;
this . cacheID = DisplayObject . _nextCacheID ++ ;
} ;
/ * *
* Clears the current cache . See { { # crossLink "DisplayObject/cache" } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ method uncache
* * /
p . uncache = function ( ) {
this . _cacheDataURL = this . cacheCanvas = null ;
this . cacheID = this . _cacheOffsetX = this . _cacheOffsetY = 0 ;
this . _cacheScale = 1 ;
} ;
/ * *
* Returns a data URL for the cache , or null if this display object is not cached .
* Uses cacheID to ensure a new data URL is not generated if the cache has not changed .
* @ method getCacheDataURL
* @ return { String } The image data url for the cache .
* * /
p . getCacheDataURL = function ( ) {
if ( ! this . cacheCanvas ) { return null ; }
if ( this . cacheID != this . _cacheDataURLID ) { this . _cacheDataURL = this . cacheCanvas . toDataURL ( ) ; }
return this . _cacheDataURL ;
} ;
/ * *
* Returns the stage that this display object will be rendered on , or null if it has not been added to one .
* @ method getStage
* @ return { Stage } The Stage instance that the display object is a descendent of . null if the DisplayObject has not
* been added to a Stage .
* * /
p . getStage = function ( ) {
var o = this ;
while ( o . parent ) {
o = o . parent ;
}
// using dynamic access to avoid circular dependencies;
if ( o instanceof createjs [ "Stage" ] ) { return o ; }
return null ;
} ;
/ * *
* Transforms the specified x and y position from the coordinate space of the display object
* to the global ( stage ) coordinate space . For example , this could be used to position an HTML label
* over a specific point on a nested display object . Returns a Point instance with x and y properties
* correlating to the transformed coordinates on the stage .
*
* < h4 > Example < / h 4 >
*
* displayObject . x = 300 ;
* displayObject . y = 200 ;
* stage . addChild ( displayObject ) ;
* var point = myDisplayObject . localToGlobal ( 100 , 100 ) ;
* // Results in x=400, y=300
*
* @ method localToGlobal
* @ param { Number } x The x position in the source display object to transform .
* @ param { Number } y The y position in the source display object to transform .
* @ return { Point } A Point instance with x and y properties correlating to the transformed coordinates
* on the stage .
* * /
p . localToGlobal = function ( x , y ) {
2014-11-18 18:26:26 -05:00
var mtx = this . getConcatenatedMatrix ( this . _props . matrix ) . prepend ( 1 , 0 , 0 , 1 , x , y ) ;
2014-01-03 13:32:13 -05:00
return new createjs . Point ( mtx . tx , mtx . ty ) ;
} ;
/ * *
* Transforms the specified x and y position from the global ( stage ) coordinate space to the
* coordinate space of the display object . For example , this could be used to determine
* the current mouse position within the display object . Returns a Point instance with x and y properties
* correlating to the transformed position in the display object ' s coordinate space .
*
* < h4 > Example < / h 4 >
*
* displayObject . x = 300 ;
* displayObject . y = 200 ;
* stage . addChild ( displayObject ) ;
* var point = myDisplayObject . globalToLocal ( 100 , 100 ) ;
* // Results in x=-200, y=-100
*
* @ method globalToLocal
* @ param { Number } x The x position on the stage to transform .
* @ param { Number } y The y position on the stage to transform .
* @ return { Point } A Point instance with x and y properties correlating to the transformed position in the
* display object ' s coordinate space .
* * /
p . globalToLocal = function ( x , y ) {
2014-11-18 18:26:26 -05:00
var mtx = this . getConcatenatedMatrix ( this . _props . matrix ) . invert ( ) . prepend ( 1 , 0 , 0 , 1 , x , y ) ;
2014-01-03 13:32:13 -05:00
return new createjs . Point ( mtx . tx , mtx . ty ) ;
} ;
/ * *
* Transforms the specified x and y position from the coordinate space of this display object to the coordinate
* space of the target display object . Returns a Point instance with x and y properties correlating to the
* transformed position in the target ' s coordinate space . Effectively the same as using the following code with
* { { # crossLink "DisplayObject/localToGlobal" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " D i s p l a y O b j e c t / g l o b a l T o L o c a l " } } { { / c r o s s L i n k } } .
*
* var pt = this . localToGlobal ( x , y ) ;
* pt = target . globalToLocal ( pt . x , pt . y ) ;
*
* @ method localToLocal
* @ param { Number } x The x position in the source display object to transform .
* @ param { Number } y The y position on the source display object to transform .
* @ param { DisplayObject } target The target display object to which the coordinates will be transformed .
* @ return { Point } Returns a Point instance with x and y properties correlating to the transformed position
* in the target ' s coordinate space .
* * /
p . localToLocal = function ( x , y , target ) {
var pt = this . localToGlobal ( x , y ) ;
return target . globalToLocal ( pt . x , pt . y ) ;
} ;
/ * *
* Shortcut method to quickly set the transform properties on the display object . All parameters are optional .
* Omitted parameters will have the default value set .
*
* < h4 > Example < / h 4 >
*
* displayObject . setTransform ( 100 , 100 , 2 , 2 ) ;
*
* @ method setTransform
* @ param { Number } [ x = 0 ] The horizontal translation ( x position ) in pixels
* @ param { Number } [ y = 0 ] The vertical translation ( y position ) in pixels
* @ param { Number } [ scaleX = 1 ] The horizontal scale , as a percentage of 1
* @ param { Number } [ scaleY = 1 ] the vertical scale , as a percentage of 1
* @ param { Number } [ rotation = 0 ] The rotation , in degrees
* @ param { Number } [ skewX = 0 ] The horizontal skew factor
* @ param { Number } [ skewY = 0 ] The vertical skew factor
* @ param { Number } [ regX = 0 ] The horizontal registration point in pixels
* @ param { Number } [ regY = 0 ] The vertical registration point in pixels
* @ return { DisplayObject } Returns this instance . Useful for chaining commands .
* /
p . setTransform = function ( x , y , scaleX , scaleY , rotation , skewX , skewY , regX , regY ) {
this . x = x || 0 ;
this . y = y || 0 ;
this . scaleX = scaleX == null ? 1 : scaleX ;
this . scaleY = scaleY == null ? 1 : scaleY ;
this . rotation = rotation || 0 ;
this . skewX = skewX || 0 ;
this . skewY = skewY || 0 ;
this . regX = regX || 0 ;
this . regY = regY || 0 ;
return this ;
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Returns a matrix based on this object ' s current transform .
2014-01-03 13:32:13 -05:00
* @ method getMatrix
* @ param { Matrix2D } matrix Optional . A Matrix2D object to populate with the calculated values . If null , a new
* Matrix object is returned .
* @ return { Matrix2D } A matrix representing this display object ' s transform .
* * /
p . getMatrix = function ( matrix ) {
2014-11-18 18:26:26 -05:00
var o = this , mtx = matrix && matrix . identity ( ) || new createjs . Matrix2D ( ) ;
return o . transformMatrix ? mtx . copy ( o . transformMatrix ) : mtx . prependTransform ( o . x , o . y , o . scaleX , o . scaleY , o . rotation , o . skewX , o . skewY , o . regX , o . regY ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Generates a Matrix2D object representing the combined transform of the display object and all of its
2014-01-03 13:32:13 -05:00
* parent Containers up to the highest level ancestor ( usually the { { # crossLink "Stage" } } { { / c r o s s L i n k } } ) . T h i s c a n
* be used to transform positions between coordinate spaces , such as with { { # crossLink "DisplayObject/localToGlobal" } } { { / c r o s s L i n k } }
* and { { # crossLink "DisplayObject/globalToLocal" } } { { / c r o s s L i n k } } .
* @ method getConcatenatedMatrix
2014-03-22 12:40:23 -04:00
* @ param { Matrix2D } [ matrix ] A { { # crossLink "Matrix2D" } } { { / c r o s s L i n k } } o b j e c t t o p o p u l a t e w i t h t h e c a l c u l a t e d v a l u e s .
2014-01-03 13:32:13 -05:00
* If null , a new Matrix2D object is returned .
2014-11-18 18:26:26 -05:00
* @ return { Matrix2D } The combined matrix .
2014-01-03 13:32:13 -05:00
* * /
p . getConcatenatedMatrix = function ( matrix ) {
2014-11-18 18:26:26 -05:00
var o = this , mtx = this . getMatrix ( matrix ) ;
while ( o = o . parent ) {
mtx . appendMatrix ( o . getMatrix ( o . _props . matrix ) ) ;
2014-01-03 13:32:13 -05:00
}
2014-11-18 18:26:26 -05:00
return mtx ;
} ;
/ * *
* Generates a DisplayProps object representing the combined display properties of the object and all of its
* parent Containers up to the highest level ancestor ( usually the { { # crossLink "Stage" } } { { / c r o s s L i n k } } ) .
* @ method getConcatenatedDisplayProps
* @ param { DisplayProps } [ props ] A { { # crossLink "DisplayProps" } } { { / c r o s s L i n k } } o b j e c t t o p o p u l a t e w i t h t h e c a l c u l a t e d v a l u e s .
* If null , a new DisplayProps object is returned .
* @ return { DisplayProps } The combined display properties .
* * /
p . getConcatenatedDisplayProps = function ( props ) {
props = props ? props . identity ( ) : new createjs . DisplayProps ( ) ;
var o = this , mtx = o . getMatrix ( props . matrix ) ;
do {
props . append ( o . visible , o . alpha , o . shadow , o . compositeOperation ) ;
// we do this to avoid problems with the matrix being used for both operations when o._props.matrix is passed in as the props param.
// this could be simplified (ie. just done as part of the append above) if we switched to using a pool.
if ( o != this ) { mtx . appendMatrix ( o . getMatrix ( o . _props . matrix ) ) ; }
} while ( o = o . parent ) ;
return props ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Tests whether the display object intersects the specified point in local coordinates ( ie . draws a pixel with alpha > 0 at
* the specified position ) . This ignores the alpha , shadow , hitArea , mask , and compositeOperation of the display object .
2014-01-03 13:32:13 -05:00
*
* < h4 > Example < / h 4 >
*
* stage . addEventListener ( "stagemousedown" , handleMouseDown ) ;
* function handleMouseDown ( event ) {
* var hit = myShape . hitTest ( event . stageX , event . stageY ) ;
* }
*
* Please note that shape - to - shape collision is not currently supported by EaselJS .
* @ method hitTest
* @ param { Number } x The x position to check in the display object ' s local coordinates .
* @ param { Number } y The y position to check in the display object ' s local coordinates .
* @ return { Boolean } A Boolean indicting whether a visible portion of the DisplayObject intersect the specified
* local Point .
* /
p . hitTest = function ( x , y ) {
var ctx = DisplayObject . _hitTestContext ;
ctx . setTransform ( 1 , 0 , 0 , 1 , - x , - y ) ;
this . draw ( ctx ) ;
var hit = this . _testHit ( ctx ) ;
ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
ctx . clearRect ( 0 , 0 , 2 , 2 ) ;
return hit ;
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Provides a chainable shortcut method for setting a number of properties on the instance .
2014-01-03 13:32:13 -05:00
*
* < h4 > Example < / h 4 >
*
* var myGraphics = new createjs . Graphics ( ) . beginFill ( "#ff0000" ) . drawCircle ( 0 , 0 , 25 ) ;
* var shape = stage . addChild ( new Shape ( ) )
* . set ( { graphics : myGraphics , x : 100 , y : 100 , alpha : 0.5 } ) ;
*
* @ method set
* @ param { Object } props A generic object containing properties to copy to the DisplayObject instance .
2014-11-18 18:26:26 -05:00
* @ return { DisplayObject } Returns the instance the method is called on ( useful for chaining calls . )
2014-01-03 13:32:13 -05:00
* /
p . set = function ( props ) {
for ( var n in props ) { this [ n ] = props [ n ] ; }
return this ;
} ;
/ * *
* Returns a rectangle representing this object ' s bounds in its local coordinate system ( ie . with no transformation ) .
* Objects that have been cached will return the bounds of the cache .
*
* Not all display objects can calculate their own bounds ( ex . Shape ) . For these objects , you can use
* { { # crossLink "DisplayObject/setBounds" } } { { / c r o s s L i n k } } s o t h a t t h e y a r e i n c l u d e d w h e n c a l c u l a t i n g C o n t a i n e r
* bounds .
*
* < table >
* < tr > < td > < b > All < / b > < / t d > < t d >
* All display objects support setting bounds manually using setBounds ( ) . Likewise , display objects that
* have been cached using cache ( ) will return the bounds of their cache . Manual and cache bounds will override
* the automatic calculations listed below .
* < / t d > < / t r >
* < tr > < td > < b > Bitmap < / b > < / t d > < t d >
* Returns the width and height of the sourceRect ( if specified ) or image , extending from ( x = 0 , y = 0 ) .
* < / t d > < / t r >
* < tr > < td > < b > Sprite < / b > < / t d > < t d >
* Returns the bounds of the current frame . May have non - zero x / y if a frame registration point was specified
* in the spritesheet data . See also { { # crossLink "SpriteSheet/getFrameBounds" } } { { / c r o s s L i n k } }
* < / t d > < / t r >
* < tr > < td > < b > Container < / b > < / t d > < t d >
* Returns the aggregate ( combined ) bounds of all children that return a non - null value from getBounds ( ) .
* < / t d > < / t r >
* < tr > < td > < b > Shape < / b > < / t d > < t d >
* Does not currently support automatic bounds calculations . Use setBounds ( ) to manually define bounds .
* < / t d > < / t r >
* < tr > < td > < b > Text < / b > < / t d > < t d >
* Returns approximate bounds . Horizontal values ( x / width ) are quite accurate , but vertical values ( y / height ) are
* not , especially when using textBaseline values other than "top" .
* < / t d > < / t r >
* < tr > < td > < b > BitmapText < / b > < / t d > < t d >
* Returns approximate bounds . Values will be more accurate if spritesheet frame registration points are close
* to ( x = 0 , y = 0 ) .
* < / t d > < / t r >
* < / t a b l e >
*
* Bounds can be expensive to calculate for some objects ( ex . text , or containers with many children ) , and
* are recalculated each time you call getBounds ( ) . You can prevent recalculation on static objects by setting the
* bounds explicitly :
*
* var bounds = obj . getBounds ( ) ;
* obj . setBounds ( bounds . x , bounds . y , bounds . width , bounds . height ) ;
* // getBounds will now use the set values, instead of recalculating
*
* To reduce memory impact , the returned Rectangle instance may be reused internally ; clone the instance or copy its
* values if you need to retain it .
*
* var myBounds = obj . getBounds ( ) . clone ( ) ;
* // OR:
* myRect . copy ( obj . getBounds ( ) ) ;
*
* @ method getBounds
* @ return { Rectangle } A Rectangle instance representing the bounds , or null if bounds are not available for this
* object .
* * /
p . getBounds = function ( ) {
if ( this . _bounds ) { return this . _rectangle . copy ( this . _bounds ) ; }
var cacheCanvas = this . cacheCanvas ;
if ( cacheCanvas ) {
var scale = this . _cacheScale ;
2014-11-18 18:26:26 -05:00
return this . _rectangle . setValues ( this . _cacheOffsetX , this . _cacheOffsetY , cacheCanvas . width / scale , cacheCanvas . height / scale ) ;
2014-01-03 13:32:13 -05:00
}
return null ;
} ;
/ * *
* Returns a rectangle representing this object 's bounds in its parent' s coordinate system ( ie . with transformations applied ) .
* Objects that have been cached will return the transformed bounds of the cache .
*
* Not all display objects can calculate their own bounds ( ex . Shape ) . For these objects , you can use
* { { # crossLink "DisplayObject/setBounds" } } { { / c r o s s L i n k } } s o t h a t t h e y a r e i n c l u d e d w h e n c a l c u l a t i n g C o n t a i n e r
* bounds .
*
* To reduce memory impact , the returned Rectangle instance may be reused internally ; clone the instance or copy its
* values if you need to retain it .
*
* Container instances calculate aggregate bounds for all children that return bounds via getBounds .
* @ method getTransformedBounds
* @ return { Rectangle } A Rectangle instance representing the bounds , or null if bounds are not available for this object .
* * /
p . getTransformedBounds = function ( ) {
return this . _getBounds ( ) ;
} ;
/ * *
* Allows you to manually specify the bounds of an object that either cannot calculate their own bounds ( ex . Shape &
* Text ) for future reference , or so the object can be included in Container bounds . Manually set bounds will always
* override calculated bounds .
*
* The bounds should be specified in the object ' s local ( untransformed ) coordinates . For example , a Shape instance
* with a 25 px radius circle centered at 0 , 0 would have bounds of ( - 25 , - 25 , 50 , 50 ) .
* @ method setBounds
* @ param { Number } x The x origin of the bounds . Pass null to remove the manual bounds .
* @ param { Number } y The y origin of the bounds .
* @ param { Number } width The width of the bounds .
* @ param { Number } height The height of the bounds .
* * /
p . setBounds = function ( x , y , width , height ) {
if ( x == null ) { this . _bounds = x ; }
2014-11-18 18:26:26 -05:00
this . _bounds = ( this . _bounds || new createjs . Rectangle ( ) ) . setValues ( x , y , width , height ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns a clone of this DisplayObject . Some properties that are specific to this instance ' s current context are
2014-11-18 18:26:26 -05:00
* reverted to their defaults ( for example . parent ) . Caches are not maintained across clones , and some elements
* are copied by reference ( masks , individual filter instances , hit area )
2014-01-03 13:32:13 -05:00
* @ method clone
* @ return { DisplayObject } A clone of the current DisplayObject instance .
* * /
p . clone = function ( ) {
2014-11-18 18:26:26 -05:00
return this . _cloneProps ( new DisplayObject ( ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[DisplayObject (name=" + this . name + ")]" ;
} ;
2014-11-18 18:26:26 -05:00
// private methods:
2014-01-03 13:32:13 -05:00
// separated so it can be used more easily in subclasses:
/ * *
2014-11-18 18:26:26 -05:00
* @ method _cloneProps
2014-01-03 13:32:13 -05:00
* @ param { DisplayObject } o The DisplayObject instance which will have properties from the current DisplayObject
* instance copied into .
2014-11-18 18:26:26 -05:00
* @ return { DisplayObject } o
* @ protected
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . _cloneProps = function ( o ) {
2014-01-03 13:32:13 -05:00
o . alpha = this . alpha ;
2014-11-18 18:26:26 -05:00
o . mouseEnabled = this . mouseEnabled ;
o . tickEnabled = this . tickEnabled ;
2014-01-03 13:32:13 -05:00
o . name = this . name ;
o . regX = this . regX ;
o . regY = this . regY ;
o . rotation = this . rotation ;
o . scaleX = this . scaleX ;
o . scaleY = this . scaleY ;
o . shadow = this . shadow ;
o . skewX = this . skewX ;
o . skewY = this . skewY ;
o . visible = this . visible ;
o . x = this . x ;
o . y = this . y ;
o . compositeOperation = this . compositeOperation ;
2014-11-18 18:26:26 -05:00
o . snapToPixel = this . snapToPixel ;
o . filters = this . filters == null ? null : this . filters . slice ( 0 ) ;
o . mask = this . mask ;
o . hitArea = this . hitArea ;
o . cursor = this . cursor ;
o . _bounds = this . _bounds ;
return o ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* @ method _applyShadow
* @ protected
* @ param { CanvasRenderingContext2D } ctx
* @ param { Shadow } shadow
* * /
p . _applyShadow = function ( ctx , shadow ) {
shadow = shadow || Shadow . identity ;
ctx . shadowColor = shadow . color ;
ctx . shadowOffsetX = shadow . offsetX ;
ctx . shadowOffsetY = shadow . offsetY ;
ctx . shadowBlur = shadow . blur ;
} ;
/ * *
* @ method _tick
2014-11-18 18:26:26 -05:00
* @ 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 .
2014-01-03 13:32:13 -05:00
* @ protected
* * /
2014-11-18 18:26:26 -05:00
p . _tick = function ( evtObj ) {
// because tick can be really performance sensitive, check for listeners before calling dispatchEvent.
2014-01-03 13:32:13 -05:00
var ls = this . _listeners ;
if ( ls && ls [ "tick" ] ) {
2014-11-18 18:26:26 -05:00
// reset & reuse the event object to avoid construction / GC costs:
evtObj . target = null ;
evtObj . propagationStopped = evtObj . immediatePropagationStopped = false ;
this . dispatchEvent ( evtObj ) ;
2014-01-03 13:32:13 -05:00
}
} ;
/ * *
* @ method _testHit
* @ protected
* @ param { CanvasRenderingContext2D } ctx
* @ return { Boolean }
* * /
p . _testHit = function ( ctx ) {
try {
var hit = ctx . getImageData ( 0 , 0 , 1 , 1 ) . data [ 3 ] > 1 ;
} catch ( e ) {
if ( ! DisplayObject . suppressCrossDomainErrors ) {
throw "An error has occurred. This is most likely due to security restrictions on reading canvas pixel data with local or cross-domain images." ;
}
}
return hit ;
} ;
/ * *
* @ method _applyFilters
* @ protected
* * /
p . _applyFilters = function ( ) {
if ( ! this . filters || this . filters . length == 0 || ! this . cacheCanvas ) { return ; }
var l = this . filters . length ;
var ctx = this . cacheCanvas . getContext ( "2d" ) ;
var w = this . cacheCanvas . width ;
var h = this . cacheCanvas . height ;
for ( var i = 0 ; i < l ; i ++ ) {
this . filters [ i ] . applyFilter ( ctx , 0 , 0 , w , h ) ;
}
} ;
/ * *
* @ method _applyFilterBounds
* @ param { Number } x
* @ param { Number } y
* @ param { Number } width
* @ param { Number } height
* @ return { Rectangle }
* @ protected
* * /
p . _applyFilterBounds = function ( x , y , width , height ) {
var bounds , l , filters = this . filters ;
if ( ! filters || ! ( l = filters . length ) ) { return null ; }
for ( var i = 0 ; i < l ; i ++ ) {
var f = this . filters [ i ] ;
var fBounds = f . getBounds && f . getBounds ( ) ;
if ( ! fBounds ) { continue ; }
2014-11-18 18:26:26 -05:00
if ( ! bounds ) { bounds = this . _rectangle . setValues ( x , y , width , height ) ; }
2014-01-03 13:32:13 -05:00
bounds . x += fBounds . x ;
bounds . y += fBounds . y ;
bounds . width += fBounds . width ;
bounds . height += fBounds . height ;
}
return bounds ;
} ;
/ * *
* @ method _getBounds
* @ param { Matrix2D } matrix
* @ param { Boolean } ignoreTransform If true , does not apply this object ' s transform .
* @ return { Rectangle }
* @ protected
* * /
p . _getBounds = function ( matrix , ignoreTransform ) {
return this . _transformBounds ( this . getBounds ( ) , matrix , ignoreTransform ) ;
} ;
/ * *
* @ method _transformBounds
* @ param { Rectangle } bounds
* @ param { Matrix2D } matrix
* @ param { Boolean } ignoreTransform
* @ return { Rectangle }
* @ protected
* * /
p . _transformBounds = function ( bounds , matrix , ignoreTransform ) {
if ( ! bounds ) { return bounds ; }
2014-11-18 18:26:26 -05:00
var x = bounds . x , y = bounds . y , width = bounds . width , height = bounds . height , mtx = this . _props . matrix ;
mtx = ignoreTransform ? mtx . identity ( ) : this . getMatrix ( mtx ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
if ( x || y ) { mtx . prependTransform ( 0 , 0 , 1 , 1 , 0 , 0 , 0 , - x , - y ) ; } // TODO: simplify this.
if ( matrix ) { mtx . appendMatrix ( matrix ) ; }
2014-01-03 13:32:13 -05:00
var x _a = width * mtx . a , x _b = width * mtx . b ;
var y _c = height * mtx . c , y _d = height * mtx . d ;
var tx = mtx . tx , ty = mtx . ty ;
var minX = tx , maxX = tx , minY = ty , maxY = ty ;
if ( ( x = x _a + tx ) < minX ) { minX = x ; } else if ( x > maxX ) { maxX = x ; }
if ( ( x = x _a + y _c + tx ) < minX ) { minX = x ; } else if ( x > maxX ) { maxX = x ; }
if ( ( x = y _c + tx ) < minX ) { minX = x ; } else if ( x > maxX ) { maxX = x ; }
if ( ( y = x _b + ty ) < minY ) { minY = y ; } else if ( y > maxY ) { maxY = y ; }
if ( ( y = x _b + y _d + ty ) < minY ) { minY = y ; } else if ( y > maxY ) { maxY = y ; }
if ( ( y = y _d + ty ) < minY ) { minY = y ; } else if ( y > maxY ) { maxY = y ; }
2014-11-18 18:26:26 -05:00
return bounds . setValues ( minX , minY , maxX - minX , maxY - minY ) ;
2014-01-03 13:32:13 -05:00
} ;
2014-02-02 19:31:06 -05:00
/ * *
* Indicates whether the display object has any mouse event listeners or a cursor .
* @ method _isMouseOpaque
* @ return { Boolean }
* @ protected
* * /
p . _hasMouseEventListener = function ( ) {
var evts = DisplayObject . _MOUSE _EVENTS ;
for ( var i = 0 , l = evts . length ; i < l ; i ++ ) {
if ( this . hasEventListener ( evts [ i ] ) ) { return true ; }
}
return ! ! this . cursor ;
} ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
createjs . DisplayObject = createjs . promote ( DisplayObject , "EventDispatcher" ) ;
2014-02-02 19:31:06 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// Container.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
2014-11-18 18:26:26 -05:00
"use strict" ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
* A Container is a nestable display list that allows you to work with compound display elements . For example you could
* group arm , leg , torso and head { { # crossLink "Bitmap" } } { { / c r o s s L i n k } } i n s t a n c e s t o g e t h e r i n t o a P e r s o n C o n t a i n e r , a n d
* transform them as a group , while still being able to move the individual parts relative to each other . Children of
* containers have their < code > transform < / c o d e > a n d < c o d e > a l p h a < / c o d e > p r o p e r t i e s c o n c a t e n a t e d w i t h t h e i r p a r e n t
* Container .
*
* For example , a { { # crossLink "Shape" } } { { / c r o s s L i n k } } w i t h x = 1 0 0 a n d a l p h a = 0 . 5 , p l a c e d i n a C o n t a i n e r w i t h < c o d e > x = 5 0 < / c o d e >
* and < code > alpha = 0.7 < / c o d e > w i l l b e r e n d e r e d t o t h e c a n v a s a t < c o d e > x = 1 5 0 < / c o d e > a n d < c o d e > a l p h a = 0 . 3 5 < / c o d e > .
* Containers have some overhead , so you generally shouldn ' t create a Container to hold a single child .
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* var container = new createjs . Container ( ) ;
* container . addChild ( bitmapInstance , shapeInstance ) ;
* container . x = 100 ;
*
* @ class Container
* @ extends DisplayObject
* @ constructor
* * /
2014-11-18 18:26:26 -05:00
function Container ( ) {
this . DisplayObject _constructor ( ) ;
// public properties:
/ * *
* The array of children in the display list . You should usually use the child management methods such as
* { { # crossLink "Container/addChild" } } { { / c r o s s L i n k } } , { { # c r o s s L i n k " C o n t a i n e r / r e m o v e C h i l d " } } { { / c r o s s L i n k } } ,
* { { # crossLink "Container/swapChildren" } } { { / c r o s s L i n k } } , e t c , r a t h e r t h a n a c c e s s i n g t h i s d i r e c t l y , b u t i t i s
* included for advanced uses .
* @ property children
* @ type Array
* @ default null
* * /
this . children = [ ] ;
/ * *
* Indicates whether the children of this container are independently enabled for mouse / pointer interaction .
* If false , the children will be aggregated under the container - for example , a click on a child shape would
* trigger a click event on the container .
* @ property mouseChildren
* @ type Boolean
* @ default true
* * /
this . mouseChildren = true ;
/ * *
* If false , the tick will not be propagated to children of this Container . This can provide some performance benefits .
* In addition to preventing the "tick" event from being dispatched , it will also prevent tick related updates
* on some display objects ( ex . Sprite & MovieClip frame advancing , DOMElement visibility handling ) .
* @ property tickChildren
* @ type Boolean
* @ default true
* * /
this . tickChildren = true ;
}
var p = createjs . extend ( Container , createjs . DisplayObject ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// public methods:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Constructor alias for backwards compatibility . This method will be removed in future versions .
* Subclasses should be updated to use { { # crossLink "Utility Methods/extends" } } { { / c r o s s L i n k } } .
2014-01-03 13:32:13 -05:00
* @ method initialize
2014-11-18 18:26:26 -05:00
* @ deprecated in favour of ` createjs.promote() `
* * /
p . initialize = Container ; // TODO: deprecated.
2014-01-03 13:32:13 -05:00
/ * *
* Returns true or false indicating whether the display object would be visible if drawn to a canvas .
* This does not account for whether it would be visible within the boundaries of the stage .
*
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method isVisible
* @ return { Boolean } Boolean indicating whether the display object would be visible if drawn to a canvas
* * /
p . isVisible = function ( ) {
var hasContent = this . cacheCanvas || this . children . length ;
return ! ! ( this . visible && this . alpha > 0 && this . scaleX != 0 && this . scaleY != 0 && hasContent ) ;
} ;
/ * *
* Draws the display object into the specified context ignoring its visible , alpha , shadow , and transform .
* Returns true if the draw was handled ( useful for overriding functionality ) .
*
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method draw
* @ param { CanvasRenderingContext2D } ctx The canvas 2 D context object to draw into .
* @ param { Boolean } [ ignoreCache = false ] Indicates whether the draw operation should ignore any current cache .
* For example , used for drawing the cache ( to prevent it from simply drawing an existing cache back
* into itself ) .
* * /
p . draw = function ( ctx , ignoreCache ) {
if ( this . DisplayObject _draw ( ctx , ignoreCache ) ) { return true ; }
// this ensures we don't have issues with display list changes that occur during a draw:
var list = this . children . slice ( 0 ) ;
for ( var i = 0 , l = list . length ; i < l ; i ++ ) {
var child = list [ i ] ;
if ( ! child . isVisible ( ) ) { continue ; }
// draw the child:
ctx . save ( ) ;
child . updateContext ( ctx ) ;
child . draw ( ctx ) ;
ctx . restore ( ) ;
}
return true ;
} ;
/ * *
* Adds a child to the top of the display list .
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* container . addChild ( bitmapInstance ) ;
*
* You can also add multiple children at once :
*
* container . addChild ( bitmapInstance , shapeInstance , textInstance ) ;
*
* @ method addChild
* @ param { DisplayObject } child The display object to add .
* @ return { DisplayObject } The child that was added , or the last child if multiple children were added .
* * /
p . addChild = function ( child ) {
if ( child == null ) { return child ; }
var l = arguments . length ;
if ( l > 1 ) {
for ( var i = 0 ; i < l ; i ++ ) { this . addChild ( arguments [ i ] ) ; }
return arguments [ l - 1 ] ;
}
if ( child . parent ) { child . parent . removeChild ( child ) ; }
child . parent = this ;
this . children . push ( child ) ;
2014-11-18 18:26:26 -05:00
child . dispatchEvent ( "added" ) ;
2014-01-03 13:32:13 -05:00
return child ;
} ;
/ * *
* Adds a child to the display list at the specified index , bumping children at equal or greater indexes up one , and
* setting its parent to this Container .
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* addChildAt ( child1 , index ) ;
*
* You can also add multiple children , such as :
*
* addChildAt ( child1 , child2 , ... , index ) ;
*
* The index must be between 0 and numChildren . For example , to add myShape under otherShape in the display list ,
* you could use :
*
* container . addChildAt ( myShape , container . getChildIndex ( otherShape ) ) ;
*
* This would also bump otherShape ' s index up by one . Fails silently if the index is out of range .
*
* @ method addChildAt
* @ param { DisplayObject } child The display object to add .
* @ param { Number } index The index to add the child at .
* @ return { DisplayObject } Returns the last child that was added , or the last child if multiple children were added .
* * /
p . addChildAt = function ( child , index ) {
var l = arguments . length ;
var indx = arguments [ l - 1 ] ; // can't use the same name as the index param or it replaces arguments[1]
if ( indx < 0 || indx > this . children . length ) { return arguments [ l - 2 ] ; }
if ( l > 2 ) {
for ( var i = 0 ; i < l - 1 ; i ++ ) { this . addChildAt ( arguments [ i ] , indx + i ) ; }
return arguments [ l - 2 ] ;
}
if ( child . parent ) { child . parent . removeChild ( child ) ; }
child . parent = this ;
this . children . splice ( index , 0 , child ) ;
2014-11-18 18:26:26 -05:00
child . dispatchEvent ( "added" ) ;
2014-01-03 13:32:13 -05:00
return child ;
} ;
/ * *
* Removes the specified child from the display list . Note that it is faster to use removeChildAt ( ) if the index is
* already known .
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* container . removeChild ( child ) ;
*
* You can also remove multiple children :
*
* removeChild ( child1 , child2 , ... ) ;
*
* Returns true if the child ( or children ) was removed , or false if it was not in the display list .
* @ method removeChild
* @ param { DisplayObject } child The child to remove .
* @ return { Boolean } true if the child ( or children ) was removed , or false if it was not in the display list .
* * /
p . removeChild = function ( child ) {
var l = arguments . length ;
if ( l > 1 ) {
var good = true ;
for ( var i = 0 ; i < l ; i ++ ) { good = good && this . removeChild ( arguments [ i ] ) ; }
return good ;
}
return this . removeChildAt ( createjs . indexOf ( this . children , child ) ) ;
} ;
/ * *
* Removes the child at the specified index from the display list , and sets its parent to null .
*
* < h4 > Example < / h 4 >
*
* container . removeChildAt ( 2 ) ;
*
* You can also remove multiple children :
*
* container . removeChild ( 2 , 7 , ... )
*
* Returns true if the child ( or children ) was removed , or false if any index was out of range .
* @ method removeChildAt
* @ param { Number } index The index of the child to remove .
* @ return { Boolean } true if the child ( or children ) was removed , or false if any index was out of range .
* * /
p . removeChildAt = function ( index ) {
var l = arguments . length ;
if ( l > 1 ) {
var a = [ ] ;
for ( var i = 0 ; i < l ; i ++ ) { a [ i ] = arguments [ i ] ; }
a . sort ( function ( a , b ) { return b - a ; } ) ;
var good = true ;
for ( var i = 0 ; i < l ; i ++ ) { good = good && this . removeChildAt ( a [ i ] ) ; }
return good ;
}
if ( index < 0 || index > this . children . length - 1 ) { return false ; }
var child = this . children [ index ] ;
if ( child ) { child . parent = null ; }
this . children . splice ( index , 1 ) ;
2014-11-18 18:26:26 -05:00
child . dispatchEvent ( "removed" ) ;
2014-01-03 13:32:13 -05:00
return true ;
} ;
/ * *
* Removes all children from the display list .
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* container . removeAlLChildren ( ) ;
*
* @ method removeAllChildren
* * /
p . removeAllChildren = function ( ) {
var kids = this . children ;
2014-11-18 18:26:26 -05:00
while ( kids . length ) { this . removeChildAt ( 0 ) ; }
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns the child at the specified index .
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* container . getChildAt ( 2 ) ;
*
* @ method getChildAt
* @ param { Number } index The index of the child to return .
* @ return { DisplayObject } The child at the specified index . Returns null if there is no child at the index .
* * /
p . getChildAt = function ( index ) {
return this . children [ index ] ;
} ;
/ * *
* Returns the child with the specified name .
* @ method getChildByName
* @ param { String } name The name of the child to return .
* @ return { DisplayObject } The child with the specified name .
* * /
p . getChildByName = function ( name ) {
var kids = this . children ;
for ( var i = 0 , l = kids . length ; i < l ; i ++ ) {
if ( kids [ i ] . name == name ) { return kids [ i ] ; }
}
return null ;
} ;
/ * *
* Performs an array sort operation on the child list .
*
* < h4 > Example : Display children with a higher y in front . < / h 4 >
*
* var sortFunction = function ( obj1 , obj2 , options ) {
* if ( obj1 . y > obj2 . y ) { return 1 ; }
* if ( obj1 . y < obj2 . y ) { return - 1 ; }
* return 0 ;
* }
* container . sortChildren ( sortFunction ) ;
*
* @ method sortChildren
* @ param { Function } sortFunction the function to use to sort the child list . See JavaScript ' s < code > Array . sort < / c o d e >
* documentation for details .
* * /
p . sortChildren = function ( sortFunction ) {
this . children . sort ( sortFunction ) ;
} ;
/ * *
* Returns the index of the specified child in the display list , or - 1 if it is not in the display list .
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* var index = container . getChildIndex ( child ) ;
*
* @ method getChildIndex
* @ param { DisplayObject } child The child to return the index of .
* @ return { Number } The index of the specified child . - 1 if the child is not found .
* * /
p . getChildIndex = function ( child ) {
return createjs . indexOf ( this . children , child ) ;
} ;
/ * *
* Returns the number of children in the display list .
* @ method getNumChildren
* @ return { Number } The number of children in the display list .
* * /
p . getNumChildren = function ( ) {
return this . children . length ;
} ;
/ * *
* Swaps the children at the specified indexes . Fails silently if either index is out of range .
* @ method swapChildrenAt
* @ param { Number } index1
* @ param { Number } index2
* * /
p . swapChildrenAt = function ( index1 , index2 ) {
var kids = this . children ;
var o1 = kids [ index1 ] ;
var o2 = kids [ index2 ] ;
if ( ! o1 || ! o2 ) { return ; }
kids [ index1 ] = o2 ;
kids [ index2 ] = o1 ;
} ;
/ * *
* Swaps the specified children ' s depth in the display list . Fails silently if either child is not a child of this
* Container .
* @ method swapChildren
* @ param { DisplayObject } child1
* @ param { DisplayObject } child2
* * /
p . swapChildren = function ( child1 , child2 ) {
var kids = this . children ;
var index1 , index2 ;
for ( var i = 0 , l = kids . length ; i < l ; i ++ ) {
if ( kids [ i ] == child1 ) { index1 = i ; }
if ( kids [ i ] == child2 ) { index2 = i ; }
if ( index1 != null && index2 != null ) { break ; }
}
if ( i == l ) { return ; } // TODO: throw error?
kids [ index1 ] = child2 ;
kids [ index2 ] = child1 ;
} ;
/ * *
* Changes the depth of the specified child . Fails silently if the child is not a child of this container , or the index is out of range .
* @ param { DisplayObject } child
* @ param { Number } index
* @ method setChildIndex
* * /
p . setChildIndex = function ( child , index ) {
var kids = this . children , l = kids . length ;
if ( child . parent != this || index < 0 || index >= l ) { return ; }
for ( var i = 0 ; i < l ; i ++ ) {
if ( kids [ i ] == child ) { break ; }
}
if ( i == l || i == index ) { return ; }
kids . splice ( i , 1 ) ;
kids . splice ( index , 0 , child ) ;
} ;
/ * *
* Returns true if the specified display object either is this container or is a descendent ( child , grandchild , etc )
* of this container .
* @ method contains
* @ param { DisplayObject } child The DisplayObject to be checked .
* @ return { Boolean } true if the specified display object either is this container or is a descendent .
* * /
p . contains = function ( child ) {
while ( child ) {
if ( child == this ) { return true ; }
child = child . parent ;
}
return false ;
} ;
/ * *
* Tests whether the display object intersects the specified local point ( ie . draws a pixel with alpha > 0 at the
* specified position ) . This ignores the alpha , shadow and compositeOperation of the display object , and all
* transform properties including regX / Y .
* @ method hitTest
* @ param { Number } x The x position to check in the display object ' s local coordinates .
* @ param { Number } y The y position to check in the display object ' s local coordinates .
* @ return { Boolean } A Boolean indicating whether there is a visible section of a DisplayObject that overlaps the specified
* coordinates .
* * /
p . hitTest = function ( x , y ) {
// TODO: optimize to use the fast cache check where possible.
return ( this . getObjectUnderPoint ( x , y ) != null ) ;
} ;
/ * *
* Returns an array of all display objects under the specified coordinates that are in this container ' s display
* list . This routine ignores any display objects with mouseEnabled set to false . The array will be sorted in order
* of visual depth , with the top - most display object at index 0. This uses shape based hit detection , and can be an
* expensive operation to run , so it is best to use it carefully . For example , if testing for objects under the
* mouse , test on tick ( instead of on mousemove ) , and only if the mouse ' s position has changed .
2014-11-18 18:26:26 -05:00
*
* By default this method evaluates all display objects . By setting the ` mode ` parameter to ` 1 ` , the ` mouseEnabled `
* and ` mouseChildren ` properties will be respected .
* Setting it to ` 2 ` additionally excludes display objects that do not have active mouse event listeners
* or a ` cursor ` property . That is , only objects that would normally intercept mouse interaction will be included .
* This can significantly improve performance in some cases by reducing the number of
* display objects that need to be tested .
*
* Accounts for both { { # crossLink "DisplayObject/hitArea:property" } } { { / c r o s s L i n k } } a n d { { # c r o s s L i n k " D i s p l a y O b j e c t / m a s k : p r o p e r t y " } } { { / c r o s s L i n k } } .
2014-01-03 13:32:13 -05:00
* @ method getObjectsUnderPoint
* @ param { Number } x The x position in the container to test .
* @ param { Number } y The y position in the container to test .
2014-11-18 18:26:26 -05:00
* @ 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 .
2014-01-03 13:32:13 -05:00
* @ return { Array } An Array of DisplayObjects under the specified coordinates .
* * /
2014-11-18 18:26:26 -05:00
p . getObjectsUnderPoint = function ( x , y , mode ) {
2014-01-03 13:32:13 -05:00
var arr = [ ] ;
var pt = this . localToGlobal ( x , y ) ;
2014-11-18 18:26:26 -05:00
this . _getObjectsUnderPoint ( pt . x , pt . y , arr , mode > 0 , mode == 1 ) ;
2014-01-03 13:32:13 -05:00
return arr ;
} ;
/ * *
* Similar to { { # crossLink "Container/getObjectsUnderPoint()" } } { { / c r o s s L i n k } } , b u t r e t u r n s o n l y t h e t o p - m o s t d i s p l a y
2014-11-18 18:26:26 -05:00
* object . This runs significantly faster than < code > getObjectsUnderPoint ( ) < / c o d e > , b u t i s s t i l l p o t e n t i a l l y a n e x p e n s i v e
2014-01-03 13:32:13 -05:00
* operation . See { { # crossLink "Container/getObjectsUnderPoint" } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ method getObjectUnderPoint
* @ param { Number } x The x position in the container to test .
* @ param { Number } y The y position in the container to test .
2014-11-18 18:26:26 -05:00
* @ 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 .
2014-01-03 13:32:13 -05:00
* @ return { DisplayObject } The top - most display object under the specified coordinates .
* * /
2014-11-18 18:26:26 -05:00
p . getObjectUnderPoint = function ( x , y , mode ) {
2014-01-03 13:32:13 -05:00
var pt = this . localToGlobal ( x , y ) ;
2014-11-18 18:26:26 -05:00
return this . _getObjectsUnderPoint ( pt . x , pt . y , null , mode > 0 , mode == 1 ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Docced in superclass .
* /
p . getBounds = function ( ) {
return this . _getBounds ( null , true ) ;
} ;
/ * *
* Docced in superclass .
* /
p . getTransformedBounds = function ( ) {
return this . _getBounds ( ) ;
} ;
/ * *
* Returns a clone of this Container . Some properties that are specific to this instance ' s current context are
* reverted to their defaults ( for example . parent ) .
* @ method clone
* @ param { Boolean } recursive If true , all of the descendants of this container will be cloned recursively . If false , the
* properties of the container will be cloned , but the new instance will not have any children .
* @ return { Container } A clone of the current Container instance .
* * /
p . clone = function ( recursive ) {
2014-11-18 18:26:26 -05:00
var o = this . _cloneProps ( new Container ( ) ) ;
if ( recursive ) { this . _cloneChildren ( o ) ; }
2014-01-03 13:32:13 -05:00
return o ;
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Container (name=" + this . name + ")]" ;
} ;
2014-11-18 18:26:26 -05:00
// private methods:
2014-01-03 13:32:13 -05:00
/ * *
* @ method _tick
2014-11-18 18:26:26 -05:00
* @ 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 .
2014-01-03 13:32:13 -05:00
* @ protected
* * /
2014-11-18 18:26:26 -05:00
p . _tick = function ( evtObj ) {
2014-01-03 13:32:13 -05:00
if ( this . tickChildren ) {
for ( var i = this . children . length - 1 ; i >= 0 ; i -- ) {
var child = this . children [ i ] ;
2014-11-18 18:26:26 -05:00
if ( child . tickEnabled && child . _tick ) { child . _tick ( evtObj ) ; }
2014-01-03 13:32:13 -05:00
}
}
2014-11-18 18:26:26 -05:00
this . DisplayObject _ _tick ( evtObj ) ;
} ;
/ * *
* Recursively clones all children of this container , and adds them to the target container .
* @ method cloneChildren
* @ protected
* @ param { Container } o The target container .
* * /
p . _cloneChildren = function ( o ) {
if ( o . children . length ) { o . removeAllChildren ( ) ; }
var arr = o . children ;
for ( var i = 0 , l = this . children . length ; i < l ; i ++ ) {
var clone = this . children [ i ] . clone ( true ) ;
clone . parent = o ;
arr . push ( clone ) ;
}
2014-01-03 13:32:13 -05:00
} ;
/ * *
* @ method _getObjectsUnderPoint
* @ param { Number } x
* @ param { Number } y
* @ param { Array } arr
2014-02-02 19:31:06 -05:00
* @ param { Boolean } mouse If true , it will respect mouse interaction properties like mouseEnabled , mouseChildren , and active listeners .
2014-11-18 18:26:26 -05:00
* @ param { Boolean } activeListener If true , there is an active mouse event listener on a parent object .
* @ param { Number } currentDepth Indicates the current depth of the search .
* @ return { DisplayObject }
2014-01-03 13:32:13 -05:00
* @ protected
* * /
2014-11-18 18:26:26 -05:00
p . _getObjectsUnderPoint = function ( x , y , arr , mouse , activeListener , currentDepth ) {
currentDepth = currentDepth || 0 ;
if ( ! currentDepth && ! this . _testMask ( this , x , y ) ) { return null ; }
var mtx , ctx = createjs . DisplayObject . _hitTestContext ;
2014-02-02 19:31:06 -05:00
activeListener = activeListener || ( mouse && this . _hasMouseEventListener ( ) ) ;
2014-01-03 13:32:13 -05:00
// draw children one at a time, and check if we get a hit:
2014-11-18 18:26:26 -05:00
var children = this . children , l = children . length ;
2014-01-03 13:32:13 -05:00
for ( var i = l - 1 ; i >= 0 ; i -- ) {
2014-02-02 19:31:06 -05:00
var child = children [ i ] ;
var hitArea = child . hitArea ;
2014-01-03 13:32:13 -05:00
if ( ! child . visible || ( ! hitArea && ! child . isVisible ( ) ) || ( mouse && ! child . mouseEnabled ) ) { continue ; }
2014-11-18 18:26:26 -05:00
if ( ! hitArea && ! this . _testMask ( child , x , y ) ) { continue ; }
2014-01-03 13:32:13 -05:00
// if a child container has a hitArea then we only need to check its hitArea, so we can treat it as a normal DO:
if ( ! hitArea && child instanceof Container ) {
2014-11-18 18:26:26 -05:00
var result = child . _getObjectsUnderPoint ( x , y , arr , mouse , activeListener , currentDepth + 1 ) ;
2014-01-03 13:32:13 -05:00
if ( ! arr && result ) { return ( mouse && ! this . mouseChildren ) ? this : result ; }
} else {
2014-02-02 19:31:06 -05:00
if ( mouse && ! activeListener && ! child . _hasMouseEventListener ( ) ) { continue ; }
2014-11-18 18:26:26 -05:00
// 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.
var props = child . getConcatenatedDisplayProps ( child . _props ) ;
mtx = props . matrix ;
2014-01-03 13:32:13 -05:00
if ( hitArea ) {
2014-11-18 18:26:26 -05:00
mtx . prependMatrix ( hitArea . getMatrix ( hitArea . _props . matrix ) ) ;
props . alpha = hitArea . alpha ;
2014-01-03 13:32:13 -05:00
}
2014-11-18 18:26:26 -05:00
ctx . globalAlpha = props . alpha ;
2014-01-03 13:32:13 -05:00
ctx . setTransform ( mtx . a , mtx . b , mtx . c , mtx . d , mtx . tx - x , mtx . ty - y ) ;
( hitArea || child ) . draw ( ctx ) ;
if ( ! this . _testHit ( ctx ) ) { continue ; }
ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
ctx . clearRect ( 0 , 0 , 2 , 2 ) ;
if ( arr ) { arr . push ( child ) ; }
else { return ( mouse && ! this . mouseChildren ) ? this : child ; }
}
}
return null ;
} ;
2014-11-18 18:26:26 -05:00
/ * *
* @ method _testMask
* @ param { DisplayObject } target
* @ param { Number } x
* @ param { Number } y
* @ return { Boolean } Indicates whether the x / y is within the masked region .
* @ protected
* * /
p . _testMask = function ( target , x , y ) {
var mask = target . mask ;
if ( ! mask || ! mask . graphics || mask . graphics . isEmpty ( ) ) { return true ; }
var mtx = this . _props . matrix , parent = target . parent ;
mtx = parent ? parent . getConcatenatedMatrix ( mtx ) : mtx . identity ( ) ;
mtx = mask . getMatrix ( mask . _props . matrix ) . appendMatrix ( mtx ) ;
var ctx = createjs . DisplayObject . _hitTestContext ;
ctx . setTransform ( mtx . a , mtx . b , mtx . c , mtx . d , mtx . tx - x , mtx . ty - y ) ;
// draw the mask as a solid fill:
mask . graphics . drawAsPath ( ctx ) ;
ctx . fillStyle = "#000" ;
ctx . fill ( ) ;
if ( ! this . _testHit ( ctx ) ) { return false ; }
ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
ctx . clearRect ( 0 , 0 , 2 , 2 ) ;
return true ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
* @ method _getBounds
* @ param { Matrix2D } matrix
* @ param { Boolean } ignoreTransform If true , does not apply this object ' s transform .
* @ return { Rectangle }
* @ protected
* * /
p . _getBounds = function ( matrix , ignoreTransform ) {
var bounds = this . DisplayObject _getBounds ( ) ;
if ( bounds ) { return this . _transformBounds ( bounds , matrix , ignoreTransform ) ; }
2014-11-18 18:26:26 -05:00
var mtx = this . _props . matrix ;
mtx = ignoreTransform ? mtx . identity ( ) : this . getMatrix ( mtx ) ;
if ( matrix ) { mtx . appendMatrix ( matrix ) ; }
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
var l = this . children . length , rect = null ;
2014-01-03 13:32:13 -05:00
for ( var i = 0 ; i < l ; i ++ ) {
var child = this . children [ i ] ;
if ( ! child . visible || ! ( bounds = child . _getBounds ( mtx ) ) ) { continue ; }
2014-11-18 18:26:26 -05:00
if ( rect ) { rect . extend ( bounds . x , bounds . y , bounds . width , bounds . height ) ; }
else { rect = bounds . clone ( ) ; }
}
return rect ;
} ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
createjs . Container = createjs . promote ( Container , "DisplayObject" ) ;
} ( ) ) ;
//##############################################################################
// Stage.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
/ * *
* A stage is the root level { { # crossLink "Container" } } { { / c r o s s L i n k } } f o r a d i s p l a y l i s t . E a c h t i m e i t s { { # c r o s s L i n k " S t a g e / t i c k " } } { { / c r o s s L i n k } }
* method is called , it will render its display list to its target canvas .
*
* < h4 > Example < / h 4 >
* This example creates a stage , adds a child to it , then uses { { # crossLink "Ticker" } } { { / c r o s s L i n k } } t o u p d a t e t h e c h i l d
* and redraw the stage using { { # crossLink "Stage/update" } } { { / c r o s s L i n k } } .
*
* var stage = new createjs . Stage ( "canvasElementId" ) ;
* var image = new createjs . Bitmap ( "imagePath.png" ) ;
* stage . addChild ( image ) ;
* createjs . Ticker . addEventListener ( "tick" , handleTick ) ;
* function handleTick ( event ) {
* image . x += 10 ;
* stage . update ( ) ;
* }
*
* @ class Stage
* @ extends Container
* @ constructor
* @ param { HTMLCanvasElement | String | Object } canvas A canvas object that the Stage will render to , or the string id
* of a canvas object in the current document .
* * /
function Stage ( canvas ) {
this . Container _constructor ( ) ;
// public properties:
/ * *
* Indicates whether the stage should automatically clear the canvas before each render . You can set this to < code > false < / c o d e >
* to manually control clearing ( for generative art , or when pointing multiple stages at the same canvas for
* example ) .
*
* < h4 > Example < / h 4 >
*
* var stage = new createjs . Stage ( "canvasId" ) ;
* stage . autoClear = false ;
*
* @ property autoClear
* @ type Boolean
* @ default true
* * /
this . autoClear = true ;
/ * *
* The canvas the stage will render to . Multiple stages can share a single canvas , but you must disable autoClear for all but the
* first stage that will be ticked ( or they will clear each other ' s render ) .
*
* When changing the canvas property you must disable the events on the old canvas , and enable events on the
* new canvas or mouse events will not work as expected . For example :
*
* myStage . enableDOMEvents ( false ) ;
* myStage . canvas = anotherCanvas ;
* myStage . enableDOMEvents ( true ) ;
*
* @ property canvas
* @ type HTMLCanvasElement | Object
* * /
this . canvas = ( typeof canvas == "string" ) ? document . getElementById ( canvas ) : canvas ;
/ * *
* The current mouse X position on the canvas . If the mouse leaves the canvas , this will indicate the most recent
* position over the canvas , and mouseInBounds will be set to false .
* @ property mouseX
* @ type Number
* @ readonly
* * /
this . mouseX = 0 ;
/ * *
* The current mouse Y position on the canvas . If the mouse leaves the canvas , this will indicate the most recent
* position over the canvas , and mouseInBounds will be set to false .
* @ property mouseY
* @ type Number
* @ readonly
* * /
this . mouseY = 0 ;
/ * *
* Specifies the area of the stage to affect when calling update . This can be use to selectively
* re - draw specific regions of the canvas . If null , the whole canvas area is drawn .
* @ property drawRect
* @ type { Rectangle }
* /
this . drawRect = null ;
/ * *
* Indicates whether display objects should be rendered on whole pixels . You can set the
* { { # crossLink "DisplayObject/snapToPixel" } } { { / c r o s s L i n k } } p r o p e r t y o f
* display objects to false to enable / disable this behaviour on a per instance basis .
* @ property snapToPixelEnabled
* @ type Boolean
* @ default false
* * /
this . snapToPixelEnabled = false ;
/ * *
* Indicates whether the mouse is currently within the bounds of the canvas .
* @ property mouseInBounds
* @ type Boolean
* @ default false
* * /
this . mouseInBounds = false ;
/ * *
* If true , tick callbacks will be called on all display objects on the stage prior to rendering to the canvas .
* @ property tickOnUpdate
* @ type Boolean
* @ default true
* * /
this . tickOnUpdate = true ;
/ * *
* If true , mouse move events will continue to be called when the mouse leaves the target canvas . See
* { { # crossLink "Stage/mouseInBounds:property" } } { { / c r o s s L i n k } } , a n d { { # c r o s s L i n k " M o u s e E v e n t " } } { { / c r o s s L i n k } }
* x / y / rawX / rawY .
* @ property mouseMoveOutside
* @ type Boolean
* @ default false
* * /
this . mouseMoveOutside = false ;
/ * *
* The hitArea property is not supported for Stage .
* @ property hitArea
* @ type { DisplayObject }
* @ default null
* /
// private properties:
/ * *
* Holds objects with data for each active pointer id . Each object has the following properties :
* x , y , event , target , overTarget , overX , overY , inBounds , posEvtObj ( native event that last updated position )
* @ property _pointerData
* @ type { Object }
* @ private
* /
this . _pointerData = { } ;
/ * *
* Number of active pointers .
* @ property _pointerCount
* @ type { Object }
* @ private
* /
this . _pointerCount = 0 ;
/ * *
* The ID of the primary pointer .
* @ property _primaryPointerID
* @ type { Object }
* @ private
* /
this . _primaryPointerID = null ;
/ * *
* @ property _mouseOverIntervalID
* @ protected
* @ type Number
* * /
this . _mouseOverIntervalID = null ;
/ * *
* @ property _nextStage
* @ protected
* @ type Stage
* * /
this . _nextStage = null ;
/ * *
* @ property _prevStage
* @ protected
* @ type Stage
* * /
this . _prevStage = null ;
// initialize:
this . enableDOMEvents ( true ) ;
}
var p = createjs . extend ( Stage , createjs . Container ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// events:
2014-01-03 13:32:13 -05:00
/ * *
* Dispatched when the user moves the mouse over the canvas .
* See the { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } } c l a s s f o r a l i s t i n g o f e v e n t p r o p e r t i e s .
* @ event stagemousemove
* @ since 0.6 . 0
* /
/ * *
* Dispatched when the user presses their left mouse button on the canvas . See the { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } }
* class for a listing of event properties .
* @ event stagemousedown
* @ since 0.6 . 0
* /
/ * *
* Dispatched when the user the user releases the mouse button anywhere that the page can detect it ( this varies slightly between browsers ) .
2014-11-18 18:26:26 -05:00
* You can use { { # crossLink "Stage/mouseInBounds:property" } } { { / c r o s s L i n k } } t o c h e c k w h e t h e r t h e m o u s e i s c u r r e n t l y w i t h i n t h e s t a g e b o u n d s .
2014-01-03 13:32:13 -05:00
* See the { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } } c l a s s f o r a l i s t i n g o f e v e n t p r o p e r t i e s .
* @ event stagemouseup
* @ since 0.6 . 0
* /
/ * *
* Dispatched when the mouse moves from within the canvas area ( mouseInBounds == true ) to outside it ( mouseInBounds == false ) .
* This is currently only dispatched for mouse input ( not touch ) . See the { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } }
* class for a listing of event properties .
* @ event mouseleave
* @ since 0.7 . 0
* /
/ * *
* Dispatched when the mouse moves into the canvas area ( mouseInBounds == false ) from outside it ( mouseInBounds == true ) .
* This is currently only dispatched for mouse input ( not touch ) . See the { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } }
* class for a listing of event properties .
* @ event mouseenter
* @ since 0.7 . 0
* /
/ * *
2014-11-18 18:26:26 -05:00
* Dispatched each update immediately before the tick event is propagated through the display list .
* You can call preventDefault on the event object to cancel propagating the tick event .
2014-01-03 13:32:13 -05:00
* @ event tickstart
* @ since 0.7 . 0
* /
/ * *
2014-11-18 18:26:26 -05:00
* Dispatched each update immediately after the tick event is propagated through the display list . Does not fire if
* tickOnUpdate is false . Precedes the "drawstart" event .
* @ event tickend
* @ since 0.7 . 0
* /
/ * *
* Dispatched each update immediately before the canvas is cleared and the display list is drawn to it .
* You can call preventDefault on the event object to cancel the draw .
* @ event drawstart
* @ since 0.7 . 0
* /
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Dispatched each update immediately after the display list is drawn to the canvas and the canvas context is restored .
* @ event drawend
* @ since 0.7 . 0
2014-01-03 13:32:13 -05:00
* /
2014-11-18 18:26:26 -05:00
2014-02-02 19:31:06 -05:00
// getter / setters:
/ * *
* Specifies a target stage that will have mouse / touch interactions relayed to it after this stage handles them .
* This can be useful in cases where you have multiple layered canvases and want user interactions
* events to pass through . For example , this would relay mouse events from topStage to bottomStage :
*
* topStage . nextStage = bottomStage ;
*
* To disable relaying , set nextStage to null .
*
* MouseOver , MouseOut , RollOver , and RollOut interactions are also passed through using the mouse over settings
* of the top - most stage , but are only processed if the target stage has mouse over interactions enabled .
* Considerations when using roll over in relay targets : < OL >
* < LI > The top - most ( first ) stage must have mouse over interactions enabled ( via enableMouseOver ) < / L I >
* < LI > All stages that wish to participate in mouse over interaction must enable them via enableMouseOver < / L I >
* < LI > All relay targets will share the frequency value of the top - most stage < / L I >
* < / O L >
* To illustrate , in this example the targetStage would process mouse over interactions at 10 hz ( despite passing
* 30 as it ' s desired frequency ) :
* topStage . nextStage = targetStage ;
* topStage . enableMouseOver ( 10 ) ;
* targetStage . enableMouseOver ( 30 ) ;
*
* If the target stage 's canvas is completely covered by this stage' s canvas , you may also want to disable its
* DOM events using :
*
* targetStage . enableDOMEvents ( false ) ;
*
* @ property nextStage
* @ type { Stage }
* * /
p . _get _nextStage = function ( ) {
return this . _nextStage ;
} ;
p . _set _nextStage = function ( value ) {
if ( this . _nextStage ) { this . _nextStage . _prevStage = null ; }
if ( value ) { value . _prevStage = this ; }
this . _nextStage = value ;
} ;
try {
Object . defineProperties ( p , {
nextStage : { get : p . _get _nextStage , set : p . _set _nextStage }
} ) ;
} catch ( e ) { } // TODO: use Log
2014-01-03 13:32:13 -05:00
// public methods:
/ * *
2014-11-18 18:26:26 -05:00
* Each time the update method is called , the stage will call { { # crossLink "Stage/tick" } } { { / c r o s s L i n k } }
* unless { { # crossLink "Stage/tickOnUpdate:property" } } { { / c r o s s L i n k } } i s s e t t o f a l s e ,
* and then render the display list to the canvas .
2014-01-03 13:32:13 -05:00
*
* @ method update
2014-11-18 18:26:26 -05:00
* @ param { Object } [ props ] Props object to pass to ` tick() ` . Should usually be a { { # crossLink "Ticker" } } { { / c r o s s L i n k } } e v e n t o b j e c t , o r s i m i l a r o b j e c t w i t h a d e l t a p r o p e r t y .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . update = function ( props ) {
2014-01-03 13:32:13 -05:00
if ( ! this . canvas ) { return ; }
2014-11-18 18:26:26 -05:00
if ( this . tickOnUpdate ) { this . tick ( props ) ; }
if ( this . dispatchEvent ( "drawstart" ) ) { return ; }
2014-02-02 19:31:06 -05:00
createjs . DisplayObject . _snapToPixelEnabled = this . snapToPixelEnabled ;
2014-11-18 18:26:26 -05:00
var r = this . drawRect , ctx = this . canvas . getContext ( "2d" ) ;
ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
if ( this . autoClear ) {
if ( r ) { ctx . clearRect ( r . x , r . y , r . width , r . height ) ; }
else { ctx . clearRect ( 0 , 0 , this . canvas . width + 1 , this . canvas . height + 1 ) ; }
}
2014-01-03 13:32:13 -05:00
ctx . save ( ) ;
2014-11-18 18:26:26 -05:00
if ( this . drawRect ) {
ctx . beginPath ( ) ;
ctx . rect ( r . x , r . y , r . width , r . height ) ;
ctx . clip ( ) ;
}
2014-01-03 13:32:13 -05:00
this . updateContext ( ctx ) ;
this . draw ( ctx , false ) ;
ctx . restore ( ) ;
this . dispatchEvent ( "drawend" ) ;
} ;
2014-11-18 18:26:26 -05:00
/ * *
* Propagates a tick event through the display list . This is automatically called by { { # crossLink "Stage/update" } } { { / c r o s s L i n k } }
* unless { { # crossLink "Stage/tickOnUpdate:property" } } { { / c r o s s L i n k } } i s s e t t o f a l s e .
*
* If a props object is passed to ` tick() ` , then all of its properties will be copied to the event object that is
* propagated to listeners .
*
* Some time - based features in EaselJS ( for example { { # crossLink "Sprite/framerate" } } { { / c r o s s L i n k } } r e q u i r e t h a t
* a { { # crossLink "Ticker/tick:event" } } { { / c r o s s L i n k } } e v e n t o b j e c t ( o r e q u i v a l e n t o b j e c t w i t h a d e l t a p r o p e r t y ) b e
* passed as the ` props ` parameter to ` tick() ` . For example :
*
* Ticker . on ( "tick" , handleTick ) ;
* function handleTick ( evtObj ) {
* // clone the event object from Ticker, and add some custom data to it:
* var evt = evtObj . clone ( ) . set ( { greeting : "hello" , name : "world" } ) ;
*
* // pass it to stage.update():
* myStage . update ( evt ) ; // subsequently calls tick() with the same param
* }
*
* // ...
* myDisplayObject . on ( "tick" , handleDisplayObjectTick ) ;
* function handleDisplayObjectTick ( evt ) {
* console . log ( evt . delta ) ; // the delta property from the Ticker tick event object
* console . log ( evt . greeting , evt . name ) ; // custom data: "hello world"
* }
*
* @ method tick
* @ 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 .
* * /
p . tick = function ( props ) {
if ( ! this . tickEnabled || this . dispatchEvent ( "tickstart" ) ) { return ; }
var evtObj = new createjs . Event ( "tick" ) ;
if ( props ) {
for ( var n in props ) {
if ( props . hasOwnProperty ( n ) ) { evtObj [ n ] = props [ n ] ; }
}
}
this . _tick ( evtObj ) ;
this . dispatchEvent ( "tickend" ) ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
* Default event handler that calls the Stage { { # crossLink "Stage/update" } } { { / c r o s s L i n k } } m e t h o d w h e n a { { # c r o s s L i n k " D i s p l a y O b j e c t / t i c k : e v e n t " } } { { / c r o s s L i n k } }
* event is received . This allows you to register a Stage instance as a event listener on { { # crossLink "Ticker" } } { { / c r o s s L i n k } }
* directly , using :
*
* Ticker . addEventListener ( "tick" , myStage " ) ;
*
* Note that if you subscribe to ticks using this pattern , then the tick event object will be passed through to
* display object tick handlers , instead of < code > delta < / c o d e > a n d < c o d e > p a u s e d < / c o d e > p a r a m e t e r s .
* @ property handleEvent
* @ type Function
* * /
p . handleEvent = function ( evt ) {
if ( evt . type == "tick" ) { this . update ( evt ) ; }
} ;
/ * *
* Clears the target canvas . Useful if { { # crossLink "Stage/autoClear:property" } } { { / c r o s s L i n k } } i s s e t t o ` f a l s e ` .
* @ method clear
* * /
p . clear = function ( ) {
if ( ! this . canvas ) { return ; }
var ctx = this . canvas . getContext ( "2d" ) ;
ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
ctx . clearRect ( 0 , 0 , this . canvas . width + 1 , this . canvas . height + 1 ) ;
} ;
/ * *
* Returns a data url that contains a Base64 - encoded image of the contents of the stage . The returned data url can
* be specified as the src value of an image element .
* @ method toDataURL
2014-11-18 18:26:26 -05:00
* @ param { String } [ backgroundColor ] The background color to be used for the generated image . Any valid CSS color
* value is allowed . The default value is a transparent background .
* @ 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
2014-01-03 13:32:13 -05:00
* is passed in , or if the browser does not support the specified MIME type , the default value will be used .
* @ return { String } a Base64 encoded image .
* * /
p . toDataURL = function ( backgroundColor , mimeType ) {
2014-11-18 18:26:26 -05:00
var data , ctx = this . canvas . getContext ( '2d' ) , w = this . canvas . width , h = this . canvas . height ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
if ( backgroundColor ) {
2014-01-03 13:32:13 -05:00
data = ctx . getImageData ( 0 , 0 , w , h ) ;
var compositeOperation = ctx . globalCompositeOperation ;
ctx . globalCompositeOperation = "destination-over" ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
ctx . fillStyle = backgroundColor ;
ctx . fillRect ( 0 , 0 , w , h ) ;
}
2014-11-18 18:26:26 -05:00
var dataURL = this . canvas . toDataURL ( mimeType || "image/png" ) ;
2014-01-03 13:32:13 -05:00
if ( backgroundColor ) {
ctx . putImageData ( data , 0 , 0 ) ;
ctx . globalCompositeOperation = compositeOperation ;
}
return dataURL ;
} ;
/ * *
* Enables or disables ( by passing a frequency of 0 ) mouse over ( { { # crossLink "DisplayObject/mouseover:event" } } { { / c r o s s L i n k } }
* and { { # crossLink "DisplayObject/mouseout:event" } } { { / c r o s s L i n k } } ) a n d r o l l o v e r e v e n t s ( { { # c r o s s L i n k " D i s p l a y O b j e c t / r o l l o v e r : e v e n t " } } { { / c r o s s L i n k } }
* and { { # crossLink "DisplayObject/rollout:event" } } { { / c r o s s L i n k } } ) f o r t h i s s t a g e ' s d i s p l a y l i s t . T h e s e e v e n t s c a n
* be expensive to generate , so they are disabled by default . The frequency of the events can be controlled
* independently of mouse move events via the optional ` frequency ` parameter .
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* var stage = new createjs . Stage ( "canvasId" ) ;
* stage . enableMouseOver ( 10 ) ; // 10 updates per second
*
* @ method enableMouseOver
* @ param { Number } [ frequency = 20 ] Optional param specifying the maximum number of times per second to broadcast
* mouse over / out events . Set to 0 to disable mouse over events completely . Maximum is 50. A lower frequency is less
* responsive , but uses less CPU .
* * /
p . enableMouseOver = function ( frequency ) {
if ( this . _mouseOverIntervalID ) {
clearInterval ( this . _mouseOverIntervalID ) ;
this . _mouseOverIntervalID = null ;
if ( frequency == 0 ) {
this . _testMouseOver ( true ) ;
}
}
if ( frequency == null ) { frequency = 20 ; }
else if ( frequency <= 0 ) { return ; }
var o = this ;
this . _mouseOverIntervalID = setInterval ( function ( ) { o . _testMouseOver ( ) ; } , 1000 / Math . min ( 50 , frequency ) ) ;
} ;
/ * *
* Enables or disables the event listeners that stage adds to DOM elements ( window , document and canvas ) . It is good
* practice to disable events when disposing of a Stage instance , otherwise the stage will continue to receive
* events from the page .
*
* When changing the canvas property you must disable the events on the old canvas , and enable events on the
* new canvas or mouse events will not work as expected . For example :
*
* myStage . enableDOMEvents ( false ) ;
* myStage . canvas = anotherCanvas ;
* myStage . enableDOMEvents ( true ) ;
*
* @ method enableDOMEvents
* @ param { Boolean } [ enable = true ] Indicates whether to enable or disable the events . Default is true .
* * /
p . enableDOMEvents = function ( enable ) {
if ( enable == null ) { enable = true ; }
var n , o , ls = this . _eventListeners ;
if ( ! enable && ls ) {
for ( n in ls ) {
o = ls [ n ] ;
o . t . removeEventListener ( n , o . f , false ) ;
}
this . _eventListeners = null ;
} else if ( enable && ! ls && this . canvas ) {
var t = window . addEventListener ? window : document ;
var _this = this ;
ls = this . _eventListeners = { } ;
ls [ "mouseup" ] = { t : t , f : function ( e ) { _this . _handleMouseUp ( e ) } } ;
ls [ "mousemove" ] = { t : t , f : function ( e ) { _this . _handleMouseMove ( e ) } } ;
ls [ "dblclick" ] = { t : this . canvas , f : function ( e ) { _this . _handleDoubleClick ( e ) } } ;
ls [ "mousedown" ] = { t : this . canvas , f : function ( e ) { _this . _handleMouseDown ( e ) } } ;
for ( n in ls ) {
o = ls [ n ] ;
o . t . addEventListener ( n , o . f , false ) ;
}
}
} ;
/ * *
2014-11-18 18:26:26 -05:00
* Stage instances cannot be cloned .
2014-01-03 13:32:13 -05:00
* @ method clone
* * /
p . clone = function ( ) {
2014-11-18 18:26:26 -05:00
throw ( "Stage cannot be cloned." ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Stage (name=" + this . name + ")]" ;
} ;
2014-11-18 18:26:26 -05:00
// private methods:
2014-01-03 13:32:13 -05:00
/ * *
* @ method _getElementRect
* @ protected
* @ param { HTMLElement } e
* * /
p . _getElementRect = function ( e ) {
var bounds ;
try { bounds = e . getBoundingClientRect ( ) ; } // this can fail on disconnected DOM elements in IE9
catch ( err ) { bounds = { top : e . offsetTop , left : e . offsetLeft , width : e . offsetWidth , height : e . offsetHeight } ; }
var offX = ( window . pageXOffset || document . scrollLeft || 0 ) - ( document . clientLeft || document . body . clientLeft || 0 ) ;
var offY = ( window . pageYOffset || document . scrollTop || 0 ) - ( document . clientTop || document . body . clientTop || 0 ) ;
2014-11-18 18:26:26 -05:00
var styles = window . getComputedStyle ? getComputedStyle ( e , null ) : e . currentStyle ; // IE <9 compatibility.
2014-01-03 13:32:13 -05:00
var padL = parseInt ( styles . paddingLeft ) + parseInt ( styles . borderLeftWidth ) ;
var padT = parseInt ( styles . paddingTop ) + parseInt ( styles . borderTopWidth ) ;
var padR = parseInt ( styles . paddingRight ) + parseInt ( styles . borderRightWidth ) ;
var padB = parseInt ( styles . paddingBottom ) + parseInt ( styles . borderBottomWidth ) ;
// note: in some browsers bounds properties are read only.
return {
left : bounds . left + offX + padL ,
right : bounds . right + offX - padR ,
top : bounds . top + offY + padT ,
bottom : bounds . bottom + offY - padB
}
} ;
/ * *
* @ method _getPointerData
* @ protected
* @ param { Number } id
* * /
p . _getPointerData = function ( id ) {
var data = this . _pointerData [ id ] ;
if ( ! data ) {
data = this . _pointerData [ id ] = { x : 0 , y : 0 } ;
// if it's the first new touch, then make it the primary pointer id:
if ( this . _primaryPointerID == null ) { this . _primaryPointerID = id ; }
2014-02-02 19:31:06 -05:00
// if it's the mouse (id == -1) or the first new touch, then make it the primary pointer id:
if ( this . _primaryPointerID == null || this . _primaryPointerID == - 1 ) { this . _primaryPointerID = id ; }
2014-01-03 13:32:13 -05:00
}
return data ;
} ;
/ * *
* @ method _handleMouseMove
* @ protected
* @ param { MouseEvent } e
* * /
p . _handleMouseMove = function ( e ) {
if ( ! e ) { e = window . event ; }
this . _handlePointerMove ( - 1 , e , e . pageX , e . pageY ) ;
} ;
/ * *
* @ method _handlePointerMove
* @ protected
* @ param { Number } id
* @ param { Event } e
* @ param { Number } pageX
* @ param { Number } pageY
2014-02-02 19:31:06 -05:00
* @ param { Stage } owner Indicates that the event has already been captured & handled by the indicated stage .
2014-01-03 13:32:13 -05:00
* * /
2014-02-02 19:31:06 -05:00
p . _handlePointerMove = function ( id , e , pageX , pageY , owner ) {
if ( this . _prevStage && owner === undefined ) { return ; } // redundant listener.
2014-01-03 13:32:13 -05:00
if ( ! this . canvas ) { return ; }
2014-02-02 19:31:06 -05:00
var nextStage = this . _nextStage , o = this . _getPointerData ( id ) ;
2014-01-03 13:32:13 -05:00
var inBounds = o . inBounds ;
this . _updatePointerPosition ( id , e , pageX , pageY ) ;
2014-02-02 19:31:06 -05:00
if ( inBounds || o . inBounds || this . mouseMoveOutside ) {
if ( id == - 1 && o . inBounds == ! inBounds ) {
this . _dispatchMouseEvent ( this , ( inBounds ? "mouseleave" : "mouseenter" ) , false , id , o , e ) ;
}
this . _dispatchMouseEvent ( this , "stagemousemove" , false , id , o , e ) ;
this . _dispatchMouseEvent ( o . target , "pressmove" , true , id , o , e ) ;
2014-01-03 13:32:13 -05:00
}
2014-02-02 19:31:06 -05:00
nextStage && nextStage . _handlePointerMove ( id , e , pageX , pageY , null ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* @ method _updatePointerPosition
* @ protected
* @ param { Number } id
* @ param { Event } e
* @ param { Number } pageX
* @ param { Number } pageY
* * /
p . _updatePointerPosition = function ( id , e , pageX , pageY ) {
var rect = this . _getElementRect ( this . canvas ) ;
pageX -= rect . left ;
pageY -= rect . top ;
var w = this . canvas . width ;
var h = this . canvas . height ;
pageX /= ( rect . right - rect . left ) / w ;
pageY /= ( rect . bottom - rect . top ) / h ;
var o = this . _getPointerData ( id ) ;
if ( o . inBounds = ( pageX >= 0 && pageY >= 0 && pageX <= w - 1 && pageY <= h - 1 ) ) {
o . x = pageX ;
o . y = pageY ;
} else if ( this . mouseMoveOutside ) {
o . x = pageX < 0 ? 0 : ( pageX > w - 1 ? w - 1 : pageX ) ;
o . y = pageY < 0 ? 0 : ( pageY > h - 1 ? h - 1 : pageY ) ;
}
o . posEvtObj = e ;
o . rawX = pageX ;
o . rawY = pageY ;
if ( id == this . _primaryPointerID ) {
this . mouseX = o . x ;
this . mouseY = o . y ;
this . mouseInBounds = o . inBounds ;
}
} ;
/ * *
* @ method _handleMouseUp
* @ protected
* @ param { MouseEvent } e
* * /
p . _handleMouseUp = function ( e ) {
this . _handlePointerUp ( - 1 , e , false ) ;
} ;
/ * *
* @ method _handlePointerUp
* @ protected
* @ param { Number } id
* @ param { Event } e
* @ param { Boolean } clear
2014-02-02 19:31:06 -05:00
* @ param { Stage } owner Indicates that the event has already been captured & handled by the indicated stage .
2014-01-03 13:32:13 -05:00
* * /
2014-02-02 19:31:06 -05:00
p . _handlePointerUp = function ( id , e , clear , owner ) {
var nextStage = this . _nextStage , o = this . _getPointerData ( id ) ;
if ( this . _prevStage && owner === undefined ) { return ; } // redundant listener.
2014-01-03 13:32:13 -05:00
this . _dispatchMouseEvent ( this , "stagemouseup" , false , id , o , e ) ;
2014-02-02 19:31:06 -05:00
var target = null , oTarget = o . target ;
if ( ! owner && ( oTarget || nextStage ) ) { target = this . _getObjectsUnderPoint ( o . x , o . y , null , true ) ; }
if ( target == oTarget ) { this . _dispatchMouseEvent ( oTarget , "click" , true , id , o , e ) ; }
this . _dispatchMouseEvent ( oTarget , "pressup" , true , id , o , e ) ;
2014-01-03 13:32:13 -05:00
if ( clear ) {
if ( id == this . _primaryPointerID ) { this . _primaryPointerID = null ; }
delete ( this . _pointerData [ id ] ) ;
2014-02-02 19:31:06 -05:00
} else { o . target = null ; }
nextStage && nextStage . _handlePointerUp ( id , e , clear , owner || target && this ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* @ method _handleMouseDown
* @ protected
* @ param { MouseEvent } e
* * /
p . _handleMouseDown = function ( e ) {
this . _handlePointerDown ( - 1 , e , e . pageX , e . pageY ) ;
} ;
/ * *
* @ method _handlePointerDown
* @ protected
* @ param { Number } id
* @ param { Event } e
* @ param { Number } pageX
* @ param { Number } pageY
2014-02-02 19:31:06 -05:00
* @ param { Stage } owner Indicates that the event has already been captured & handled by the indicated stage .
2014-01-03 13:32:13 -05:00
* * /
2014-02-02 19:31:06 -05:00
p . _handlePointerDown = function ( id , e , pageX , pageY , owner ) {
2014-01-03 13:32:13 -05:00
if ( pageY != null ) { this . _updatePointerPosition ( id , e , pageX , pageY ) ; }
2014-02-02 19:31:06 -05:00
var target = null , nextStage = this . _nextStage , o = this . _getPointerData ( id ) ;
2014-01-03 13:32:13 -05:00
2014-02-02 19:31:06 -05:00
if ( o . inBounds ) { this . _dispatchMouseEvent ( this , "stagemousedown" , false , id , o , e ) ; }
if ( ! owner ) {
target = o . target = this . _getObjectsUnderPoint ( o . x , o . y , null , true ) ;
this . _dispatchMouseEvent ( o . target , "mousedown" , true , id , o , e ) ;
}
2014-01-03 13:32:13 -05:00
2014-02-02 19:31:06 -05:00
nextStage && nextStage . _handlePointerDown ( id , e , pageX , pageY , owner || target && this ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* @ method _testMouseOver
* @ param { Boolean } clear If true , clears the mouseover / rollover ( ie . no target )
2014-02-02 19:31:06 -05:00
* @ param { Stage } owner Indicates that the event has already been captured & handled by the indicated stage .
* @ param { Stage } eventTarget The stage that the cursor is actively over .
2014-01-03 13:32:13 -05:00
* @ protected
* * /
2014-02-02 19:31:06 -05:00
p . _testMouseOver = function ( clear , owner , eventTarget ) {
if ( this . _prevStage && owner === undefined ) { return ; } // redundant listener.
var nextStage = this . _nextStage ;
if ( ! this . _mouseOverIntervalID ) {
// not enabled for mouseover, but should still relay the event.
nextStage && nextStage . _testMouseOver ( clear , owner , eventTarget ) ;
return ;
}
2014-01-03 13:32:13 -05:00
// only update if the mouse position has changed. This provides a lot of optimization, but has some trade-offs.
if ( this . _primaryPointerID != - 1 || ( ! clear && this . mouseX == this . _mouseOverX && this . mouseY == this . _mouseOverY && this . mouseInBounds ) ) { return ; }
2014-02-02 19:31:06 -05:00
var o = this . _getPointerData ( - 1 ) , e = o . posEvtObj ;
var isEventTarget = eventTarget || e && ( e . target == this . canvas ) ;
var target = null , common = - 1 , cursor = "" , t , i , l ;
if ( ! owner && ( clear || this . mouseInBounds && isEventTarget ) ) {
2014-01-03 13:32:13 -05:00
target = this . _getObjectsUnderPoint ( this . mouseX , this . mouseY , null , true ) ;
this . _mouseOverX = this . mouseX ;
this . _mouseOverY = this . mouseY ;
}
var oldList = this . _mouseOverTarget || [ ] ;
var oldTarget = oldList [ oldList . length - 1 ] ;
var list = this . _mouseOverTarget = [ ] ;
// generate ancestor list and check for cursor:
t = target ;
while ( t ) {
list . unshift ( t ) ;
if ( t . cursor != null ) { cursor = t . cursor ; }
t = t . parent ;
}
this . canvas . style . cursor = cursor ;
2014-02-02 19:31:06 -05:00
if ( ! owner && eventTarget ) { eventTarget . canvas . style . cursor = cursor ; }
2014-01-03 13:32:13 -05:00
// find common ancestor:
for ( i = 0 , l = list . length ; i < l ; i ++ ) {
if ( list [ i ] != oldList [ i ] ) { break ; }
common = i ;
}
if ( oldTarget != target ) {
this . _dispatchMouseEvent ( oldTarget , "mouseout" , true , - 1 , o , e ) ;
}
for ( i = oldList . length - 1 ; i > common ; i -- ) {
this . _dispatchMouseEvent ( oldList [ i ] , "rollout" , false , - 1 , o , e ) ;
}
for ( i = list . length - 1 ; i > common ; i -- ) {
this . _dispatchMouseEvent ( list [ i ] , "rollover" , false , - 1 , o , e ) ;
}
if ( oldTarget != target ) {
this . _dispatchMouseEvent ( target , "mouseover" , true , - 1 , o , e ) ;
}
2014-02-02 19:31:06 -05:00
nextStage && nextStage . _testMouseOver ( clear , owner || target && this , eventTarget || isEventTarget && this ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* @ method _handleDoubleClick
* @ protected
* @ param { MouseEvent } e
2014-02-02 19:31:06 -05:00
* @ param { Stage } owner Indicates that the event has already been captured & handled by the indicated stage .
2014-01-03 13:32:13 -05:00
* * /
2014-02-02 19:31:06 -05:00
p . _handleDoubleClick = function ( e , owner ) {
var target = null , nextStage = this . _nextStage , o = this . _getPointerData ( - 1 ) ;
if ( ! owner ) {
target = this . _getObjectsUnderPoint ( o . x , o . y , null , true ) ;
this . _dispatchMouseEvent ( target , "dblclick" , true , - 1 , o , e ) ;
}
nextStage && nextStage . _handleDoubleClick ( e , owner || target && this ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* @ method _dispatchMouseEvent
* @ protected
* @ param { DisplayObject } target
* @ param { String } type
* @ param { Boolean } bubbles
* @ param { Number } pointerId
* @ param { Object } o
* @ param { MouseEvent } [ nativeEvent ]
* * /
p . _dispatchMouseEvent = function ( target , type , bubbles , pointerId , o , nativeEvent ) {
// TODO: might be worth either reusing MouseEvent instances, or adding a willTrigger method to avoid GC.
if ( ! target || ( ! bubbles && ! target . hasEventListener ( type ) ) ) { return ; }
/ *
// TODO: account for stage transformations:
this . _mtx = this . getConcatenatedMatrix ( this . _mtx ) . invert ( ) ;
var pt = this . _mtx . transformPoint ( o . x , o . y ) ;
var evt = new createjs . MouseEvent ( type , bubbles , false , pt . x , pt . y , nativeEvent , pointerId , pointerId == this . _primaryPointerID , o . rawX , o . rawY ) ;
* /
var evt = new createjs . MouseEvent ( type , bubbles , false , o . x , o . y , nativeEvent , pointerId , pointerId == this . _primaryPointerID , o . rawX , o . rawY ) ;
target . dispatchEvent ( evt ) ;
} ;
2014-11-18 18:26:26 -05:00
createjs . Stage = createjs . promote ( Stage , "Container" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// Bitmap.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
/ * *
2014-11-18 18:26:26 -05:00
* A Bitmap represents an Image , Canvas , or Video in the display list . A Bitmap can be instantiated using an existing
* HTML element , or a string .
*
* < h4 > Example < / h 4 >
*
* var bitmap = new createjs . Bitmap ( "imagePath.jpg" ) ;
*
* < strong > Notes : < / s t r o n g >
* < ol >
* < li > When a string path or image tag that is not yet loaded is used , the stage may need to be redrawn before it
* will be displayed . < / l i >
* < li > Bitmaps with an SVG source currently will not respect an alpha value other than 0 or 1. To get around this ,
* the Bitmap can be cached . < / l i >
* < li > Bitmaps with an SVG source will taint the canvas with cross - origin data , which prevents interactivity . This
* happens in all browsers except recent Firefox builds . < / l i >
* < li > Images loaded cross - origin will throw cross - origin security errors when interacted with using a mouse , using
* methods such as ` getObjectUnderPoint ` , or using filters , or caching . You can get around this by setting
* ` crossOrigin ` flags on your images before passing them to EaselJS , eg : ` img.crossOrigin="Anonymous"; ` < / l i >
* < / o l >
*
* @ class Bitmap
* @ extends DisplayObject
* @ constructor
2014-01-03 13:32:13 -05:00
* @ param { Image | HTMLCanvasElement | HTMLVideoElement | String } imageOrUri The source object or URI to an image to
* display . This can be either an Image , Canvas , or Video object , or a string URI to an image file to load and use .
2014-11-18 18:26:26 -05:00
* If it is a URI , a new Image object will be constructed and assigned to the . image property .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
function Bitmap ( imageOrUri ) {
this . DisplayObject _constructor ( ) ;
// public properties:
/ * *
* The image to render . This can be an Image , a Canvas , or a Video .
* @ property image
* @ type Image | HTMLCanvasElement | HTMLVideoElement
* * /
2014-01-03 13:32:13 -05:00
if ( typeof imageOrUri == "string" ) {
this . image = document . createElement ( "img" ) ;
this . image . src = imageOrUri ;
} else {
this . image = imageOrUri ;
}
2014-11-18 18:26:26 -05:00
/ * *
* Specifies an area of the source image to draw . If omitted , the whole image will be drawn .
* @ property sourceRect
* @ type Rectangle
* @ default null
* /
this . sourceRect = null ;
}
var p = createjs . extend ( Bitmap , createjs . DisplayObject ) ;
2014-01-03 13:32:13 -05:00
// public methods:
/ * *
* Returns true or false indicating whether the display object would be visible if drawn to a canvas .
* This does not account for whether it would be visible within the boundaries of the stage .
*
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method isVisible
* @ return { Boolean } Boolean indicating whether the display object would be visible if drawn to a canvas
* * /
p . isVisible = function ( ) {
var hasContent = this . cacheCanvas || ( this . image && ( this . image . complete || this . image . getContext || this . image . readyState >= 2 ) ) ;
return ! ! ( this . visible && this . alpha > 0 && this . scaleX != 0 && this . scaleY != 0 && hasContent ) ;
} ;
/ * *
* Draws the display object into the specified context ignoring its visible , alpha , shadow , and transform .
* Returns true if the draw was handled ( useful for overriding functionality ) .
*
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method draw
* @ param { CanvasRenderingContext2D } ctx The canvas 2 D context object to draw into .
* @ param { Boolean } [ ignoreCache = false ] Indicates whether the draw operation should ignore any current cache .
* For example , used for drawing the cache ( to prevent it from simply drawing an existing cache back
* into itself ) .
* @ return { Boolean }
* * /
p . draw = function ( ctx , ignoreCache ) {
2014-11-18 18:26:26 -05:00
if ( this . DisplayObject _draw ( ctx , ignoreCache ) || ! this . image . complete ) { return true ; }
var img = this . image , rect = this . sourceRect ;
2014-01-03 13:32:13 -05:00
if ( rect ) {
2014-11-18 18:26:26 -05:00
// some browsers choke on out of bound values, so we'll fix them:
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 ;
if ( x1 < 0 ) { x -= x1 ; x1 = 0 ; }
if ( x2 > w ) { x2 = w ; }
if ( y1 < 0 ) { y -= y1 ; y1 = 0 ; }
if ( y2 > h ) { y2 = h ; }
ctx . drawImage ( img , x1 , y1 , x2 - x1 , y2 - y1 , x , y , x2 - x1 , y2 - y1 ) ;
2014-01-03 13:32:13 -05:00
} else {
2014-11-18 18:26:26 -05:00
ctx . drawImage ( img , 0 , 0 ) ;
2014-01-03 13:32:13 -05:00
}
return true ;
} ;
//Note, the doc sections below document using the specified APIs (from DisplayObject) from
//Bitmap. This is why they have no method implementations.
/ * *
* Because the content of a Bitmap is already in a simple format , cache is unnecessary for Bitmap instances .
* You should < b > not < / b > c a c h e B i t m a p i n s t a n c e s a s i t c a n d e g r a d e p e r f o r m a n c e .
*
* < strong > However : If you want to use a filter on a Bitmap , you < em > MUST < / e m > c a c h e i t , o r i t w i l l n o t w o r k . < / s t r o n g >
* To see the API for caching , please visit the DisplayObject { { # crossLink "DisplayObject/cache" } } { { / c r o s s L i n k } }
* method .
* @ method cache
* * /
/ * *
* Because the content of a Bitmap is already in a simple format , cache is unnecessary for Bitmap instances .
* You should < b > not < / b > c a c h e B i t m a p i n s t a n c e s a s i t c a n d e g r a d e p e r f o r m a n c e .
*
* < strong > However : If you want to use a filter on a Bitmap , you < em > MUST < / e m > c a c h e i t , o r i t w i l l n o t w o r k . < / s t r o n g >
* To see the API for caching , please visit the DisplayObject { { # crossLink "DisplayObject/cache" } } { { / c r o s s L i n k } }
* method .
* @ method updateCache
* * /
/ * *
* Because the content of a Bitmap is already in a simple format , cache is unnecessary for Bitmap instances .
* You should < b > not < / b > c a c h e B i t m a p i n s t a n c e s a s i t c a n d e g r a d e p e r f o r m a n c e .
*
* < strong > However : If you want to use a filter on a Bitmap , you < em > MUST < / e m > c a c h e i t , o r i t w i l l n o t w o r k . < / s t r o n g >
* To see the API for caching , please visit the DisplayObject { { # crossLink "DisplayObject/cache" } } { { / c r o s s L i n k } }
* method .
* @ method uncache
* * /
/ * *
* Docced in superclass .
* /
p . getBounds = function ( ) {
var rect = this . DisplayObject _getBounds ( ) ;
if ( rect ) { return rect ; }
var o = this . sourceRect || this . image ;
var hasContent = ( this . image && ( this . image . complete || this . image . getContext || this . image . readyState >= 2 ) ) ;
2014-11-18 18:26:26 -05:00
return hasContent ? this . _rectangle . setValues ( 0 , 0 , o . width , o . height ) : null ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns a clone of the Bitmap instance .
* @ method clone
* @ return { Bitmap } a clone of the Bitmap instance .
* * /
p . clone = function ( ) {
var o = new Bitmap ( this . image ) ;
if ( this . sourceRect ) { o . sourceRect = this . sourceRect . clone ( ) ; }
2014-11-18 18:26:26 -05:00
this . _cloneProps ( o ) ;
2014-01-03 13:32:13 -05:00
return o ;
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Bitmap (name=" + this . name + ")]" ;
} ;
2014-11-18 18:26:26 -05:00
createjs . Bitmap = createjs . promote ( Bitmap , "DisplayObject" ) ;
} ( ) ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
//##############################################################################
// Sprite.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Displays a frame or sequence of frames ( ie . an animation ) from a SpriteSheet instance . A sprite sheet is a series of
* images ( usually animation frames ) combined into a single image . For example , an animation consisting of 8 100 x100
* images could be combined into a 400 x200 sprite sheet ( 4 frames across by 2 high ) . You can display individual frames ,
* play frames as an animation , and even sequence animations together .
2014-01-03 13:32:13 -05:00
*
2014-11-18 18:26:26 -05:00
* See the { { # crossLink "SpriteSheet" } } { { / c r o s s L i n k } } c l a s s f o r m o r e i n f o r m a t i o n o n s e t t i n g u p f r a m e s a n d a n i m a t i o n s .
2014-01-03 13:32:13 -05:00
*
2014-11-18 18:26:26 -05:00
* < h4 > Example < / h 4 >
2014-01-03 13:32:13 -05:00
*
2014-11-18 18:26:26 -05:00
* var instance = new createjs . Sprite ( spriteSheet ) ;
* instance . gotoAndStop ( "frameName" ) ;
*
* Until { { # crossLink "Sprite/gotoAndStop" } } { { / c r o s s L i n k } } o r { { # c r o s s L i n k " S p r i t e / g o t o A n d P l a y " } } { { / c r o s s L i n k } } i s c a l l e d ,
* only the first defined frame defined in the sprite sheet will be displayed .
*
* @ class Sprite
* @ extends DisplayObject
* @ constructor
* @ param { SpriteSheet } spriteSheet The SpriteSheet instance to play back . This includes the source image ( s ) , frame
* dimensions , and frame data . See { { # crossLink "SpriteSheet" } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ param { String | Number } [ frameOrAnimation ] The frame number or animation to play initially .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
function Sprite ( spriteSheet , frameOrAnimation ) {
this . DisplayObject _constructor ( ) ;
// public properties:
/ * *
* The frame index that will be drawn when draw is called . Note that with some { { # crossLink "SpriteSheet" } } { { / c r o s s L i n k } }
* definitions , this will advance non - sequentially . This will always be an integer value .
* @ property currentFrame
* @ type { Number }
* @ default 0
* @ readonly
* * /
this . currentFrame = 0 ;
/ * *
* Returns the name of the currently playing animation .
* @ property currentAnimation
* @ type { String }
* @ final
* @ readonly
* * /
this . currentAnimation = null ;
/ * *
* Prevents the animation from advancing each tick automatically . For example , you could create a sprite
* sheet of icons , set paused to true , and display the appropriate icon by setting < code > currentFrame < / c o d e > .
* @ property paused
* @ type { Boolean }
* @ default false
* * /
this . paused = true ;
/ * *
* The SpriteSheet instance to play back . This includes the source image , frame dimensions , and frame
* data . See { { # crossLink "SpriteSheet" } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n .
* @ property spriteSheet
* @ type { SpriteSheet }
* @ readonly
* * /
this . spriteSheet = spriteSheet ;
/ * *
* Specifies the current frame index within the currently playing animation . When playing normally , this will increase
* from 0 to n - 1 , where n is the number of frames in the current animation .
*
* This could be a non - integer value if
* using time - based playback ( see { { # crossLink "Sprite/framerate" } } { { / c r o s s L i n k } } , o r i f t h e a n i m a t i o n ' s s p e e d i s
* not an integer .
* @ property currentAnimationFrame
* @ type { Number }
* @ default 0
* * /
this . currentAnimationFrame = 0 ;
/ * *
* By default Sprite instances advance one frame per tick . Specifying a framerate for the Sprite ( or its related
* SpriteSheet ) will cause it to advance based on elapsed time between ticks as appropriate to maintain the target
* framerate .
*
* For example , if a Sprite with a framerate of 10 is placed on a Stage being updated at 40 fps , then the Sprite will
* advance roughly one frame every 4 ticks . This will not be exact , because the time between each tick will
* vary slightly between frames .
*
* This feature is dependent on the tick event object ( or an object with an appropriate "delta" property ) being
* passed into { { # crossLink "Stage/update" } } { { / c r o s s L i n k } } .
* @ property framerate
* @ type { Number }
* @ default 0
* * /
this . framerate = 0 ;
// private properties:
/ * *
* Current animation object .
* @ property _animation
* @ protected
* @ type { Object }
* @ default null
* * /
this . _animation = null ;
/ * *
* Current frame index .
* @ property _currentFrame
* @ protected
* @ type { Number }
* @ default null
* * /
this . _currentFrame = null ;
/ * *
* Skips the next auto advance . Used by gotoAndPlay to avoid immediately jumping to the next frame
* @ property _skipAdvance
* @ protected
* @ type { Boolean }
* @ default false
* * /
this . _skipAdvance = false ;
if ( frameOrAnimation ) { this . gotoAndPlay ( frameOrAnimation ) ; }
}
var p = createjs . extend ( Sprite , createjs . DisplayObject ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// events:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Dispatched when an animation reaches its ends .
* @ event animationend
* @ param { Object } target The object that dispatched the event .
* @ param { String } type The event type .
* @ param { String } name The name of the animation that just ended .
* @ 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 .
* @ since 0.6 . 0
* /
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Dispatched any time the current frame changes . For example , this could be due to automatic advancement on a tick ,
* or calling gotoAndPlay ( ) or gotoAndStop ( ) .
* @ event change
* @ param { Object } target The object that dispatched the event .
* @ param { String } type The event type .
* /
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// public methods:
2014-01-03 13:32:13 -05:00
/ * *
* Returns true or false indicating whether the display object would be visible if drawn to a canvas .
* This does not account for whether it would be visible within the boundaries of the stage .
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method isVisible
* @ return { Boolean } Boolean indicating whether the display object would be visible if drawn to a canvas
* * /
p . isVisible = function ( ) {
var hasContent = this . cacheCanvas || this . spriteSheet . complete ;
return ! ! ( this . visible && this . alpha > 0 && this . scaleX != 0 && this . scaleY != 0 && hasContent ) ;
} ;
/ * *
* Draws the display object into the specified context ignoring its visible , alpha , shadow , and transform .
* Returns true if the draw was handled ( useful for overriding functionality ) .
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method draw
* @ param { CanvasRenderingContext2D } ctx The canvas 2 D context object to draw into .
* @ param { Boolean } ignoreCache Indicates whether the draw operation should ignore any current cache .
* For example , used for drawing the cache ( to prevent it from simply drawing an existing cache back
* into itself ) .
* * /
p . draw = function ( ctx , ignoreCache ) {
if ( this . DisplayObject _draw ( ctx , ignoreCache ) ) { return true ; }
this . _normalizeFrame ( ) ;
var o = this . spriteSheet . getFrame ( this . _currentFrame | 0 ) ;
if ( ! o ) { return false ; }
var rect = o . rect ;
2014-11-18 18:26:26 -05:00
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 ) ; }
2014-01-03 13:32:13 -05:00
return true ;
} ;
//Note, the doc sections below document using the specified APIs (from DisplayObject) from
//Bitmap. This is why they have no method implementations.
/ * *
2014-11-18 18:26:26 -05:00
* Because the content of a Sprite is already in a raster format , cache is unnecessary for Sprite instances .
* You should not cache Sprite instances as it can degrade performance .
2014-01-03 13:32:13 -05:00
* @ method cache
* * /
/ * *
2014-11-18 18:26:26 -05:00
* Because the content of a Sprite is already in a raster format , cache is unnecessary for Sprite instances .
* You should not cache Sprite instances as it can degrade performance .
2014-01-03 13:32:13 -05:00
* @ method updateCache
* * /
/ * *
2014-11-18 18:26:26 -05:00
* Because the content of a Sprite is already in a raster format , cache is unnecessary for Sprite instances .
* You should not cache Sprite instances as it can degrade performance .
2014-01-03 13:32:13 -05:00
* @ method uncache
* * /
/ * *
* Play ( unpause ) the current animation . The Sprite will be paused if either { { # crossLink "Sprite/stop" } } { { / c r o s s L i n k } }
* or { { # crossLink "Sprite/gotoAndStop" } } { { / c r o s s L i n k } } i s c a l l e d . S i n g l e f r a m e a n i m a t i o n s w i l l r e m a i n
* unchanged .
* @ method play
* * /
p . play = function ( ) {
this . paused = false ;
} ;
/ * *
* Stop playing a running animation . The Sprite will be playing if { { # crossLink "Sprite/gotoAndPlay" } } { { / c r o s s L i n k } }
* is called . Note that calling { { # crossLink "Sprite/gotoAndPlay" } } { { / c r o s s L i n k } } o r { { # c r o s s L i n k " S p r i t e / p l a y " } } { { / c r o s s L i n k } }
* will resume playback .
* @ method stop
* * /
p . stop = function ( ) {
this . paused = true ;
} ;
/ * *
* Sets paused to false and plays the specified animation name , named frame , or frame number .
* @ method gotoAndPlay
* @ param { String | Number } frameOrAnimation The frame number or animation name that the playhead should move to
* and begin playing .
* * /
p . gotoAndPlay = function ( frameOrAnimation ) {
this . paused = false ;
2014-11-18 18:26:26 -05:00
this . _skipAdvance = true ;
2014-01-03 13:32:13 -05:00
this . _goto ( frameOrAnimation ) ;
} ;
/ * *
* Sets paused to true and seeks to the specified animation name , named frame , or frame number .
* @ method gotoAndStop
* @ param { String | Number } frameOrAnimation The frame number or animation name that the playhead should move to
* and stop .
* * /
p . gotoAndStop = function ( frameOrAnimation ) {
this . paused = true ;
this . _goto ( frameOrAnimation ) ;
} ;
/ * *
* Advances the playhead . This occurs automatically each tick by default .
* @ param [ time ] { Number } The amount of time in ms to advance by . Only applicable if framerate is set on the Sprite
* or its SpriteSheet .
* @ method advance
* /
p . advance = function ( time ) {
var fps = this . framerate || this . spriteSheet . framerate ;
var t = ( fps && time != null ) ? time / ( 1000 / fps ) : 1 ;
2014-11-18 18:26:26 -05:00
this . _normalizeFrame ( t ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns a { { # crossLink "Rectangle" } } { { / c r o s s L i n k } } i n s t a n c e d e f i n i n g t h e b o u n d s o f t h e c u r r e n t f r a m e r e l a t i v e t o
* the origin . For example , a 90 x 70 frame with < code > regX = 50 < / c o d e > a n d < c o d e > r e g Y = 4 0 < / c o d e > w o u l d r e t u r n a
* rectangle with [ x = - 50 , y = - 40 , width = 90 , height = 70 ] . This ignores transformations on the display object .
*
* Also see the SpriteSheet { { # crossLink "SpriteSheet/getFrameBounds" } } { { / c r o s s L i n k } } m e t h o d .
* @ method getBounds
* @ return { Rectangle } A Rectangle instance . Returns null if the frame does not exist , or the image is not fully
* loaded .
* * /
p . getBounds = function ( ) {
// TODO: should this normalizeFrame?
return this . DisplayObject _getBounds ( ) || this . spriteSheet . getFrameBounds ( this . currentFrame , this . _rectangle ) ;
} ;
/ * *
* Returns a clone of the Sprite instance . Note that the same SpriteSheet is shared between cloned
* instances .
* @ method clone
* @ return { Sprite } a clone of the Sprite instance .
* * /
p . clone = function ( ) {
2014-11-18 18:26:26 -05:00
return this . _cloneProps ( new Sprite ( this . spriteSheet ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Sprite (name=" + this . name + ")]" ;
} ;
// private methods:
/ * *
2014-11-18 18:26:26 -05:00
* @ method _cloneProps
* @ param { Sprite } o
* @ return { Sprite } o
* @ protected
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . _cloneProps = function ( o ) {
this . DisplayObject _ _cloneProps ( o ) ;
o . currentFrame = this . currentFrame ;
o . currentAnimation = this . currentAnimation ;
o . paused = this . paused ;
o . currentAnimationFrame = this . currentAnimationFrame ;
o . framerate = this . framerate ;
o . _animation = this . _animation ;
o . _currentFrame = this . _currentFrame ;
o . _skipAdvance = this . _skipAdvance ;
return o ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
* Advances the < code > currentFrame < / c o d e > i f p a u s e d i s n o t t r u e . T h i s i s c a l l e d a u t o m a t i c a l l y w h e n t h e { { # c r o s s L i n k " S t a g e " } } { { / c r o s s L i n k } }
* ticks .
2014-11-18 18:26:26 -05:00
* @ 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 .
2014-01-03 13:32:13 -05:00
* @ protected
* @ method _tick
* * /
2014-11-18 18:26:26 -05:00
p . _tick = function ( evtObj ) {
2014-01-03 13:32:13 -05:00
if ( ! this . paused ) {
2014-11-18 18:26:26 -05:00
if ( ! this . _skipAdvance ) { this . advance ( evtObj && evtObj . delta ) ; }
this . _skipAdvance = false ;
2014-01-03 13:32:13 -05:00
}
2014-11-18 18:26:26 -05:00
this . DisplayObject _ _tick ( evtObj ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Normalizes the current frame , advancing animations and dispatching callbacks as appropriate .
* @ protected
* @ method _normalizeFrame
* * /
2014-11-18 18:26:26 -05:00
p . _normalizeFrame = function ( frameDelta ) {
frameDelta = frameDelta || 0 ;
2014-01-03 13:32:13 -05:00
var animation = this . _animation ;
var paused = this . paused ;
var frame = this . _currentFrame ;
var l ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
if ( animation ) {
2014-11-18 18:26:26 -05:00
var speed = animation . speed || 1 ;
var animFrame = this . currentAnimationFrame ;
2014-01-03 13:32:13 -05:00
l = animation . frames . length ;
2014-11-18 18:26:26 -05:00
if ( animFrame + frameDelta * speed >= l ) {
2014-01-03 13:32:13 -05:00
var next = animation . next ;
2014-11-18 18:26:26 -05:00
if ( this . _dispatchAnimationEnd ( animation , frame , paused , next , l - 1 ) ) {
// something changed in the event stack, so we shouldn't make any more changes here.
return ;
2014-01-03 13:32:13 -05:00
} else if ( next ) {
2014-11-18 18:26:26 -05:00
// sequence. Automatically calls _normalizeFrame again with the remaining frames.
return this . _goto ( next , frameDelta - ( l - animFrame ) / speed ) ;
2014-01-03 13:32:13 -05:00
} else {
// end.
this . paused = true ;
2014-11-18 18:26:26 -05:00
animFrame = animation . frames . length - 1 ;
2014-01-03 13:32:13 -05:00
}
} else {
2014-11-18 18:26:26 -05:00
animFrame += frameDelta * speed ;
2014-01-03 13:32:13 -05:00
}
2014-11-18 18:26:26 -05:00
this . currentAnimationFrame = animFrame ;
this . _currentFrame = animation . frames [ animFrame | 0 ]
2014-01-03 13:32:13 -05:00
} else {
2014-11-18 18:26:26 -05:00
frame = ( this . _currentFrame += frameDelta ) ;
2014-01-03 13:32:13 -05:00
l = this . spriteSheet . getNumFrames ( ) ;
2014-11-18 18:26:26 -05:00
if ( frame >= l && l > 0 ) {
if ( ! this . _dispatchAnimationEnd ( animation , frame , paused , l - 1 ) ) {
2014-01-03 13:32:13 -05:00
// looped.
if ( ( this . _currentFrame -= l ) >= l ) { return this . _normalizeFrame ( ) ; }
}
}
}
2014-11-18 18:26:26 -05:00
frame = this . _currentFrame | 0 ;
if ( this . currentFrame != frame ) {
this . currentFrame = frame ;
this . dispatchEvent ( "change" ) ;
}
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Dispatches the "animationend" event . Returns true if a handler changed the animation ( ex . calling { { # crossLink "Sprite/stop" } } { { / c r o s s L i n k } } ,
* { { # crossLink "Sprite/gotoAndPlay" } } { { / c r o s s L i n k } } , e t c . )
* @ property _dispatchAnimationEnd
* @ private
* @ type { Function }
* * /
p . _dispatchAnimationEnd = function ( animation , frame , paused , next , end ) {
var name = animation ? animation . name : null ;
if ( this . hasEventListener ( "animationend" ) ) {
var evt = new createjs . Event ( "animationend" ) ;
evt . name = name ;
evt . next = next ;
this . dispatchEvent ( evt ) ;
}
// did the animation get changed in the event stack?:
var changed = ( this . _animation != animation || this . _currentFrame != frame ) ;
// if the animation hasn't changed, but the sprite was paused, then we want to stick to the last frame:
if ( ! changed && ! paused && this . paused ) { this . currentAnimationFrame = end ; changed = true ; }
return changed ;
} ;
/ * *
* Moves the playhead to the specified frame number or animation .
* @ method _goto
* @ param { String | Number } frameOrAnimation The frame number or animation that the playhead should move to .
* @ param { Boolean } [ frame ] The frame of the animation to go to . Defaults to 0.
* @ protected
* * /
p . _goto = function ( frameOrAnimation , frame ) {
2014-11-18 18:26:26 -05:00
this . currentAnimationFrame = 0 ;
2014-01-03 13:32:13 -05:00
if ( isNaN ( frameOrAnimation ) ) {
var data = this . spriteSheet . getAnimation ( frameOrAnimation ) ;
if ( data ) {
this . _animation = data ;
this . currentAnimation = frameOrAnimation ;
2014-11-18 18:26:26 -05:00
this . _normalizeFrame ( frame ) ;
2014-01-03 13:32:13 -05:00
}
} else {
this . currentAnimation = this . _animation = null ;
this . _currentFrame = frameOrAnimation ;
this . _normalizeFrame ( ) ;
}
} ;
2014-11-18 18:26:26 -05:00
createjs . Sprite = createjs . promote ( Sprite , "DisplayObject" ) ;
} ( ) ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
//##############################################################################
// Shape.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
// constructor:
/ * *
2014-11-18 18:26:26 -05:00
* A Shape allows you to display vector art in the display list . It composites a { { # crossLink "Graphics" } } { { / c r o s s L i n k } }
* instance which exposes all of the vector drawing methods . The Graphics instance can be shared between multiple Shape
* instances to display the same vector graphics with different positions or transforms .
*
* If the vector art will not
* change between draws , you may want to use the { { # crossLink "DisplayObject/cache" } } { { / c r o s s L i n k } } m e t h o d t o r e d u c e t h e
* rendering cost .
*
* < h4 > Example < / h 4 >
*
* var graphics = new createjs . Graphics ( ) . beginFill ( "#ff0000" ) . drawRect ( 0 , 0 , 100 , 100 ) ;
* var shape = new createjs . Shape ( graphics ) ;
*
* //Alternatively use can also use the graphics property of the Shape class to renderer the same as above.
* var shape = new createjs . Shape ( ) ;
* shape . graphics . beginFill ( "#ff0000" ) . drawRect ( 0 , 0 , 100 , 100 ) ;
*
* @ class Shape
* @ extends DisplayObject
* @ constructor
* @ param { Graphics } graphics Optional . The graphics instance to display . If null , a new Graphics instance will be created .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
function Shape ( graphics ) {
this . DisplayObject _constructor ( ) ;
// public properties:
/ * *
* The graphics instance to display .
* @ property graphics
* @ type Graphics
* * /
2014-01-03 13:32:13 -05:00
this . graphics = graphics ? graphics : new createjs . Graphics ( ) ;
}
2014-11-18 18:26:26 -05:00
var p = createjs . extend ( Shape , createjs . DisplayObject ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// public methods:
2014-01-03 13:32:13 -05:00
/ * *
* Returns true or false indicating whether the Shape would be visible if drawn to a canvas .
* This does not account for whether it would be visible within the boundaries of the stage .
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method isVisible
* @ return { Boolean } Boolean indicating whether the Shape would be visible if drawn to a canvas
* * /
p . isVisible = function ( ) {
var hasContent = this . cacheCanvas || ( this . graphics && ! this . graphics . isEmpty ( ) ) ;
return ! ! ( this . visible && this . alpha > 0 && this . scaleX != 0 && this . scaleY != 0 && hasContent ) ;
} ;
/ * *
* Draws the Shape into the specified context ignoring its visible , alpha , shadow , and transform . Returns true if
* the draw was handled ( useful for overriding functionality ) .
*
* < i > NOTE : This method is mainly for internal use , though it may be useful for advanced uses . < / i >
* @ method draw
* @ param { CanvasRenderingContext2D } ctx The canvas 2 D context object to draw into .
* @ param { Boolean } [ ignoreCache = false ] Indicates whether the draw operation should ignore any current cache . For example ,
* used for drawing the cache ( to prevent it from simply drawing an existing cache back into itself ) .
* @ return { Boolean }
* * /
p . draw = function ( ctx , ignoreCache ) {
if ( this . DisplayObject _draw ( ctx , ignoreCache ) ) { return true ; }
2014-11-18 18:26:26 -05:00
this . graphics . draw ( ctx , this ) ;
2014-01-03 13:32:13 -05:00
return true ;
2014-11-18 18:26:26 -05:00
} ;
2014-01-03 13:32:13 -05:00
/ * *
* Returns a clone of this Shape . Some properties that are specific to this instance ' s current context are reverted to
* their defaults ( for example . parent ) .
* @ method clone
* @ param { Boolean } recursive If true , this Shape ' s { { # crossLink "Graphics" } } { { / c r o s s L i n k } } i n s t a n c e w i l l a l s o b e
* cloned . If false , the Graphics instance will be shared with the new Shape .
* * /
p . clone = function ( recursive ) {
2014-11-18 18:26:26 -05:00
var g = ( recursive && this . graphics ) ? this . graphics . clone ( ) : this . graphics ;
return this . _cloneProps ( new Shape ( g ) ) ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Shape (name=" + this . name + ")]" ;
2014-11-18 18:26:26 -05:00
} ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
createjs . Shape = createjs . promote ( Shape , "DisplayObject" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// Text.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
/ * *
* Display one or more lines of dynamic text ( not user editable ) in the display list . Line wrapping support ( using the
* lineWidth ) is very basic , wrapping on spaces and tabs only . Note that as an alternative to Text , you can position HTML
* text above or below the canvas relative to items in the display list using the { { # crossLink "DisplayObject/localToGlobal" } } { { / c r o s s L i n k } }
* method , or using { { # crossLink "DOMElement" } } { { / c r o s s L i n k } } .
*
* < b > Please note that Text does not support HTML text , and can only display one font style at a time . < / b > T o u s e
* multiple font styles , you will need to create multiple text instances , and position them manually .
*
* < h4 > Example < / h 4 >
*
* var text = new createjs . Text ( "Hello World" , "20px Arial" , "#ff7700" ) ;
* text . x = 100 ;
* text . textBaseline = "alphabetic" ;
*
* CreateJS Text supports web fonts ( the same rules as Canvas ) . The font must be loaded and supported by the browser
* before it can be displayed .
*
* < strong > Note : < / s t r o n g > T e x t c a n b e e x p e n s i v e t o g e n e r a t e , s o c a c h e i n s t a n c e s w h e r e p o s s i b l e . B e a w a r e t h a t n o t a l l
* browsers will render Text exactly the same .
* @ class Text
* @ extends DisplayObject
* @ constructor
* @ param { String } [ text ] The text to display .
* @ param { String } [ font ] The font style to use . Any valid value for the CSS font attribute is acceptable ( ex . " bold
* 36 px Arial " ) .
* @ param { String } [ color ] The color to draw the text in . Any valid value for the CSS color attribute is acceptable ( ex .
* "#F00" , "red" , or "#FF0000" ) .
* * /
function Text ( text , font , color ) {
this . DisplayObject _constructor ( ) ;
// public properties:
/ * *
* The text to display .
* @ property text
* @ type String
* * /
this . text = text ;
/ * *
* The font style to use . Any valid value for the CSS font attribute is acceptable ( ex . "bold 36px Arial" ) .
* @ property font
* @ type String
* * /
this . font = font ;
/ * *
* The color to draw the text in . Any valid value for the CSS color attribute is acceptable ( ex . "#F00" ) . Default is "#000" .
* It will also accept valid canvas fillStyle values .
* @ property color
* @ type String
* * /
this . color = color ;
/ * *
* The horizontal text alignment . Any of "start" , "end" , "left" , "right" , and "center" . For detailed
* information view the
* < a href = "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles" >
* whatwg spec < / a > . D e f a u l t i s " l e f t " .
* @ property textAlign
* @ type String
* * /
this . textAlign = "left" ;
/ * *
* The vertical alignment point on the font . Any of "top" , "hanging" , "middle" , "alphabetic" , "ideographic" , or
* "bottom" . For detailed information view the < a href = "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles" >
* whatwg spec < / a > . D e f a u l t i s " t o p " .
* @ property textBaseline
* @ type String
* /
this . textBaseline = "top" ;
/ * *
* The maximum width to draw the text . If maxWidth is specified ( not null ) , the text will be condensed or
* shrunk to make it fit in this width . For detailed information view the
* < a href = "http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles" >
* whatwg spec < / a > .
* @ property maxWidth
* @ type Number
* /
this . maxWidth = null ;
/ * *
* If greater than 0 , the text will be drawn as a stroke ( outline ) of the specified width .
* @ property outline
* @ type Number
* * /
this . outline = 0 ;
/ * *
* Indicates the line height ( vertical distance between baselines ) for multi - line text . If null or 0 ,
* the value of getMeasuredLineHeight is used .
* @ property lineHeight
* @ type Number
* * /
this . lineHeight = 0 ;
/ * *
* Indicates the maximum width for a line of text before it is wrapped to multiple lines . If null ,
* the text will not be wrapped .
* @ property lineWidth
* @ type Number
* * /
this . lineWidth = null ;
}
var p = createjs . extend ( Text , createjs . DisplayObject ) ;
// static properties:
2014-01-03 13:32:13 -05:00
/ * *
* @ property _workingContext
* @ type CanvasRenderingContext2D
* @ private
* * /
var canvas = ( createjs . createCanvas ? createjs . createCanvas ( ) : document . createElement ( "canvas" ) ) ;
if ( canvas . getContext ) { Text . _workingContext = canvas . getContext ( "2d" ) ; canvas . width = canvas . height = 1 ; }
2014-11-18 18:26:26 -05:00
// constants:
2014-01-03 13:32:13 -05:00
/ * *
* Lookup table for the ratio to offset bounds x calculations based on the textAlign property .
* @ property H _OFFSETS
* @ type Object
* @ protected
* @ static
* * /
Text . H _OFFSETS = { start : 0 , left : 0 , center : - 0.5 , end : - 1 , right : - 1 } ;
/ * *
* Lookup table for the ratio to offset bounds y calculations based on the textBaseline property .
* @ property H _OFFSETS
* @ type Object
* @ protected
* @ static
* * /
Text . V _OFFSETS = { top : 0 , hanging : - 0.01 , middle : - 0.4 , alphabetic : - 0.8 , ideographic : - 0.85 , bottom : - 1 } ;
2014-11-18 18:26:26 -05:00
// public methods:
2014-01-03 13:32:13 -05:00
/ * *
* Returns true or false indicating whether the display object would be visible if drawn to a canvas .
* This does not account for whether it would be visible within the boundaries of the stage .
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method isVisible
* @ return { Boolean } Whether the display object would be visible if drawn to a canvas
* * /
p . isVisible = function ( ) {
var hasContent = this . cacheCanvas || ( this . text != null && this . text !== "" ) ;
return ! ! ( this . visible && this . alpha > 0 && this . scaleX != 0 && this . scaleY != 0 && hasContent ) ;
} ;
/ * *
* Draws the Text into the specified context ignoring its visible , alpha , shadow , and transform .
* Returns true if the draw was handled ( useful for overriding functionality ) .
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method draw
* @ param { CanvasRenderingContext2D } ctx The canvas 2 D context object to draw into .
* @ param { Boolean } ignoreCache Indicates whether the draw operation should ignore any current cache .
* For example , used for drawing the cache ( to prevent it from simply drawing an existing cache back
* into itself ) .
* * /
p . draw = function ( ctx , ignoreCache ) {
if ( this . DisplayObject _draw ( ctx , ignoreCache ) ) { return true ; }
var col = this . color || "#000" ;
if ( this . outline ) { ctx . strokeStyle = col ; ctx . lineWidth = this . outline * 1 ; }
else { ctx . fillStyle = col ; }
this . _drawText ( this . _prepContext ( ctx ) ) ;
return true ;
} ;
/ * *
* Returns the measured , untransformed width of the text without wrapping . Use getBounds for a more robust value .
* @ method getMeasuredWidth
* @ return { Number } The measured , untransformed width of the text .
* * /
p . getMeasuredWidth = function ( ) {
2014-11-18 18:26:26 -05:00
return this . _getMeasuredWidth ( this . text ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns an approximate line height of the text , ignoring the lineHeight property . This is based on the measured
* width of a "M" character multiplied by 1.2 , which provides an approximate line height for most fonts .
* @ method getMeasuredLineHeight
* @ return { Number } an approximate line height of the text , ignoring the lineHeight property . This is
* based on the measured width of a "M" character multiplied by 1.2 , which approximates em for most fonts .
* * /
p . getMeasuredLineHeight = function ( ) {
2014-11-18 18:26:26 -05:00
return this . _getMeasuredWidth ( "M" ) * 1.2 ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns the approximate height of multi - line text by multiplying the number of lines against either the
* < code > lineHeight < / c o d e > ( i f s p e c i f i e d ) o r { { # c r o s s L i n k " T e x t / g e t M e a s u r e d L i n e H e i g h t " } } { { / c r o s s L i n k } } . N o t e t h a t
* this operation requires the text flowing logic to run , which has an associated CPU cost .
* @ method getMeasuredHeight
* @ return { Number } The approximate height of the untransformed multi - line text .
* * /
p . getMeasuredHeight = function ( ) {
return this . _drawText ( null , { } ) . height ;
} ;
/ * *
* Docced in superclass .
* /
p . getBounds = function ( ) {
var rect = this . DisplayObject _getBounds ( ) ;
if ( rect ) { return rect ; }
if ( this . text == null || this . text == "" ) { return null ; }
var o = this . _drawText ( null , { } ) ;
var w = ( this . maxWidth && this . maxWidth < o . width ) ? this . maxWidth : o . width ;
var x = w * Text . H _OFFSETS [ this . textAlign || "left" ] ;
var lineHeight = this . lineHeight || this . getMeasuredLineHeight ( ) ;
var y = lineHeight * Text . V _OFFSETS [ this . textBaseline || "top" ] ;
2014-11-18 18:26:26 -05:00
return this . _rectangle . setValues ( x , y , w , o . height ) ;
} ;
/ * *
* Returns an object with width , height , and lines properties . The width and height are the visual width and height
* of the drawn text . The lines property contains an array of strings , one for
* each line of text that will be drawn , accounting for line breaks and wrapping . These strings have trailing
* whitespace removed .
* @ method getMetrics
* @ return { Object } An object with width , height , and lines properties .
* * /
p . getMetrics = function ( ) {
var o = { lines : [ ] } ;
o . lineHeight = this . lineHeight || this . getMeasuredLineHeight ( ) ;
o . vOffset = o . lineHeight * Text . V _OFFSETS [ this . textBaseline || "top" ] ;
return this . _drawText ( null , o , o . lines ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns a clone of the Text instance .
* @ method clone
* @ return { Text } a clone of the Text instance .
* * /
p . clone = function ( ) {
2014-11-18 18:26:26 -05:00
return this . _cloneProps ( new Text ( this . text , this . font , this . color ) ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Text (text=" + ( this . text . length > 20 ? this . text . substr ( 0 , 17 ) + "..." : this . text ) + ")]" ;
} ;
2014-11-18 18:26:26 -05:00
// private methods:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* @ method _cloneProps
2014-01-03 13:32:13 -05:00
* @ param { Text } o
* @ protected
2014-11-18 18:26:26 -05:00
* @ return { Text } o
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
p . _cloneProps = function ( o ) {
this . DisplayObject _ _cloneProps ( o ) ;
2014-01-03 13:32:13 -05:00
o . textAlign = this . textAlign ;
o . textBaseline = this . textBaseline ;
o . maxWidth = this . maxWidth ;
o . outline = this . outline ;
o . lineHeight = this . lineHeight ;
o . lineWidth = this . lineWidth ;
2014-11-18 18:26:26 -05:00
return o ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* @ method _getWorkingContext
* @ param { CanvasRenderingContext2D } ctx
* @ return { CanvasRenderingContext2D }
* @ protected
* * /
p . _prepContext = function ( ctx ) {
2014-11-18 18:26:26 -05:00
ctx . font = this . font || "10px sans-serif" ;
2014-01-03 13:32:13 -05:00
ctx . textAlign = this . textAlign || "left" ;
ctx . textBaseline = this . textBaseline || "top" ;
return ctx ;
} ;
/ * *
* Draws multiline text .
* @ method _drawText
* @ param { CanvasRenderingContext2D } ctx
* @ param { Object } o
2014-11-18 18:26:26 -05:00
* @ param { Array } lines
2014-01-03 13:32:13 -05:00
* @ return { Object }
* @ protected
* * /
2014-11-18 18:26:26 -05:00
p . _drawText = function ( ctx , o , lines ) {
2014-01-03 13:32:13 -05:00
var paint = ! ! ctx ;
2014-11-18 18:26:26 -05:00
if ( ! paint ) {
ctx = Text . _workingContext ;
ctx . save ( ) ;
this . _prepContext ( ctx ) ;
}
2014-01-03 13:32:13 -05:00
var lineHeight = this . lineHeight || this . getMeasuredLineHeight ( ) ;
var maxW = 0 , count = 0 ;
2014-11-18 18:26:26 -05:00
var hardLines = String ( this . text ) . split ( /(?:\r\n|\r|\n)/ ) ;
for ( var i = 0 , l = hardLines . length ; i < l ; i ++ ) {
var str = hardLines [ i ] ;
2014-01-03 13:32:13 -05:00
var w = null ;
if ( this . lineWidth != null && ( w = ctx . measureText ( str ) . width ) > this . lineWidth ) {
// text wrapping:
var words = str . split ( /(\s)/ ) ;
str = words [ 0 ] ;
w = ctx . measureText ( str ) . width ;
for ( var j = 1 , jl = words . length ; j < jl ; j += 2 ) {
// Line needs to wrap:
var wordW = ctx . measureText ( words [ j ] + words [ j + 1 ] ) . width ;
if ( w + wordW > this . lineWidth ) {
if ( paint ) { this . _drawTextLine ( ctx , str , count * lineHeight ) ; }
2014-11-18 18:26:26 -05:00
if ( lines ) { lines . push ( str ) ; }
2014-01-03 13:32:13 -05:00
if ( w > maxW ) { maxW = w ; }
str = words [ j + 1 ] ;
w = ctx . measureText ( str ) . width ;
count ++ ;
} else {
str += words [ j ] + words [ j + 1 ] ;
w += wordW ;
}
}
}
if ( paint ) { this . _drawTextLine ( ctx , str , count * lineHeight ) ; }
2014-11-18 18:26:26 -05:00
if ( lines ) { lines . push ( str ) ; }
2014-01-03 13:32:13 -05:00
if ( o && w == null ) { w = ctx . measureText ( str ) . width ; }
if ( w > maxW ) { maxW = w ; }
count ++ ;
}
if ( o ) {
o . width = maxW ;
o . height = count * lineHeight ;
}
2014-11-18 18:26:26 -05:00
if ( ! paint ) { ctx . restore ( ) ; }
2014-01-03 13:32:13 -05:00
return o ;
} ;
/ * *
* @ method _drawTextLine
* @ param { CanvasRenderingContext2D } ctx
* @ param { String } text
* @ param { Number } y
* @ protected
* * /
p . _drawTextLine = function ( ctx , text , y ) {
// Chrome 17 will fail to draw the text if the last param is included but null, so we feed it a large value instead:
2014-11-18 18:26:26 -05:00
if ( this . outline ) { ctx . strokeText ( text , 0 , y , this . maxWidth || 0xFFFF ) ; }
else { ctx . fillText ( text , 0 , y , this . maxWidth || 0xFFFF ) ; }
} ;
/ * *
* @ method _getMeasuredWidth
* @ param { String } text
* @ protected
* * /
p . _getMeasuredWidth = function ( text ) {
var ctx = Text . _workingContext ;
ctx . save ( ) ;
var w = this . _prepContext ( ctx ) . measureText ( text ) . width ;
ctx . restore ( ) ;
return w ;
2014-01-03 13:32:13 -05:00
} ;
2014-11-18 18:26:26 -05:00
createjs . Text = createjs . promote ( Text , "DisplayObject" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// BitmapText.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
/ * *
* Displays text using bitmap glyphs defined in a sprite sheet . Multi - line text is supported
* using new line characters , but automatic wrapping is not supported . See the
* { { # crossLink "BitmapText/spriteSheet:property" } } { { / c r o s s L i n k } }
* property for more information on defining glyphs .
*
* < strong > Important : < / s t r o n g > B i t m a p T e x t e x t e n d s C o n t a i n e r , b u t i s n o t d e s i g n e d t o b e u s e d a s o n e .
* As such , methods like addChild and removeChild are disabled .
* @ class BitmapText
* @ extends DisplayObject
* @ param { String } [ text = "" ] The text to display .
* @ param { SpriteSheet } [ spriteSheet = null ] The spritesheet that defines the character glyphs .
* @ constructor
* * /
function BitmapText ( text , spriteSheet ) {
this . Container _constructor ( ) ;
// public properties:
/ * *
* The text to display .
* @ property text
* @ type String
* @ default ""
* * /
this . text = text || "" ;
/ * *
* A SpriteSheet instance that defines the glyphs for this bitmap text . Each glyph / character
* should have a single frame animation defined in the sprite sheet named the same as
* corresponding character . For example , the following animation definition :
*
* "A" : { frames : [ 0 ] }
*
* would indicate that the frame at index 0 of the spritesheet should be drawn for the "A" character . The short form
* is also acceptable :
*
* "A" : 0
*
* Note that if a character in the text is not found in the sprite sheet , it will also
* try to use the alternate case ( upper or lower ) .
*
* See SpriteSheet for more information on defining sprite sheet data .
* @ property spriteSheet
* @ type String
* @ default null
* * /
this . spriteSheet = spriteSheet ;
/ * *
* The height of each line of text . If 0 , then it will use a line height calculated
* by checking for the height of the "1" , "T" , or "L" character ( in that order ) . If
* those characters are not defined , it will use the height of the first frame of the
* sprite sheet .
* @ property lineHeight
* @ type Number
* @ default 0
* * /
this . lineHeight = 0 ;
/ * *
* This spacing ( in pixels ) will be added after each character in the output .
* @ property letterSpacing
* @ type Number
* @ default 0
* * /
this . letterSpacing = 0 ;
/ * *
* If a space character is not defined in the sprite sheet , then empty pixels equal to
* spaceWidth will be inserted instead . If 0 , then it will use a value calculated
* by checking for the width of the "1" , "l" , "E" , or "A" character ( in that order ) . If
* those characters are not defined , it will use the width of the first frame of the
* sprite sheet .
* @ property spaceWidth
* @ type Number
* @ default 0
* * /
this . spaceWidth = 0 ;
// private properties:
/ * *
* @ property _oldProps
* @ type Object
* @ protected
* * /
this . _oldProps = { text : 0 , spriteSheet : 0 , lineHeight : 0 , letterSpacing : 0 , spaceWidth : 0 } ;
}
var p = createjs . extend ( BitmapText , createjs . Container ) ;
2014-01-03 13:32:13 -05:00
// static properties:
2014-02-02 19:31:06 -05:00
/ * *
* BitmapText uses Sprite instances to draw text . To reduce the creation and destruction of instances ( and thus garbage collection ) , it maintains
* an internal object pool of sprite instances to reuse . Increasing this value can cause more sprites to be
* retained , slightly increasing memory use , but reducing instantiation .
* @ property maxPoolSize
* @ type Number
* @ static
* @ default 100
* * /
BitmapText . maxPoolSize = 100 ;
/ * *
* Sprite object pool .
* @ type { Array }
* @ static
* @ private
* /
BitmapText . _spritePool = [ ] ;
2014-01-03 13:32:13 -05:00
// public methods:
/ * *
2014-02-02 19:31:06 -05:00
* Docced in superclass .
2014-01-03 13:32:13 -05:00
* * /
p . draw = function ( ctx , ignoreCache ) {
2014-02-02 19:31:06 -05:00
if ( this . DisplayObject _draw ( ctx , ignoreCache ) ) { return ; }
this . _updateText ( ) ;
this . Container _draw ( ctx , ignoreCache ) ;
} ;
/ * *
* Docced in superclass .
* * /
p . getBounds = function ( ) {
this . _updateText ( ) ;
return this . Container _getBounds ( ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Returns true or false indicating whether the display object would be visible if drawn to a canvas .
* This does not account for whether it would be visible within the boundaries of the stage .
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method isVisible
* @ return { Boolean } Boolean indicating whether the display object would be visible if drawn to a canvas
* * /
p . isVisible = function ( ) {
var hasContent = this . cacheCanvas || ( this . spriteSheet && this . spriteSheet . complete && this . text ) ;
return ! ! ( this . visible && this . alpha > 0 && this . scaleX != 0 && this . scaleY != 0 && hasContent ) ;
} ;
2014-11-18 18:26:26 -05:00
p . clone = function ( ) {
return this . _cloneProps ( new BitmapText ( this . text , this . spriteSheet ) ) ;
} ;
/ * *
* < strong > Disabled in BitmapText . < / s t r o n g >
* @ method addChild
* * /
/ * *
* < strong > Disabled in BitmapText . < / s t r o n g >
* @ method addChildAt
* * /
/ * *
* < strong > Disabled in BitmapText . < / s t r o n g >
* @ method removeChild
* * /
/ * *
* < strong > Disabled in BitmapText . < / s t r o n g >
* @ method removeChildAt
* * /
/ * *
* < strong > Disabled in BitmapText . < / s t r o n g >
* @ method removeAllChildren
* * /
p . addChild = p . addChildAt = p . removeChild = p . removeChildAt = p . removeAllChildren = function ( ) { } ;
2014-01-03 13:32:13 -05:00
// private methods:
2014-11-18 18:26:26 -05:00
/ * *
* @ method _cloneProps
* @ param { BitmapText } o
* @ return { BitmapText } o
* @ protected
* * /
p . _cloneProps = function ( o ) {
this . DisplayObject _ _cloneProps ( o ) ;
o . lineHeight = this . lineHeight ;
o . letterSpacing = this . letterSpacing ;
o . spaceWidth = this . spaceWidth ;
return o ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
2014-02-02 19:31:06 -05:00
* @ method _getFrameIndex
2014-01-03 13:32:13 -05:00
* @ param { String } character
* @ param { SpriteSheet } spriteSheet
2014-02-02 19:31:06 -05:00
* @ return { Number }
2014-01-03 13:32:13 -05:00
* @ protected
* * /
2014-02-02 19:31:06 -05:00
p . _getFrameIndex = function ( character , spriteSheet ) {
2014-01-03 13:32:13 -05:00
var c , o = spriteSheet . getAnimation ( character ) ;
if ( ! o ) {
( character != ( c = character . toUpperCase ( ) ) ) || ( character != ( c = character . toLowerCase ( ) ) ) || ( c = null ) ;
if ( c ) { o = spriteSheet . getAnimation ( c ) ; }
}
2014-02-02 19:31:06 -05:00
return o && o . frames [ 0 ] ;
} ;
/ * *
* @ method _getFrame
* @ param { String } character
* @ param { SpriteSheet } spriteSheet
* @ return { Object }
* @ protected
* * /
p . _getFrame = function ( character , spriteSheet ) {
var index = this . _getFrameIndex ( character , spriteSheet ) ;
return index == null ? index : spriteSheet . getFrame ( index ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* @ method _getLineHeight
* @ param { SpriteSheet } ss
2014-02-02 19:31:06 -05:00
* @ return { Number }
2014-01-03 13:32:13 -05:00
* @ protected
* * /
p . _getLineHeight = function ( ss ) {
var frame = this . _getFrame ( "1" , ss ) || this . _getFrame ( "T" , ss ) || this . _getFrame ( "L" , ss ) || ss . getFrame ( 0 ) ;
return frame ? frame . rect . height : 1 ;
} ;
/ * *
* @ method _getSpaceWidth
* @ param { SpriteSheet } ss
2014-02-02 19:31:06 -05:00
* @ return { Number }
2014-01-03 13:32:13 -05:00
* @ protected
* * /
p . _getSpaceWidth = function ( ss ) {
var frame = this . _getFrame ( "1" , ss ) || this . _getFrame ( "l" , ss ) || this . _getFrame ( "e" , ss ) || this . _getFrame ( "a" , ss ) || ss . getFrame ( 0 ) ;
return frame ? frame . rect . width : 1 ;
} ;
/ * *
* @ method _drawText
* @ protected
* * /
2014-02-02 19:31:06 -05:00
p . _updateText = function ( ) {
var x = 0 , y = 0 , o = this . _oldProps , change = false , spaceW = this . spaceWidth , lineH = this . lineHeight , ss = this . spriteSheet ;
var pool = BitmapText . _spritePool , kids = this . children , childIndex = 0 , numKids = kids . length , sprite ;
for ( var n in o ) {
if ( o [ n ] != this [ n ] ) {
o [ n ] = this [ n ] ;
change = true ;
}
}
if ( ! change ) { return ; }
2014-01-03 13:32:13 -05:00
var hasSpace = ! ! this . _getFrame ( " " , ss ) ;
if ( ! hasSpace && spaceW == 0 ) { spaceW = this . _getSpaceWidth ( ss ) ; }
if ( lineH == 0 ) { lineH = this . _getLineHeight ( ss ) ; }
for ( var i = 0 , l = this . text . length ; i < l ; i ++ ) {
var character = this . text . charAt ( i ) ;
2014-02-02 19:31:06 -05:00
if ( character == " " && ! hasSpace ) {
2014-01-03 13:32:13 -05:00
x += spaceW ;
continue ;
} else if ( character == "\n" || character == "\r" ) {
if ( character == "\r" && this . text . charAt ( i + 1 ) == "\n" ) { i ++ ; } // crlf
x = 0 ;
y += lineH ;
continue ;
}
2014-02-02 19:31:06 -05:00
var index = this . _getFrameIndex ( character , ss ) ;
if ( index == null ) { continue ; }
2014-01-03 13:32:13 -05:00
2014-02-02 19:31:06 -05:00
if ( childIndex < numKids ) {
sprite = kids [ childIndex ] ;
} else {
2014-11-18 18:26:26 -05:00
kids . push ( sprite = pool . length ? pool . pop ( ) : new createjs . Sprite ( ) ) ;
sprite . parent = this ;
2014-02-02 19:31:06 -05:00
numKids ++ ;
}
sprite . spriteSheet = ss ;
sprite . gotoAndStop ( index ) ;
sprite . x = x ;
sprite . y = y ;
childIndex ++ ;
x += sprite . getBounds ( ) . width + this . letterSpacing ;
2014-01-03 13:32:13 -05:00
}
2014-11-18 18:26:26 -05:00
while ( numKids > childIndex ) { pool . push ( sprite = kids . pop ( ) ) ; sprite . parent = null ; numKids -- ; } // faster than removeChild.
2014-02-02 19:31:06 -05:00
if ( pool . length > BitmapText . maxPoolSize ) { pool . length = BitmapText . maxPoolSize ; }
2014-01-03 13:32:13 -05:00
} ;
2014-11-18 18:26:26 -05:00
createjs . BitmapText = createjs . promote ( BitmapText , "Container" ) ;
} ( ) ) ;
//##############################################################################
// SpriteSheetUtils.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
// constructor:
2014-11-18 18:26:26 -05:00
/ * *
* The SpriteSheetUtils class is a collection of static methods for working with { { # crossLink "SpriteSheet" } } { { / c r o s s L i n k } } s .
* A sprite sheet is a series of images ( usually animation frames ) combined into a single image on a regular grid . For
* example , an animation consisting of 8 100 x100 images could be combined into a 400 x200 sprite sheet ( 4 frames across
* by 2 high ) . The SpriteSheetUtils class uses a static interface and should not be instantiated .
* @ class SpriteSheetUtils
* @ static
* * /
function SpriteSheetUtils ( ) {
throw "SpriteSheetUtils cannot be instantiated" ;
}
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// private static properties:
2014-01-03 13:32:13 -05:00
/ * *
* @ property _workingCanvas
* @ static
* @ type HTMLCanvasElement | Object
* @ protected
* /
/ * *
* @ property _workingContext
* @ static
* @ type CanvasRenderingContext2D
* @ protected
* /
var canvas = ( createjs . createCanvas ? createjs . createCanvas ( ) : document . createElement ( "canvas" ) ) ;
if ( canvas . getContext ) {
SpriteSheetUtils . _workingCanvas = canvas ;
SpriteSheetUtils . _workingContext = canvas . getContext ( "2d" ) ;
canvas . width = canvas . height = 1 ;
}
// public static methods:
/ * *
* < b > This is an experimental method , and may be buggy . Please report issues . < /b><br/ > < br / >
* Extends the existing sprite sheet by flipping the original frames horizontally , vertically , or both ,
* and adding appropriate animation & frame data . The flipped animations will have a suffix added to their names
* ( _h , _v , _hv as appropriate ) . Make sure the sprite sheet images are fully loaded before using this method .
* < br / > < br / >
* For example : < br / >
* SpriteSheetUtils . addFlippedFrames ( mySpriteSheet , true , true ) ;
* The above would add frames that are flipped horizontally AND frames that are flipped vertically .
* < br / > < br / >
* Note that you can also flip any display object by setting its scaleX or scaleY to a negative value . On some
* browsers ( especially those without hardware accelerated canvas ) this can result in slightly degraded performance ,
* which is why addFlippedFrames is available .
* @ method addFlippedFrames
* @ static
* @ param { SpriteSheet } spriteSheet
* @ param { Boolean } horizontal If true , horizontally flipped frames will be added .
* @ param { Boolean } vertical If true , vertically flipped frames will be added .
* @ param { Boolean } both If true , frames that are flipped both horizontally and vertically will be added .
* @ deprecated Modern browsers perform better when flipping via a transform ( ex . scaleX = - 1 ) rendering this obsolete .
* * /
SpriteSheetUtils . addFlippedFrames = function ( spriteSheet , horizontal , vertical , both ) {
if ( ! horizontal && ! vertical && ! both ) { return ; }
var count = 0 ;
if ( horizontal ) { SpriteSheetUtils . _flip ( spriteSheet , ++ count , true , false ) ; }
if ( vertical ) { SpriteSheetUtils . _flip ( spriteSheet , ++ count , false , true ) ; }
if ( both ) { SpriteSheetUtils . _flip ( spriteSheet , ++ count , true , true ) ; }
} ;
/ * *
* Returns a single frame of the specified sprite sheet as a new PNG image . An example of when this may be useful is
* to use a spritesheet frame as the source for a bitmap fill .
*
* < strong > WARNING : < / s t r o n g > I n a l m o s t a l l c a s e s i t i s b e t t e r t o d i s p l a y a s i n g l e f r a m e u s i n g a { { # c r o s s L i n k " S p r i t e " } } { { / c r o s s L i n k } }
* with a { { # crossLink "Sprite/gotoAndStop" } } { { / c r o s s L i n k } } c a l l t h a n i t i s t o s l i c e o u t a f r a m e u s i n g t h i s
* method and display it with a Bitmap instance . You can also crop an image using the { { # crossLink "Bitmap/sourceRect" } } { { / c r o s s L i n k } }
* property of { { # crossLink "Bitmap" } } { { / c r o s s L i n k } } .
*
* The extractFrame method may cause cross - domain warnings since it accesses pixels directly on the canvas .
* @ method extractFrame
* @ static
* @ param { Image } spriteSheet The SpriteSheet instance to extract a frame from .
* @ param { Number | String } frameOrAnimation The frame number or animation name to extract . If an animation
* name is specified , only the first frame of the animation will be extracted .
* @ return { Image } a single frame of the specified sprite sheet as a new PNG image .
* /
SpriteSheetUtils . extractFrame = function ( spriteSheet , frameOrAnimation ) {
if ( isNaN ( frameOrAnimation ) ) {
frameOrAnimation = spriteSheet . getAnimation ( frameOrAnimation ) . frames [ 0 ] ;
}
var data = spriteSheet . getFrame ( frameOrAnimation ) ;
if ( ! data ) { return null ; }
var r = data . rect ;
var canvas = SpriteSheetUtils . _workingCanvas ;
canvas . width = r . width ;
canvas . height = r . height ;
SpriteSheetUtils . _workingContext . drawImage ( data . image , r . x , r . y , r . width , r . height , 0 , 0 , r . width , r . height ) ;
var img = document . createElement ( "img" ) ;
img . src = canvas . toDataURL ( "image/png" ) ;
return img ;
} ;
/ * *
* Merges the rgb channels of one image with the alpha channel of another . This can be used to combine a compressed
* JPEG image containing color data with a PNG32 monochromatic image containing alpha data . With certain types of
* images ( those with detail that lend itself to JPEG compression ) this can provide significant file size savings
* versus a single RGBA PNG32 . This method is very fast ( generally on the order of 1 - 2 ms to run ) .
* @ method mergeAlpha
* @ static
* @ param { Image } rbgImage The image ( or canvas ) containing the RGB channels to use .
* @ param { Image } alphaImage The image ( or canvas ) containing the alpha channel to use .
* @ param { Canvas } canvas Optional . If specified , this canvas will be used and returned . If not , a new canvas will be created .
* @ return { Canvas } A canvas with the combined image data . This can be used as a source for Bitmap or SpriteSheet .
* @ deprecated Tools such as ImageAlpha generally provide better results . This will be moved to sandbox in the future .
* /
SpriteSheetUtils . mergeAlpha = function ( rgbImage , alphaImage , canvas ) {
if ( ! canvas ) { canvas = createjs . createCanvas ? createjs . createCanvas ( ) : document . createElement ( "canvas" ) ; }
canvas . width = Math . max ( alphaImage . width , rgbImage . width ) ;
canvas . height = Math . max ( alphaImage . height , rgbImage . height ) ;
var ctx = canvas . getContext ( "2d" ) ;
ctx . save ( ) ;
ctx . drawImage ( rgbImage , 0 , 0 ) ;
ctx . globalCompositeOperation = "destination-in" ;
ctx . drawImage ( alphaImage , 0 , 0 ) ;
ctx . restore ( ) ;
return canvas ;
} ;
// private static methods:
SpriteSheetUtils . _flip = function ( spriteSheet , count , h , v ) {
var imgs = spriteSheet . _images ;
var canvas = SpriteSheetUtils . _workingCanvas ;
var ctx = SpriteSheetUtils . _workingContext ;
var il = imgs . length / count ;
for ( var i = 0 ; i < il ; i ++ ) {
var src = imgs [ i ] ;
src . _ _tmp = i ; // a bit hacky, but faster than doing indexOf below.
ctx . setTransform ( 1 , 0 , 0 , 1 , 0 , 0 ) ;
ctx . clearRect ( 0 , 0 , canvas . width + 1 , canvas . height + 1 ) ;
canvas . width = src . width ;
canvas . height = src . height ;
ctx . setTransform ( h ? - 1 : 1 , 0 , 0 , v ? - 1 : 1 , h ? src . width : 0 , v ? src . height : 0 ) ;
ctx . drawImage ( src , 0 , 0 ) ;
var img = document . createElement ( "img" ) ;
img . src = canvas . toDataURL ( "image/png" ) ;
// work around a strange bug in Safari:
img . width = src . width ;
img . height = src . height ;
imgs . push ( img ) ;
}
var frames = spriteSheet . _frames ;
var fl = frames . length / count ;
for ( i = 0 ; i < fl ; i ++ ) {
src = frames [ i ] ;
var rect = src . rect . clone ( ) ;
img = imgs [ src . image . _ _tmp + il * count ] ;
var frame = { image : img , rect : rect , regX : src . regX , regY : src . regY } ;
if ( h ) {
rect . x = img . width - rect . x - rect . width ; // update rect
frame . regX = rect . width - src . regX ; // update registration point
}
if ( v ) {
rect . y = img . height - rect . y - rect . height ; // update rect
frame . regY = rect . height - src . regY ; // update registration point
}
frames . push ( frame ) ;
}
var sfx = "_" + ( h ? "h" : "" ) + ( v ? "v" : "" ) ;
var names = spriteSheet . _animations ;
var data = spriteSheet . _data ;
var al = names . length / count ;
for ( i = 0 ; i < al ; i ++ ) {
var name = names [ i ] ;
src = data [ name ] ;
var anim = { name : name + sfx , speed : src . speed , next : src . next , frames : [ ] } ;
if ( src . next ) { anim . next += sfx ; }
frames = src . frames ;
for ( var j = 0 , l = frames . length ; j < l ; j ++ ) {
anim . frames . push ( frames [ j ] + fl * count ) ;
}
data [ anim . name ] = anim ;
names . push ( anim . name ) ;
}
} ;
2014-11-18 18:26:26 -05:00
createjs . SpriteSheetUtils = SpriteSheetUtils ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// SpriteSheetBuilder.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
/ * *
* The SpriteSheetBuilder allows you to generate sprite sheets at run time from any display object . This can allow
* you to maintain your assets as vector graphics ( for low file size ) , and render them at run time as sprite sheets
* for better performance .
*
* Sprite sheets can be built either synchronously , or asynchronously , so that large sprite sheets can be generated
* without locking the UI .
*
* Note that the "images" used in the generated sprite sheet are actually canvas elements , and that they will be sized
* to the nearest power of 2 up to the value of < code > maxWidth < / c o d e > o r < c o d e > m a x H e i g h t < / c o d e > .
* @ class SpriteSheetBuilder
* @ extends EventDispatcher
* @ constructor
* * /
function SpriteSheetBuilder ( ) {
this . EventDispatcher _constructor ( ) ;
// public properties:
/ * *
* The maximum width for the images ( not individual frames ) in the generated sprite sheet . It is recommended to use
* a power of 2 for this value ( ex . 1024 , 2048 , 4096 ) . If the frames cannot all fit within the max dimensions , then
* additional images will be created as needed .
* @ property maxWidth
* @ type Number
* @ default 2048
* /
this . maxWidth = 2048 ;
/ * *
* The maximum height for the images ( not individual frames ) in the generated sprite sheet . It is recommended to use
* a power of 2 for this value ( ex . 1024 , 2048 , 4096 ) . If the frames cannot all fit within the max dimensions , then
* additional images will be created as needed .
* @ property maxHeight
* @ type Number
* @ default 2048
* * /
this . maxHeight = 2048 ;
/ * *
* The sprite sheet that was generated . This will be null before a build is completed successfully .
* @ property spriteSheet
* @ type SpriteSheet
* * /
this . spriteSheet = null ;
/ * *
* The scale to apply when drawing all frames to the sprite sheet . This is multiplied against any scale specified
* in the addFrame call . This can be used , for example , to generate a sprite sheet at run time that is tailored to
* the a specific device resolution ( ex . tablet vs mobile ) .
* @ property scale
* @ type Number
* @ default 1
* * /
this . scale = 1 ;
/ * *
* The padding to use between frames . This is helpful to preserve antialiasing on drawn vector content .
* @ property padding
* @ type Number
* @ default 1
* * /
this . padding = 1 ;
/ * *
* A number from 0.01 to 0.99 that indicates what percentage of time the builder can use . This can be
* thought of as the number of seconds per second the builder will use . For example , with a timeSlice value of 0.3 ,
* the builder will run 20 times per second , using approximately 15 ms per build ( 30 % of available time , or 0.3 s per second ) .
* Defaults to 0.3 .
* @ property timeSlice
* @ type Number
* @ default 0.3
* * /
this . timeSlice = 0.3 ;
/ * *
* A value between 0 and 1 that indicates the progress of a build , or - 1 if a build has not
* been initiated .
* @ property progress
* @ type Number
* @ default - 1
* @ readonly
* * /
this . progress = - 1 ;
// private properties:
/ * *
* @ property _frames
* @ protected
* @ type Array
* * /
this . _frames = [ ] ;
/ * *
* @ property _animations
* @ protected
* @ type Array
* * /
this . _animations = { } ;
/ * *
* @ property _data
* @ protected
* @ type Array
* * /
this . _data = null ;
/ * *
* @ property _nextFrameIndex
* @ protected
* @ type Number
* * /
this . _nextFrameIndex = 0 ;
/ * *
* @ property _index
* @ protected
* @ type Number
* * /
this . _index = 0 ;
/ * *
* @ property _timerID
* @ protected
* @ type Number
* * /
this . _timerID = null ;
/ * *
* @ property _scale
* @ protected
* @ type Number
* * /
this . _scale = 1 ;
}
var p = createjs . extend ( SpriteSheetBuilder , createjs . EventDispatcher ) ;
2014-01-03 13:32:13 -05:00
// constants:
SpriteSheetBuilder . ERR _DIMENSIONS = "frame dimensions exceed max spritesheet dimensions" ;
SpriteSheetBuilder . ERR _RUNNING = "a build is already running" ;
// events:
/ * *
* Dispatched when a build completes .
* @ event complete
* @ param { Object } target The object that dispatched the event .
* @ param { String } type The event type .
* @ since 0.6 . 0
* /
/ * *
* Dispatched when an asynchronous build has progress .
2014-11-18 18:26:26 -05:00
* @ event progress
2014-01-03 13:32:13 -05:00
* @ param { Object } target The object that dispatched the event .
* @ param { String } type The event type .
* @ param { Number } progress The current progress value ( 0 - 1 ) .
* @ since 0.6 . 0
2014-11-18 18:26:26 -05:00
* /
2014-01-03 13:32:13 -05:00
// public methods:
/ * *
* Adds a frame to the { { # crossLink "SpriteSheet" } } { { / c r o s s L i n k } } . N o t e t h a t t h e f r a m e w i l l n o t b e d r a w n u n t i l y o u
* call { { # crossLink "SpriteSheetBuilder/build" } } { { / c r o s s L i n k } } m e t h o d . T h e o p t i o n a l s e t u p p a r a m s a l l o w y o u t o h a v e
* a function run immediately before the draw occurs . For example , this allows you to add a single source multiple
* times , but manipulate it or its children to change it to generate different frames .
*
* Note that the source ' s transformations ( x , y , scale , rotate , alpha ) will be ignored , except for regX / Y . To apply
* transforms to a source object and have them captured in the sprite sheet , simply place it into a { { # crossLink "Container" } } { { / c r o s s L i n k } }
* and pass in the Container as the source .
* @ method addFrame
* @ param { DisplayObject } source The source { { # crossLink "DisplayObject" } } { { / c r o s s L i n k } } t o d r a w a s t h e f r a m e .
* @ param { Rectangle } [ sourceRect ] A { { # crossLink "Rectangle" } } { { / c r o s s L i n k } } d e f i n i n g t h e p o r t i o n o f t h e
* source to draw to the frame . If not specified , it will look for a < code > getBounds < / c o d e > m e t h o d , b o u n d s p r o p e r t y ,
* or < code > nominalBounds < / c o d e > p r o p e r t y o n t h e s o u r c e t o u s e . I f o n e i s n o t f o u n d , t h e f r a m e w i l l b e s k i p p e d .
* @ param { Number } [ scale = 1 ] Optional . The scale to draw this frame at . Default is 1.
2014-03-22 12:40:23 -04:00
* @ param { Function } [ setupFunction ] A function to call immediately before drawing this frame . It will be called with two parameters : the source , and setupData .
* @ param { Object } [ setupData ] Arbitrary setup data to pass to setupFunction as the second parameter .
2014-01-03 13:32:13 -05:00
* @ return { Number } The index of the frame that was just added , or null if a sourceRect could not be determined .
* * /
2014-03-22 12:40:23 -04:00
p . addFrame = function ( source , sourceRect , scale , setupFunction , setupData ) {
2014-01-03 13:32:13 -05:00
if ( this . _data ) { throw SpriteSheetBuilder . ERR _RUNNING ; }
var rect = sourceRect || source . bounds || source . nominalBounds ;
if ( ! rect && source . getBounds ) { rect = source . getBounds ( ) ; }
if ( ! rect ) { return null ; }
scale = scale || 1 ;
2014-03-22 12:40:23 -04:00
return this . _frames . push ( { source : source , sourceRect : rect , scale : scale , funct : setupFunction , data : setupData , index : this . _frames . length , height : rect . height * scale } ) - 1 ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Adds an animation that will be included in the created sprite sheet .
* @ method addAnimation
* @ param { String } name The name for the animation .
* @ param { Array } frames An array of frame indexes that comprise the animation . Ex . [ 3 , 6 , 5 ] would describe an animation
* that played frame indexes 3 , 6 , and 5 in that order .
* @ param { String } [ next ] Specifies the name of the animation to continue to after this animation ends . You can
* also pass false to have the animation stop when it ends . By default it will loop to the start of the same animation .
* @ param { Number } [ frequency ] Specifies a frame advance frequency for this animation . For example , a value
* of 2 would cause the animation to advance every second tick .
* * /
p . addAnimation = function ( name , frames , next , frequency ) {
if ( this . _data ) { throw SpriteSheetBuilder . ERR _RUNNING ; }
this . _animations [ name ] = { frames : frames , next : next , frequency : frequency } ;
} ;
/ * *
2014-03-22 12:40:23 -04:00
* This will take a MovieClip instance , and add its frames and labels to this builder . Labels will be added as an animation
2014-01-03 13:32:13 -05:00
* running from the label index to the next label . For example , if there is a label named "foo" at frame 0 and a label
* named "bar" at frame 10 , in a MovieClip with 15 frames , it will add an animation named "foo" that runs from frame
* index 0 to 9 , and an animation named "bar" that runs from frame index 10 to 14.
*
* Note that this will iterate through the full MovieClip with actionsEnabled set to false , ending on the last frame .
* @ method addMovieClip
2014-03-22 12:40:23 -04:00
* @ param { MovieClip } source The source MovieClip instance to add to the sprite sheet .
2014-01-03 13:32:13 -05:00
* @ param { Rectangle } [ sourceRect ] A { { # crossLink "Rectangle" } } { { / c r o s s L i n k } } d e f i n i n g t h e p o r t i o n o f t h e s o u r c e t o
* draw to the frame . If not specified , it will look for a < code > getBounds < / c o d e > m e t h o d , < c o d e > f r a m e B o u n d s < / c o d e >
* Array , < code > bounds < / c o d e > p r o p e r t y , o r < c o d e > n o m i n a l B o u n d s < / c o d e > p r o p e r t y o n t h e s o u r c e t o u s e . I f o n e i s n o t
* found , the MovieClip will be skipped .
* @ param { Number } [ scale = 1 ] The scale to draw the movie clip at .
2014-03-22 12:40:23 -04:00
* @ param { Function } [ setupFunction ] A function to call immediately before drawing each frame . It will be called with three parameters : the source , setupData , and the frame index .
* @ param { Object } [ setupData ] Arbitrary setup data to pass to setupFunction as the second parameter .
* @ param { Function } [ labelFunction ] This method will be called for each movieclip label that is added with four parameters : the label name , the source movieclip instance , the starting frame index ( in the movieclip timeline ) and the end index . It must return a new name for the label / animation , or false to exclude the label .
2014-01-03 13:32:13 -05:00
* * /
2014-03-22 12:40:23 -04:00
p . addMovieClip = function ( source , sourceRect , scale , setupFunction , setupData , labelFunction ) {
2014-01-03 13:32:13 -05:00
if ( this . _data ) { throw SpriteSheetBuilder . ERR _RUNNING ; }
var rects = source . frameBounds ;
var rect = sourceRect || source . bounds || source . nominalBounds ;
if ( ! rect && source . getBounds ) { rect = source . getBounds ( ) ; }
2014-03-22 12:40:23 -04:00
if ( ! rect && ! rects ) { return ; }
2014-01-03 13:32:13 -05:00
2014-03-22 12:40:23 -04:00
var i , l , baseFrameIndex = this . _frames . length ;
2014-01-03 13:32:13 -05:00
var duration = source . timeline . duration ;
2014-03-22 12:40:23 -04:00
for ( i = 0 ; i < duration ; i ++ ) {
2014-01-03 13:32:13 -05:00
var r = ( rects && rects [ i ] ) ? rects [ i ] : rect ;
2014-03-22 12:40:23 -04:00
this . addFrame ( source , r , scale , this . _setupMovieClipFrame , { i : i , f : setupFunction , d : setupData } ) ;
2014-01-03 13:32:13 -05:00
}
var labels = source . timeline . _labels ;
var lbls = [ ] ;
for ( var n in labels ) {
lbls . push ( { index : labels [ n ] , label : n } ) ;
}
if ( lbls . length ) {
lbls . sort ( function ( a , b ) { return a . index - b . index ; } ) ;
2014-03-22 12:40:23 -04:00
for ( i = 0 , l = lbls . length ; i < l ; i ++ ) {
2014-01-03 13:32:13 -05:00
var label = lbls [ i ] . label ;
var start = baseFrameIndex + lbls [ i ] . index ;
var end = baseFrameIndex + ( ( i == l - 1 ) ? duration : lbls [ i + 1 ] . index ) ;
var frames = [ ] ;
for ( var j = start ; j < end ; j ++ ) { frames . push ( j ) ; }
2014-03-22 12:40:23 -04:00
if ( labelFunction ) {
label = labelFunction ( label , source , start , end ) ;
if ( ! label ) { continue ; }
}
2014-01-03 13:32:13 -05:00
this . addAnimation ( label , frames , true ) ; // for now, this loops all animations.
}
}
} ;
/ * *
* Builds a SpriteSheet instance based on the current frames .
* @ method build
* @ return { SpriteSheet } The created SpriteSheet instance , or null if a build is already running or an error occurred .
* * /
p . build = function ( ) {
if ( this . _data ) { throw SpriteSheetBuilder . ERR _RUNNING ; }
this . _startBuild ( ) ;
while ( this . _drawNext ( ) ) { }
this . _endBuild ( ) ;
return this . spriteSheet ;
} ;
/ * *
* Asynchronously builds a { { # crossLink "SpriteSheet" } } { { / c r o s s L i n k } } i n s t a n c e b a s e d o n t h e c u r r e n t f r a m e s . I t w i l l
* run 20 times per second , using an amount of time defined by < code > timeSlice < / c o d e > . W h e n i t i s c o m p l e t e i t w i l l
* call the specified callback .
* @ method buildAsync
* @ param { Number } [ timeSlice ] Sets the timeSlice property on this instance .
* * /
p . buildAsync = function ( timeSlice ) {
if ( this . _data ) { throw SpriteSheetBuilder . ERR _RUNNING ; }
this . timeSlice = timeSlice ;
this . _startBuild ( ) ;
var _this = this ;
this . _timerID = setTimeout ( function ( ) { _this . _run ( ) ; } , 50 - Math . max ( 0.01 , Math . min ( 0.99 , this . timeSlice || 0.3 ) ) * 50 ) ;
} ;
/ * *
* Stops the current asynchronous build .
* @ method stopAsync
* * /
p . stopAsync = function ( ) {
clearTimeout ( this . _timerID ) ;
this . _data = null ;
} ;
/ * *
* SpriteSheetBuilder instances cannot be cloned .
* @ method clone
* * /
p . clone = function ( ) {
throw ( "SpriteSheetBuilder cannot be cloned." ) ;
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[SpriteSheetBuilder]" ;
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
// private methods:
/ * *
* @ method _startBuild
* @ protected
* * /
p . _startBuild = function ( ) {
var pad = this . padding || 0 ;
this . progress = 0 ;
this . spriteSheet = null ;
this . _index = 0 ;
this . _scale = this . scale ;
var dataFrames = [ ] ;
this . _data = {
images : [ ] ,
frames : dataFrames ,
animations : this . _animations // TODO: should we "clone" _animations in case someone adds more animations after a build?
} ;
var frames = this . _frames . slice ( ) ;
frames . sort ( function ( a , b ) { return ( a . height <= b . height ) ? - 1 : 1 ; } ) ;
if ( frames [ frames . length - 1 ] . height + pad * 2 > this . maxHeight ) { throw SpriteSheetBuilder . ERR _DIMENSIONS ; }
var y = 0 , x = 0 ;
var img = 0 ;
while ( frames . length ) {
var o = this . _fillRow ( frames , y , img , dataFrames , pad ) ;
if ( o . w > x ) { x = o . w ; }
y += o . h ;
if ( ! o . h || ! frames . length ) {
var canvas = createjs . createCanvas ? createjs . createCanvas ( ) : document . createElement ( "canvas" ) ;
canvas . width = this . _getSize ( x , this . maxWidth ) ;
canvas . height = this . _getSize ( y , this . maxHeight ) ;
this . _data . images [ img ] = canvas ;
if ( ! o . h ) {
x = y = 0 ;
img ++ ;
}
}
}
} ;
2014-03-22 12:40:23 -04:00
/ * *
* @ method _setupMovieClipFrame
* @ protected
* @ return { Number } The width & height of the row .
* * /
p . _setupMovieClipFrame = function ( source , data ) {
var ae = source . actionsEnabled ;
source . actionsEnabled = false ;
source . gotoAndStop ( data . i ) ;
source . actionsEnabled = ae ;
data . f && data . f ( source , data . d , data . i ) ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
* @ method _getSize
* @ protected
* @ return { Number } The width & height of the row .
* * /
p . _getSize = function ( size , max ) {
var pow = 4 ;
while ( Math . pow ( 2 , ++ pow ) < size ) { }
return Math . min ( max , Math . pow ( 2 , pow ) ) ;
} ;
/ * *
* @ method _fillRow
* @ param { Array } frames
* @ param { Number } y
* @ param { Image } img
* @ param { Object } dataFrames
* @ param { Number } pad
* @ protected
* @ return { Number } The width & height of the row .
* * /
p . _fillRow = function ( frames , y , img , dataFrames , pad ) {
var w = this . maxWidth ;
var maxH = this . maxHeight ;
y += pad ;
var h = maxH - y ;
var x = pad ;
var height = 0 ;
for ( var i = frames . length - 1 ; i >= 0 ; i -- ) {
var frame = frames [ i ] ;
var sc = this . _scale * frame . scale ;
var rect = frame . sourceRect ;
var source = frame . source ;
var rx = Math . floor ( sc * rect . x - pad ) ;
var ry = Math . floor ( sc * rect . y - pad ) ;
var rh = Math . ceil ( sc * rect . height + pad * 2 ) ;
var rw = Math . ceil ( sc * rect . width + pad * 2 ) ;
if ( rw > w ) { throw SpriteSheetBuilder . ERR _DIMENSIONS ; }
if ( rh > h || x + rw > w ) { continue ; }
frame . img = img ;
frame . rect = new createjs . Rectangle ( x , y , rw , rh ) ;
height = height || rh ;
frames . splice ( i , 1 ) ;
dataFrames [ frame . index ] = [ x , y , rw , rh , img , Math . round ( - rx + sc * source . regX - pad ) , Math . round ( - ry + sc * source . regY - pad ) ] ;
x += rw ;
}
return { w : x , h : height } ;
} ;
/ * *
* @ method _endBuild
* @ protected
* * /
p . _endBuild = function ( ) {
this . spriteSheet = new createjs . SpriteSheet ( this . _data ) ;
this . _data = null ;
this . progress = 1 ;
this . dispatchEvent ( "complete" ) ;
} ;
/ * *
* @ method _run
* @ protected
* * /
p . _run = function ( ) {
var ts = Math . max ( 0.01 , Math . min ( 0.99 , this . timeSlice || 0.3 ) ) * 50 ;
var t = ( new Date ( ) ) . getTime ( ) + ts ;
var complete = false ;
while ( t > ( new Date ( ) ) . getTime ( ) ) {
if ( ! this . _drawNext ( ) ) { complete = true ; break ; }
}
if ( complete ) {
this . _endBuild ( ) ;
} else {
var _this = this ;
this . _timerID = setTimeout ( function ( ) { _this . _run ( ) ; } , 50 - ts ) ;
}
var p = this . progress = this . _index / this . _frames . length ;
if ( this . hasEventListener ( "progress" ) ) {
var evt = new createjs . Event ( "progress" ) ;
evt . progress = p ;
this . dispatchEvent ( evt ) ;
}
} ;
/ * *
* @ method _drawNext
* @ protected
* @ return Boolean Returns false if this is the last draw .
* * /
p . _drawNext = function ( ) {
var frame = this . _frames [ this . _index ] ;
var sc = frame . scale * this . _scale ;
var rect = frame . rect ;
var sourceRect = frame . sourceRect ;
var canvas = this . _data . images [ frame . img ] ;
var ctx = canvas . getContext ( "2d" ) ;
2014-03-22 12:40:23 -04:00
frame . funct && frame . funct ( frame . source , frame . data ) ;
2014-01-03 13:32:13 -05:00
ctx . save ( ) ;
ctx . beginPath ( ) ;
ctx . rect ( rect . x , rect . y , rect . width , rect . height ) ;
ctx . clip ( ) ;
ctx . translate ( Math . ceil ( rect . x - sourceRect . x * sc ) , Math . ceil ( rect . y - sourceRect . y * sc ) ) ;
ctx . scale ( sc , sc ) ;
frame . source . draw ( ctx ) ; // display object will draw itself.
ctx . restore ( ) ;
return ( ++ this . _index ) < this . _frames . length ;
} ;
2014-11-18 18:26:26 -05:00
createjs . SpriteSheetBuilder = createjs . promote ( SpriteSheetBuilder , "EventDispatcher" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// DOMElement.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
// constructor:
/ * *
2014-11-18 18:26:26 -05:00
* < b > This class is still experimental , and more advanced use is likely to be buggy . Please report bugs . < / b >
*
* A DOMElement allows you to associate a HTMLElement with the display list . It will be transformed
* within the DOM as though it is child of the { { # crossLink "Container" } } { { / c r o s s L i n k } } i t i s a d d e d t o . H o w e v e r , i t i s
* not rendered to canvas , and as such will retain whatever z - index it has relative to the canvas ( ie . it will be
* drawn in front of or behind the canvas ) .
*
* The position of a DOMElement is relative to their parent node in the DOM . It is recommended that
* the DOM Object be added to a div that also contains the canvas so that they share the same position
* on the page .
*
* DOMElement is useful for positioning HTML elements over top of canvas content , and for elements
* that you want to display outside the bounds of the canvas . For example , a tooltip with rich HTML
* content .
*
* < h4 > Mouse Interaction < / h 4 >
*
* DOMElement instances are not full EaselJS display objects , and do not participate in EaselJS mouse
* events or support methods like hitTest . To get mouse events from a DOMElement , you must instead add handlers to
* the htmlElement ( note , this does not support EventDispatcher )
*
* var domElement = new createjs . DOMElement ( htmlElement ) ;
* domElement . htmlElement . onclick = function ( ) {
* console . log ( "clicked" ) ;
* }
*
* @ class DOMElement
* @ extends DisplayObject
* @ constructor
2014-01-03 13:32:13 -05:00
* @ param { HTMLElement } htmlElement A reference or id for the DOM element to manage .
2014-11-18 18:26:26 -05:00
* /
function DOMElement ( htmlElement ) {
this . DisplayObject _constructor ( ) ;
2014-01-03 13:32:13 -05:00
if ( typeof ( htmlElement ) == "string" ) { htmlElement = document . getElementById ( htmlElement ) ; }
this . mouseEnabled = false ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
var style = htmlElement . style ;
style . position = "absolute" ;
style . transformOrigin = style . WebkitTransformOrigin = style . msTransformOrigin = style . MozTransformOrigin = style . OTransformOrigin = "0% 0%" ;
2014-11-18 18:26:26 -05:00
// public properties:
/ * *
* The DOM object to manage .
* @ property htmlElement
* @ type HTMLElement
* /
this . htmlElement = htmlElement ;
// private properties:
/ * *
* @ property _oldMtx
* @ type Matrix2D
* @ protected
* /
this . _oldProps = null ;
}
var p = createjs . extend ( DOMElement , createjs . DisplayObject ) ;
2014-01-03 13:32:13 -05:00
// public methods:
/ * *
* Returns true or false indicating whether the display object would be visible if drawn to a canvas .
* This does not account for whether it would be visible within the boundaries of the stage .
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method isVisible
* @ return { Boolean } Boolean indicating whether the display object would be visible if drawn to a canvas
* /
p . isVisible = function ( ) {
return this . htmlElement != null ;
} ;
/ * *
* Draws the display object into the specified context ignoring its visible , alpha , shadow , and transform .
* Returns true if the draw was handled ( useful for overriding functionality ) .
* NOTE : This method is mainly for internal use , though it may be useful for advanced uses .
* @ method draw
* @ param { CanvasRenderingContext2D } ctx The canvas 2 D context object to draw into .
* @ param { Boolean } ignoreCache Indicates whether the draw operation should ignore any current cache .
* For example , used for drawing the cache ( to prevent it from simply drawing an existing cache back
* into itself ) .
* @ return { Boolean }
* /
p . draw = function ( ctx , ignoreCache ) {
2014-11-18 18:26:26 -05:00
// this relies on the _tick method because draw isn't called if the parent is not visible.
2014-01-03 13:32:13 -05:00
// the actual update happens in _handleDrawEnd
return true ;
} ;
/ * *
* Not applicable to DOMElement .
* @ method cache
* /
p . cache = function ( ) { } ;
/ * *
* Not applicable to DOMElement .
* @ method uncache
* /
p . uncache = function ( ) { } ;
/ * *
* Not applicable to DOMElement .
* @ method updateCache
* /
p . updateCache = function ( ) { } ;
/ * *
* Not applicable to DOMElement .
* @ method hitTest
* /
p . hitTest = function ( ) { } ;
/ * *
* Not applicable to DOMElement .
* @ method localToGlobal
* /
p . localToGlobal = function ( ) { } ;
/ * *
* Not applicable to DOMElement .
* @ method globalToLocal
* /
p . globalToLocal = function ( ) { } ;
/ * *
* Not applicable to DOMElement .
* @ method localToLocal
* /
p . localToLocal = function ( ) { } ;
/ * *
* DOMElement cannot be cloned . Throws an error .
* @ method clone
* /
p . clone = function ( ) {
throw ( "DOMElement cannot be cloned." )
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* /
p . toString = function ( ) {
return "[DOMElement (name=" + this . name + ")]" ;
} ;
/ * *
* Interaction events should be added to ` htmlElement ` , and not the DOMElement instance , since DOMElement instances
* are not full EaselJS display objects and do not participate in EaselJS mouse events .
* @ event click
* /
/ * *
* Interaction events should be added to ` htmlElement ` , and not the DOMElement instance , since DOMElement instances
* are not full EaselJS display objects and do not participate in EaselJS mouse events .
* @ event dblClick
* /
/ * *
* Interaction events should be added to ` htmlElement ` , and not the DOMElement instance , since DOMElement instances
* are not full EaselJS display objects and do not participate in EaselJS mouse events .
* @ event mousedown
* /
/ * *
* The HTMLElement can listen for the mouseover event , not the DOMElement instance .
* Since DOMElement instances are not full EaselJS display objects and do not participate in EaselJS mouse events .
* @ event mouseover
* /
/ * *
* Not applicable to DOMElement .
* @ event tick
* /
// private methods:
/ * *
* @ method _tick
2014-11-18 18:26:26 -05:00
* @ 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 .
2014-01-03 13:32:13 -05:00
* function .
* @ protected
* /
2014-11-18 18:26:26 -05:00
p . _tick = function ( evtObj ) {
2014-01-03 13:32:13 -05:00
var stage = this . getStage ( ) ;
stage && stage . on ( "drawend" , this . _handleDrawEnd , this , true ) ;
2014-11-18 18:26:26 -05:00
this . DisplayObject _ _tick ( evtObj ) ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* @ method _handleDrawEnd
* @ param { Event } evt
* @ protected
* /
p . _handleDrawEnd = function ( evt ) {
var o = this . htmlElement ;
if ( ! o ) { return ; }
var style = o . style ;
2014-11-18 18:26:26 -05:00
var props = this . getConcatenatedDisplayProps ( this . _props ) , mtx = props . matrix ;
2014-02-02 19:31:06 -05:00
2014-11-18 18:26:26 -05:00
var visibility = props . visible ? "visible" : "hidden" ;
2014-01-03 13:32:13 -05:00
if ( visibility != style . visibility ) { style . visibility = visibility ; }
2014-11-18 18:26:26 -05:00
if ( ! props . visible ) { return ; }
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
var oldProps = this . _oldProps , oldMtx = oldProps && oldProps . matrix ;
2014-01-03 13:32:13 -05:00
var n = 10000 ; // precision
2014-11-18 18:26:26 -05:00
if ( ! oldMtx || ! oldMtx . equals ( mtx ) ) {
2014-01-03 13:32:13 -05:00
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 ) ;
style . transform = style . WebkitTransform = style . OTransform = style . msTransform = str + "," + ( mtx . ty + 0.5 | 0 ) + ")" ;
style . MozTransform = str + "px," + ( mtx . ty + 0.5 | 0 ) + "px)" ;
2014-11-18 18:26:26 -05:00
if ( ! oldProps ) { oldProps = this . _oldProps = new createjs . DisplayProps ( true , NaN ) ; }
oldProps . matrix . copy ( mtx ) ;
}
if ( oldProps . alpha != props . alpha ) {
style . opacity = "" + ( props . alpha * n | 0 ) / n ;
oldProps . alpha = props . alpha ;
2014-01-03 13:32:13 -05:00
}
} ;
2014-11-18 18:26:26 -05:00
createjs . DOMElement = createjs . promote ( DOMElement , "DisplayObject" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// Filter.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
// constructor:
/ * *
2014-11-18 18:26:26 -05:00
* Base class that all filters should inherit from . Filters need to be applied to objects that have been cached using
* the { { # crossLink "DisplayObject/cache" } } { { / c r o s s L i n k } } m e t h o d . I f a n o b j e c t c h a n g e s , p l e a s e c a c h e i t a g a i n , o r u s e
* { { # crossLink "DisplayObject/updateCache" } } { { / c r o s s L i n k } } . N o t e t h a t t h e f i l t e r s m u s t b e a p p l i e d b e f o r e c a c h i n g .
*
* < h4 > Example < / h 4 >
*
* myInstance . filters = [
* new createjs . ColorFilter ( 0 , 0 , 0 , 1 , 255 , 0 , 0 ) ,
* new createjs . BlurFilter ( 5 , 5 , 10 )
* ] ;
* myInstance . cache ( 0 , 0 , 100 , 100 ) ;
*
* Note that each filter can implement a { { # crossLink "Filter/getBounds" } } { { / c r o s s L i n k } } m e t h o d , w h i c h r e t u r n s t h e
* margins that need to be applied in order to fully display the filter . For example , the { { # crossLink "BlurFilter" } } { { / c r o s s L i n k } }
* will cause an object to feather outwards , resulting in a margin around the shape .
*
* < h4 > EaselJS Filters < / h 4 >
* EaselJS comes with a number of pre - built filters . Note that individual filters are not compiled into the minified
* version of EaselJS . To use them , you must include them manually in the HTML .
* < ul > < li > { { # crossLink "AlphaMapFilter" } } { { / c r o s s L i n k } } : M a p a g r e y s c a l e i m a g e t o t h e a l p h a c h a n n e l o f a d i s p l a y o b j e c t < / l i >
* < li > { { # crossLink "AlphaMaskFilter" } } { { / c r o s s L i n k } } : M a p a n i m a g e ' s a l p h a c h a n n e l t o t h e a l p h a c h a n n e l o f a d i s p l a y o b j e c t < / l i >
* < li > { { # crossLink "BlurFilter" } } { { / c r o s s L i n k } } : A p p l y v e r t i c a l a n d h o r i z o n t a l b l u r t o a d i s p l a y o b j e c t < / l i >
* < li > { { # crossLink "ColorFilter" } } { { / c r o s s L i n k } } : C o l o r t r a n s f o r m a d i s p l a y o b j e c t < / l i >
* < li > { { # crossLink "ColorMatrixFilter" } } { { / c r o s s L i n k } } : T r a n s f o r m a n i m a g e u s i n g a { { # c r o s s L i n k " C o l o r M a t r i x " } } { { / c r o s s L i n k } } < / l i >
* < / u l >
*
* @ class Filter
* @ constructor
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
function Filter ( ) { }
var p = Filter . prototype ;
2014-01-03 13:32:13 -05:00
// public methods:
/ * *
* Returns a rectangle with values indicating the margins required to draw the filter or null .
* For example , a filter that will extend the drawing area 4 pixels to the left , and 7 pixels to the right
* ( but no pixels up or down ) would return a rectangle with ( x = - 4 , y = 0 , width = 11 , height = 0 ) .
* @ method getBounds
* @ return { Rectangle } a rectangle object indicating the margins required to draw the filter or null if the filter does not effect bounds .
* * /
p . getBounds = function ( ) {
return null ;
} ;
/ * *
* Applies the filter to the specified context .
* @ method applyFilter
* @ param { CanvasRenderingContext2D } ctx The 2 D context to use as the source .
* @ param { Number } x The x position to use for the source rect .
* @ param { Number } y The y position to use for the source rect .
* @ param { Number } width The width to use for the source rect .
* @ param { Number } height The height to use for the source rect .
* @ param { CanvasRenderingContext2D } [ targetCtx ] The 2 D context to draw the result to . Defaults to the context passed to ctx .
* @ param { Number } [ targetX ] The x position to draw the result to . Defaults to the value passed to x .
* @ param { Number } [ targetY ] The y position to draw the result to . Defaults to the value passed to y .
* @ return { Boolean } If the filter was applied successfully .
* * /
2014-11-18 18:26:26 -05:00
p . applyFilter = function ( ctx , x , y , width , height , targetCtx , targetX , targetY ) {
// this is the default behaviour because most filters access pixel data. It is overridden when not needed.
targetCtx = targetCtx || ctx ;
if ( targetX == null ) { targetX = x ; }
if ( targetY == null ) { targetY = y ; }
try {
var imageData = ctx . getImageData ( x , y , width , height ) ;
} catch ( e ) {
return false ;
}
if ( this . _applyFilter ( imageData ) ) {
targetCtx . putImageData ( imageData , targetX , targetY ) ;
return true ;
}
return false ;
} ;
2014-01-03 13:32:13 -05:00
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[Filter]" ;
} ;
/ * *
* Returns a clone of this Filter instance .
* @ method clone
* @ return { Filter } A clone of the current Filter instance .
* * /
p . clone = function ( ) {
return new Filter ( ) ;
} ;
2014-11-18 18:26:26 -05:00
// private methods:
/ * *
* @ method _applyFilter
* @ param { ImageData } imageData Target ImageData instance .
* @ return { Boolean }
* * /
p . _applyFilter = function ( imageData ) { return true ; } ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
createjs . Filter = Filter ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// BlurFilter.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
// constructor:
2014-11-18 18:26:26 -05:00
/ * *
* Applies a box blur to DisplayObjects . Note that this filter is fairly CPU intensive , particularly if the quality is
* set higher than 1.
*
* < h4 > Example < / h 4 >
* This example creates a red circle , and then applies a 5 pixel blur to it . It uses the { { # crossLink "Filter/getBounds" } } { { / c r o s s L i n k } }
* method to account for the spread that the blur causes .
*
* var shape = new createjs . Shape ( ) . set ( { x : 100 , y : 100 } ) ;
* shape . graphics . beginFill ( "#ff0000" ) . drawCircle ( 0 , 0 , 50 ) ;
*
* var blurFilter = new createjs . BlurFilter ( 5 , 5 , 1 ) ;
* shape . filters = [ blurFilter ] ;
* var bounds = blurFilter . getBounds ( ) ;
*
* shape . cache ( - 50 + bounds . x , - 50 + bounds . y , 100 + bounds . width , 100 + bounds . height ) ;
*
* See { { # crossLink "Filter" } } { { / c r o s s L i n k } } f o r a n m o r e i n f o r m a t i o n o n a p p l y i n g f i l t e r s .
* @ class BlurFilter
* @ extends Filter
* @ constructor
* @ param { Number } [ blurX = 0 ] The horizontal blur radius in pixels .
* @ param { Number } [ blurY = 0 ] The vertical blur radius in pixels .
* @ param { Number } [ quality = 1 ] The number of blur iterations .
* * /
function BlurFilter ( blurX , blurY , quality ) {
2014-01-03 13:32:13 -05:00
if ( isNaN ( blurX ) || blurX < 0 ) blurX = 0 ;
if ( isNaN ( blurY ) || blurY < 0 ) blurY = 0 ;
if ( isNaN ( quality ) || quality < 1 ) quality = 1 ;
2014-11-18 18:26:26 -05:00
// public properties:
/ * *
* Horizontal blur radius in pixels
* @ property blurX
* @ default 0
* @ type Number
* * /
this . blurX = blurX | 0 ;
/ * *
* Vertical blur radius in pixels
* @ property blurY
* @ default 0
* @ type Number
* * /
this . blurY = blurY | 0 ;
/ * *
* Number of blur iterations . For example , a value of 1 will produce a rough blur . A value of 2 will produce a
* smoother blur , but take twice as long to run .
* @ property quality
* @ default 1
* @ type Number
* * /
2014-01-03 13:32:13 -05:00
this . quality = quality | 0 ;
2014-11-18 18:26:26 -05:00
}
var p = createjs . extend ( BlurFilter , createjs . Filter ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// constants:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Array of multiply values for blur calculations .
* @ property MUL _TABLE
* @ type Array
* @ protected
* @ static
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
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 ] ;
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Array of shift values for blur calculations .
* @ property SHG _TABLE
* @ type Array
* @ protected
* @ static
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
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 ] ;
2014-01-03 13:32:13 -05:00
// public methods:
/** docced in super class **/
p . getBounds = function ( ) {
var q = Math . pow ( this . quality , 0.6 ) * 0.5 ;
return new createjs . Rectangle ( - this . blurX * q , - this . blurY * q , 2 * this . blurX * q , 2 * this . blurY * q ) ;
} ;
2014-11-18 18:26:26 -05:00
/** docced in super class **/
p . clone = function ( ) {
return new BlurFilter ( this . blurX , this . blurY , this . quality ) ;
} ;
/** docced in super class **/
p . toString = function ( ) {
return "[BlurFilter]" ;
} ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// private methods:
/** docced in super class **/
p . _applyFilter = function ( imageData ) {
2014-01-03 13:32:13 -05:00
var radiusX = this . blurX / 2 ;
2014-11-18 18:26:26 -05:00
if ( isNaN ( radiusX ) || radiusX < 0 ) { return false ; }
2014-01-03 13:32:13 -05:00
radiusX |= 0 ;
var radiusY = this . blurY / 2 ;
2014-11-18 18:26:26 -05:00
if ( isNaN ( radiusY ) || radiusY < 0 ) { return false ; }
2014-01-03 13:32:13 -05:00
radiusY |= 0 ;
2014-11-18 18:26:26 -05:00
if ( radiusX == 0 && radiusY == 0 ) { return false ; }
2014-01-03 13:32:13 -05:00
var iterations = this . quality ;
2014-11-18 18:26:26 -05:00
if ( isNaN ( iterations ) || iterations < 1 ) { iterations = 1 ; }
2014-01-03 13:32:13 -05:00
iterations |= 0 ;
2014-11-18 18:26:26 -05:00
if ( iterations > 3 ) { iterations = 3 ; }
if ( iterations < 1 ) { iterations = 1 ; }
var pixels = imageData . data , width = imageData . width , height = imageData . height ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// TODO: there are a lot of unused variables in this method:
var x , y , i , p , yp , yi , yw , r _sum , g _sum , b _sum , a _sum , pr , pg , pb , pa ;
2014-01-03 13:32:13 -05:00
var divx = radiusX + radiusX + 1 ;
var divy = radiusY + radiusY + 1 ;
var widthMinus1 = width - 1 ;
var heightMinus1 = height - 1 ;
var rxp1 = radiusX + 1 ;
var ryp1 = radiusY + 1 ;
var stackStartX = { r : 0 , b : 0 , g : 0 , a : 0 , next : null } ;
var stackx = stackStartX ;
for ( i = 1 ; i < divx ; i ++ )
{
stackx = stackx . next = { r : 0 , b : 0 , g : 0 , a : 0 , next : null } ;
}
stackx . next = stackStartX ;
var stackStartY = { r : 0 , b : 0 , g : 0 , a : 0 , next : null } ;
var stacky = stackStartY ;
for ( i = 1 ; i < divy ; i ++ )
{
stacky = stacky . next = { r : 0 , b : 0 , g : 0 , a : 0 , next : null } ;
}
stacky . next = stackStartY ;
var stackIn = null ;
2014-11-18 18:26:26 -05:00
var mul _table = BlurFilter . MUL _TABLE ;
var shg _table = BlurFilter . SHG _TABLE ;
2014-01-03 13:32:13 -05:00
while ( iterations -- > 0 ) {
yw = yi = 0 ;
2014-11-18 18:26:26 -05:00
var mul _sum = mul _table [ radiusX ] ;
var shg _sum = shg _table [ radiusX ] ;
2014-01-03 13:32:13 -05:00
for ( y = height ; -- y > - 1 ; )
{
r _sum = rxp1 * ( pr = pixels [ yi ] ) ;
g _sum = rxp1 * ( pg = pixels [ yi + 1 ] ) ;
b _sum = rxp1 * ( pb = pixels [ yi + 2 ] ) ;
a _sum = rxp1 * ( pa = pixels [ yi + 3 ] ) ;
stackx = stackStartX ;
for ( i = rxp1 ; -- i > - 1 ; )
{
stackx . r = pr ;
stackx . g = pg ;
stackx . b = pb ;
stackx . a = pa ;
stackx = stackx . next ;
}
for ( i = 1 ; i < rxp1 ; i ++ )
{
p = yi + ( ( widthMinus1 < i ? widthMinus1 : i ) << 2 ) ;
r _sum += ( stackx . r = pixels [ p ] ) ;
g _sum += ( stackx . g = pixels [ p + 1 ] ) ;
b _sum += ( stackx . b = pixels [ p + 2 ] ) ;
a _sum += ( stackx . a = pixels [ p + 3 ] ) ;
stackx = stackx . next ;
}
stackIn = stackStartX ;
for ( x = 0 ; x < width ; x ++ )
{
pixels [ yi ++ ] = ( r _sum * mul _sum ) >>> shg _sum ;
pixels [ yi ++ ] = ( g _sum * mul _sum ) >>> shg _sum ;
pixels [ yi ++ ] = ( b _sum * mul _sum ) >>> shg _sum ;
pixels [ yi ++ ] = ( a _sum * mul _sum ) >>> shg _sum ;
p = ( yw + ( ( p = x + radiusX + 1 ) < widthMinus1 ? p : widthMinus1 ) ) << 2 ;
r _sum -= stackIn . r - ( stackIn . r = pixels [ p ] ) ;
g _sum -= stackIn . g - ( stackIn . g = pixels [ p + 1 ] ) ;
b _sum -= stackIn . b - ( stackIn . b = pixels [ p + 2 ] ) ;
a _sum -= stackIn . a - ( stackIn . a = pixels [ p + 3 ] ) ;
stackIn = stackIn . next ;
}
yw += width ;
}
2014-11-18 18:26:26 -05:00
mul _sum = mul _table [ radiusY ] ;
shg _sum = shg _table [ radiusY ] ;
2014-01-03 13:32:13 -05:00
for ( x = 0 ; x < width ; x ++ )
{
yi = x << 2 ;
r _sum = ryp1 * ( pr = pixels [ yi ] ) ;
g _sum = ryp1 * ( pg = pixels [ yi + 1 ] ) ;
b _sum = ryp1 * ( pb = pixels [ yi + 2 ] ) ;
a _sum = ryp1 * ( pa = pixels [ yi + 3 ] ) ;
stacky = stackStartY ;
for ( i = 0 ; i < ryp1 ; i ++ )
{
stacky . r = pr ;
stacky . g = pg ;
stacky . b = pb ;
stacky . a = pa ;
stacky = stacky . next ;
}
yp = width ;
for ( i = 1 ; i <= radiusY ; i ++ )
{
yi = ( yp + x ) << 2 ;
r _sum += ( stacky . r = pixels [ yi ] ) ;
g _sum += ( stacky . g = pixels [ yi + 1 ] ) ;
b _sum += ( stacky . b = pixels [ yi + 2 ] ) ;
a _sum += ( stacky . a = pixels [ yi + 3 ] ) ;
stacky = stacky . next ;
if ( i < heightMinus1 )
{
yp += width ;
}
}
yi = x ;
stackIn = stackStartY ;
if ( iterations > 0 )
{
for ( y = 0 ; y < height ; y ++ )
{
p = yi << 2 ;
pixels [ p + 3 ] = pa = ( a _sum * mul _sum ) >>> shg _sum ;
if ( pa > 0 )
{
pixels [ p ] = ( ( r _sum * mul _sum ) >>> shg _sum ) ;
pixels [ p + 1 ] = ( ( g _sum * mul _sum ) >>> shg _sum ) ;
pixels [ p + 2 ] = ( ( b _sum * mul _sum ) >>> shg _sum ) ;
} else {
pixels [ p ] = pixels [ p + 1 ] = pixels [ p + 2 ] = 0
}
p = ( x + ( ( ( p = y + ryp1 ) < heightMinus1 ? p : heightMinus1 ) * width ) ) << 2 ;
r _sum -= stackIn . r - ( stackIn . r = pixels [ p ] ) ;
g _sum -= stackIn . g - ( stackIn . g = pixels [ p + 1 ] ) ;
b _sum -= stackIn . b - ( stackIn . b = pixels [ p + 2 ] ) ;
a _sum -= stackIn . a - ( stackIn . a = pixels [ p + 3 ] ) ;
stackIn = stackIn . next ;
yi += width ;
}
} else {
for ( y = 0 ; y < height ; y ++ )
{
p = yi << 2 ;
pixels [ p + 3 ] = pa = ( a _sum * mul _sum ) >>> shg _sum ;
if ( pa > 0 )
{
pa = 255 / pa ;
pixels [ p ] = ( ( r _sum * mul _sum ) >>> shg _sum ) * pa ;
pixels [ p + 1 ] = ( ( g _sum * mul _sum ) >>> shg _sum ) * pa ;
pixels [ p + 2 ] = ( ( b _sum * mul _sum ) >>> shg _sum ) * pa ;
} else {
pixels [ p ] = pixels [ p + 1 ] = pixels [ p + 2 ] = 0
}
p = ( x + ( ( ( p = y + ryp1 ) < heightMinus1 ? p : heightMinus1 ) * width ) ) << 2 ;
r _sum -= stackIn . r - ( stackIn . r = pixels [ p ] ) ;
g _sum -= stackIn . g - ( stackIn . g = pixels [ p + 1 ] ) ;
b _sum -= stackIn . b - ( stackIn . b = pixels [ p + 2 ] ) ;
a _sum -= stackIn . a - ( stackIn . a = pixels [ p + 3 ] ) ;
stackIn = stackIn . next ;
yi += width ;
}
}
}
}
return true ;
} ;
2014-11-18 18:26:26 -05:00
createjs . BlurFilter = createjs . promote ( BlurFilter , "Filter" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// AlphaMapFilter.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
* Applies a greyscale alpha map image ( or canvas ) to the target , such that the alpha channel of the result will
* be copied from the red channel of the map , and the RGB channels will be copied from the target .
*
* Generally , it is recommended that you use { { # crossLink "AlphaMaskFilter" } } { { / c r o s s L i n k } } , b e c a u s e i t h a s m u c h
* better performance .
*
* < h4 > Example < / h 4 >
* This example draws a red - > blue box , caches it , and then uses the cache canvas as an alpha map on a 100 x100 image .
*
* var box = new createjs . Shape ( ) ;
* box . graphics . beginLinearGradientFill ( [ "#ff0000" , "#0000ff" ] , [ 0 , 1 ] , 0 , 0 , 0 , 100 )
* box . graphics . drawRect ( 0 , 0 , 100 , 100 ) ;
* box . cache ( 0 , 0 , 100 , 100 ) ;
*
* var bmp = new createjs . Bitmap ( "path/to/image.jpg" ) ;
* bmp . filters = [
* new createjs . AlphaMapFilter ( box . cacheCanvas )
* ] ;
* bmp . cache ( 0 , 0 , 100 , 100 ) ;
* stage . addChild ( bmp ) ;
*
* See { { # crossLink "Filter" } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n o n a p p l y i n g f i l t e r s .
* @ class AlphaMapFilter
* @ extends Filter
* @ constructor
* @ param { Image | HTMLCanvasElement } alphaMap The greyscale image ( or canvas ) to use as the alpha value for the
* result . This should be exactly the same dimensions as the target .
* * /
2014-11-18 18:26:26 -05:00
function AlphaMapFilter ( alphaMap ) {
// public properties:
/ * *
* The greyscale image ( or canvas ) to use as the alpha value for the result . This should be exactly the same
* dimensions as the target .
* @ property alphaMap
* @ type Image | HTMLCanvasElement
* * /
2014-01-03 13:32:13 -05:00
this . alphaMap = alphaMap ;
2014-11-18 18:26:26 -05:00
// private properties:
/ * *
* @ property _alphaMap
* @ protected
* @ type Image | HTMLCanvasElement
* * /
this . _alphaMap = null ;
/ * *
* @ property _mapData
* @ protected
* @ type Uint8ClampedArray
* * /
this . _mapData = null ;
}
var p = createjs . extend ( AlphaMapFilter , createjs . Filter ) ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// public methods:
/** docced in super class **/
2014-01-03 13:32:13 -05:00
p . clone = function ( ) {
2014-11-18 18:26:26 -05:00
var o = new AlphaMapFilter ( this . alphaMap ) ;
o . _alphaMap = this . _alphaMap ;
o . _mapData = this . _mapData ;
return o ;
2014-01-03 13:32:13 -05:00
} ;
2014-11-18 18:26:26 -05:00
/** docced in super class **/
2014-01-03 13:32:13 -05:00
p . toString = function ( ) {
return "[AlphaMapFilter]" ;
} ;
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
// private methods:
2014-11-18 18:26:26 -05:00
/** docced in super class **/
p . _applyFilter = function ( imageData ) {
if ( ! this . alphaMap ) { return true ; }
if ( ! this . _prepAlphaMap ( ) ) { return false ; }
// TODO: update to support scenarios where the target has different dimensions.
var data = imageData . data ;
var map = this . _mapData ;
for ( var i = 0 , l = data . length ; i < l ; i += 4 ) { data [ i + 3 ] = map [ i ] || 0 ; }
return true ;
} ;
/ * *
* @ method _prepAlphaMap
* @ protected
* * /
2014-01-03 13:32:13 -05:00
p . _prepAlphaMap = function ( ) {
2014-11-18 18:26:26 -05:00
if ( ! this . alphaMap ) { return false ; }
if ( this . alphaMap == this . _alphaMap && this . _mapData ) { return true ; }
2014-01-03 13:32:13 -05:00
this . _mapData = null ;
var map = this . _alphaMap = this . alphaMap ;
var canvas = map ;
var ctx ;
if ( map instanceof HTMLCanvasElement ) {
ctx = canvas . getContext ( "2d" ) ;
} else {
canvas = createjs . createCanvas ? createjs . createCanvas ( ) : document . createElement ( "canvas" ) ;
canvas . width = map . width ;
canvas . height = map . height ;
ctx = canvas . getContext ( "2d" ) ;
ctx . drawImage ( map , 0 , 0 ) ;
}
try {
var imgData = ctx . getImageData ( 0 , 0 , map . width , map . height ) ;
} catch ( e ) {
//if (!this.suppressCrossDomainErrors) throw new Error("unable to access local image data: " + e);
return false ;
}
2014-11-18 18:26:26 -05:00
2014-01-03 13:32:13 -05:00
this . _mapData = imgData . data ;
return true ;
} ;
2014-11-18 18:26:26 -05:00
createjs . AlphaMapFilter = createjs . promote ( AlphaMapFilter , "Filter" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// AlphaMaskFilter.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
* Applies the alpha from the mask image ( or canvas ) to the target , such that the alpha channel of the result will
* be derived from the mask , and the RGB channels will be copied from the target . This can be used , for example , to
* apply an alpha mask to a display object . This can also be used to combine a JPG compressed RGB image with a PNG32
* alpha mask , which can result in a much smaller file size than a single PNG32 containing ARGB .
*
* < b > IMPORTANT NOTE : This filter currently does not support the targetCtx , or targetX / Y parameters correctly . < / b >
*
* < h4 > Example < / h 4 >
* This example draws a gradient box , then caches it and uses the "cacheCanvas" as the alpha mask on a 100 x100 image .
*
* var box = new createjs . Shape ( ) ;
* box . graphics . beginLinearGradientFill ( [ "#000000" , "rgba(0, 0, 0, 0)" ] , [ 0 , 1 ] , 0 , 0 , 100 , 100 )
* box . graphics . drawRect ( 0 , 0 , 100 , 100 ) ;
* box . cache ( 0 , 0 , 100 , 100 ) ;
*
* var bmp = new createjs . Bitmap ( "path/to/image.jpg" ) ;
* bmp . filters = [
* new createjs . AlphaMaskFilter ( box . cacheCanvas )
* ] ;
* bmp . cache ( 0 , 0 , 100 , 100 ) ;
*
* See { { # crossLink "Filter" } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n o n a p p l y i n g f i l t e r s .
* @ class AlphaMaskFilter
* @ extends Filter
* @ constructor
* @ param { Image } mask
* * /
2014-11-18 18:26:26 -05:00
function AlphaMaskFilter ( mask ) {
// public properties:
/ * *
* The image ( or canvas ) to use as the mask .
* @ property mask
* @ type Image
* * /
2014-01-03 13:32:13 -05:00
this . mask = mask ;
2014-11-18 18:26:26 -05:00
}
var p = createjs . extend ( AlphaMaskFilter , createjs . Filter ) ;
2014-01-03 13:32:13 -05:00
// public methods:
/ * *
* Applies the filter to the specified context .
*
* < strong > IMPORTANT NOTE : This filter currently does not support the targetCtx , or targetX / Y parameters
* correctly . < / s t r o n g >
* @ method applyFilter
* @ param { CanvasRenderingContext2D } ctx The 2 D context to use as the source .
* @ param { Number } x The x position to use for the source rect .
* @ param { Number } y The y position to use for the source rect .
* @ param { Number } width The width to use for the source rect .
* @ param { Number } height The height to use for the source rect .
2014-11-18 18:26:26 -05:00
* @ param { CanvasRenderingContext2D } [ targetCtx ] NOT SUPPORTED IN THIS FILTER . The 2 D context to draw the result to . Defaults to the context passed to ctx .
* @ param { Number } [ targetX ] NOT SUPPORTED IN THIS FILTER . The x position to draw the result to . Defaults to the value passed to x .
* @ param { Number } [ targetY ] NOT SUPPORTED IN THIS FILTER . The y position to draw the result to . Defaults to the value passed to y .
2014-01-03 13:32:13 -05:00
* @ return { Boolean } If the filter was applied successfully .
* * /
p . applyFilter = function ( ctx , x , y , width , height , targetCtx , targetX , targetY ) {
2014-11-18 18:26:26 -05:00
if ( ! this . mask ) { return true ; }
2014-01-03 13:32:13 -05:00
targetCtx = targetCtx || ctx ;
2014-11-18 18:26:26 -05:00
if ( targetX == null ) { targetX = x ; }
if ( targetY == null ) { targetY = y ; }
2014-01-03 13:32:13 -05:00
targetCtx . save ( ) ;
if ( ctx != targetCtx ) {
// TODO: support targetCtx and targetX/Y
// clearRect, then draw the ctx in?
2014-11-18 18:26:26 -05:00
return false ;
2014-01-03 13:32:13 -05:00
}
targetCtx . globalCompositeOperation = "destination-in" ;
targetCtx . drawImage ( this . mask , targetX , targetY ) ;
targetCtx . restore ( ) ;
return true ;
} ;
2014-11-18 18:26:26 -05:00
/** docced in super class **/
2014-01-03 13:32:13 -05:00
p . clone = function ( ) {
return new AlphaMaskFilter ( this . mask ) ;
} ;
2014-11-18 18:26:26 -05:00
/** docced in super class **/
2014-01-03 13:32:13 -05:00
p . toString = function ( ) {
return "[AlphaMaskFilter]" ;
} ;
2014-11-18 18:26:26 -05:00
createjs . AlphaMaskFilter = createjs . promote ( AlphaMaskFilter , "Filter" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// ColorFilter.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
// constructor:
/ * *
2014-11-18 18:26:26 -05:00
* Applies a color transform to DisplayObjects .
*
* < h4 > Example < / h 4 >
* This example draws a red circle , and then transforms it to Blue . This is accomplished by multiplying all the channels
* to 0 ( except alpha , which is set to 1 ) , and then adding 255 to the blue channel .
*
* var shape = new createjs . Shape ( ) . set ( { x : 100 , y : 100 } ) ;
* shape . graphics . beginFill ( "#ff0000" ) . drawCircle ( 0 , 0 , 50 ) ;
*
* shape . filters = [
* new createjs . ColorFilter ( 0 , 0 , 0 , 1 , 0 , 0 , 255 , 0 )
* ] ;
* shape . cache ( - 50 , - 50 , 100 , 100 ) ;
*
* See { { # crossLink "Filter" } } { { / c r o s s L i n k } } f o r a n m o r e i n f o r m a t i o n o n a p p l y i n g f i l t e r s .
* @ class ColorFilter
2014-01-03 13:32:13 -05:00
* @ param { Number } [ redMultiplier = 1 ] The amount to multiply against the red channel . This is a range between 0 and 1.
* @ param { Number } [ greenMultiplier = 1 ] The amount to multiply against the green channel . This is a range between 0 and 1.
* @ param { Number } [ blueMultiplier = 1 ] The amount to multiply against the blue channel . This is a range between 0 and 1.
* @ param { Number } [ alphaMultiplier = 1 ] The amount to multiply against the alpha channel . This is a range between 0 and 1.
* @ param { Number } [ redOffset = 0 ] The amount to add to the red channel after it has been multiplied . This is a range
* between - 255 and 255.
* @ param { Number } [ greenOffset = 0 ] The amount to add to the green channel after it has been multiplied . This is a range
2014-11-18 18:26:26 -05:00
* between - 255 and 255.
2014-01-03 13:32:13 -05:00
* @ param { Number } [ blueOffset = 0 ] The amount to add to the blue channel after it has been multiplied . This is a range
2014-11-18 18:26:26 -05:00
* between - 255 and 255.
2014-01-03 13:32:13 -05:00
* @ param { Number } [ alphaOffset = 0 ] The amount to add to the alpha channel after it has been multiplied . This is a range
2014-11-18 18:26:26 -05:00
* between - 255 and 255.
* @ constructor
* @ extends Filter
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
function ColorFilter ( redMultiplier , greenMultiplier , blueMultiplier , alphaMultiplier , redOffset , greenOffset , blueOffset , alphaOffset ) {
// public properties:
/ * *
* Red channel multiplier .
* @ property redMultiplier
* @ type Number
* * /
2014-01-03 13:32:13 -05:00
this . redMultiplier = redMultiplier != null ? redMultiplier : 1 ;
2014-11-18 18:26:26 -05:00
/ * *
* Green channel multiplier .
* @ property greenMultiplier
* @ type Number
* * /
2014-01-03 13:32:13 -05:00
this . greenMultiplier = greenMultiplier != null ? greenMultiplier : 1 ;
2014-11-18 18:26:26 -05:00
/ * *
* Blue channel multiplier .
* @ property blueMultiplier
* @ type Number
* * /
2014-01-03 13:32:13 -05:00
this . blueMultiplier = blueMultiplier != null ? blueMultiplier : 1 ;
2014-11-18 18:26:26 -05:00
/ * *
* Alpha channel multiplier .
* @ property alphaMultiplier
* @ type Number
* * /
2014-01-03 13:32:13 -05:00
this . alphaMultiplier = alphaMultiplier != null ? alphaMultiplier : 1 ;
2014-11-18 18:26:26 -05:00
/ * *
* Red channel offset ( added to value ) .
* @ property redOffset
* @ type Number
* * /
2014-01-03 13:32:13 -05:00
this . redOffset = redOffset || 0 ;
2014-11-18 18:26:26 -05:00
/ * *
* Green channel offset ( added to value ) .
* @ property greenOffset
* @ type Number
* * /
2014-01-03 13:32:13 -05:00
this . greenOffset = greenOffset || 0 ;
2014-11-18 18:26:26 -05:00
/ * *
* Blue channel offset ( added to value ) .
* @ property blueOffset
* @ type Number
* * /
2014-01-03 13:32:13 -05:00
this . blueOffset = blueOffset || 0 ;
2014-11-18 18:26:26 -05:00
/ * *
* Alpha channel offset ( added to value ) .
* @ property alphaOffset
* @ type Number
* * /
2014-01-03 13:32:13 -05:00
this . alphaOffset = alphaOffset || 0 ;
}
2014-11-18 18:26:26 -05:00
var p = createjs . extend ( ColorFilter , createjs . Filter ) ;
2014-01-03 13:32:13 -05:00
// public methods:
2014-11-18 18:26:26 -05:00
/** docced in super class **/
p . toString = function ( ) {
return "[ColorFilter]" ;
} ;
/** docced in super class **/
p . clone = function ( ) {
return new ColorFilter ( this . redMultiplier , this . greenMultiplier , this . blueMultiplier , this . alphaMultiplier , this . redOffset , this . greenOffset , this . blueOffset , this . alphaOffset ) ;
} ;
// private methods:
/** docced in super class **/
p . _applyFilter = function ( imageData ) {
2014-01-03 13:32:13 -05:00
var data = imageData . data ;
var l = data . length ;
for ( var i = 0 ; i < l ; i += 4 ) {
data [ i ] = data [ i ] * this . redMultiplier + this . redOffset ;
data [ i + 1 ] = data [ i + 1 ] * this . greenMultiplier + this . greenOffset ;
data [ i + 2 ] = data [ i + 2 ] * this . blueMultiplier + this . blueOffset ;
data [ i + 3 ] = data [ i + 3 ] * this . alphaMultiplier + this . alphaOffset ;
}
return true ;
2014-11-18 18:26:26 -05:00
} ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
createjs . ColorFilter = createjs . promote ( ColorFilter , "Filter" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// ColorMatrix.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Provides helper functions for assembling a matrix for use with the { { # crossLink "ColorMatrixFilter" } } { { / c r o s s L i n k } } .
* Most methods return the instance to facilitate chained calls .
2014-01-03 13:32:13 -05:00
*
* < h4 > Example < / h 4 >
2014-11-18 18:26:26 -05:00
*
2014-01-03 13:32:13 -05:00
* myColorMatrix . adjustHue ( 20 ) . adjustBrightness ( 50 ) ;
*
* See { { # crossLink "Filter" } } { { / c r o s s L i n k } } f o r a n e x a m p l e o f h o w t o a p p l y f i l t e r s , o r { { # c r o s s L i n k " C o l o r M a t r i x F i l t e r " } } { { / c r o s s L i n k } }
* for an example of how to use ColorMatrix to change a DisplayObject ' s color .
* @ class ColorMatrix
* @ param { Number } brightness
* @ param { Number } contrast
* @ param { Number } saturation
* @ param { Number } hue
* @ constructor
* * /
2014-11-18 18:26:26 -05:00
function ColorMatrix ( brightness , contrast , saturation , hue ) {
this . setColor ( brightness , contrast , saturation , hue ) ;
}
2014-01-03 13:32:13 -05:00
var p = ColorMatrix . prototype ;
2014-11-18 18:26:26 -05:00
// constants:
2014-01-03 13:32:13 -05:00
/ * *
* Array of delta values for contrast calculations .
* @ property DELTA _INDEX
* @ type Array
* @ protected
* @ static
* * /
ColorMatrix . DELTA _INDEX = [
0 , 0.01 , 0.02 , 0.04 , 0.05 , 0.06 , 0.07 , 0.08 , 0.1 , 0.11 ,
0.12 , 0.14 , 0.15 , 0.16 , 0.17 , 0.18 , 0.20 , 0.21 , 0.22 , 0.24 ,
0.25 , 0.27 , 0.28 , 0.30 , 0.32 , 0.34 , 0.36 , 0.38 , 0.40 , 0.42 ,
0.44 , 0.46 , 0.48 , 0.5 , 0.53 , 0.56 , 0.59 , 0.62 , 0.65 , 0.68 ,
0.71 , 0.74 , 0.77 , 0.80 , 0.83 , 0.86 , 0.89 , 0.92 , 0.95 , 0.98 ,
1.0 , 1.06 , 1.12 , 1.18 , 1.24 , 1.30 , 1.36 , 1.42 , 1.48 , 1.54 ,
1.60 , 1.66 , 1.72 , 1.78 , 1.84 , 1.90 , 1.96 , 2.0 , 2.12 , 2.25 ,
2.37 , 2.50 , 2.62 , 2.75 , 2.87 , 3.0 , 3.2 , 3.4 , 3.6 , 3.8 ,
4.0 , 4.3 , 4.7 , 4.9 , 5.0 , 5.5 , 6.0 , 6.5 , 6.8 , 7.0 ,
7.3 , 7.5 , 7.8 , 8.0 , 8.4 , 8.7 , 9.0 , 9.4 , 9.6 , 9.8 ,
10.0
] ;
/ * *
* Identity matrix values .
* @ property IDENTITY _MATRIX
* @ type Array
* @ protected
* @ static
* * /
ColorMatrix . IDENTITY _MATRIX = [
1 , 0 , 0 , 0 , 0 ,
0 , 1 , 0 , 0 , 0 ,
0 , 0 , 1 , 0 , 0 ,
0 , 0 , 0 , 1 , 0 ,
0 , 0 , 0 , 0 , 1
] ;
/ * *
* The constant length of a color matrix .
* @ property LENGTH
* @ type Number
* @ protected
* @ static
* * /
ColorMatrix . LENGTH = ColorMatrix . IDENTITY _MATRIX . length ;
2014-11-18 18:26:26 -05:00
// public methods:
2014-01-03 13:32:13 -05:00
/ * *
2014-11-18 18:26:26 -05:00
* Resets the instance with the specified values .
* @ method setColor
2014-01-03 13:32:13 -05:00
* @ param { Number } brightness
* @ param { Number } contrast
* @ param { Number } saturation
* @ param { Number } hue
* @ protected
* /
2014-11-18 18:26:26 -05:00
p . setColor = function ( brightness , contrast , saturation , hue ) {
return this . reset ( ) . adjustColor ( brightness , contrast , saturation , hue ) ; ;
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Resets the matrix to identity values .
* @ method reset
* @ return { ColorMatrix } The ColorMatrix instance the method is called on ( useful for chaining calls . )
* /
p . reset = function ( ) {
return this . copyMatrix ( ColorMatrix . IDENTITY _MATRIX ) ;
} ;
/ * *
* Shortcut method to adjust brightness , contrast , saturation and hue .
* Equivalent to calling adjustHue ( hue ) , adjustContrast ( contrast ) ,
* adjustBrightness ( brightness ) , adjustSaturation ( saturation ) , in that order .
* @ method adjustColor
* @ param { Number } brightness
* @ param { Number } contrast
* @ param { Number } saturation
* @ param { Number } hue
* @ return { ColorMatrix } The ColorMatrix instance the method is called on ( useful for chaining calls . )
* * /
p . adjustColor = function ( brightness , contrast , saturation , hue ) {
this . adjustHue ( hue ) ;
this . adjustContrast ( contrast ) ;
this . adjustBrightness ( brightness ) ;
return this . adjustSaturation ( saturation ) ;
} ;
/ * *
* Adjusts the brightness of pixel color by adding the specified value to the red , green and blue channels .
* Positive values will make the image brighter , negative values will make it darker .
* @ method adjustBrightness
* @ param { Number } value A value between - 255 & 255 that will be added to the RGB channels .
* @ return { ColorMatrix } The ColorMatrix instance the method is called on ( useful for chaining calls . )
* * /
p . adjustBrightness = function ( value ) {
if ( value == 0 || isNaN ( value ) ) { return this ; }
value = this . _cleanValue ( value , 255 ) ;
this . _multiplyMatrix ( [
1 , 0 , 0 , 0 , value ,
0 , 1 , 0 , 0 , value ,
0 , 0 , 1 , 0 , value ,
0 , 0 , 0 , 1 , 0 ,
0 , 0 , 0 , 0 , 1
] ) ;
return this ;
} ;
/ * *
* Adjusts the contrast of pixel color .
* Positive values will increase contrast , negative values will decrease contrast .
* @ method adjustContrast
* @ param { Number } value A value between - 100 & 100.
* @ return { ColorMatrix } The ColorMatrix instance the method is called on ( useful for chaining calls . )
* * /
p . adjustContrast = function ( value ) {
if ( value == 0 || isNaN ( value ) ) { return this ; }
value = this . _cleanValue ( value , 100 ) ;
var x ;
if ( value < 0 ) {
x = 127 + value / 100 * 127 ;
} else {
x = value % 1 ;
if ( x == 0 ) {
x = ColorMatrix . DELTA _INDEX [ value ] ;
} else {
x = ColorMatrix . DELTA _INDEX [ ( value << 0 ) ] * ( 1 - x ) + ColorMatrix . DELTA _INDEX [ ( value << 0 ) + 1 ] * x ; // use linear interpolation for more granularity.
}
x = x * 127 + 127 ;
}
this . _multiplyMatrix ( [
x / 127 , 0 , 0 , 0 , 0.5 * ( 127 - x ) ,
0 , x / 127 , 0 , 0 , 0.5 * ( 127 - x ) ,
0 , 0 , x / 127 , 0 , 0.5 * ( 127 - x ) ,
0 , 0 , 0 , 1 , 0 ,
0 , 0 , 0 , 0 , 1
] ) ;
return this ;
} ;
/ * *
* Adjusts the color saturation of the pixel .
* Positive values will increase saturation , negative values will decrease saturation ( trend towards greyscale ) .
* @ method adjustSaturation
* @ param { Number } value A value between - 100 & 100.
* @ return { ColorMatrix } The ColorMatrix instance the method is called on ( useful for chaining calls . )
* * /
p . adjustSaturation = function ( value ) {
if ( value == 0 || isNaN ( value ) ) { return this ; }
value = this . _cleanValue ( value , 100 ) ;
var x = 1 + ( ( value > 0 ) ? 3 * value / 100 : value / 100 ) ;
var lumR = 0.3086 ;
var lumG = 0.6094 ;
var lumB = 0.0820 ;
this . _multiplyMatrix ( [
lumR * ( 1 - x ) + x , lumG * ( 1 - x ) , lumB * ( 1 - x ) , 0 , 0 ,
lumR * ( 1 - x ) , lumG * ( 1 - x ) + x , lumB * ( 1 - x ) , 0 , 0 ,
lumR * ( 1 - x ) , lumG * ( 1 - x ) , lumB * ( 1 - x ) + x , 0 , 0 ,
0 , 0 , 0 , 1 , 0 ,
0 , 0 , 0 , 0 , 1
] ) ;
return this ;
} ;
/ * *
* Adjusts the hue of the pixel color .
* @ method adjustHue
* @ param { Number } value A value between - 180 & 180.
* @ return { ColorMatrix } The ColorMatrix instance the method is called on ( useful for chaining calls . )
* * /
p . adjustHue = function ( value ) {
if ( value == 0 || isNaN ( value ) ) { return this ; }
value = this . _cleanValue ( value , 180 ) / 180 * Math . PI ;
var cosVal = Math . cos ( value ) ;
var sinVal = Math . sin ( value ) ;
var lumR = 0.213 ;
var lumG = 0.715 ;
var lumB = 0.072 ;
this . _multiplyMatrix ( [
lumR + cosVal * ( 1 - lumR ) + sinVal * ( - lumR ) , lumG + cosVal * ( - lumG ) + sinVal * ( - lumG ) , lumB + cosVal * ( - lumB ) + sinVal * ( 1 - lumB ) , 0 , 0 ,
lumR + cosVal * ( - lumR ) + sinVal * ( 0.143 ) , lumG + cosVal * ( 1 - lumG ) + sinVal * ( 0.140 ) , lumB + cosVal * ( - lumB ) + sinVal * ( - 0.283 ) , 0 , 0 ,
lumR + cosVal * ( - lumR ) + sinVal * ( - ( 1 - lumR ) ) , lumG + cosVal * ( - lumG ) + sinVal * ( lumG ) , lumB + cosVal * ( 1 - lumB ) + sinVal * ( lumB ) , 0 , 0 ,
0 , 0 , 0 , 1 , 0 ,
0 , 0 , 0 , 0 , 1
] ) ;
return this ;
} ;
/ * *
* Concatenates ( multiplies ) the specified matrix with this one .
* @ method concat
* @ param { Array } matrix An array or ColorMatrix instance .
* @ return { ColorMatrix } The ColorMatrix instance the method is called on ( useful for chaining calls . )
* * /
p . concat = function ( matrix ) {
matrix = this . _fixMatrix ( matrix ) ;
if ( matrix . length != ColorMatrix . LENGTH ) { return this ; }
this . _multiplyMatrix ( matrix ) ;
return this ;
} ;
/ * *
* Returns a clone of this ColorMatrix .
* @ method clone
* @ return { ColorMatrix } A clone of this ColorMatrix .
* * /
p . clone = function ( ) {
return ( new ColorMatrix ( ) ) . copyMatrix ( this ) ;
} ;
/ * *
* Return a length 25 ( 5 x5 ) array instance containing this matrix ' s values .
* @ method toArray
* @ return { Array } An array holding this matrix ' s values .
* * /
p . toArray = function ( ) {
var arr = [ ] ;
for ( var i = 0 , l = ColorMatrix . LENGTH ; i < l ; i ++ ) {
arr [ i ] = this [ i ] ;
}
return arr ;
} ;
/ * *
* Copy the specified matrix ' s values to this matrix .
* @ method copyMatrix
* @ param { Array } matrix An array or ColorMatrix instance .
* @ return { ColorMatrix } The ColorMatrix instance the method is called on ( useful for chaining calls . )
* * /
p . copyMatrix = function ( matrix ) {
var l = ColorMatrix . LENGTH ;
for ( var i = 0 ; i < l ; i ++ ) {
this [ i ] = matrix [ i ] ;
}
return this ;
} ;
/ * *
* Returns a string representation of this object .
* @ method toString
* @ return { String } a string representation of the instance .
* * /
p . toString = function ( ) {
return "[ColorMatrix]" ;
} ;
2014-11-18 18:26:26 -05:00
// private methods:
2014-01-03 13:32:13 -05:00
/ * *
* @ method _multiplyMatrix
* @ param { Array } matrix
* @ protected
* * /
p . _multiplyMatrix = function ( matrix ) {
2014-11-18 18:26:26 -05:00
var i , j , k , col = [ ] ;
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
for ( i = 0 ; i < 5 ; i ++ ) {
for ( j = 0 ; j < 5 ; j ++ ) {
2014-01-03 13:32:13 -05:00
col [ j ] = this [ j + i * 5 ] ;
}
2014-11-18 18:26:26 -05:00
for ( j = 0 ; j < 5 ; j ++ ) {
2014-01-03 13:32:13 -05:00
var val = 0 ;
2014-11-18 18:26:26 -05:00
for ( k = 0 ; k < 5 ; k ++ ) {
2014-01-03 13:32:13 -05:00
val += matrix [ j + k * 5 ] * col [ k ] ;
}
this [ j + i * 5 ] = val ;
}
}
} ;
/ * *
* Make sure values are within the specified range , hue has a limit of 180 , brightness is 255 , others are 100.
* @ method _cleanValue
* @ param { Number } value The raw number
* @ param { Number } limit The maximum that the number can be . The minimum is the limit * - 1.
* @ protected
* * /
p . _cleanValue = function ( value , limit ) {
return Math . min ( limit , Math . max ( - limit , value ) ) ;
} ;
/ * *
* Makes sure matrixes are 5 x5 ( 25 long ) .
* @ method _fixMatrix
* @ param { Array } matrix
* @ protected
* * /
p . _fixMatrix = function ( matrix ) {
if ( matrix instanceof ColorMatrix ) { matrix = matrix . toArray ( ) ; }
if ( matrix . length < ColorMatrix . LENGTH ) {
matrix = matrix . slice ( 0 , matrix . length ) . concat ( ColorMatrix . IDENTITY _MATRIX . slice ( matrix . length , ColorMatrix . LENGTH ) ) ;
} else if ( matrix . length > ColorMatrix . LENGTH ) {
matrix = matrix . slice ( 0 , ColorMatrix . LENGTH ) ;
}
return matrix ;
} ;
2014-11-18 18:26:26 -05:00
createjs . ColorMatrix = ColorMatrix ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// ColorMatrixFilter.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
// constructor:
/ * *
2014-11-18 18:26:26 -05:00
* Allows you to carry out complex color operations such as modifying saturation , brightness , or inverting . See the
* { { # crossLink "ColorMatrix" } } { { / c r o s s L i n k } } f o r m o r e i n f o r m a t i o n o n c h a n g i n g c o l o r s . F o r a n e a s i e r c o l o r t r a n s f o r m ,
* consider the { { # crossLink "ColorFilter" } } { { / c r o s s L i n k } } .
*
* < h4 > Example < / h 4 >
* This example creates a red circle , inverts its hue , and then saturates it to brighten it up .
*
* var shape = new createjs . Shape ( ) . set ( { x : 100 , y : 100 } ) ;
* shape . graphics . beginFill ( "#ff0000" ) . drawCircle ( 0 , 0 , 50 ) ;
*
* var matrix = new createjs . ColorMatrix ( ) . adjustHue ( 180 ) . adjustSaturation ( 100 ) ;
* shape . filters = [
* new createjs . ColorMatrixFilter ( matrix )
* ] ;
*
* shape . cache ( - 50 , - 50 , 100 , 100 ) ;
*
* See { { # crossLink "Filter" } } { { / c r o s s L i n k } } f o r a n m o r e i n f o r m a t i o n o n a p p l y i n g f i l t e r s .
* @ class ColorMatrixFilter
* @ constructor
* @ extends Filter
* @ param { Array | ColorMatrix } matrix A 4 x5 matrix describing the color operation to perform . See also the { { # crossLink "ColorMatrix" } } { { / c r o s s L i n k } }
* class .
2014-01-03 13:32:13 -05:00
* * /
2014-11-18 18:26:26 -05:00
function ColorMatrixFilter ( matrix ) {
// public properties:
/ * *
* A 4 x5 matrix describing the color operation to perform . See also the { { # crossLink "ColorMatrix" } } { { / c r o s s L i n k } }
* @ property matrix
* @ type Array | ColorMatrix
* * /
2014-01-03 13:32:13 -05:00
this . matrix = matrix ;
2014-11-18 18:26:26 -05:00
}
var p = createjs . extend ( ColorMatrixFilter , createjs . Filter ) ;
2014-01-03 13:32:13 -05:00
// public methods:
2014-11-18 18:26:26 -05:00
/** docced in super class **/
p . toString = function ( ) {
return "[ColorMatrixFilter]" ;
} ;
/** docced in super class **/
p . clone = function ( ) {
return new ColorMatrixFilter ( this . matrix ) ;
} ;
// private methods:
/** docced in super class **/
p . _applyFilter = function ( imageData ) {
2014-01-03 13:32:13 -05:00
var data = imageData . data ;
var l = data . length ;
var r , g , b , a ;
var mtx = this . matrix ;
var m0 = mtx [ 0 ] , m1 = mtx [ 1 ] , m2 = mtx [ 2 ] , m3 = mtx [ 3 ] , m4 = mtx [ 4 ] ;
var m5 = mtx [ 5 ] , m6 = mtx [ 6 ] , m7 = mtx [ 7 ] , m8 = mtx [ 8 ] , m9 = mtx [ 9 ] ;
var m10 = mtx [ 10 ] , m11 = mtx [ 11 ] , m12 = mtx [ 12 ] , m13 = mtx [ 13 ] , m14 = mtx [ 14 ] ;
var m15 = mtx [ 15 ] , m16 = mtx [ 16 ] , m17 = mtx [ 17 ] , m18 = mtx [ 18 ] , m19 = mtx [ 19 ] ;
for ( var i = 0 ; i < l ; i += 4 ) {
r = data [ i ] ;
g = data [ i + 1 ] ;
b = data [ i + 2 ] ;
a = data [ i + 3 ] ;
data [ i ] = r * m0 + g * m1 + b * m2 + a * m3 + m4 ; // red
data [ i + 1 ] = r * m5 + g * m6 + b * m7 + a * m8 + m9 ; // green
data [ i + 2 ] = r * m10 + g * m11 + b * m12 + a * m13 + m14 ; // blue
data [ i + 3 ] = r * m15 + g * m16 + b * m17 + a * m18 + m19 ; // alpha
}
return true ;
} ;
2014-11-18 18:26:26 -05:00
createjs . ColorMatrixFilter = createjs . promote ( ColorMatrixFilter , "Filter" ) ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// Touch.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
2014-11-18 18:26:26 -05:00
// constructor:
/ * *
2014-01-03 13:32:13 -05:00
* Global utility for working with multi - touch enabled devices in EaselJS . Currently supports W3C Touch API ( iOS and
* modern Android browser ) and the Pointer API ( IE ) , including ms - prefixed events in IE10 , and unprefixed in IE11 .
*
* Ensure that you { { # crossLink "Touch/disable" } } { { / c r o s s L i n k } } t o u c h w h e n c l e a n i n g u p y o u r a p p l i c a t i o n . Y o u d o n o t h a v e
* to check if touch is supported to enable it , as it will fail gracefully if it is not supported .
*
* < h4 > Example < / h 4 >
*
* var stage = new createjs . Stage ( "canvasId" ) ;
* createjs . Touch . enable ( stage ) ;
*
* < strong > Note : < / s t r o n g > I t i s i m p o r t a n t t o d i s a b l e T o u c h o n a s t a g e t h a t y o u a r e n o l o n g e r u s i n g :
*
* createjs . Touch . disable ( stage ) ;
*
* @ class Touch
* @ static
* * /
2014-11-18 18:26:26 -05:00
function Touch ( ) {
throw "Touch cannot be instantiated" ;
}
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
// public static methods:
2014-01-03 13:32:13 -05:00
/ * *
* Returns ` true ` if touch is supported in the current browser .
* @ method isSupported
* @ return { Boolean } Indicates whether touch is supported in the current browser .
* @ static
* * /
Touch . isSupported = function ( ) {
2014-11-18 18:26:26 -05:00
return ! ! ( ( 'ontouchstart' in window ) // iOS & Android
2014-02-02 19:31:06 -05:00
|| ( window . navigator [ 'msPointerEnabled' ] && window . navigator [ 'msMaxTouchPoints' ] > 0 ) // IE10
2014-11-18 18:26:26 -05:00
|| ( window . navigator [ 'pointerEnabled' ] && window . navigator [ 'maxTouchPoints' ] > 0 ) ) ; // IE11+
2014-01-03 13:32:13 -05:00
} ;
/ * *
* Enables touch interaction for the specified EaselJS { { # crossLink "Stage" } } { { / c r o s s L i n k } } . C u r r e n t l y s u p p o r t s i O S
* ( and compatible browsers , such as modern Android browsers ) , and IE10 / 11. Supports both single touch and
* multi - touch modes . Extends the EaselJS { { # crossLink "MouseEvent" } } { { / c r o s s L i n k } } m o d e l , b u t w i t h o u t s u p p o r t f o r
* double click or over / out events . See the MouseEvent { { # crossLink "MouseEvent/pointerId:property" } } { { / c r o s s L i n k } }
* for more information .
* @ method enable
* @ param { Stage } stage The { { # crossLink "Stage" } } { { / c r o s s L i n k } } t o e n a b l e t o u c h o n .
* @ param { Boolean } [ singleTouch = false ] If ` true ` , only a single touch will be active at a time .
* @ param { Boolean } [ allowDefault = false ] If ` true ` , then default gesture actions ( ex . scrolling , zooming ) will be
* allowed when the user is interacting with the target canvas .
* @ return { Boolean } Returns ` true ` if touch was successfully enabled on the target stage .
* @ static
* * /
Touch . enable = function ( stage , singleTouch , allowDefault ) {
if ( ! stage || ! stage . canvas || ! Touch . isSupported ( ) ) { return false ; }
2014-11-18 18:26:26 -05:00
if ( stage . _ _touch ) { return true ; }
2014-01-03 13:32:13 -05:00
// inject required properties on stage:
stage . _ _touch = { pointers : { } , multitouch : ! singleTouch , preventDefault : ! allowDefault , count : 0 } ;
// note that in the future we may need to disable the standard mouse event model before adding
// these to prevent duplicate calls. It doesn't seem to be an issue with iOS devices though.
if ( 'ontouchstart' in window ) { Touch . _IOS _enable ( stage ) ; }
else if ( window . navigator [ 'msPointerEnabled' ] || window . navigator [ "pointerEnabled" ] ) { Touch . _IE _enable ( stage ) ; }
return true ;
} ;
/ * *
* Removes all listeners that were set up when calling ` Touch.enable() ` on a stage .
* @ method disable
* @ param { Stage } stage The { { # crossLink "Stage" } } { { / c r o s s L i n k } } t o d i s a b l e t o u c h o n .
* @ static
* * /
Touch . disable = function ( stage ) {
if ( ! stage ) { return ; }
if ( 'ontouchstart' in window ) { Touch . _IOS _disable ( stage ) ; }
else if ( window . navigator [ 'msPointerEnabled' ] || window . navigator [ "pointerEnabled" ] ) { Touch . _IE _disable ( stage ) ; }
2014-11-18 18:26:26 -05:00
delete stage . _ _touch ;
2014-01-03 13:32:13 -05:00
} ;
2014-11-18 18:26:26 -05:00
// Private static methods:
2014-01-03 13:32:13 -05:00
/ * *
* @ method _IOS _enable
* @ protected
* @ param { Stage } stage
* @ static
* * /
Touch . _IOS _enable = function ( stage ) {
var canvas = stage . canvas ;
var f = stage . _ _touch . f = function ( e ) { Touch . _IOS _handleEvent ( stage , e ) ; } ;
canvas . addEventListener ( "touchstart" , f , false ) ;
canvas . addEventListener ( "touchmove" , f , false ) ;
canvas . addEventListener ( "touchend" , f , false ) ;
canvas . addEventListener ( "touchcancel" , f , false ) ;
} ;
/ * *
* @ method _IOS _disable
* @ protected
* @ param { Stage } stage
* @ static
* * /
Touch . _IOS _disable = function ( stage ) {
var canvas = stage . canvas ;
if ( ! canvas ) { return ; }
var f = stage . _ _touch . f ;
canvas . removeEventListener ( "touchstart" , f , false ) ;
canvas . removeEventListener ( "touchmove" , f , false ) ;
canvas . removeEventListener ( "touchend" , f , false ) ;
canvas . removeEventListener ( "touchcancel" , f , false ) ;
} ;
/ * *
* @ method _IOS _handleEvent
* @ param { Stage } stage
* @ param { Object } e The event to handle
* @ protected
* @ static
* * /
Touch . _IOS _handleEvent = function ( stage , e ) {
if ( ! stage ) { return ; }
if ( stage . _ _touch . preventDefault ) { e . preventDefault && e . preventDefault ( ) ; }
var touches = e . changedTouches ;
var type = e . type ;
for ( var i = 0 , l = touches . length ; i < l ; i ++ ) {
var touch = touches [ i ] ;
var id = touch . identifier ;
if ( touch . target != stage . canvas ) { continue ; }
if ( type == "touchstart" ) {
this . _handleStart ( stage , id , e , touch . pageX , touch . pageY ) ;
} else if ( type == "touchmove" ) {
this . _handleMove ( stage , id , e , touch . pageX , touch . pageY ) ;
} else if ( type == "touchend" || type == "touchcancel" ) {
this . _handleEnd ( stage , id , e ) ;
}
}
} ;
/ * *
* @ method _IE _enable
* @ protected
* @ param { Stage } stage
* @ static
* * /
Touch . _IE _enable = function ( stage ) {
var canvas = stage . canvas ;
var f = stage . _ _touch . f = function ( e ) { Touch . _IE _handleEvent ( stage , e ) ; } ;
2014-02-02 19:31:06 -05:00
if ( window . navigator [ "pointerEnabled" ] === undefined ) {
2014-01-03 13:32:13 -05:00
canvas . addEventListener ( "MSPointerDown" , f , false ) ;
window . addEventListener ( "MSPointerMove" , f , false ) ;
window . addEventListener ( "MSPointerUp" , f , false ) ;
window . addEventListener ( "MSPointerCancel" , f , false ) ;
if ( stage . _ _touch . preventDefault ) { canvas . style . msTouchAction = "none" ; }
} else {
canvas . addEventListener ( "pointerdown" , f , false ) ;
window . addEventListener ( "pointermove" , f , false ) ;
window . addEventListener ( "pointerup" , f , false ) ;
window . addEventListener ( "pointercancel" , f , false ) ;
if ( stage . _ _touch . preventDefault ) { canvas . style . touchAction = "none" ; }
}
stage . _ _touch . activeIDs = { } ;
} ;
/ * *
* @ method _IE _disable
* @ protected
* @ param { Stage } stage
* @ static
* * /
Touch . _IE _disable = function ( stage ) {
var f = stage . _ _touch . f ;
2014-02-02 19:31:06 -05:00
if ( window . navigator [ "pointerEnabled" ] === undefined ) {
2014-01-03 13:32:13 -05:00
window . removeEventListener ( "MSPointerMove" , f , false ) ;
window . removeEventListener ( "MSPointerUp" , f , false ) ;
window . removeEventListener ( "MSPointerCancel" , f , false ) ;
if ( stage . canvas ) {
stage . canvas . removeEventListener ( "MSPointerDown" , f , false ) ;
}
} else {
window . removeEventListener ( "pointermove" , f , false ) ;
window . removeEventListener ( "pointerup" , f , false ) ;
window . removeEventListener ( "pointercancel" , f , false ) ;
if ( stage . canvas ) {
stage . canvas . removeEventListener ( "pointerdown" , f , false ) ;
}
}
} ;
/ * *
* @ method _IE _handleEvent
* @ param { Stage } stage
* @ param { Object } e The event to handle .
* @ protected
* @ static
* * /
Touch . _IE _handleEvent = function ( stage , e ) {
if ( ! stage ) { return ; }
if ( stage . _ _touch . preventDefault ) { e . preventDefault && e . preventDefault ( ) ; }
var type = e . type ;
var id = e . pointerId ;
var ids = stage . _ _touch . activeIDs ;
if ( type == "MSPointerDown" || type == "pointerdown" ) {
if ( e . srcElement != stage . canvas ) { return ; }
ids [ id ] = true ;
this . _handleStart ( stage , id , e , e . pageX , e . pageY ) ;
} else if ( ids [ id ] ) { // it's an id we're watching
if ( type == "MSPointerMove" || type == "pointermove" ) {
this . _handleMove ( stage , id , e , e . pageX , e . pageY ) ;
} else if ( type == "MSPointerUp" || type == "MSPointerCancel"
|| type == "pointerup" || type == "pointercancel" ) {
delete ( ids [ id ] ) ;
this . _handleEnd ( stage , id , e ) ;
}
}
} ;
/ * *
* @ method _handleStart
* @ param { Stage } stage
* @ param { String | Number } id
* @ param { Object } e
* @ param { Number } x
* @ param { Number } y
* @ protected
* * /
Touch . _handleStart = function ( stage , id , e , x , y ) {
var props = stage . _ _touch ;
if ( ! props . multitouch && props . count ) { return ; }
var ids = props . pointers ;
if ( ids [ id ] ) { return ; }
ids [ id ] = true ;
props . count ++ ;
stage . _handlePointerDown ( id , e , x , y ) ;
} ;
/ * *
* @ method _handleMove
* @ param { Stage } stage
* @ param { String | Number } id
* @ param { Object } e
* @ param { Number } x
* @ param { Number } y
* @ protected
* * /
Touch . _handleMove = function ( stage , id , e , x , y ) {
if ( ! stage . _ _touch . pointers [ id ] ) { return ; }
stage . _handlePointerMove ( id , e , x , y ) ;
} ;
/ * *
* @ method _handleEnd
* @ param { Stage } stage
* @ param { String | Number } id
* @ param { Object } e
* @ protected
* * /
Touch . _handleEnd = function ( stage , id , e ) {
// TODO: cancel should be handled differently for proper UI (ex. an up would trigger a click, a cancel would more closely resemble an out).
var props = stage . _ _touch ;
var ids = props . pointers ;
if ( ! ids [ id ] ) { return ; }
props . count -- ;
stage . _handlePointerUp ( id , e , true ) ;
delete ( ids [ id ] ) ;
} ;
2014-11-18 18:26:26 -05:00
createjs . Touch = Touch ;
2014-01-03 13:32:13 -05:00
} ( ) ) ;
2014-11-18 18:26:26 -05:00
//##############################################################################
// version.js
//##############################################################################
2014-01-03 13:32:13 -05:00
this . createjs = this . createjs || { } ;
( function ( ) {
"use strict" ;
/ * *
* Static class holding library specific information such as the version and buildDate of
* the library .
* @ class EaselJS
* * /
var s = createjs . EaselJS = createjs . EaselJS || { } ;
/ * *
* The version string for this release .
* @ property version
* @ type String
* @ static
* * /
2014-11-18 18:26:26 -05:00
s . version = /*=version*/ "" ; // injected by build process
2014-01-03 13:32:13 -05:00
/ * *
* The build date for this release in UTC format .
* @ property buildDate
* @ type String
* @ static
* * /
2014-11-18 18:26:26 -05:00
s . buildDate = /*=date*/ "" ; // injected by build process
2014-01-03 13:32:13 -05:00
2014-11-18 18:26:26 -05:00
} ) ( ) ;