File

libs/map/src/lib/base/cached-map-component.ts

Implements

OnChanges DoCheck OnDestroy OnInit

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(mapCache: MapCache, kvDiffers: KeyValueDiffers)
Parameters :
Name Type Optional
mapCache MapCache No
kvDiffers KeyValueDiffers No

Properties

Private _baseMaps
Type : LayerMap
Private _differBaseMaps
Type : KeyValueDiffer<string | LayerOptions>
Private _differOverlayMaps
Type : KeyValueDiffer<string | LayerOptions>
Private _overlayMaps
Type : LayerMap
Protected layerControl
Type : L.Control.Layers
Protected map
Type : L.Map

The map object.

Protected oldBaseLayer
Type : L.Control.LayersObject
Default value : {}
Protected oldOverlayLayer
Type : L.Control.LayersObject
Default value : {}
Protected zoomControl
Type : L.Control.Zoom

Methods

Private addBaseMap
addBaseMap(layerOptions?: LayerOptions)
Parameters :
Name Type Optional
layerOptions LayerOptions Yes
Returns : void
Private addOverlayMap
addOverlayMap(layerOptions: LayerOptions)
Parameters :
Name Type Optional
layerOptions LayerOptions No
Returns : void
Protected createMap
createMap()
Returns : void
Private generateUUID
generateUUID()
Returns : string
Public ngDoCheck
ngDoCheck()
Returns : void
Public ngOnChanges
ngOnChanges(changes: SimpleChanges)
Parameters :
Name Type Optional
changes SimpleChanges No
Returns : void
Public ngOnDestroy
ngOnDestroy()
Returns : void
Public ngOnInit
ngOnInit()
Returns : void
Private removeBaseMap
removeBaseMap(layerOptions: LayerOptions)
Parameters :
Name Type Optional
layerOptions LayerOptions No
Returns : void
Private removeOverlayMap
removeOverlayMap(layerOptions: LayerOptions)
Parameters :
Name Type Optional
layerOptions LayerOptions No
Returns : void
Private updateLayerControl
updateLayerControl()
Returns : void
Private updateZoomControl
updateZoomControl()
Returns : void

Inputs

baseMaps
Type : LayerMap

Map, which holds all base map layer (see: https://leafletjs.com/reference-1.3.4.html#layer)

fitBounds
Type : L.LatLngBoundsExpression

Bounds for the map

layerControlOptions
Type : L.Control.LayersOptions

Describes the the zoom options (see: https://leafletjs.com/reference-1.3.4.html#control-layers)

mapId
Type : string

A map with the given ID is created inside this component. This ID can be used the get the map instance over the map cache service.

mapOptions
Type : L.MapOptions

The corresponding leaflet map options (see: https://leafletjs.com/reference-1.3.4.html#map-option)

overlayMaps
Type : LayerMap

Map, which holds all overlay map layer (see: https://leafletjs.com/reference-1.3.4.html#layer)

zoomControlOptions
Type : L.Control.ZoomOptions

Describes the the zoom control options (see: https://leafletjs.com/reference-1.3.4.html#control-zoom)

Outputs

mapInitialized
Type : EventEmitter<string>

Informs when initialization is done with map id.

import {
    DoCheck,
    EventEmitter,
    Input,
    KeyValueDiffer,
    KeyValueDiffers,
    OnChanges,
    OnDestroy,
    OnInit,
    Output,
    SimpleChanges,
} from '@angular/core';
import * as L from 'leaflet';

import { MapCache } from './map-cache.service';
import { LayerOptions, LayerMap } from './map-options';

const DEFAULT_BASE_LAYER_NAME = 'BaseLayer';
const DEFAULT_BASE_LAYER_URL = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
const DEFAULT_BASE_LAYER_ATTRIBUTION = '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors';

export abstract class CachedMapComponent implements OnChanges, DoCheck, OnDestroy, OnInit {

    /**
     * A map with the given ID is created inside this component. This ID can be used the get the map instance over the map cache service.
     */
    @Input()
    public mapId: string;

    /**
     * The corresponding leaflet map options (see: https://leafletjs.com/reference-1.3.4.html#map-option)
     */
    @Input()
    public mapOptions: L.MapOptions;

    /**
     * Bounds for the map
     */
    @Input()
    public fitBounds: L.LatLngBoundsExpression;

    /**
     * Map, which holds all overlay map layer (see: https://leafletjs.com/reference-1.3.4.html#layer)
     */
    @Input()
    public overlayMaps: LayerMap;

    /**
     * Map, which holds all base map layer (see: https://leafletjs.com/reference-1.3.4.html#layer)
     */
    @Input()
    public baseMaps: LayerMap;

    /**
     * Describes the the zoom options (see: https://leafletjs.com/reference-1.3.4.html#control-layers)
     */
    @Input()
    public layerControlOptions: L.Control.LayersOptions;

    /**
     * Describes the the zoom control options (see: https://leafletjs.com/reference-1.3.4.html#control-zoom)
     */
    @Input()
    public zoomControlOptions: L.Control.ZoomOptions;

    /**
     * Informs when initialization is done with map id.
     */
    @Output()
    public mapInitialized: EventEmitter<string> = new EventEmitter();

    /**
     * The map object.
     */
    protected map: L.Map;

    protected oldOverlayLayer: L.Control.LayersObject = {};
    protected oldBaseLayer: L.Control.LayersObject = {};
    protected layerControl: L.Control.Layers;
    protected zoomControl: L.Control.Zoom;

    private _overlayMaps: LayerMap;
    private _differOverlayMaps: KeyValueDiffer<string, LayerOptions>;
    private _baseMaps: LayerMap;
    private _differBaseMaps: KeyValueDiffer<string, LayerOptions>;

    constructor(
        protected mapCache: MapCache,
        protected kvDiffers: KeyValueDiffers
    ) {
        this._differOverlayMaps = this.kvDiffers.find({}).create();
        this._differBaseMaps = this.kvDiffers.find({}).create();
    }

    public ngOnInit(): void {
        if (this.mapId === undefined || this.mapId === null) {
            this.mapId = this.generateUUID();
        }
    }

    public ngOnChanges(changes: SimpleChanges): void {
        if (this.map) {
            if (changes.fitBounds) {
                this.map.fitBounds(this.fitBounds);
            }
            if (changes.zoomControlOptions) {
                this.updateZoomControl();
            }
        }
    }

    public ngDoCheck(): void {
        if (this._differOverlayMaps) {
            const changes = this._differOverlayMaps.diff(this.overlayMaps);
            if (changes) {
                changes.forEachRemovedItem((e) => this.removeOverlayMap(e.previousValue));
                changes.forEachAddedItem((e) => this.addOverlayMap(e.currentValue));
                this.updateLayerControl();
            }
        }
        if (this._differBaseMaps) {
            const changes = this._differBaseMaps.diff(this.baseMaps);
            if (changes) {
                changes.forEachRemovedItem((e) => this.removeBaseMap(e.previousValue));
                changes.forEachAddedItem((e) => this.addBaseMap(e.currentValue));
                this.updateLayerControl();
            }
        }
    }

    public ngOnDestroy(): void {
        this.map.remove();
        this.map = null;
        this.mapCache.deleteMap(this.mapId);
    }

    protected createMap(): void {
        if (!this.mapOptions || this.zoomControlOptions) { this.mapOptions = { zoomControl: false }; }
        this.map = L.map(this.mapId, this.mapOptions);
        this.mapCache.setMap(this.mapId, this.map);
        this.mapInitialized.emit(this.mapId);
        if (this.baseMaps && this.baseMaps.size > 0) {
            this.baseMaps.forEach((entry, key) => this.addBaseMap(entry));
        } else {
            this.addBaseMap();
        }
        if (this.overlayMaps) { this.overlayMaps.forEach((entry, key) => this.addOverlayMap(entry)); }
        this.updateZoomControl();
        this.updateLayerControl();
        if (this.fitBounds) {
            this.map.fitBounds(this.fitBounds);
        }
    }

    private generateUUID(): string {
        function s4() {
            return Math.floor((1 + Math.random()) * 0x10000)
                .toString(16)
                .substring(1);
        }
        return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
    }

    private addOverlayMap(layerOptions: LayerOptions) {
        if (this.map) {
            if (!this.oldOverlayLayer.hasOwnProperty[layerOptions.label]) {
                this.oldOverlayLayer[layerOptions.label] = layerOptions.layer;
                if (layerOptions.visible) { layerOptions.layer.addTo(this.map); }
            }
        }
    }

    private removeOverlayMap(layerOptions: LayerOptions) {
        if (this.map && this.oldOverlayLayer.hasOwnProperty(layerOptions.label)) {
            this.map.removeLayer(this.oldOverlayLayer[layerOptions.label]);
            delete this.oldOverlayLayer[layerOptions.label];
        }
    }

    private addBaseMap(layerOptions?: LayerOptions) {
        if (this.map) {
            if (!this.baseMaps || this.baseMaps.size === 0) {
                layerOptions = {
                    label: DEFAULT_BASE_LAYER_NAME,
                    visible: true,
                    layer: L.tileLayer(DEFAULT_BASE_LAYER_URL, {
                        attribution: DEFAULT_BASE_LAYER_ATTRIBUTION
                    })
                };
            }
            if (!this.oldBaseLayer.hasOwnProperty[layerOptions.label]) {
                this.oldBaseLayer[layerOptions.label] = layerOptions.layer;
                if (layerOptions.visible) { layerOptions.layer.addTo(this.map); }
            }
        }
    }

    private removeBaseMap(layerOptions: LayerOptions) {
        if (this.map && this.oldBaseLayer.hasOwnProperty(layerOptions.label)) {
            this.map.removeLayer(this.oldBaseLayer[layerOptions.label]);
            delete this.oldBaseLayer[layerOptions.label];
        }
    }

    private updateLayerControl() {
        if (this.map) {
            if (this.layerControl) {
                this.map.removeControl(this.layerControl);
            }
            if (this.layerControlOptions
                && (Object.keys(this.oldBaseLayer).length > 1 || Object.keys(this.oldOverlayLayer).length > 0)) {
                this.layerControl =
                    L.control.layers(this.oldBaseLayer, this.oldOverlayLayer, this.layerControlOptions).addTo(this.map);
            }
        }
    }

    private updateZoomControl() {
        if (this.zoomControl) { this.map.removeControl(this.zoomControl); }
        if (this.zoomControlOptions) {
            this.zoomControl = L.control.zoom(this.zoomControlOptions).addTo(this.map);
        }
    }
}

result-matching ""

    No results matching ""