summaryrefslogtreecommitdiff
path: root/client/simple/src/js/plugin/MapView.ts
blob: b1e199a571a91c1e96333693bf434277d1e893ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// SPDX-License-Identifier: AGPL-3.0-or-later

import "ol/ol.css?inline";
import { Feature, Map as OlMap, View } from "ol";
import { GeoJSON } from "ol/format";
import { Point } from "ol/geom";
import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer";
import { fromLonLat } from "ol/proj";
import { OSM, Vector as VectorSource } from "ol/source";
import { Circle, Fill, Stroke, Style } from "ol/style";
import { Plugin } from "../Plugin.ts";

/**
 * MapView
 */
export default class MapView extends Plugin {
  private readonly map: HTMLElement;

  public constructor(map: HTMLElement) {
    super("mapView");

    this.map = map;
  }

  protected async run(): Promise<void> {
    const { leafletTarget: target, mapLon, mapLat, mapGeojson } = this.map.dataset;

    const lon = Number.parseFloat(mapLon || "0");
    const lat = Number.parseFloat(mapLat || "0");
    const view = new View({ maxZoom: 16, enableRotation: false });
    const map = new OlMap({
      target: target,
      layers: [new TileLayer({ source: new OSM({ maxZoom: 16 }) })],
      view: view
    });

    try {
      const markerSource = new VectorSource({
        features: [
          new Feature({
            geometry: new Point(fromLonLat([lon, lat]))
          })
        ]
      });

      const markerLayer = new VectorLayer({
        source: markerSource,
        style: new Style({
          image: new Circle({
            radius: 6,
            fill: new Fill({ color: "#3050ff" })
          })
        })
      });

      map.addLayer(markerLayer);
    } catch (error) {
      console.error("Failed to create marker layer:", error);
    }

    if (mapGeojson) {
      try {
        const geoSource = new VectorSource({
          features: new GeoJSON().readFeatures(JSON.parse(mapGeojson), {
            dataProjection: "EPSG:4326",
            featureProjection: "EPSG:3857"
          })
        });

        const geoLayer = new VectorLayer({
          source: geoSource,
          style: new Style({
            stroke: new Stroke({ color: "#3050ff", width: 2 }),
            fill: new Fill({ color: "#3050ff33" })
          })
        });

        map.addLayer(geoLayer);

        view.fit(geoSource.getExtent(), { padding: [20, 20, 20, 20] });
      } catch (error) {
        console.error("Failed to create GeoJSON layer:", error);
      }
    }
  }

  protected async post(): Promise<void> {
    // noop
  }
}