✨ Show marker dot on trip itinerary map
This commit is contained in:
parent
002555ce37
commit
c9df0c6d33
@ -16,7 +16,12 @@ import {
|
|||||||
TripStatus,
|
TripStatus,
|
||||||
} from "../../types/trip";
|
} from "../../types/trip";
|
||||||
import { Place } from "../../types/poi";
|
import { Place } from "../../types/poi";
|
||||||
import { createMap, placeToMarker, createClusterGroup } from "../../shared/map";
|
import {
|
||||||
|
createMap,
|
||||||
|
placeToMarker,
|
||||||
|
createClusterGroup,
|
||||||
|
tripDayMarker,
|
||||||
|
} from "../../shared/map";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { DialogService, DynamicDialogRef } from "primeng/dynamicdialog";
|
import { DialogService, DynamicDialogRef } from "primeng/dynamicdialog";
|
||||||
import { TripPlaceSelectModalComponent } from "../../modals/trip-place-select-modal/trip-place-select-modal.component";
|
import { TripPlaceSelectModalComponent } from "../../modals/trip-place-select-modal/trip-place-select-modal.component";
|
||||||
@ -58,7 +63,7 @@ export class TripComponent implements AfterViewInit {
|
|||||||
placesUsedInTable = new Set<number>();
|
placesUsedInTable = new Set<number>();
|
||||||
|
|
||||||
trip: Trip | undefined;
|
trip: Trip | undefined;
|
||||||
tripMapAntLayer: undefined;
|
tripMapAntLayer: L.LayerGroup<any> | undefined;
|
||||||
tripMapAntLayerDayID: number | undefined;
|
tripMapAntLayerDayID: number | undefined;
|
||||||
isMapFullscreen: boolean = false;
|
isMapFullscreen: boolean = false;
|
||||||
|
|
||||||
@ -294,6 +299,7 @@ export class TripComponent implements AfterViewInit {
|
|||||||
|
|
||||||
toggleMapFullscreen() {
|
toggleMapFullscreen() {
|
||||||
this.isMapFullscreen = !this.isMapFullscreen;
|
this.isMapFullscreen = !this.isMapFullscreen;
|
||||||
|
document.body.classList.toggle("overflow-hidden");
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.map.invalidateSize();
|
this.map.invalidateSize();
|
||||||
@ -365,28 +371,49 @@ export class TripComponent implements AfterViewInit {
|
|||||||
|
|
||||||
if (!this.trip) return;
|
if (!this.trip) return;
|
||||||
|
|
||||||
const items = this.trip.days.flatMap((day) =>
|
const items = this.trip.days
|
||||||
day.items.sort((a, b) => a.time.localeCompare(b.time)),
|
.flatMap((day) => day.items.sort((a, b) => a.time.localeCompare(b.time)))
|
||||||
);
|
|
||||||
|
|
||||||
const coords = items
|
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
if (item.lat && item.lng) return [item.lat, item.lng];
|
if (item.lat && item.lng)
|
||||||
if (item.place && item.place) return [item.place.lat, item.place.lng];
|
return { text: item.text, lat: item.lat, lng: item.lng };
|
||||||
|
if (item.place && item.place)
|
||||||
|
return { text: item.text, lat: item.place.lat, lng: item.place.lng };
|
||||||
return undefined;
|
return undefined;
|
||||||
})
|
})
|
||||||
.filter((n): n is number[] => n !== undefined);
|
.filter((n) => n !== undefined);
|
||||||
this.map.fitBounds(coords, { padding: [30, 30] });
|
|
||||||
|
|
||||||
const path = antPath(coords, {
|
if (items.length < 2) {
|
||||||
delay: 600,
|
this.utilsService.toast(
|
||||||
dashArray: [10, 20],
|
"info",
|
||||||
weight: 5,
|
"Info",
|
||||||
color: "#0000FF",
|
"Not enough values to map an itinerary",
|
||||||
pulseColor: "#FFFFFF",
|
);
|
||||||
paused: false,
|
return;
|
||||||
reverse: false,
|
}
|
||||||
hardwareAccelerated: true,
|
|
||||||
|
this.map.fitBounds(
|
||||||
|
items.map((c) => [c.lat, c.lng]),
|
||||||
|
{ padding: [30, 30] },
|
||||||
|
);
|
||||||
|
|
||||||
|
const path = antPath(
|
||||||
|
items.map((c) => [c.lat, c.lng]),
|
||||||
|
{
|
||||||
|
delay: 600,
|
||||||
|
dashArray: [10, 20],
|
||||||
|
weight: 5,
|
||||||
|
color: "#0000FF",
|
||||||
|
pulseColor: "#FFFFFF",
|
||||||
|
paused: false,
|
||||||
|
reverse: false,
|
||||||
|
hardwareAccelerated: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const layGroup = L.layerGroup();
|
||||||
|
layGroup.addLayer(path);
|
||||||
|
items.forEach((item) => {
|
||||||
|
layGroup.addLayer(tripDayMarker(item));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.tripMapAntLayer) {
|
if (this.tripMapAntLayer) {
|
||||||
@ -396,10 +423,10 @@ export class TripComponent implements AfterViewInit {
|
|||||||
|
|
||||||
// UX
|
// UX
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.map.addLayer(path);
|
layGroup.addTo(this.map);
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
this.tripMapAntLayer = path;
|
this.tripMapAntLayer = layGroup;
|
||||||
this.tripMapAntLayerDayID = -1; //Hardcoded value for global trace
|
this.tripMapAntLayerDayID = -1; //Hardcoded value for global trace
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,7 +443,19 @@ export class TripComponent implements AfterViewInit {
|
|||||||
if (!this.trip || index == -1) return;
|
if (!this.trip || index == -1) return;
|
||||||
|
|
||||||
const data = this.trip.days[index as number].items;
|
const data = this.trip.days[index as number].items;
|
||||||
if (data.length == 1) {
|
|
||||||
|
data.sort((a, b) => a.time.localeCompare(b.time));
|
||||||
|
const items = data
|
||||||
|
.map((item) => {
|
||||||
|
if (item.lat && item.lng)
|
||||||
|
return { text: item.text, lat: item.lat, lng: item.lng };
|
||||||
|
if (item.place && item.place)
|
||||||
|
return { text: item.text, lat: item.place.lat, lng: item.place.lng };
|
||||||
|
return undefined;
|
||||||
|
})
|
||||||
|
.filter((n) => n !== undefined);
|
||||||
|
|
||||||
|
if (items.length < 2) {
|
||||||
this.utilsService.toast(
|
this.utilsService.toast(
|
||||||
"info",
|
"info",
|
||||||
"Info",
|
"Info",
|
||||||
@ -425,25 +464,29 @@ export class TripComponent implements AfterViewInit {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.sort((a, b) => a.time.localeCompare(b.time));
|
this.map.fitBounds(
|
||||||
const coords = data
|
items.map((c) => [c.lat, c.lng]),
|
||||||
.map((item) => {
|
{ padding: [30, 30] },
|
||||||
if (item.lat && item.lng) return [item.lat, item.lng];
|
);
|
||||||
if (item.place && item.place) return [item.place.lat, item.place.lng];
|
|
||||||
return undefined;
|
|
||||||
})
|
|
||||||
.filter((n): n is number[] => n !== undefined);
|
|
||||||
this.map.fitBounds(coords, { padding: [30, 30] });
|
|
||||||
|
|
||||||
const path = antPath(coords, {
|
const path = antPath(
|
||||||
delay: 400,
|
items.map((c) => [c.lat, c.lng]),
|
||||||
dashArray: [10, 20],
|
{
|
||||||
weight: 5,
|
delay: 400,
|
||||||
color: "#0000FF",
|
dashArray: [10, 20],
|
||||||
pulseColor: "#FFFFFF",
|
weight: 5,
|
||||||
paused: false,
|
color: "#0000FF",
|
||||||
reverse: false,
|
pulseColor: "#FFFFFF",
|
||||||
hardwareAccelerated: true,
|
paused: false,
|
||||||
|
reverse: false,
|
||||||
|
hardwareAccelerated: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const layGroup = L.layerGroup();
|
||||||
|
layGroup.addLayer(path);
|
||||||
|
items.forEach((item) => {
|
||||||
|
layGroup.addLayer(tripDayMarker(item));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.tripMapAntLayer) {
|
if (this.tripMapAntLayer) {
|
||||||
@ -453,10 +496,10 @@ export class TripComponent implements AfterViewInit {
|
|||||||
|
|
||||||
// UX
|
// UX
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.map.addLayer(path);
|
layGroup.addTo(this.map);
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
this.tripMapAntLayer = path;
|
this.tripMapAntLayer = layGroup;
|
||||||
this.tripMapAntLayerDayID = day_id;
|
this.tripMapAntLayerDayID = day_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import * as L from "leaflet";
|
|||||||
import "leaflet.markercluster";
|
import "leaflet.markercluster";
|
||||||
import "leaflet-contextmenu";
|
import "leaflet-contextmenu";
|
||||||
import { Place } from "../types/poi";
|
import { Place } from "../types/poi";
|
||||||
|
import { TripItem } from "../types/trip";
|
||||||
|
|
||||||
export interface ContextMenuItem {
|
export interface ContextMenuItem {
|
||||||
text: string;
|
text: string;
|
||||||
@ -69,6 +70,32 @@ export function createClusterGroup(): L.MarkerClusterGroup {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function tripDayMarker(item: {
|
||||||
|
text: string;
|
||||||
|
lat: number;
|
||||||
|
lng: number;
|
||||||
|
}): L.Marker {
|
||||||
|
const marker = new L.Marker([item.lat!, item.lng], {
|
||||||
|
icon: L.divIcon({
|
||||||
|
className: "bg-black rounded-full",
|
||||||
|
iconSize: [14, 14],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
let touchDevice = "ontouchstart" in window;
|
||||||
|
if (!touchDevice) {
|
||||||
|
marker.bindTooltip(
|
||||||
|
`<div class="font-semibold mb-1 truncate text-base">${item.text}</div>`,
|
||||||
|
{
|
||||||
|
direction: "right",
|
||||||
|
offset: [10, 0],
|
||||||
|
className: "class-tooltip",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return marker;
|
||||||
|
}
|
||||||
|
|
||||||
export function placeToMarker(
|
export function placeToMarker(
|
||||||
place: Place,
|
place: Place,
|
||||||
isLowNet: boolean = true,
|
isLowNet: boolean = true,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user