mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 13:36:48 +00:00
fix(shared): cluster the public share page's markers
The share page drew every stop as its own pin while the planner drew the same trip as a handful of clusters, so a shared link opened on three dozen overlapping markers. On a 300px-tall map that covers a whole city, the pins underneath can be neither read nor tapped (#2343). The option block and the icon factory move to components/Map/markerCluster.ts, which both maps import, so the two cannot drift apart again. The planner's options are unchanged. leaflet.markercluster's two stylesheets were imported by MapView.tsx alone. The share page never mounts MapView, so it imports them itself: without them the bubbles keep the library's default styling and spiderfy's legs are invisible.
This commit is contained in:
@@ -4,6 +4,7 @@ import { renderIconMarkup } from '../../utils/iconMarkup'
|
||||
import { MapContainer, TileLayer, Marker, Polyline, CircleMarker, Circle, useMap, Tooltip } from 'react-leaflet'
|
||||
import MarkerClusterGroup from 'react-leaflet-cluster'
|
||||
import { makeMarkerDraggable, makePoiDraggable, draggedPoiId } from './markerDrag'
|
||||
import { CLUSTER_OPTIONS, createClusterIcon } from './markerCluster'
|
||||
import RoadtripViaMarkers from './RoadtripViaMarkers'
|
||||
import HazardLayers from './HazardLayers'
|
||||
import { ALT_CASING, ALT_LABEL_TEXT } from '../Roadtrip/alternativeColors'
|
||||
@@ -868,16 +869,6 @@ export const MapView = memo(function MapView({
|
||||
}
|
||||
}, [placeIds, placesPhotosEnabled])
|
||||
|
||||
const clusterIconCreateFunction = useCallback((cluster) => {
|
||||
const count = cluster.getChildCount()
|
||||
const size = count < 10 ? 36 : count < 50 ? 42 : 48
|
||||
return L.divIcon({
|
||||
html: `<div class="marker-cluster-custom" style="width:${size}px;height:${size}px;"><span>${count}</span></div>`,
|
||||
className: 'marker-cluster-wrapper',
|
||||
iconSize: L.point(size, size),
|
||||
})
|
||||
}, [])
|
||||
|
||||
const isTouchDevice = typeof window !== 'undefined' && navigator.maxTouchPoints > 0
|
||||
// Drag a marker onto a day (#891). Pointer-driven, so it is off wherever
|
||||
// HTML5 drag does not exist — and the day plan is not on screen there anyway.
|
||||
@@ -1061,18 +1052,7 @@ export const MapView = memo(function MapView({
|
||||
<PoiDropTarget onPoiDropOnRoute={onPoiDropOnRoute} />
|
||||
<LeafletLocationLayer position={userPosition} mode={trackingMode} />
|
||||
|
||||
<MarkerClusterGroup
|
||||
chunkedLoading
|
||||
chunkInterval={30}
|
||||
chunkDelay={0}
|
||||
maxClusterRadius={20}
|
||||
disableClusteringAtZoom={9}
|
||||
spiderfyOnMaxZoom
|
||||
showCoverageOnHover={false}
|
||||
zoomToBoundsOnClick
|
||||
animate={false}
|
||||
iconCreateFunction={clusterIconCreateFunction}
|
||||
>
|
||||
<MarkerClusterGroup {...CLUSTER_OPTIONS} iconCreateFunction={createClusterIcon}>
|
||||
{markers}
|
||||
</MarkerClusterGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import L from 'leaflet'
|
||||
|
||||
/**
|
||||
* The cluster group every place map is drawn with.
|
||||
*
|
||||
* The planner and the public share page draw the same trip, so they have to
|
||||
* cluster it the same way: a shared link that opens on three dozen overlapping
|
||||
* pins while the planner shows four tidy bubbles is one trip told two different
|
||||
* ways. Both maps build their group from this block and this factory (#2343).
|
||||
*/
|
||||
export const CLUSTER_OPTIONS = {
|
||||
chunkedLoading: true,
|
||||
chunkInterval: 30,
|
||||
chunkDelay: 0,
|
||||
// Pixels at the current zoom, so ordinary stops still come apart by zooming in.
|
||||
maxClusterRadius: 20,
|
||||
disableClusteringAtZoom: 9,
|
||||
spiderfyOnMaxZoom: true,
|
||||
showCoverageOnHover: false,
|
||||
zoomToBoundsOnClick: true,
|
||||
animate: false,
|
||||
}
|
||||
|
||||
/** The part of a Leaflet cluster this factory reads. */
|
||||
export interface ClusterLike {
|
||||
getChildCount: () => number
|
||||
}
|
||||
|
||||
/**
|
||||
* A count bubble, sized by what it stands for.
|
||||
*
|
||||
* Markup rather than a component because Leaflet owns this element:
|
||||
* `L.divIcon`'s html lands in the marker pane, outside React's tree — which is
|
||||
* also why its styling lives in index.css (`.marker-cluster-custom`).
|
||||
*/
|
||||
export function createClusterIcon(cluster: ClusterLike) {
|
||||
const count = cluster.getChildCount()
|
||||
const size = count < 10 ? 36 : count < 50 ? 42 : 48
|
||||
return L.divIcon({
|
||||
html: `<div class="marker-cluster-custom" style="width:${size}px;height:${size}px;"><span>${count}</span></div>`,
|
||||
className: 'marker-cluster-wrapper',
|
||||
iconSize: L.point(size, size),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user