Minor optimizations

This commit is contained in:
itskovacs 2025-08-06 21:11:19 +02:00
parent 0b7af7ce99
commit 6703a197fb

View File

@ -3,6 +3,8 @@ import "leaflet.markercluster";
import "leaflet-contextmenu"; import "leaflet-contextmenu";
import { Place } from "../types/poi"; import { Place } from "../types/poi";
export const DEFAULT_TILE_URL =
"https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png";
export interface ContextMenuItem { export interface ContextMenuItem {
text: string; text: string;
index?: number; index?: number;
@ -19,41 +21,34 @@ export interface MarkerOptions extends L.MarkerOptions {
} }
export function createMap( export function createMap(
contextMenuItems?: ContextMenuItem[], contextMenuItems: ContextMenuItem[] = [],
tilelayer?: string, tilelayer: string = DEFAULT_TILE_URL,
): L.Map { ): L.Map {
let southWest = L.latLng(-89.99, -180); const southWest = L.latLng(-89.99, -180);
let northEast = L.latLng(89.99, 180); const northEast = L.latLng(89.99, 180);
let bounds = L.latLngBounds(southWest, northEast); const bounds = L.latLngBounds(southWest, northEast);
let _contextMenuItems = contextMenuItems || []; const map = L.map("map", {
let map = L.map("map", {
maxBoundsViscosity: 1.0, maxBoundsViscosity: 1.0,
zoomControl: false, zoomControl: false,
contextmenu: true, contextmenu: true,
contextmenuItems: _contextMenuItems, contextmenuItems: contextMenuItems,
} as MapOptions) } as MapOptions)
.setZoom(10) .setZoom(10)
.setMaxBounds(bounds); .setMaxBounds(bounds);
L.tileLayer( L.tileLayer(tilelayer, {
tilelayer || maxZoom: 17,
"https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png", minZoom: 3,
{ attribution:
maxZoom: 17, '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, &copy; <a href="https://carto.com/attributions">CARTO</a>',
minZoom: 3, }).addTo(map);
attribution:
'&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, &copy; <a href="https://carto.com/attributions">CARTO</a>',
},
).addTo(map);
return map; return map;
} }
export function placeHoverTooltip(place: Place): string { export function placeHoverTooltip(place: Place): string {
let content = `<div class="font-semibold mb-1 truncate" style="font-size:1.1em">${place.name}</div>`; return `<div class="font-semibold mb-1 truncate" style="font-size:1.1em">${place.name}</div><div><span style="color:${place.category.color}; background:${place.category.color}1A;" class="text-xs font-medium px-2.5 py-0.5 rounded">${place.category.name}</span></div>`.trim();
content += `<div><span style="color:${place.category.color}; background:${place.category.color}1A;" class="text-xs font-medium px-2.5 py-0.5 rounded">${place.category.name}</span></div>`;
return content;
} }
export function createClusterGroup(): L.MarkerClusterGroup { export function createClusterGroup(): L.MarkerClusterGroup {
@ -62,7 +57,7 @@ export function createClusterGroup(): L.MarkerClusterGroup {
disableClusteringAtZoom: 11, disableClusteringAtZoom: 11,
showCoverageOnHover: false, showCoverageOnHover: false,
maxClusterRadius: 50, maxClusterRadius: 50,
iconCreateFunction: function (cluster) { iconCreateFunction: (cluster) => {
const count = cluster.getChildCount(); const count = cluster.getChildCount();
return L.divIcon({ return L.divIcon({
html: `<div class="custom-cluster">${count}</div>`, html: `<div class="custom-cluster">${count}</div>`,
@ -85,7 +80,7 @@ export function tripDayMarker(item: {
}), }),
}); });
let touchDevice = "ontouchstart" in window; const touchDevice = "ontouchstart" in window;
if (!touchDevice) { if (!touchDevice) {
marker.bindTooltip( marker.bindTooltip(
`<div class="font-semibold mb-1 truncate text-base">${item.text}</div>`, `<div class="font-semibold mb-1 truncate text-base">${item.text}</div>`,
@ -105,11 +100,9 @@ export function placeToMarker(
grayscale: boolean = false, grayscale: boolean = false,
gpxInBubble: boolean = false, gpxInBubble: boolean = false,
): L.Marker { ): L.Marker {
let marker: L.Marker; const options: Partial<L.MarkerOptions> = {
let options: any = {
riseOnHover: true, riseOnHover: true,
title: place.name, title: place.name,
place_id: place.id,
alt: "", alt: "",
}; };
@ -119,6 +112,7 @@ export function placeToMarker(
let markerClasses = "w-full h-full rounded-full bg-center bg-cover bg-white"; let markerClasses = "w-full h-full rounded-full bg-center bg-cover bg-white";
if (grayscale) markerClasses += " grayscale"; if (grayscale) markerClasses += " grayscale";
const iconHtml = ` const iconHtml = `
<div class="flex items-center justify-center relative rounded-full marker-anchor size-14 box-border" style="border: 2px solid ${place.category.color};"> <div class="flex items-center justify-center relative rounded-full marker-anchor size-14 box-border" style="border: 2px solid ${place.category.color};">
<div class="${markerClasses}" style="background-image: url('${markerImage}');"></div> <div class="${markerClasses}" style="background-image: url('${markerImage}');"></div>
@ -127,17 +121,17 @@ export function placeToMarker(
`; `;
const icon = L.divIcon({ const icon = L.divIcon({
html: iconHtml, html: iconHtml.trim(),
iconSize: [56, 56], iconSize: [56, 56],
className: "", className: "",
}); });
marker = new L.Marker([+place.lat, +place.lng], { const marker = new L.Marker([+place.lat, +place.lng], {
...options, ...options,
icon, icon,
}); });
let touchDevice = "ontouchstart" in window; const touchDevice = "ontouchstart" in window;
if (!touchDevice) { if (!touchDevice) {
marker.bindTooltip(placeHoverTooltip(place), { marker.bindTooltip(placeHoverTooltip(place), {
direction: "right", direction: "right",
@ -153,12 +147,13 @@ export function gpxToPolyline(gpx: string): L.Polyline {
const gpxDoc = parser.parseFromString(gpx, "application/xml"); const gpxDoc = parser.parseFromString(gpx, "application/xml");
const trkpts = Array.from(gpxDoc.querySelectorAll("trkpt")); const trkpts = Array.from(gpxDoc.querySelectorAll("trkpt"));
const latlngs = trkpts.map((pt) => { const latlngs = trkpts.map(
return [ (pt) =>
parseFloat(pt.getAttribute("lat")!), [
parseFloat(pt.getAttribute("lon")!), parseFloat(pt.getAttribute("lat")!),
] as [number, number]; parseFloat(pt.getAttribute("lon")!),
}); ] as [number, number],
);
return L.polyline(latlngs, { color: "blue" }); return L.polyline(latlngs, { color: "blue" });
} }