mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-04-06 03:40:21 +00:00
Merge branch 'maplibre' into dev
This commit is contained in:
@@ -15,11 +15,12 @@
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { getURLForLanguage } from '$lib/utils';
|
||||
import { Trash2 } from '@lucide/svelte';
|
||||
import { ANCHOR_LAYER_KEY, map } from '$lib/components/map/map';
|
||||
import type { GeoJSONSource } from 'mapbox-gl';
|
||||
import { map } from '$lib/components/map/map';
|
||||
import type { GeoJSONSource } from 'maplibre-gl';
|
||||
import { selection } from '$lib/logic/selection';
|
||||
import { fileActions } from '$lib/logic/file-actions';
|
||||
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
||||
import { ANCHOR_LAYER_KEY } from '$lib/components/map/style';
|
||||
|
||||
let props: {
|
||||
class?: string;
|
||||
@@ -28,7 +29,7 @@
|
||||
let cleanType = $state(CleanType.INSIDE);
|
||||
let deleteTrackpoints = $state(true);
|
||||
let deleteWaypoints = $state(true);
|
||||
let rectangleCoordinates: mapboxgl.LngLat[] = $state([]);
|
||||
let rectangleCoordinates: maplibregl.LngLat[] = $state([]);
|
||||
|
||||
$effect(() => {
|
||||
if ($map) {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { ListItem, ListTrackSegmentItem } from '$lib/components/file-list/file-list';
|
||||
import { ANCHOR_LAYER_KEY, map } from '$lib/components/map/map';
|
||||
import { map } from '$lib/components/map/map';
|
||||
import { ANCHOR_LAYER_KEY } from '$lib/components/map/style';
|
||||
import { fileActions } from '$lib/logic/file-actions';
|
||||
import { GPXFileStateCollectionObserver, type GPXFileState } from '$lib/logic/file-state';
|
||||
import { selection } from '$lib/logic/selection';
|
||||
import { ramerDouglasPeucker, TrackPoint, type SimplifiedTrackPoint } from 'gpx';
|
||||
import type { GeoJSONSource } from 'mapbox-gl';
|
||||
import type { GeoJSONSource } from 'maplibre-gl';
|
||||
import { get, writable } from 'svelte/store';
|
||||
|
||||
export const minTolerance = 0.1;
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
}: {
|
||||
minimized?: boolean;
|
||||
minimizable?: boolean;
|
||||
popup?: mapboxgl.Popup;
|
||||
popup?: maplibregl.Popup;
|
||||
popupElement?: HTMLDivElement;
|
||||
class?: string;
|
||||
} = $props();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,15 +2,21 @@ import { ramerDouglasPeucker, type GPXFile, type TrackSegment } from 'gpx';
|
||||
|
||||
const earthRadius = 6371008.8;
|
||||
|
||||
export const MIN_ANCHOR_ZOOM = 0;
|
||||
export const MAX_ANCHOR_ZOOM = 22;
|
||||
|
||||
export function getZoomLevelForDistance(latitude: number, distance?: number): number {
|
||||
if (distance === undefined) {
|
||||
return 0;
|
||||
return MIN_ANCHOR_ZOOM;
|
||||
}
|
||||
|
||||
const rad = Math.PI / 180;
|
||||
const lat = latitude * rad;
|
||||
|
||||
return Math.min(22, Math.max(0, Math.log2((earthRadius * Math.cos(lat)) / distance)));
|
||||
return Math.min(
|
||||
MAX_ANCHOR_ZOOM,
|
||||
Math.max(MIN_ANCHOR_ZOOM, Math.round(Math.log2((earthRadius * Math.cos(lat)) / distance)))
|
||||
);
|
||||
}
|
||||
|
||||
export function updateAnchorPoints(file: GPXFile) {
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
onMount(() => {
|
||||
if ($map) {
|
||||
splitControls = new SplitControls($map);
|
||||
splitControls = new SplitControls($map, map.layerEventManager!);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -8,40 +8,33 @@ import { get } from 'svelte/store';
|
||||
import { fileStateCollection } from '$lib/logic/file-state';
|
||||
import { fileActions } from '$lib/logic/file-actions';
|
||||
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
||||
import { ANCHOR_LAYER_KEY } from '$lib/components/map/map';
|
||||
import type { GeoJSONSource } from 'maplibre-gl';
|
||||
import { ANCHOR_LAYER_KEY } from '$lib/components/map/style';
|
||||
import type { MapLayerEventManager } from '$lib/components/map/map-layer-event-manager';
|
||||
import { loadSVGIcon } from '$lib/utils';
|
||||
|
||||
export class SplitControls {
|
||||
map: mapboxgl.Map;
|
||||
map: maplibregl.Map;
|
||||
layerEventManager: MapLayerEventManager;
|
||||
unsubscribes: Function[] = [];
|
||||
|
||||
layerOnMouseEnterBinded: (e: any) => void = this.layerOnMouseEnter.bind(this);
|
||||
layerOnMouseLeaveBinded: () => void = this.layerOnMouseLeave.bind(this);
|
||||
layerOnClickBinded: (e: any) => void = this.layerOnClick.bind(this);
|
||||
|
||||
constructor(map: mapboxgl.Map) {
|
||||
constructor(map: maplibregl.Map, layerEventManager: MapLayerEventManager) {
|
||||
this.map = map;
|
||||
|
||||
if (!this.map.hasImage('split-control')) {
|
||||
let icon = new Image(100, 100);
|
||||
icon.onload = () => {
|
||||
if (!this.map.hasImage('split-control')) {
|
||||
this.map.addImage('split-control', icon);
|
||||
}
|
||||
};
|
||||
|
||||
// Lucide icons are SVG files with a 24x24 viewBox
|
||||
// Create a new SVG with a 32x32 viewBox and center the icon in a circle
|
||||
icon.src =
|
||||
'data:image/svg+xml,' +
|
||||
encodeURIComponent(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">
|
||||
<circle cx="20" cy="20" r="20" fill="white" />
|
||||
<g transform="translate(8 8)">
|
||||
${Scissors.replace('stroke="currentColor"', 'stroke="black"')}
|
||||
</g>
|
||||
</svg>
|
||||
`);
|
||||
}
|
||||
this.layerEventManager = layerEventManager;
|
||||
loadSVGIcon(
|
||||
this.map,
|
||||
'split-control',
|
||||
`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">
|
||||
<circle cx="20" cy="20" r="20" fill="white" />
|
||||
<g transform="translate(8 8)">
|
||||
${Scissors.replace('stroke="currentColor"', 'stroke="black"')}
|
||||
</g>
|
||||
</svg>`
|
||||
);
|
||||
|
||||
this.unsubscribes.push(gpxStatistics.subscribe(this.addIfNeeded.bind(this)));
|
||||
this.unsubscribes.push(currentTool.subscribe(this.addIfNeeded.bind(this)));
|
||||
@@ -98,7 +91,7 @@ export class SplitControls {
|
||||
}, false);
|
||||
|
||||
try {
|
||||
let source = this.map.getSource('split-controls') as mapboxgl.GeoJSONSource | undefined;
|
||||
let source = this.map.getSource('split-controls') as GeoJSONSource | undefined;
|
||||
if (source) {
|
||||
source.setData(data);
|
||||
} else {
|
||||
@@ -124,9 +117,17 @@ export class SplitControls {
|
||||
ANCHOR_LAYER_KEY.interactions
|
||||
);
|
||||
|
||||
this.map.on('mouseenter', 'split-controls', this.layerOnMouseEnterBinded);
|
||||
this.map.on('mouseleave', 'split-controls', this.layerOnMouseLeaveBinded);
|
||||
this.map.on('click', 'split-controls', this.layerOnClickBinded);
|
||||
this.layerEventManager.on(
|
||||
'mouseenter',
|
||||
'split-controls',
|
||||
this.layerOnMouseEnterBinded
|
||||
);
|
||||
this.layerEventManager.on(
|
||||
'mouseleave',
|
||||
'split-controls',
|
||||
this.layerOnMouseLeaveBinded
|
||||
);
|
||||
this.layerEventManager.on('click', 'split-controls', this.layerOnClickBinded);
|
||||
}
|
||||
} catch (e) {
|
||||
// No reliable way to check if the map is ready to add sources and layers
|
||||
@@ -134,9 +135,9 @@ export class SplitControls {
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.map.off('mouseenter', 'split-controls', this.layerOnMouseEnterBinded);
|
||||
this.map.off('mouseleave', 'split-controls', this.layerOnMouseLeaveBinded);
|
||||
this.map.off('click', 'split-controls', this.layerOnClickBinded);
|
||||
this.layerEventManager.off('mouseenter', 'split-controls', this.layerOnMouseEnterBinded);
|
||||
this.layerEventManager.off('mouseleave', 'split-controls', this.layerOnMouseLeaveBinded);
|
||||
this.layerEventManager.off('click', 'split-controls', this.layerOnClickBinded);
|
||||
|
||||
try {
|
||||
if (this.map.getLayer('split-controls')) {
|
||||
@@ -159,7 +160,7 @@ export class SplitControls {
|
||||
mapCursor.notify(MapCursorState.SPLIT_CONTROL, false);
|
||||
}
|
||||
|
||||
layerOnClick(e: mapboxgl.MapMouseEvent) {
|
||||
layerOnClick(e: maplibregl.MapLayerMouseEvent) {
|
||||
let coordinates = (e.features![0].geometry as GeoJSON.Point).coordinates;
|
||||
fileActions.split(
|
||||
get(splitAs),
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
import { fileActions } from '$lib/logic/file-actions';
|
||||
import { map } from '$lib/components/map/map';
|
||||
import { mapCursor, MapCursorState } from '$lib/logic/map-cursor';
|
||||
import mapboxgl from 'mapbox-gl';
|
||||
import maplibregl from 'maplibre-gl';
|
||||
import { getSvgForSymbol } from '$lib/components/map/gpx-layer/gpx-layer';
|
||||
|
||||
let props: {
|
||||
@@ -41,7 +41,7 @@
|
||||
})
|
||||
);
|
||||
|
||||
let marker: mapboxgl.Marker | null = null;
|
||||
let marker: maplibregl.Marker | null = null;
|
||||
|
||||
function reset() {
|
||||
if ($selectedWaypoint) {
|
||||
@@ -125,7 +125,7 @@
|
||||
let element = document.createElement('div');
|
||||
element.classList.add('w-8', 'h-8');
|
||||
element.innerHTML = getSvgForSymbol(symbolKey);
|
||||
marker = new mapboxgl.Marker({
|
||||
marker = new maplibregl.Marker({
|
||||
element,
|
||||
anchor: 'bottom',
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user