]> git.openstreetmap.org Git - rails.git/blob - app/assets/javascripts/maplibre.map.js
Add `OSM.MapLibre` and `OSM.MapLibre.Styles`
[rails.git] / app / assets / javascripts / maplibre.map.js
1 //= require maplibre-gl/dist/maplibre-gl
2
3 OSM.MapLibre.Styles.Mapnik = {
4   version: 8,
5   sources: {
6     osm: {
7       type: "raster",
8       tiles: [
9         "https://tile.openstreetmap.org/{z}/{x}/{y}.png"
10       ],
11       tileSize: 256,
12       maxzoom: 19
13     }
14   },
15   layers: [
16     {
17       id: "osm",
18       type: "raster",
19       source: "osm"
20     }
21   ]
22 };
23
24 // Helper function to create Leaflet style (SVG comes from Leaflet) markers for MapLibre
25 // new maplibregl.Marker({ color: color }) is simpler, but does not have the exact same gradient
26 OSM.MapLibre.getMarker = function ({ icon = "dot", color = "var(--marker-red)", ...options }) {
27   const el = document.createElement("div");
28   el.className = "maplibre-gl-marker";
29   el.style.width = "25px";
30   el.style.height = "40px";
31
32   const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
33   svg.setAttribute("viewBox", "0 0 25 40");
34   svg.setAttribute("width", "25");
35   svg.setAttribute("height", "40");
36   svg.classList.add("pe-none");
37   svg.style.overflow = "visible";
38
39   // Use the marker icons from NoteMarker.svg
40   const use1 = document.createElementNS("http://www.w3.org/2000/svg", "use");
41   use1.setAttribute("href", "#pin-shadow");
42
43   const use2 = document.createElementNS("http://www.w3.org/2000/svg", "use");
44   use2.setAttribute("href", `#pin-${icon}`);
45   use2.setAttribute("color", color);
46   use2.classList.add("pe-auto");
47
48   svg.appendChild(use1);
49   svg.appendChild(use2);
50   el.appendChild(svg);
51
52   return new maplibregl.Marker({
53     element: el,
54     anchor: "bottom",
55     offset: [0, 0],
56     ...options
57   });
58 };
59
60 // Helper function to create MapLibre popups that don't overlap with Leaflets' markers
61 OSM.MapLibre.getPopup = function (content) {
62   // General offset 5px for each side, but the offset depends on the popup position:
63   // Popup above the marker -> lift it by height + 5px = 45px
64   // Popup left the marker -> lift it by width/2 + 5px = 22.5px ~= 17px
65   const offset = {
66     "bottom": [0, -45],
67     "bottom-left": [0, -45],
68     "bottom-right": [0, -45],
69     "top": [0, 5],
70     "top-left": [0, 5],
71     "top-right": [0, 5],
72     // our marker is bigger at the top, but this does not attach there -> tucked 2px more
73     "right": [-15, -10],
74     "left": [15, -10]
75   };
76   return new maplibregl.Popup({ offset }).setHTML(content);
77 };