mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-13 15:51:00 +00:00
fix(journey): keep GL photo markers absolutely positioned so thumbnails sit on their coordinates
The journey map's photo thumbnails set position:relative inline on the marker element. That overrides the engine's .mapboxgl-marker/.maplibregl-marker position:absolute, so every thumbnail entered the normal flow below the ones drawn before it and the engine's translate was added on top: the further down the list, the further the photo drifted from its spot. The location dot had the same inline position. Both now leave position to the engine's class. Closes #2910
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// FE-COMP-JMAPGL-001 to FE-COMP-JMAPGL-048, FE-COMP-JMAPGL-2453
|
||||
// FE-COMP-JMAPGL-001 to FE-COMP-JMAPGL-048, FE-COMP-JMAPGL-2453, FE-COMP-JMAPGL-2910
|
||||
|
||||
type Spy = ReturnType<typeof vi.fn>
|
||||
|
||||
@@ -644,6 +644,15 @@ describe('JourneyMapGL', () => {
|
||||
expect(gl.map.on).toHaveBeenCalledWith('moveend', expect.any(Function))
|
||||
})
|
||||
|
||||
it('FE-COMP-JMAPGL-2910: no marker element sets its own position, so the engine keeps it absolute', () => {
|
||||
withToken()
|
||||
const photos = [{ id: 'a', lat: 45, lng: 5, thumbUrl: '/api/photos/1/thumbnail' }]
|
||||
const marks = [{ kind: 'stay', key: 's1', lat: 46, lng: 6, color: '#14b8a6', stay: {} }]
|
||||
render(<JourneyMapGL checkins={[]} entries={entries} photos={photos} marks={marks} />)
|
||||
expect(gl.markers.some(m => m.element.innerHTML.includes('/api/photos/'))).toBe(true)
|
||||
for (const marker of gl.markers) expect(marker.element.style.position).toBe('')
|
||||
})
|
||||
|
||||
it('FE-COMP-JMAPGL-2889: panning keeps the photo and mark groups, only a zoom regroups them', () => {
|
||||
withToken()
|
||||
const photos = [
|
||||
|
||||
@@ -557,7 +557,10 @@ function JourneyMapGL(
|
||||
if (!photos?.length) return
|
||||
for (const cluster of clusterPhotos(photos, glWorldPx(map))) {
|
||||
const el = document.createElement('div')
|
||||
el.style.cssText = 'position:relative;width:48px;height:48px;cursor:pointer'
|
||||
// No inline `position` (#2910): the engine's marker class positions the element
|
||||
// absolutely, and `position:relative` would drop it into the normal flow, where
|
||||
// every thumbnail sits below the ones drawn before it.
|
||||
el.style.cssText = 'width:48px;height:48px;cursor:pointer'
|
||||
el.innerHTML = photoMarkerHtml(cluster.members[0].thumbUrl, cluster.members.length)
|
||||
el.addEventListener('click', (ev) => {
|
||||
ev.stopPropagation()
|
||||
|
||||
@@ -97,6 +97,8 @@ describe('attachLocationMarker', () => {
|
||||
expect(root.children).toHaveLength(3)
|
||||
// The cone starts hidden — there is no heading until the first fix.
|
||||
expect((root.children[1] as HTMLElement).style.display).toBe('none')
|
||||
// The GL marker class owns `position`; an inline one would drop it into the flow.
|
||||
expect(root.style.position).toBe('')
|
||||
})
|
||||
|
||||
it('FE-COMP-LOCMARKERGL-003: adds the accuracy source and fill layer when the map is already loaded', () => {
|
||||
|
||||
@@ -13,7 +13,9 @@ type MarkerConstructor = new (options?: { element?: HTMLElement; anchor?: string
|
||||
// and mapbox doesn't get confused about which element to position.
|
||||
function buildLocationEl(): { root: HTMLDivElement; cone: HTMLDivElement } {
|
||||
const root = document.createElement('div')
|
||||
root.style.cssText = 'width:28px;height:28px;position:relative;pointer-events:none;'
|
||||
// No inline `position`: the GL marker class keeps the root absolute, which the
|
||||
// children's insets resolve against (see the note on markers in MapViewGL).
|
||||
root.style.cssText = 'width:28px;height:28px;pointer-events:none;'
|
||||
// Accuracy pulse behind the dot
|
||||
const pulse = document.createElement('div')
|
||||
pulse.style.cssText = `
|
||||
|
||||
Reference in New Issue
Block a user