import * as React from 'react' ; import _isEqual from 'lodash/isEqual' ; import Logger from '@terrestris/base-util/dist/Logger' ; import { ArrayTwoOrMore } from '@terrestris/base-util/dist/types' ; import OlMap from 'ol/Map' ; import OlLayerGroup from 'ol/layer/Group' ; import OlLayerTile from 'ol/layer/Tile' ; import OlTileSource from 'ol/source/Tile' ; import { CSS_PREFIX } from '../constants' ; import MapComponent from '../Map/MapComponent/MapComponent' ; import './LayerSwitcher.less' ; export interface extends React . HTMLAttributes < HTMLDivElement > export interface BaseProps { /**
     * An optional CSS class which will be added to the wrapping div Element.
     */ className ? : string ; /**
     * The layers to be available in the switcher.
     */ layers : ArrayTwoOrMore < OlLayerTile < OlTileSource > | OlLayerGroup > ; /**
     * The main map the layers should be synced with.
     */ map : OlMap ; } interface LayerSwitcherState { previewLayer : OlLayerTile < OlTileSource > | OlLayerGroup ; } export type LayerSwitcherProps = BaseProps & React . HTMLAttributes < HTMLDivElement > ; class extends React . Component export class LayerSwitcher extends React . Component < LayerSwitcherProps , LayerSwitcherState > { private _map : OlMap = null ; private _visibleLayerIndex : number = null ; private _layerClones : Array < OlLayerTile < OlTileSource > | OlLayerGroup > = [ ] ; private _className = `${ CSS_PREFIX }layer-switcher` ; constructs constructor ( props ) { super ( props ) ; this . _map = this . getMap ( ) ; this . state = { previewLayer : null } ; } /**
     * A react lifecycle method called when the component did mount.
     */ componentDidMount ( ) { this . setMapLayers ( ) ; this . updateLayerVisibility ( ) ; } memberof componentWillUnMount ( ) { this . _map . getLayers ( ) . clear ( ) ; this . _map . setTarget ( null ) ; this . _map = null ; } param prevProps componentDidUpdate ( prevProps ) { if ( ! ( _isEqual ( this . props . layers , prevProps . layers ) ) ) { this . setMapLayers ( ) ; this . updateLayerVisibility ( ) ; } } param layer returns cloneLayer = ( layer ) => { let layerClone ; if ( layer instanceof OlLayerGroup ) { layerClone = new OlLayerGroup ( { layers : layer . getLayers ( ) . getArray ( ) . map ( this . cloneLayer ) , properties : { originalLayer : layer } , ... layer . getProperties ( ) } ) ; } else { layerClone = new OlLayerTile ( { source : layer . getSource ( ) , properties : { originalLayer : layer } , ... layer . getProperties ( ) } ) ; } return layerClone ; } ; /**
     * (Re-)adds the layers to the preview map and sets the visibleLayerIndex.
     *
     */ setMapLayers = ( ) => { const { layers } = this . props ; if ( layers . length < 2 ) { Logger . warn ( 'LayerSwitcher requires two or more layers.' ) ; } this . _map . getLayers ( ) . clear ( ) ; this . _layerClones = layers . map ( ( layer , index ) => { const layerClone = this . cloneLayer ( layer ) ; if ( layerClone . getVisible ( ) ) { this . _visibleLayerIndex = index ; } this . _map . addLayer ( layerClone ) ; return layerClone ; } ) ; } ; /**
     * Sets the visiblity of the layers in the props.map and this._map.
     * Also sets the previewLayer in the state.
     *
     */ updateLayerVisibility = ( ) => { const { layers } = this . props ; layers . forEach ( ( l , i ) => { if ( this . _visibleLayerIndex === i ) { l . setVisible ( true ) ; } else { l . setVisible ( false ) ; } } ) ; this . _layerClones . forEach ( ( l , i ) => { if ( this . _visibleLayerIndex === this . _layerClones . length - 1 && i === 0 ) { l . setVisible ( true ) ; this . setState ( { previewLayer : l } ) ; } else if ( this . _visibleLayerIndex + 1 === i ) { l . setVisible ( true ) ; this . setState ( { previewLayer : l } ) ; } else { l . setVisible ( false ) ; } } ) ; } ; /**
     * Constructs this._map
     */ getMap = ( ) : OlMap => { const { map } = this . props ; return new OlMap ( { view : map . getView ( ) , controls : [ ] } ) ; } ; /**
     * Clickhandler for the overview switch.
     *
     */ onSwitcherClick = ( evt ) => { evt . stopPropagation ( ) ; this . _map . getLayers ( ) . getArray ( ) . forEach ( ( layer , index ) => { if ( layer . getVisible ( ) ) { this . _visibleLayerIndex = index ; } } ) ; this . updateLayerVisibility ( ) ; } ; /**
     * The render function.
     */ render ( ) { const { className , ... passThroughProps } = this . props ; const finalClassName = className ? `${ className } ${ this . _className }` : this . _className ; return ( < div className = { finalClassName } { ... passThroughProps } > < div className = "clip" onClick = { this . onSwitcherClick } role = "button" > < MapComponent mapDivId = "layer-switcher-map" map = { this . _map } role = "img" / > { this . state . previewLayer && < span className = "layer-title" > { this . state . previewLayer . get ( 'name' ) } < /span>} < /div> < /div>); } } export default LayerSwitcher ;