namespace Impact { export class Person extends Pioneer { public title : Title ; public avatar : Snap . Element ; public radius : number ; public padding : number ; private initialPoint : Vector ; private image : HTMLImageElement ; public static MAX_ZOOM = 250 ; public static MAX_SIZE = 350 ; public static MIN_PADDING = 4 ; public static MAX_PADDING = 13 ; constructor ( public svg , public details , public point ) { super ( ) ; this . initialPoint = this . point . clone ( ) ; this . title = new Title ( this ) ; this . image = new Image ( ) ; this . image . src = Helpers . imageSource ( "people" , this . details . picture ) ; this . padding = 12 ; } public draw ( unit ) { let mass = Math . round ( Math . min ( Person . MAX_SIZE , this . details . impact * unit ) ) ; this . radius = mass / 2 ; let tl = this . topLeft ( ) ; let pattern = this . svg . image ( this . image . src , tl . x , tl . y , mass , mass ) ; this . avatar = this . svg . circle ( this . point . x , this . point . y , this . radius ) ; this . avatar . attr ( { fill : pattern . pattern ( tl . x , tl . y , mass , mass ) , stroke : "#888" , strokeWidth : 1 , cursor : "pointer" } ) ; this . avatar . click ( ( _ ) => this . highlight ( ) ) ; this . avatar . hover ( ( _ ) => this . highlight ( ) , ( _ ) => { if ( this . title . waiting ( ) ) { this . unhighlight ( ) ; } } ) ; this . title . draw ( ) ; } public position ( ) { let v = Vector . sub ( this . point , this . initialPoint ) ; this . avatar . transform ( `translate(${ v . x }, ${ v . y })` ) ; } public reset ( ) { this . point = this . initialPoint . clone ( ) ; } public detract ( p ) { let dist = this . point . distanceFrom ( p . point ) ; let radii = this . radius + p . radius + this . padding ; if ( dist < radii ) { let mid = ( c ) => { return ( c / dist ) * ( radii - dist ) * 0.5 ; } ; let v = Vector . sub ( p . point , this . point ) ; let tv = new Vector ( mid ( v . x ) , mid ( v . y ) ) ; this . point . sub ( tv ) ; p . point . add ( tv ) ; } } public attract ( to , damping ) { let v = Vector . sub ( this . point , to ) ; v . mul ( damping ) ; this . point . sub ( v ) ; } public preloaded ( ) { return this . image . complete && this . image . naturalHeight != 0 ; } public topLeft ( ) { return Vector . sub ( this . point , new Vector ( this . radius , this . radius ) ) ; } public bottomRight ( ) { return Vector . sub ( this . point , new Vector ( - this . radius , - this . radius ) ) ; } public highlight ( ) { this . title . initiate ( ) ; this . avatar . animate ( { strokeWidth : 6 } , 690 , mina . easein , ( ) => { this . hide ( ) ; this . title . zoom ( ) ; } ) ; } public unhighlight ( ) { this . avatar . stop ( ) . animate ( { strokeWidth : 1 } , 300 ) ; this . unhide ( ) ; this . title . finalize ( ) ; } public normalizePadding ( [ low , high ] ) { if ( low !== high ) { this . padding = Person . MIN_PADDING + ( ( this . details . impact - low ) / ( high - low ) * ( Person . MAX_PADDING - Person . MIN_PADDING ) ) ; } } public offScreen ( ) { let height = Helpers . canvasDimensions ( this . svg ) . y , allowance = this . radius / 2 , y = this . point . y ; return ( y < 0 + allowance ) || ( y > ( height - allowance ) ) ; } public recenter ( offset ) { let dim = Helpers . canvasDimensions ( this . svg ) , y = this . radius + offset + this . padding ; this . point . y = y ; this . point . x = dim . x ; } public moveTo ( p ) { let point = new Vector ( p . point . x + ( this . radius + p . radius + this . padding ) , this . point . y ) ; this . attract ( point , 1 ) ; } public collidingOn ( p , axis ) { return this . point . distanceFrom ( p . point , axis ) < ( this . radius + p . radius ) ; } private hide ( ) { this . avatar . attr ( { display : "none" } ) ; } private unhide ( ) { this . avatar . attr ( { display : "" } ) ; } } }