mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 13:36:48 +00:00
Draw tracks in their own colour on both map engines
The MapLibre layer was already data-driven, so it only needed the feature property filled. Leaflet needed more work: the GPX polyline passed its style as bare color/weight props, and react-leaflet only calls setStyle when the pathOptions reference changes — a recoloured track would have kept its mount-time colour until the next reload. Every other vector layer in here already uses pathOptions. A track with a colour gets a white casing so it survives satellite imagery and dark basemaps. The casings live in their own pane below the lines: Leaflet stacks paths in insertion order, so drawn inline they end up over the line of a track that was added earlier. They are always mounted and hidden by opacity, otherwise giving a track a colour remounts the path into the wrong position. Tracks are clickable now — 3.5px is not a target, so the hit area is a transparent 14px line on top. bubblingMouseEvents is off on it: paths bubble to the map by default (markers do not), and the map's own click handler would clear the selection the track just made. The GL side needs the mirror image of that, a guard so a click on a cluster bubble over a track still belongs to the cluster.
This commit is contained in:
@@ -676,4 +676,38 @@ describe('MapViewGL', () => {
|
||||
|
||||
expect(glMap.fitBounds.mock.calls.length).toBe(afterDayFit)
|
||||
})
|
||||
// ── Track colours (#776) ──────────────────────────────────────────────────
|
||||
// The gpx layer paints from a per-feature property, so what matters is the
|
||||
// GeoJSON handed to setData. getSource returns null by default in this suite,
|
||||
// which makes the effect bail out — the source has to be stubbed per test.
|
||||
const gpxFeatures = () => {
|
||||
const gpxSource = { setData: vi.fn() }
|
||||
glMap.getSource.mockImplementation((id: string) => (id === 'trip-gpx' ? gpxSource : null))
|
||||
return () => {
|
||||
const calls = gpxSource.setData.mock.calls
|
||||
return calls.length ? (calls[calls.length - 1][0]?.features ?? []) : []
|
||||
}
|
||||
}
|
||||
|
||||
it('FE-COMP-MAPVIEWGL-021: a picked route_color reaches the feature, casing on', async () => {
|
||||
const features = gpxFeatures()
|
||||
const places = [buildMapPlace({
|
||||
id: 5, lat: 48, lng: 2, route_geometry: '[[48.0,2.0],[49.0,3.0]]',
|
||||
category_color: '#00ff00', route_color: '#e11d48',
|
||||
})]
|
||||
render(<MapViewGL places={places} fitKey={1} glProvider="maplibre-gl" />)
|
||||
await act(async () => {})
|
||||
expect(features()[0]?.properties).toMatchObject({ color: '#e11d48', cased: true, place_id: 5 })
|
||||
})
|
||||
|
||||
it('FE-COMP-MAPVIEWGL-022: without a pick it stays on the category colour and skips the casing', async () => {
|
||||
const features = gpxFeatures()
|
||||
const places = [buildMapPlace({
|
||||
id: 6, lat: 48, lng: 2, route_geometry: '[[48.0,2.0],[49.0,3.0]]',
|
||||
category_color: '#00ff00',
|
||||
})]
|
||||
render(<MapViewGL places={places} fitKey={1} glProvider="maplibre-gl" />)
|
||||
await act(async () => {})
|
||||
expect(features()[0]?.properties).toMatchObject({ color: '#00ff00', cased: false })
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user