File

components/map/map.component.ts

Description

Leaflet map with layers showing NSHM boundary, fault sections, and test sites.

Metadata

Index

Properties
Methods

Constructor

constructor(service: AppService, zone: NgZone)
Parameters :
Name Type Optional
service AppService No
zone NgZone No

Methods

Private mapOff
mapOff(map: L.Map, event: "baselayerchange" | "zoom")

Turn off map event.

Parameters :
Name Type Optional Description
map L.Map No

The map

event "baselayerchange" | "zoom" No

The event to turn off

Returns : void
Private onMap
onMap(map: L.Map, layers: Layers, model: NshmId)

Handle event on map, layers, and control form.

Set on zoom event and add attribution.

Parameters :
Name Type Optional Description
map L.Map No

The map

layers Layers No

Leaflet layers

model NshmId No

NSHM

Returns : void
onMapReady
onMapReady(map: L.Map)

Handle on map event.

Set map and main events.

Parameters :
Name Type Optional Description
map L.Map No

The leaflet map

Returns : void
Private onTestSitesZoom
onTestSitesZoom(testSitesLayer: L.GeoJSON, zoom: number, model: NshmId)

Open tooltip on test sites if zoomed in.

Parameters :
Name Type Optional Description
testSitesLayer L.GeoJSON No

The test sites layer

zoom number No

Map zoom number

model NshmId No

NSHM

Returns : void
Private onZoom
onZoom(layers: Layers, zoom: number, model: NshmId)

On zoom event function.

Parameters :
Name Type Optional Description
layers Layers No

The layers

zoom number No

Map zoom level

model NshmId No

NSHM

Returns : void
Private testSitesTooltipClose
testSitesTooltipClose(testSitesLayer: L.GeoJSON)

Close test sites tooltips.

Parameters :
Name Type Optional Description
testSitesLayer L.GeoJSON No

The test sites layer

Returns : void
Private testSitesTooltipOpen
testSitesTooltipOpen(testSitesLayer: L.GeoJSON)

Open test sites tooltips.

Parameters :
Name Type Optional Description
testSitesLayer L.GeoJSON No

The test sites layer

Returns : void

Properties

bounds
Default value : this.service.bounds

Map bounds state

formGroup
Default value : this.service.formGroup

Form field state

layers
Default value : this.service.layers

Map layers state

Readonly mapEl
Default value : viewChild<ElementRef<HTMLElement>>('map')
mapOptions
Default value : this.service.mapOptions

Map options state

mousePositionControl
Default value : new mapUtils.MousePosition()

Leaflet mouse position control

Public service
Type : AppService
siteZoomLevel
Type : Partial<Record<NshmId, number>>
Default value : { ALASKA_2023: 8, CONUS_2018: 7, CONUS_2023: 9, HAWAII_2021: 9, }

Zoom levels for certain NSHMs

import {Component, effect, ElementRef, NgZone, viewChild} from '@angular/core';
import {LeafletModule} from '@bluehalo/ngx-leaflet';
import {
  mapUtils,
  NshmpLibNgMapBaseLayersControlComponent,
  NshmpLibNgMapLeafletControlComponent,
} from '@ghsc/nshmp-lib-ng/map';
import {NshmId} from '@ghsc/nshmp-utils-ts/libs/nshmp-lib/nshm';
import * as L from 'leaflet';

import {Layers} from '../../models/layers.model';
import {AppService} from '../../services/app.service';
import {LegendComponent} from '../legend/legend.component';

/**
 * Leaflet map with layers showing NSHM boundary, fault sections, and test sites.
 */
@Component({
  imports: [
    LegendComponent,
    LeafletModule,
    NshmpLibNgMapLeafletControlComponent,
    NshmpLibNgMapBaseLayersControlComponent,
  ],
  selector: 'app-map',
  styleUrl: './map.component.scss',
  templateUrl: './map.component.html',
})
export class MapComponent {
  /** Leaflet mouse position control */
  mousePositionControl = new mapUtils.MousePosition();

  /** Zoom levels for certain NSHMs */
  siteZoomLevel: Partial<Record<NshmId, number>> = {
    ALASKA_2023: 8,
    CONUS_2018: 7,
    CONUS_2023: 9,
    HAWAII_2021: 9,
  };

  /** Map bounds state */
  bounds = this.service.bounds;
  /** Form field state */
  formGroup = this.service.formGroup;
  /** Map layers state */
  layers = this.service.layers;
  /** Map options state */
  mapOptions = this.service.mapOptions;

  readonly mapEl = viewChild<ElementRef<HTMLElement>>('map');

  constructor(
    public service: AppService,
    private zone: NgZone,
  ) {
    effect(() => {
      this.onMap(
        this.service.map(),
        this.layers(),
        this.formGroup.getRawValue().model,
      );
    });
  }

  /**
   * Handle on map event.
   *
   * Set map and main events.
   *
   * @param map The leaflet map
   */
  onMapReady(map: L.Map): void {
    this.service.map = map;

    map.on('click', () =>
      this.zone.run(() => {
        this.service.resetLayers();
        this.service.updateState({
          earthquakeInfoPopupData:
            this.service.initialState().earthquakeInfoPopupData,
          infoPopupData: this.service.initialState().infoPopupData,
        });
      }),
    );

    if (!L.Browser.mobile) {
      this.mousePositionControl.addTo(map);
    }

    L.control.scale({position: 'bottomleft'}).addTo(map);
  }

  /**
   * Turn off map event.
   *
   * @param map The map
   * @param event The event to turn off
   */
  private mapOff(map: L.Map, event: 'baselayerchange' | 'zoom'): void {
    if (map.listens(event)) {
      map.off(event);
    }
  }

  /**
   * Handle event on map, layers, and control form.
   *
   * Set on zoom event and add attribution.
   *
   * @param map The map
   * @param layers Leaflet layers
   * @param model NSHM
   */
  private onMap(map: L.Map, layers: Layers, model: NshmId): void {
    if (!map || !layers) {
      return;
    }

    this.mapOff(map, 'zoom');
    map.on('zoom', () => this.onZoom(layers, map.getZoom(), model));

    map.attributionControl.addAttribution(layers.baseLayer.getAttribution());
  }

  /**
   * Open tooltip on test sites if zoomed in.
   *
   * @param testSitesLayer The test sites layer
   * @param zoom Map zoom number
   * @param model NSHM
   */
  private onTestSitesZoom(
    testSitesLayer: L.GeoJSON,
    zoom: number,
    model: NshmId,
  ): void {
    if (zoom >= this.siteZoomLevel[model]) {
      this.testSitesTooltipOpen(testSitesLayer);
    } else {
      this.testSitesTooltipClose(testSitesLayer);
    }
  }

  /**
   * On zoom event function.
   *
   * @param layers The layers
   * @param zoom Map zoom level
   * @param model NSHM
   */
  private onZoom(layers: Layers, zoom: number, model: NshmId) {
    if (layers.testSitesLayer) {
      this.onTestSitesZoom(layers.testSitesLayer, zoom, model);
    }

    if (layers.faultSectionLayer) {
      layers.faultSectionLayer.setStyle({
        weight: this.service.faultsWeight(),
      });
    }
  }

  /**
   * Close test sites tooltips.
   * @param testSitesLayer The test sites layer
   */
  private testSitesTooltipClose(testSitesLayer: L.GeoJSON): void {
    testSitesLayer.getLayers().forEach(layer => {
      const tooltip = layer.getTooltip();
      layer.unbindTooltip();

      layer.bindTooltip(tooltip, {
        permanent: false,
      });

      layer.closeTooltip();
    });
  }

  /**
   * Open test sites tooltips.
   *
   * @param testSitesLayer The test sites layer
   */
  private testSitesTooltipOpen(testSitesLayer: L.GeoJSON): void {
    testSitesLayer.getLayers().forEach(layer => {
      if (!layer.isTooltipOpen()) {
        const tooltip = layer.getTooltip();
        layer.unbindTooltip();

        layer.bindTooltip(tooltip, {
          permanent: true,
        });

        layer.openTooltip();
      }
    });
  }
}
<div
  class="map"
  #map
  leaflet
  [leafletOptions]="mapOptions()"
  [leafletFitBounds]="bounds()"
  (leafletMapReady)="onMapReady($event)"
>
  <!-- Base layer -->
  @if (layers()?.baseLayer; as baseLayer) {
    <div [leafletLayer]="baseLayer"></div>
  }

  <!-- Decollement layer -->
  @if (formGroup?.value?.hasDecollementLayer) {
    <div [leafletLayer]="layers()?.decollementLayer"></div>
  }

  <!-- Fault sections layer -->
  @if (formGroup?.value?.hasFaultSectionLayer) {
    <div [leafletLayer]="layers()?.faultSectionLayer"></div>
  }

  <!-- Interface sections layer -->
  @if (formGroup?.value?.hasInterfaceSectionsLayer) {
    <div [leafletLayer]="layers()?.interfaceSectionsLayer"></div>
  }

  <!-- Zone sources layer -->
  @if (formGroup?.value?.hasZoneSourcesLayer) {
    <div [leafletLayer]="layers()?.zoneSourcesLayer"></div>
  }

  <!-- Test sites layer -->
  @if (formGroup?.value?.hasTestSitesLayer) {
    <div [leafletLayer]="layers()?.testSitesLayer"></div>
  }

  <!-- NSHM boundary layer -->
  @if (formGroup?.value?.hasNshmBoundaryLayer) {
    <div [leafletLayer]="layers()?.nshmBoundaryLayer"></div>
  }

  <!-- Hazard map layer-->
  @if (formGroup?.value?.hasHazardTiles) {
    <div [leafletLayer]="layers()?.hazardLayer"></div>
  }

  <!-- Earthquakes layer-->
  @if (formGroup?.value?.hasEarthquakesLayer) {
    <div [leafletLayer]="layers()?.earthquakesLayer"></div>
  }
</div>

<!-- Base layers control -->
<nshmp-lib-ng-map-base-layers-control
  [map]="service.map()"
  (baseLayerChanged)="service.baseLayer($event)"
/>

<nshmp-lib-ng-map-leaflet-control
  icon="leaflet-legend.svg"
  id="custom-map-legend-control"
  [map]="service.map()"
  position="topright"
  title="Legend"
>
  <app-legend />
</nshmp-lib-ng-map-leaflet-control>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""