|
247 | 247 | }; |
248 | 248 | }); |
249 | 249 |
|
250 | | - const HIGHLIGHT_SOURCE_ID = 'elevation-selection'; |
251 | | - const HIGHLIGHT_LAYER_CASING_ID = 'elevation-selection-casing'; |
252 | | - const HIGHLIGHT_LAYER_ID = 'elevation-selection'; |
253 | | -
|
254 | 250 | onMount(async () => { |
255 | 251 | Chart.register((await import('chartjs-plugin-zoom')).default); // dynamic import to avoid SSR and 'window is not defined' error |
256 | 252 |
|
|
543 | 539 | } |
544 | 540 |
|
545 | 541 | $: $slicedGPXStatistics, $mode, updateOverlay(); |
546 | | - $: $slicedGPXStatistics, $gpxStatistics, $mode, $map, updateMapHighlight(); |
547 | | -
|
548 | | - function ensureHighlightLayers() { |
549 | | - if (!$map) return; |
550 | | - const map = $map as mapboxgl.Map; |
551 | | - if (!map.getSource(HIGHLIGHT_SOURCE_ID)) { |
552 | | - map.addSource(HIGHLIGHT_SOURCE_ID, { |
553 | | - type: 'geojson', |
554 | | - data: { |
555 | | - type: 'Feature', |
556 | | - geometry: { type: 'LineString', coordinates: [] }, |
557 | | - properties: {}, |
558 | | - }, |
559 | | - }); |
560 | | - } |
561 | | - if (!map.getLayer(HIGHLIGHT_LAYER_CASING_ID)) { |
562 | | - map.addLayer({ |
563 | | - id: HIGHLIGHT_LAYER_CASING_ID, |
564 | | - type: 'line', |
565 | | - source: HIGHLIGHT_SOURCE_ID, |
566 | | - layout: { 'line-join': 'round', 'line-cap': 'round' }, |
567 | | - paint: { |
568 | | - 'line-color': $mode === 'dark' ? '#ffffff' : '#000000', |
569 | | - 'line-width': 10, |
570 | | - 'line-opacity': 0.9, |
571 | | - 'line-blur': 0.2, |
572 | | - }, |
573 | | - }); |
574 | | - } |
575 | | - if (!map.getLayer(HIGHLIGHT_LAYER_ID)) { |
576 | | - map.addLayer({ |
577 | | - id: HIGHLIGHT_LAYER_ID, |
578 | | - type: 'line', |
579 | | - source: HIGHLIGHT_SOURCE_ID, |
580 | | - layout: { 'line-join': 'round', 'line-cap': 'round' }, |
581 | | - paint: { |
582 | | - 'line-color': '#ffeb3b', // bright yellow |
583 | | - 'line-width': 6, |
584 | | - 'line-opacity': 1, |
585 | | - }, |
586 | | - }); |
587 | | - } |
588 | | - try { |
589 | | - map.moveLayer(HIGHLIGHT_LAYER_CASING_ID); |
590 | | - map.moveLayer(HIGHLIGHT_LAYER_ID); |
591 | | - } catch (e) { |
592 | | - // ignore if already on top or not movable yet |
593 | | - } |
594 | | - } |
595 | | -
|
596 | | - function updateMapHighlight() { |
597 | | - if (!$map) return; |
598 | | - const map = $map as mapboxgl.Map; |
599 | | - if ($slicedGPXStatistics === undefined) { |
600 | | - if (map.getLayer(HIGHLIGHT_LAYER_ID)) map.removeLayer(HIGHLIGHT_LAYER_ID); |
601 | | - if (map.getLayer(HIGHLIGHT_LAYER_CASING_ID)) map.removeLayer(HIGHLIGHT_LAYER_CASING_ID); |
602 | | - if (map.getSource(HIGHLIGHT_SOURCE_ID)) map.removeSource(HIGHLIGHT_SOURCE_ID); |
603 | | - return; |
604 | | - } |
605 | | - if (!$gpxStatistics?.local?.points?.length) return; |
606 | | -
|
607 | | - let startIndex = Math.min($slicedGPXStatistics[1], $slicedGPXStatistics[2]); |
608 | | - let endIndex = Math.max($slicedGPXStatistics[1], $slicedGPXStatistics[2]); |
609 | | -
|
610 | | - startIndex = Math.max(0, Math.min(startIndex, $gpxStatistics.local.points.length - 1)); |
611 | | - endIndex = Math.max(0, Math.min(endIndex, $gpxStatistics.local.points.length - 1)); |
612 | | - if (endIndex <= startIndex) return; |
613 | | -
|
614 | | - const coords: [number, number][] = []; |
615 | | - for (let i = startIndex; i <= endIndex; i++) { |
616 | | - const c = $gpxStatistics.local.points[i].getCoordinates(); |
617 | | - coords.push([c.lon, c.lat]); |
618 | | - } |
619 | | -
|
620 | | - ensureHighlightLayers(); |
621 | | - const src = $map.getSource(HIGHLIGHT_SOURCE_ID) as mapboxgl.GeoJSONSource; |
622 | | - if (src) { |
623 | | - src.setData({ |
624 | | - type: 'Feature', |
625 | | - geometry: { type: 'LineString', coordinates: coords }, |
626 | | - properties: {}, |
627 | | - } as GeoJSON.Feature); |
628 | | - } |
629 | | - if ($map.getLayer(HIGHLIGHT_LAYER_CASING_ID)) { |
630 | | - $map.setPaintProperty( |
631 | | - HIGHLIGHT_LAYER_CASING_ID, |
632 | | - 'line-color', |
633 | | - $mode === 'dark' ? '#ffffff' : '#000000' |
634 | | - ); |
635 | | - } |
636 | | - try { |
637 | | - $map.moveLayer(HIGHLIGHT_LAYER_CASING_ID); |
638 | | - $map.moveLayer(HIGHLIGHT_LAYER_ID); |
639 | | - } catch (e) {} |
640 | | - } |
641 | | -
|
642 | | - let styledataHooked = false; |
643 | | - $: if ($map && !styledataHooked) { |
644 | | - updateMapHighlight(); |
645 | | - const handler = () => { |
646 | | - if ($slicedGPXStatistics) updateMapHighlight(); |
647 | | - }; |
648 | | - $map.on('styledata', handler); |
649 | | - styledataHooked = true; |
650 | | - onDestroy(() => { |
651 | | - if ($map) { |
652 | | - try { |
653 | | - $map.off('styledata', handler); |
654 | | - } catch (e) {} |
655 | | - if ($map.getLayer(HIGHLIGHT_LAYER_ID)) $map.removeLayer(HIGHLIGHT_LAYER_ID); |
656 | | - if ($map.getLayer(HIGHLIGHT_LAYER_CASING_ID)) |
657 | | - $map.removeLayer(HIGHLIGHT_LAYER_CASING_ID); |
658 | | - if ($map.getSource(HIGHLIGHT_SOURCE_ID)) $map.removeSource(HIGHLIGHT_SOURCE_ID); |
659 | | - } |
660 | | - }); |
661 | | - } |
662 | 542 |
|
663 | 543 | onDestroy(() => { |
664 | 544 | if (chart) { |
|
0 commit comments