/**
 * Original code from https://github.com/Viglino/ol-ext/blob/master/src/control/Swipe.js
 */ import { Control } from 'ol/control' ; import { Layer } from 'ol/layer' ; import { Source } from 'ol/source' ; import { LayerListItem } from '../../../common/layer-shifting/layer-shifting.service' ; param layers param rightLayer param className param position param orientation export type SwipeControlOptions = { layers ? : LayerListItem [ ] ; rightLayers ? : LayerListItem [ ] ; className ? : string ; position ? : number ; orientation ? : string ; } ; export class SwipeControl extends Control { options : SwipeControlOptions ; layers : LayerListItem [ ] ; rightLayers : LayerListItem [ ] ; isMoving : boolean ; constructor ( options ? ) { const button = document . createElement ( 'button' ) ; const element = document . createElement ( 'div' ) ; element . className = ( options ?. className || 'ol-swipe' ) + ' ol-unselectable ol-control' ; element . appendChild ( button ) ; super ( { element : element } ) ; this . options = options || { } ; element . addEventListener ( 'mousedown' , this . move . bind ( this ) ) ; element . addEventListener ( 'touchstart' , this . move . bind ( this ) ) ; this . precomposeRight = this . precomposeRight . bind ( this ) ; this . precomposeLeft = this . precomposeLeft . bind ( this ) ; this . postcompose = this . postcompose . bind ( this ) ; this . layers = [ ] ; this . rightLayers = [ ] ; if ( options ?. layers ) { this . addLayers ( options . layers ) ; } if ( options ?. rightLayers ) { this . addLayers ( options . rightLayers , true ) ; } this . on ( 'propertychange' , ( ) => { if ( this . getMap ( ) ) { try { this . getMap ( ) . renderSync ( ) ; } catch ( e ) { console . error ( e ) ; } } if ( this . get ( 'orientation' ) === 'horizontal' ) { this . element . style . top = this . get ( 'position' ) * 100 + '%' ; this . element . style . left = '' ; } else { if ( this . get ( 'orientation' ) !== 'vertical' ) { this . set ( 'orientation' , 'vertical' ) ; } this . element . style . left = this . get ( 'position' ) * 100 + '%' ; this . element . style . top = '' ; } this . element . classList . remove ( 'horizontal' , 'vertical' ) ; this . element . classList . add ( this . get ( 'orientation' ) ) ; } ) ; this . set ( 'position' , options ?. position || 0.5 ) ; this . set ( 'orientation' , options ?. orientation || 'vertical' ) ; } param map setTargetMap ( map ) { if ( map ) { this . setMap ( map ) ; } if ( this . getMap ( ) ) { for ( const l of this . layers ) { this . disableEvents ( l ) ; } for ( const l of this . rightLayers ) { this . disableEvents ( l , true ) ; } try { this . getMap ( ) . renderSync ( ) ; } catch ( e ) { } } } private enableEvents ( l , right ? ) { if ( right ) { ( l . layer as any ) . on ( [ 'precompose' , 'prerender' ] , this . precomposeRight ) ; } else { ( l . layer as any ) . on ( [ 'precompose' , 'prerender' ] , this . precomposeLeft ) ; } ( l . layer as any ) . on ( [ 'postcompose' , 'postrender' ] , this . postcompose ) ; } private disableEvents ( l , right ? ) { if ( right ) { ( l . layer as any ) . un ( [ 'precompose' , 'prerender' ] , this . precomposeRight ) ; } else { ( l . layer as any ) . un ( [ 'precompose' , 'prerender' ] , this . precomposeLeft ) ; } ( l . layer as any ) . un ( [ 'postcompose' , 'postrender' ] , this . postcompose ) ; } private isLayerAdded ( lyr , right ? ) { const found = right ? this . rightLayers . find ( ( l ) => l . layer == lyr . layer ) : this . layers . find ( ( l ) => l . layer == lyr . layer ) ; if ( ! found ) { return - 1 ; } else { const index = right ? this . rightLayers . indexOf ( found ) : this . layers . indexOf ( found ) ; return index ; } } param layers param right addLayers ( layers , right ? ) { if ( ! ( layers instanceof Array ) ) { layers = [ layers ] ; } for ( const l of layers ) { this . addLayer ( l , right ) ; } } param layer param right addLayer ( layer , right ? ) { if ( this . isLayerAdded ( layer , right ) < 0 ) { right ? this . rightLayers . push ( layer ) : this . layers . push ( layer ) ; if ( this . getMap ( ) ) { this . enableEvents ( layer , right ) ; try { this . getMap ( ) . renderSync ( ) ; } catch ( e ) { console . error ( e ) ; } } } } param enabled setEvents ( enabled ? ) { this . layers . forEach ( ( l ) => { enabled ? this . enableEvents ( l ) : this . disableEvents ( l ) ; } ) ; this . rightLayers . forEach ( ( l ) => { enabled ? this . enableEvents ( l , true ) : this . disableEvents ( l , true ) ; } ) ; } /** Remove all layers
     */ removeLayers ( ) { this . layers . forEach ( ( l ) => { this . removeLayer ( l ) ; } ) ; this . rightLayers . forEach ( ( l ) => { this . removeLayer ( l , true ) ; } ) ; } /** Remove a specific layer from swipe control completely
     */ removeCompletely ( layerToRm ) { let layerFound ; layerFound = this . layers . find ( ( l ) => l . layer == layerToRm ) ; if ( layerFound ) { this . removeLayer ( layerFound ) ; } else { layerFound = this . rightLayers . find ( ( l ) => l . layer == layerToRm ) ; if ( layerFound ) { this . removeLayer ( layerFound , true ) ; } } } param layer param right removeLayer ( layer , right ? ) { const k = this . isLayerAdded ( layer , right ) ; if ( k > - 1 ) { this . disableEvents ( layer , right ) ; right ? this . rightLayers . splice ( k , 1 ) : this . layers . splice ( k , 1 ) ; } if ( this . getMap ( ) ) { try { this . getMap ( ) . renderSync ( ) ; } catch ( e ) { console . error ( e ) ; } } } private move ( e ) { let l ; switch ( e . type ) { case 'touchcancel' : case 'touchend' : case 'mouseup' : { this . isMoving = false ; [ 'mouseup' , 'mousemove' , 'touchend' , 'touchcancel' , 'touchmove' , ] . forEach ( ( eventName ) => { document . removeEventListener ( eventName , this . move ) ; } ) ; break ; } case 'mousedown' : case 'touchstart' : { this . isMoving = true ; [ 'mouseup' , 'mousemove' , 'touchend' , 'touchcancel' , 'touchmove' , ] . forEach ( ( eventName ) => { document . addEventListener ( eventName , this . move . bind ( this ) ) ; } ) ; } case 'mousemove' : case 'touchmove' : { if ( this . isMoving ) { if ( this . get ( 'orientation' ) === 'vertical' ) { let pageX = e . pageX || ( e . touches && e . touches . length && e . touches [ 0 ] . pageX ) || ( e . changedTouches && e . changedTouches . length && e . changedTouches [ 0 ] . pageX ) ; if ( ! pageX ) { break ; } pageX -= this . getMap ( ) . getTargetElement ( ) . getBoundingClientRect ( ) . left + window . pageXOffset - document . documentElement . clientLeft ; l = this . getMap ( ) . getSize ( ) [ 0 ] ; const w = l - Math . min ( Math . max ( 0 , l - pageX ) , l ) ; l = w / l ; this . set ( 'position' , l ) ; this . dispatchEvent ( 'moving' ) ; } else { let pageY = e . pageY || ( e . touches && e . touches . length && e . touches [ 0 ] . pageY ) || ( e . changedTouches && e . changedTouches . length && e . changedTouches [ 0 ] . pageY ) ; if ( ! pageY ) { break ; } pageY -= this . getMap ( ) . getTargetElement ( ) . getBoundingClientRect ( ) . top + window . pageYOffset - document . documentElement . clientTop ; l = this . getMap ( ) . getSize ( ) [ 1 ] ; const h = l - Math . min ( Math . max ( 0 , l - pageY ) , l ) ; l = h / l ; this . set ( 'position' , l ) ; this . dispatchEvent ( 'moving' ) ; } } break ; } default : break ; } } private drawRect ( e , pts ) { const tr = e . inversePixelTransform ; if ( tr ) { const r = [ [ pts [ 0 ] [ 0 ] , pts [ 0 ] [ 1 ] ] , [ pts [ 0 ] [ 0 ] , pts [ 1 ] [ 1 ] ] , [ pts [ 1 ] [ 0 ] , pts [ 1 ] [ 1 ] ] , [ pts [ 1 ] [ 0 ] , pts [ 0 ] [ 1 ] ] , [ pts [ 0 ] [ 0 ] , pts [ 0 ] [ 1 ] ] , ] ; r . forEach ( ( pt , i ) => { pt = [ pt [ 0 ] * tr [ 0 ] - pt [ 1 ] * tr [ 1 ] + tr [ 4 ] , - pt [ 0 ] * tr [ 2 ] + pt [ 1 ] * tr [ 3 ] + tr [ 5 ] , ] ; if ( ! i ) { e . context . moveTo ( pt [ 0 ] , pt [ 1 ] ) ; } else { e . context . lineTo ( pt [ 0 ] , pt [ 1 ] ) ; } } ) ; } else { const ratio = e . frameState . pixelRatio ; e . context . rect ( pts [ 0 ] [ 0 ] * ratio , pts [ 0 ] [ 1 ] * ratio , pts [ 1 ] [ 0 ] * ratio , pts [ 1 ] [ 1 ] * ratio ) ; } } precomposeLeft ( e ) { const size = e . frameState . size ; const pts = [ [ 0 , 0 ] , [ size [ 0 ] , size [ 1 ] ] , ] ; if ( this . get ( 'orientation' ) === 'vertical' ) { pts [ 1 ] = [ size [ 0 ] * this . get ( 'position' ) , size [ 1 ] ] ; } else { pts [ 1 ] = [ size [ 0 ] , size [ 1 ] * this . get ( 'position' ) ] ; } this . precompose ( e , pts ) ; } precompose ( e , pts ) { const ctx = e . context ; ctx . save ( ) ; ctx . beginPath ( ) ; this . drawRect ( e , pts ) ; ctx . clip ( ) ; } precomposeRight ( e ) { const size = e . frameState . size ; const pts = [ [ 0 , 0 ] , [ size [ 0 ] , size [ 1 ] ] , ] ; if ( this . get ( 'orientation' ) === 'vertical' ) { pts [ 0 ] = [ size [ 0 ] * this . get ( 'position' ) , 0 ] ; } else { pts [ 0 ] = [ 0 , size [ 1 ] * this . get ( 'position' ) ] ; } this . precompose ( e , pts ) ; } postcompose ( e ) { if ( e . target . getClassName && e . target . getClassName ( ) !== 'ol-layer' && e . target . get ( 'declutter' ) ) { setTimeout ( ( ) => { e . context . restore ( ) ; } , 0 ) ; } else { e . context . restore ( ) ; } } }