import { GlyphplotComponent } from './glyphplot.component' ; export class SelectionRect { private component : GlyphplotComponent ; private context : any ; private helper ; private _animationIntervalId : number = 0 ; private _animationProgress = 0 ; private _data : any ; private _start : any = { x : - 1 , y : - 1 } ; private _end : any = { x : - 1 , y : - 1 } ; private _offset : any = { x : 0 , y : 0 } ; static applyEasing ( x ) { const a = 1.25 ; return Math . pow ( x , a ) / ( Math . pow ( x , a ) + Math . pow ( ( 1 - x ) , a ) ) ; } static animationTick ( component ) { return ( ) => { component . increaseAnimationProgress ( ) ; component . onTicked ( ) ; } ; } public onTicked ( ) { this . drawHighlightedGlyph ( ) ; } constructor ( component , context , helper ) { this . context = context ; this . helper = helper ; this . component = component ; } public draw ( event ) { if ( ! arguments . length ) { return ; } if ( event . type !== 'zoom' ) { return ; } this . clear ( ) ; this . context . save ( ) ; this . context . lineWidth = 1 ; this . context . setLineDash ( [ 4 , 2 ] ) ; this . context . strokeStyle = 'rgba(48, 48, 48, .73)' ; const w = event . sourceEvent . offsetX - this . start . x ; const h = event . sourceEvent . offsetY - this . start . y ; this . end . x = this . start . x + w ; this . end . y = this . start . y + h ; this . context . strokeRect ( this . start . x + this . offset . x , this . start . y + this . offset . y , w , h ) ; this . context . restore ( ) ; } public clear ( ) { this . context . save ( ) ; this . context . clearRect ( this . offset . x , this . offset . y , this . component . width , this . component . height ) ; this . context . restore ( ) ; } public get selectedGlyphs ( ) : any { const selectedArea = { start : this . _start , end : this . _end } ; const top = ( selectedArea . end . y < selectedArea . start . y ) ? selectedArea . end . y : selectedArea . start . y ; const bottom = ( top === selectedArea . end . y ) ? selectedArea . start . y : selectedArea . end . y ; const left = ( selectedArea . end . x < selectedArea . start . x ) ? selectedArea . end . x : selectedArea . start . x ; const right = ( left === selectedArea . end . x ) ? selectedArea . start . x : selectedArea . end . x ; const filteredData = Object . create ( this . _data ) ; const selectedIds = [ ] ; filteredData . positions = filteredData . positions . filter ( ( elem ) => { const position = elem . position ; if ( ! this . helper . checkClipping ( position ) && position . x > left && position . x < right && position . y > top && position . y < bottom ) { selectedIds . push ( elem . id ) ; return true ; } ; return false ; } ) ; filteredData . features = filteredData . features . filter ( ( elem ) => { return selectedIds . indexOf ( elem . id ) !== - 1 ; } ) ; return filteredData ; } public increaseAnimationProgress ( ) { this . _animationProgress += 0.01 ; if ( this . _animationProgress > 1 ) { this . _animationProgress = 0 ; } } public drawHighlightedGlyph ( ) { if ( this . component . configuration . showHighlightInNormalMode || this . component . configuration . useDragSelection ) { const idOfHoveredGlyph = this . component . configuration . idOfHoveredGlyph ; if ( idOfHoveredGlyph !== undefined && idOfHoveredGlyph > 0 ) { let hoveredGlyph ; for ( const glyph of this . component . data . positions ) { if ( glyph . id === idOfHoveredGlyph ) { hoveredGlyph = glyph ; break ; } } this . clear ( ) ; this . context . save ( ) ; const featuresOfHoveredGlyph = this . component . layoutController . getFeaturesForItem ( hoveredGlyph ) ; this . component . circle . context = this . context ; this . component . configuration . glyph . context = this . context ; const positions = { x : hoveredGlyph . position . x + ( this . offset . x ) , y : hoveredGlyph . position . y + ( this . offset . y ) } ; this . component . layoutController . drawSingleGlyph ( positions , featuresOfHoveredGlyph ! . features , 0 , false , true , SelectionRect . applyEasing ( this . _animationProgress ) ) ; this . context . restore ( ) ; this . component . circle . context = this . component . context ; this . component . configuration . glyph . context = this . component . context ; if ( this . _animationIntervalId === undefined || this . _animationIntervalId === null ) { this . _animationIntervalId = window . setInterval ( SelectionRect . animationTick ( this ) , 10 ) ; } else { if ( this . _animationProgress >= 1 ) { this . _animationProgress = 0 ; } } } else if ( this . _animationIntervalId !== undefined && this . _animationIntervalId !== null ) { clearInterval ( this . _animationIntervalId ) ; this . _animationIntervalId = 0 ; this . _animationProgress = 0 ; } } } public get start ( ) : any { return this . _start ; } public set start ( start ) { this . _start = start ; } public get end ( ) : any { return this . _end ; } public set end ( end ) { this . _end = end ; } public get offset ( ) : any { return this . _offset ; } public set offset ( value ) { this . _offset = value ; this . context . canvas . height = window . innerHeight ; this . context . canvas . width = window . innerWidth ; } public set data ( _data ) { this . _data = _data ; } }