mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-08-31 23:53:25 +00:00
improve mapillary integration, closes #127
This commit is contained in:
@@ -1,16 +1,17 @@
|
|||||||
import mapboxgl from "mapbox-gl";
|
import mapboxgl, { type LayerSpecification, type VectorSourceSpecification } from "mapbox-gl";
|
||||||
import { Viewer } from 'mapillary-js/dist/mapillary.module';
|
import { Viewer, type ViewerBearingEvent } from 'mapillary-js/dist/mapillary.module';
|
||||||
import 'mapillary-js/dist/mapillary.css';
|
import 'mapillary-js/dist/mapillary.css';
|
||||||
import { resetCursor, setPointerCursor } from "$lib/utils";
|
import { resetCursor, setPointerCursor } from "$lib/utils";
|
||||||
|
import type { Writable } from "svelte/store";
|
||||||
|
|
||||||
const mapillarySource = {
|
const mapillarySource: VectorSourceSpecification = {
|
||||||
type: 'vector',
|
type: 'vector',
|
||||||
tiles: ['https://tiles.mapillary.com/maps/vtp/mly1_computed_public/2/{z}/{x}/{y}?access_token=MLY|4381405525255083|3204871ec181638c3c31320490f03011'],
|
tiles: ['https://tiles.mapillary.com/maps/vtp/mly1_computed_public/2/{z}/{x}/{y}?access_token=MLY|4381405525255083|3204871ec181638c3c31320490f03011'],
|
||||||
minzoom: 6,
|
minzoom: 6,
|
||||||
maxzoom: 14,
|
maxzoom: 14,
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapillarySequenceLayer = {
|
const mapillarySequenceLayer: LayerSpecification = {
|
||||||
id: 'mapillary-sequence',
|
id: 'mapillary-sequence',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
source: 'mapillary',
|
source: 'mapillary',
|
||||||
@@ -26,7 +27,7 @@ const mapillarySequenceLayer = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapillaryImageLayer = {
|
const mapillaryImageLayer: LayerSpecification = {
|
||||||
id: 'mapillary-image',
|
id: 'mapillary-image',
|
||||||
type: 'circle',
|
type: 'circle',
|
||||||
source: 'mapillary',
|
source: 'mapillary',
|
||||||
@@ -40,35 +41,56 @@ const mapillaryImageLayer = {
|
|||||||
|
|
||||||
export class MapillaryLayer {
|
export class MapillaryLayer {
|
||||||
map: mapboxgl.Map;
|
map: mapboxgl.Map;
|
||||||
popup: mapboxgl.Popup;
|
marker: mapboxgl.Marker;
|
||||||
viewer: Viewer;
|
viewer: Viewer;
|
||||||
|
|
||||||
|
active = false;
|
||||||
|
popupOpen: Writable<boolean>;
|
||||||
|
|
||||||
addBinded = this.add.bind(this);
|
addBinded = this.add.bind(this);
|
||||||
onMouseEnterBinded = this.onMouseEnter.bind(this);
|
onMouseEnterBinded = this.onMouseEnter.bind(this);
|
||||||
onMouseLeaveBinded = this.onMouseLeave.bind(this);
|
onMouseLeaveBinded = this.onMouseLeave.bind(this);
|
||||||
|
|
||||||
constructor(map: mapboxgl.Map, container: HTMLElement) {
|
constructor(map: mapboxgl.Map, container: HTMLElement, popupOpen: Writable<boolean>) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
|
|
||||||
this.viewer = new Viewer({
|
this.viewer = new Viewer({
|
||||||
accessToken: 'MLY|4381405525255083|3204871ec181638c3c31320490f03011',
|
accessToken: 'MLY|4381405525255083|3204871ec181638c3c31320490f03011',
|
||||||
container,
|
container,
|
||||||
});
|
});
|
||||||
container.classList.remove('hidden');
|
|
||||||
|
|
||||||
this.popup = new mapboxgl.Popup({
|
const element = document.createElement('div');
|
||||||
closeButton: false,
|
element.className = 'mapboxgl-user-location mapboxgl-user-location-show-heading';
|
||||||
maxWidth: container.style.width,
|
const dot = document.createElement('div');
|
||||||
}).setDOMContent(container);
|
dot.className = 'mapboxgl-user-location-dot';
|
||||||
|
const heading = document.createElement('div');
|
||||||
|
heading.className = 'mapboxgl-user-location-heading';
|
||||||
|
element.appendChild(dot);
|
||||||
|
element.appendChild(heading);
|
||||||
|
|
||||||
|
this.marker = new mapboxgl.Marker({
|
||||||
|
rotationAlignment: 'map',
|
||||||
|
element
|
||||||
|
});
|
||||||
|
|
||||||
this.viewer.on('position', async () => {
|
this.viewer.on('position', async () => {
|
||||||
if (this.popup.isOpen()) {
|
if (this.active) {
|
||||||
|
popupOpen.set(true);
|
||||||
let latLng = await this.viewer.getPosition();
|
let latLng = await this.viewer.getPosition();
|
||||||
this.popup.setLngLat(latLng);
|
this.marker.setLngLat(latLng).addTo(this.map);
|
||||||
if (!this.map.getBounds().contains(latLng)) {
|
if (!this.map.getBounds()?.contains(latLng)) {
|
||||||
this.map.panTo(latLng);
|
this.map.panTo(latLng);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.viewer.on('bearing', (e: ViewerBearingEvent) => {
|
||||||
|
if (this.active) {
|
||||||
|
this.marker.setRotation(e.bearing);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.popupOpen = popupOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
add() {
|
add() {
|
||||||
@@ -101,15 +123,19 @@ export class MapillaryLayer {
|
|||||||
this.map.removeSource('mapillary');
|
this.map.removeSource('mapillary');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.popup.remove();
|
this.marker.remove();
|
||||||
|
this.popupOpen.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
closePopup() {
|
closePopup() {
|
||||||
this.popup.remove();
|
this.active = false;
|
||||||
|
this.marker.remove();
|
||||||
|
this.popupOpen.set(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseEnter(e: mapboxgl.MapLayerMouseEvent) {
|
onMouseEnter(e: mapboxgl.MapMouseEvent) {
|
||||||
this.popup.addTo(this.map).setLngLat(e.lngLat);
|
this.active = true;
|
||||||
|
|
||||||
this.viewer.resize();
|
this.viewer.resize();
|
||||||
this.viewer.moveTo(e.features[0].properties.id);
|
this.viewer.moveTo(e.features[0].properties.id);
|
||||||
|
|
||||||
|
@@ -8,16 +8,18 @@
|
|||||||
import { map, streetViewEnabled } from '$lib/stores';
|
import { map, streetViewEnabled } from '$lib/stores';
|
||||||
import { settings } from '$lib/db';
|
import { settings } from '$lib/db';
|
||||||
import { _ } from 'svelte-i18n';
|
import { _ } from 'svelte-i18n';
|
||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
const { streetViewSource } = settings;
|
const { streetViewSource } = settings;
|
||||||
|
|
||||||
let googleRedirect: GoogleRedirect;
|
let googleRedirect: GoogleRedirect;
|
||||||
let mapillaryLayer: MapillaryLayer;
|
let mapillaryLayer: MapillaryLayer;
|
||||||
|
let mapillaryOpen = writable(false);
|
||||||
let container: HTMLElement;
|
let container: HTMLElement;
|
||||||
|
|
||||||
$: if ($map) {
|
$: if ($map) {
|
||||||
googleRedirect = new GoogleRedirect($map);
|
googleRedirect = new GoogleRedirect($map);
|
||||||
mapillaryLayer = new MapillaryLayer($map, container);
|
mapillaryLayer = new MapillaryLayer($map, container, mapillaryOpen);
|
||||||
}
|
}
|
||||||
|
|
||||||
$: if (mapillaryLayer) {
|
$: if (mapillaryLayer) {
|
||||||
@@ -53,7 +55,9 @@
|
|||||||
|
|
||||||
<div
|
<div
|
||||||
bind:this={container}
|
bind:this={container}
|
||||||
class="hidden relative w-[50vw] h-[40vh] rounded-md border-background border-2"
|
class="{$mapillaryOpen
|
||||||
|
? ''
|
||||||
|
: 'hidden'} !absolute bottom-[44px] right-2.5 z-10 w-[40%] h-[40%] bg-background rounded-md overflow-hidden border-background border-2"
|
||||||
>
|
>
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
|
@@ -3,7 +3,6 @@ import { TrackPoint, distance } from "gpx";
|
|||||||
import { derived, get, writable } from "svelte/store";
|
import { derived, get, writable } from "svelte/store";
|
||||||
import { settings } from "$lib/db";
|
import { settings } from "$lib/db";
|
||||||
import { _, isLoading, locale } from "svelte-i18n";
|
import { _, isLoading, locale } from "svelte-i18n";
|
||||||
import { map } from "$lib/stores";
|
|
||||||
import { getElevation } from "$lib/utils";
|
import { getElevation } from "$lib/utils";
|
||||||
|
|
||||||
const { routing, routingProfile, privateRoads } = settings;
|
const { routing, routingProfile, privateRoads } = settings;
|
||||||
|
@@ -2,16 +2,15 @@ import { distance, type Coordinates, TrackPoint, TrackSegment, Track, projectedP
|
|||||||
import { get, writable, type Readable } from "svelte/store";
|
import { get, writable, type Readable } from "svelte/store";
|
||||||
import mapboxgl from "mapbox-gl";
|
import mapboxgl from "mapbox-gl";
|
||||||
import { route } from "./Routing";
|
import { route } from "./Routing";
|
||||||
|
|
||||||
import { toast } from "svelte-sonner";
|
import { toast } from "svelte-sonner";
|
||||||
|
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { dbUtils, type GPXFileWithStatistics } from "$lib/db";
|
import { dbUtils, settings, type GPXFileWithStatistics } from "$lib/db";
|
||||||
import { getOrderedSelection, selection } from "$lib/components/file-list/Selection";
|
import { getOrderedSelection, selection } from "$lib/components/file-list/Selection";
|
||||||
import { ListFileItem, ListTrackItem, ListTrackSegmentItem } from "$lib/components/file-list/FileList";
|
import { ListFileItem, ListTrackItem, ListTrackSegmentItem } from "$lib/components/file-list/FileList";
|
||||||
import { currentTool, streetViewEnabled, Tool } from "$lib/stores";
|
import { currentTool, streetViewEnabled, Tool } from "$lib/stores";
|
||||||
import { getClosestLinePoint, resetCursor, setGrabbingCursor } from "$lib/utils";
|
import { getClosestLinePoint, resetCursor, setGrabbingCursor } from "$lib/utils";
|
||||||
|
|
||||||
|
const { streetViewSource } = settings;
|
||||||
export const canChangeStart = writable(false);
|
export const canChangeStart = writable(false);
|
||||||
|
|
||||||
function stopPropagation(e: any) {
|
function stopPropagation(e: any) {
|
||||||
@@ -458,7 +457,7 @@ export class RoutingControls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async appendAnchor(e: mapboxgl.MapMouseEvent) { // Add a new anchor to the end of the last segment
|
async appendAnchor(e: mapboxgl.MapMouseEvent) { // Add a new anchor to the end of the last segment
|
||||||
if (get(streetViewEnabled)) {
|
if (get(streetViewEnabled) && get(streetViewSource) === 'google') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user