|
1 | 1 | <script> |
2 | 2 | import { onMount, onDestroy } from "svelte"; |
3 | | - import L from "leaflet"; |
| 3 | + import L, { marker } from "leaflet"; |
4 | 4 | import "leaflet/dist/leaflet.css"; |
5 | 5 | import { createEventDispatcher } from "svelte"; |
6 | 6 |
|
|
11 | 11 |
|
12 | 12 | let mapElement; |
13 | 13 | let map; |
14 | | - let markerLayer; |
15 | | - let startZoom = 0; |
| 14 | + // Create a layers object to hold different marker type layers |
| 15 | + let markerLayer = null; |
16 | 16 | // Use the traditional event dispatcher |
17 | 17 | const dispatch = createEventDispatcher(); |
18 | 18 |
|
19 | 19 | let isFlying = false; // Track if map is currently in flyTo animation |
20 | 20 |
|
21 | | - let selectedMarker = null; |
22 | | -
|
| 21 | + let hoveredMarker = null; |
23 | 22 | function computeMarkerHtml(marker) { |
24 | 23 | const iconByType = { |
25 | 24 | adm1st: "map", |
|
63 | 62 | } |
64 | 63 | } |
65 | 64 | return ` |
66 | | - <div class="map-marker marker-size-${marker.sizeClass} ${ |
67 | | - marker.isSelected ? "marker-selected" : "" |
68 | | - }" > |
| 65 | + <div class="map-marker marker-display-${marker.displayClass}" > |
69 | 66 | <div class="marker-icon-circle"> |
70 | 67 | <img src="/icons/${icon}.svg"> |
71 | 68 | </div> |
|
97 | 94 | }) |
98 | 95 | .addTo(map); |
99 | 96 |
|
100 | | - // Create a layer group for markers |
| 97 | + // Create layer groups for different marker types |
| 98 | + for (const layerType of [ |
| 99 | + { name: "tinydot", zIndex: 100 }, |
| 100 | + { name: "dot", zIndex: 200 }, |
| 101 | + { name: "reduced", zIndex: 300 }, |
| 102 | + { name: "full", zIndex: 400 }, |
| 103 | + { name: "selected", zIndex: 500 }, |
| 104 | + ]) { |
| 105 | + map.createPane(layerType.name); |
| 106 | + map.getPane(layerType.name).style.zIndex = layerType.zIndex; |
| 107 | + } |
| 108 | +
|
101 | 109 | markerLayer = L.layerGroup().addTo(map); |
102 | 110 |
|
103 | 111 | // Add initial markers |
|
168 | 176 | // Function to update markers when the markers prop changes |
169 | 177 | function updateMarkers() { |
170 | 178 | if (!map || !markerLayer) return; |
171 | | -
|
172 | 179 | // Clear existing markers |
173 | 180 | markerLayer.clearLayers(); |
174 | | -
|
175 | 181 | // Add new markers |
176 | | - markers.forEach((marker) => { |
177 | | - // Set isSelected property based on selected marker |
178 | 182 |
|
| 183 | + const iconSizesByDisplayClass = { |
| 184 | + tinydot: [12, 12], |
| 185 | + dot: [18, 18], |
| 186 | + reduced: [28, 28], |
| 187 | + full: [128, 32], |
| 188 | + selected: [128, 32], |
| 189 | + }; |
| 190 | + markers.forEach((marker) => { |
179 | 191 | const markerHtml = computeMarkerHtml(marker); |
| 192 | + let displayClass = marker.displayClass; |
| 193 | + let pane = marker.displayClass; |
| 194 | + if (hoveredMarker === marker) { |
| 195 | + console.log("hovered"); |
| 196 | + displayClass = "full"; |
| 197 | + pane = "selected"; |
| 198 | + } |
180 | 199 | const icon = L.divIcon({ |
181 | 200 | className: "custom-div-icon", |
182 | 201 | html: markerHtml, |
183 | | - iconSize: [128, 32], |
| 202 | + iconSize: iconSizesByDisplayClass[displayClass], |
184 | 203 | }); |
| 204 | +
|
185 | 205 | const mapMarker = L.marker([marker.lat, marker.lon], { |
186 | 206 | icon: icon, |
187 | | - }).addTo(markerLayer); |
| 207 | + pane: pane, |
| 208 | + }); |
188 | 209 |
|
189 | 210 | // Add click handler to dispatch custom markerclick event |
190 | 211 | mapMarker.on("click", () => { |
191 | 212 | dispatch("markerclick", marker); |
192 | 213 | }); |
| 214 | + mapMarker.on("mouseover", () => { |
| 215 | + if (hoveredMarker !== marker) { |
| 216 | + hoveredMarker = marker; |
| 217 | + updateMarkers(); |
| 218 | + } |
| 219 | + }); |
| 220 | +
|
| 221 | + // Add marker to the appropriate layer based on its size class and selection state |
| 222 | + mapMarker.addTo(markerLayer); |
193 | 223 | }); |
194 | 224 | } |
195 | 225 |
|
|
233 | 263 | z-index: 1000 !important; /* Ensure hovered markers appear above others */ |
234 | 264 | } |
235 | 265 | &:hover > .marker-icon-circle, |
236 | | - &.marker-selected > .marker-icon-circle { |
| 266 | + &.marker-display-selected > .marker-icon-circle { |
237 | 267 | --circle-size: 32px !important; |
238 | 268 | box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.35); |
239 | 269 | z-index: 1000 !important; |
240 | 270 | } |
241 | 271 |
|
242 | | - &.marker-selected { |
| 272 | + &.marker-display-selected { |
243 | 273 | /* Ensure hovered markers appear above others */ |
244 | 274 | z-index: 1000 !important; |
245 | 275 | } |
246 | 276 |
|
247 | 277 | &:hover > .marker-text-container, |
248 | | - &.marker-selected > .marker-text-container { |
| 278 | + &.marker-display-selected > .marker-text-container { |
249 | 279 | visibility: visible; |
250 | 280 | opacity: 1; |
251 | 281 | } |
252 | 282 |
|
253 | | - &.marker-selected > .marker-icon-circle { |
| 283 | + &.marker-display-selected > .marker-icon-circle { |
254 | 284 | border: 6px solid #f00707; |
255 | 285 | box-shadow: 8px 8px 16px rgba(0, 0, 0, 0.95); |
256 | 286 | } |
257 | 287 |
|
258 | | - &.marker-size-full > .marker-text-container { |
| 288 | + &.marker-display-full > .marker-text-container { |
259 | 289 | visibility: visible; |
260 | 290 | opacity: 1; |
261 | 291 | } |
262 | 292 |
|
263 | | - &.marker-size-full > .marker-icon-circle { |
| 293 | + &.marker-display-full > .marker-icon-circle { |
264 | 294 | --circle-size: 32px; |
265 | 295 | box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.35); |
266 | 296 | } |
267 | 297 |
|
268 | | - &.marker-size-reduced > .marker-icon-circle { |
| 298 | + &.marker-display-reduced > .marker-icon-circle { |
269 | 299 | --circle-size: 24px; |
270 | 300 | } |
271 | 301 |
|
272 | | - &.marker-size-dot > .marker-icon-circle { |
| 302 | + &.marker-display-dot > .marker-icon-circle { |
273 | 303 | --circle-size: 12px; |
274 | 304 | } |
275 | 305 |
|
276 | | - &.marker-size-tinydot > .marker-icon-circle { |
| 306 | + &.marker-display-tinydot > .marker-icon-circle { |
277 | 307 | --circle-size: 4px; |
278 | 308 | } |
279 | 309 |
|
|
341 | 371 | color: white; |
342 | 372 | -webkit-text-stroke: 6px white; |
343 | 373 | text-stroke: 6px white; |
| 374 | + -webkit-text-stroke-linejoin: round; |
| 375 | + text-stroke-linejoin: round; |
344 | 376 | z-index: 1; |
345 | 377 | } |
346 | 378 | </style> |
0 commit comments