File

libs/open-layers/src/lib/layers/ol-station-selector-layer/ol-station-selector-layer.component.ts

Description

Component to display station based on the input parameters. The component must be embedded as seen in the example:

Extends

OlBaseComponent

Example

<n52-ol-map>
<n52-ol-station-selector-layer [serviceUrl]="serviceUrl" [filter]="filter"></n52-ol-station-selector-layer>
</n52-ol-map>

Metadata

selector n52-ol-station-selector-layer

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(mapService: OlMapService, mapidService: OlMapId, servicesConnector: HelgolandServicesConnector)
Parameters :
Name Type Optional
mapService OlMapService No
mapidService OlMapId No
servicesConnector HelgolandServicesConnector No

Inputs

cluster
Default value : true

Cluster stations

filter
Type : HelgolandParameterFilter

The filter which should be used, while fetching the selection.

serviceUrl
Type : string

The serviceUrl, where the selection should be loaded.

zoomToResult
Default value : true

Zoom to the stations after collected and displayed

Outputs

onContentLoading
Type : EventEmitter<boolean>

Inform, while stations are loaded

onNoResultsFound
Type : EventEmitter<boolean>

Inform, when no stations are found

onSelected
Type : EventEmitter<HelgolandPlatform>

Inform, when a station is selected

Methods

Private createClickInteraction
createClickInteraction()
Returns : void
Private createClusterStyle
createClusterStyle(size: number)
Parameters :
Name Type Optional
size number No
Returns : {}
Private createFeatureList
createFeatureList(stations: HelgolandPlatform[])
Parameters :
Name Type Optional
stations HelgolandPlatform[] No
Returns : {}
Private createHoverInteraction
createHoverInteraction()
Returns : void
Private createLayer
createLayer(features: Feature[])
Parameters :
Name Type Optional
features Feature[] No
Returns : void
Private createMarkerStyle
createMarkerStyle()
Returns : Style
Private createStationGeometries
createStationGeometries()
Returns : void
Private drawGeometries
drawGeometries()
Returns : void
mapInitialized
mapInitialized(map: Map)
Parameters :
Name Type Optional
map Map No
Returns : void
Private styleClusterLayer
styleClusterLayer(feature: FeatureLike)
Parameters :
Name Type Optional
feature FeatureLike No
Returns : Style | []
Private zoomToFeatures
zoomToFeatures(features: Feature[])
Parameters :
Name Type Optional
features Feature[] No
Returns : void
Abstract mapInitialized
mapInitialized(map: Map)
Inherited from OlBaseComponent
Defined in OlBaseComponent:33

This method will be triggered, when the corrsponding map is initialized.

Parameters :
Name Type Optional Description
map Map No
  • the created map
Returns : any
ngAfterViewInit
ngAfterViewInit()
Inherited from OlBaseComponent
Defined in OlBaseComponent:24

Subscribes for the initialization of the map after view is initialized

Returns : void

Properties

Private layer
Type : VectorLayer
Private map
Type : Map
import { Component, EventEmitter, Host, Input, Output } from '@angular/core';
import { HelgolandParameterFilter, HelgolandPlatform, HelgolandServicesConnector, Required } from '@helgoland/core';
import { Feature, Map } from 'ol';
import { unlistenByKey } from 'ol/events';
import { click, pointerMove } from 'ol/events/condition';
import { extend } from 'ol/extent';
import { FeatureLike } from 'ol/Feature';
import Point from 'ol/geom/Point';
import { Select } from 'ol/interaction.js';
import VectorLayer from 'ol/layer/Vector';
import { Cluster } from 'ol/source';
import VectorSource from 'ol/source/Vector';
import { Circle, Fill, Stroke, Style, Text } from 'ol/style';

import { OlBaseComponent } from '../../ol-base.component';
import { OlMapService } from '../../services/map.service';
import { OlMapId } from '../../services/mapid.service';

/**
 * Component to display station based on the input parameters. The component must be embedded as seen in the example:
 *
 * @example
 * <n52-ol-map>
 *     <n52-ol-station-selector-layer [serviceUrl]="serviceUrl" [filter]="filter"></n52-ol-station-selector-layer>
 * </n52-ol-map>
 */
@Component({
  selector: 'n52-ol-station-selector-layer',
  template: '',
})
export class OlStationSelectorLayerComponent extends OlBaseComponent {

  /**
   * The serviceUrl, where the selection should be loaded.
   */
  @Required @Input() public serviceUrl: string;

  /**
   * The filter which should be used, while fetching the selection.
   */
  @Input() public filter: HelgolandParameterFilter;

  /**
   * Zoom to the stations after collected and displayed
   */
  @Input() public zoomToResult = true;

  /**
   * Cluster stations
   */
  @Input() public cluster = true;

  /**
   * Inform, when a station is selected
   */
  @Output() public onSelected: EventEmitter<HelgolandPlatform> = new EventEmitter<HelgolandPlatform>();

  /**
   * Inform, while stations are loaded
   */
  @Output() public onContentLoading: EventEmitter<boolean> = new EventEmitter();

  /**
   * Inform, when no stations are found
   */
  @Output() public onNoResultsFound: EventEmitter<boolean> = new EventEmitter();

  private map: Map;

  private layer: VectorLayer;

  constructor(
    protected mapService: OlMapService,
    @Host() protected mapidService: OlMapId,
    protected servicesConnector: HelgolandServicesConnector,
  ) {
    super(mapService, mapidService);
  }

  mapInitialized(map: Map) {
    this.map = map;
    this.drawGeometries();
  }

  private drawGeometries() {
    // TODO: on filter changes
    // TODO: draw marker for results
    this.createStationGeometries();
  }

  private createStationGeometries() {
    this.servicesConnector.getPlatforms(this.serviceUrl, this.filter)
      .subscribe((stations) => {
        const features: Feature[] = this.createFeatureList(stations);

        this.createLayer(features);

        this.createHoverInteraction();

        this.createClickInteraction();

        if (this.zoomToResult) {
          this.zoomToFeatures(features);
        }
      });
  }

  private createLayer(features: Feature[]) {
    if (this.cluster) {
      this.layer = new VectorLayer({
        source: new Cluster({
          distance: 100,
          source: new VectorSource({
            features
          })
        }),
        style: feature => this.styleClusterLayer(feature)
      });
    } else {
      this.layer = new VectorLayer({
        source: new VectorSource({
          features
        }),
        style: () => this.createMarkerStyle(),
      });
    }
    this.map.addLayer(this.layer);
  }

  private createFeatureList(stations: HelgolandPlatform[]) {
    const features: Feature[] = [];
    stations.forEach(st => {
      // TODO: add to service
      if (st.geometry.type === 'Point') {
        const point = new Point(st.geometry.coordinates);
        point.transform('EPSG:4326', this.map.getView().getProjection());
        const feature = new Feature(point);
        feature.set('station', st, true);
        features.push(feature);
      }
    });
    return features;
  }

  private createHoverInteraction() {
    if (this.cluster) {
      const hoverSelect = new Select({
        condition: pointerMove,
        style: feature => this.styleClusterLayer(feature),
        layers: [this.layer]
      });

      hoverSelect.on('select', (evt => {
        if (evt.selected.length >= 1) {
          const temp = hoverSelect.getFeatures().on('remove', () => {
            unlistenByKey(temp);
          });
        }
      }));
      this.map.addInteraction(hoverSelect);
    }
  }

  private createClickInteraction() {
    const clickSelect = new Select({
      condition: click,
      style: feature => this.cluster ? this.styleClusterLayer(feature) : this.createMarkerStyle(),
      layers: [this.layer]
    });
    clickSelect.on('select', (evt => {
      if (evt.selected.length >= 1) {
        if (evt.selected[0].getProperties().station) {
          this.onSelected.emit(evt.selected[0].getProperties().station);
        } else {
          const selectedFeatures = evt.selected[0].getProperties().features;
          if (selectedFeatures.length > 1) {
            clickSelect.getFeatures().clear();
            setTimeout(() => {
              this.zoomToFeatures(selectedFeatures);
            }, 10);
          } else if (selectedFeatures.length === 1) {
            this.onSelected.emit(selectedFeatures[0].getProperties().station);
          }
        }
      }
    }));
    this.map.addInteraction(clickSelect);
  }

  private styleClusterLayer(feature: FeatureLike): Style | Style[] {
    const size = feature.get('features').length;
    if (size > 1) {
      return this.createClusterStyle(size);
    } else {
      return this.createMarkerStyle();
    }
  }

  private createClusterStyle(size: number) {
    const color = size > 25 ? '248, 128, 0' : size > 8 ? '248, 192, 0' : '128, 192, 64';
    const radius = Math.max(8, Math.min(size * 0.75, 20));
    return [
      new Style({
        image: new Circle({
          radius: radius + 2,
          stroke: new Stroke({
            color: 'rgba(' + color + ',0.3)',
            width: 4
          })
        })
      }),
      new Style({
        image: new Circle({
          radius: radius,
          fill: new Fill({
            color: 'rgba(' + color + ',0.6)'
          })
        }),
        text: new Text({
          text: size.toString(),
          fill: new Fill({
            color: '#000'
          })
        })
      })
    ];
  }

  private zoomToFeatures(features: Feature[]) {
    if (features.length > 0) {
      const extent = features[0].getGeometry().getExtent().slice(0);
      features.forEach(f => extend(extent, f.getGeometry().getExtent()));
      this.map.getView().fit(extent, { duration: 300 });
    }
  }

  private createMarkerStyle(): Style {
    return new Style({
      image: new Circle({
        radius: 6,
        fill: new Fill({
          color: 'blue',
        })
      })
    });
  }
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""