visgl / react-map-gl

React friendly API wrapper around MapboxGL JS
http://visgl.github.io/react-map-gl/
Other
7.87k stars 1.36k forks source link

Pointer event lat lng position doesn't factor in terrain #2248

Open jonshutt opened 1 year ago

jonshutt commented 1 year ago

Description

In the example shown below, when clicking the map to add points, the markers appear correct until you move the map. It appears that however the mouse screen X Y position is converted to a lat lng coordinates is not factoring in terrain.

A similar issue happens with draggable markers, or clicking on the map to show features at that position.

` <Map initialViewState={{ latitude: 32.6141, longitude: -114.34411, zoom: 14, bearing: 80, pitch: 80 }} maxPitch={85} mapStyle="mapbox://styles/mapbox/satellite-v9" mapboxAccessToken={TOKEN} terrain={{source: 'mapbox-dem', exaggeration: 3}} onClick={event => { setPoints([...points, event.lngLat]); }}

<Source id="mapbox-dem" type="raster-dem" url="mapbox://mapbox.mapbox-terrain-dem-v1" tileSize={512} maxzoom={14} /> <Layer {...skyLayer} /> {points.map(point => (

))} `

Expected Behavior

When moving the map, the position on the marker remains in the same place. Eg, the lat lng position is correct

Steps to Reproduce

Using the terrain example, add a click event and markers

based on terrain\src\app.tsx in the repo

`import React, {useEffect, useRef, useState} from 'react';

import {createRoot} from 'react-dom/client'; import Map, {Source, Layer, Marker} from 'react-map-gl';

import ControlPanel from './control-panel';

import type {SkyLayer} from 'react-map-gl';

const TOKEN = ''; // Set your mapbox token here

const skyLayer: SkyLayer = { id: 'sky', type: 'sky', paint: { 'sky-type': 'atmosphere', 'sky-atmosphere-sun': [0.0, 0.0], 'sky-atmosphere-sun-intensity': 15 } };

export default function App() { const [points, setPoints] = useState([]);

return ( <> <Map initialViewState={{ latitude: 32.6141, longitude: -114.34411, zoom: 14, bearing: 80, pitch: 80 }} maxPitch={85} mapStyle="mapbox://styles/mapbox/satellite-v9" mapboxAccessToken={TOKEN} terrain={{source: 'mapbox-dem', exaggeration: 3}} onClick={event => { setPoints([...points, event.lngLat]); }}

<Source id="mapbox-dem" type="raster-dem" url="mapbox://mapbox.mapbox-terrain-dem-v1" tileSize={512} maxzoom={14} /> <Layer {...skyLayer} /> {points.map(point => (

))}

</> ); }

export function renderToDom(container) { createRoot(container).render(); } `

Environment

Logs

No response

jonshutt commented 1 year ago

Just been checking behaviour over previous release versions (all using same underlying mapbox-gl

jonshutt commented 1 year ago

I've been playing around with the source code, and found that the issue started happening when changes were made to the _onAfterRepaint function.

After various trail and error attempts, I found that simply commenting out the map.transform = tr; on line 747 of src\mapbox\mapbox.ts seems to fix things.

jonshutt commented 1 year ago

https://github.com/visgl/react-map-gl/assets/1441033/0aeba108-932b-42e3-a148-aa44cd2817ac latest release

https://github.com/visgl/react-map-gl/assets/1441033/d1d77f49-07c7-4851-9374-cf1279f2b88b with above change to src\mapbox\mapbox.ts

Pessimistress commented 1 year ago

Try 7.1.6.

jonshutt commented 1 year ago

Hi @Pessimistress - Sorry for the delay responding. I've tried the latest versions, and the issue still exists.

I've made a code sandbox here - you'll need to add a mapbox token. Click the map to add some markers - then right click to drag the pitch/bearing - and the markers haven't been added to the lat/lng you would have expected. https://codesandbox.io/s/react-map-gl-3d-terrain-with-locations-added-to-click-position-sxrnqc?file=/src/App.js

https://github.com/visgl/react-map-gl/assets/1441033/95d035b4-f79d-411e-9f0a-9c9a89faf916

jonshutt commented 11 months ago

@Pessimistress wondering if there's any update to this?

I've tried to investigate further, and what I'm seeing is that the transform being applied on line 704 of src\components\src\mapbox\mapbox.ts doesn't have the elevation property, but _renderTransform does have it

console.log(Boolean(tr.elevation)) // false
console.log(Boolean(this._renderTransform.elevation)) // true

I've tried to look where the elevation is being added/removed, but can't spot it. My guess is both should have elevation properties - and by not adding it, click events are picking the lat/lng using a transform with no elevation.

jonshutt commented 11 months ago

Another thought -

_queryRenderedFeatures() sets the transforms map.transform = this._renderTransform;, then after sets it back map.transform = tr;

But this doesn't happen anywhere for basic click events.

if I add

_onPointerEvent() {

  ...
  if (e.type === 'mousedown') {
      this._map.transform = this._renderTransform;
    }`
   ...
}

the click event picks the correct point

AnDanilova commented 2 months ago

I have the same problem. Even if pitch and exaggeration params are 0, just adding a raster-dem source is enouth. Makers jumps on map (not marker) hover, map move, zoom