React-mapbox-gl: Bug: Zoom in/out with scroll stops to work if mouse is over marker

Created on 7 May 2017  路  31Comments  路  Source: alex3165/react-mapbox-gl

PS library is super useful, because it works with CRA. Thanks

v4

Most helpful comment

@alex3165 Can you reopen this? Because in original example it managed to pass through scroll events, but catch click events

All 31 comments

There is not much to do here if you use the Marker component, the marker is rendered on top of the canvas en prevent the canvas from listening the scroll. I would suggest you to use Layer component to display your marker in the canvas

Pure mapbox-gl can do this https://www.mapbox.com/bites/00281/

Ah you are right, let me have a look at this

Hey you actually just need to pass pointerEvents: none to the marker, see: https://github.com/alex3165/react-mapbox-gl/commit/2052309558b50edb0b4047e97254aa1ff289b964

@alex3165 Can you reopen this? Because in original example it managed to pass through scroll events, but catch click events

Hi, I'm having the same issue with markers. Can't zoom map because of cursor is over the marker.
pointer-events: none; prevents onclick events.
The only difference I've noticed that original example has markers inside the .mapboxgl-canvas-container.
Any thought how to solve it?

@alex3165 @Wykks Hey! I just switched to your library instead of Uber's because it has latest feature support but this bug is preventing me from continuing work. Can I help in any way? Are you working on it yet?

Hey @amitassaraf no one is working on it, but we don't really have any good solution in mind for now.

If you don't need any pointer events on your marker you could do something like this:

<Marker style={{ pointerEvents: 'none' }}/>

Although it will break onClick ...

@alex3165 Yeah, I need the onClick functionality sadly :( I hope you figure this out. Tried debugging it myself with no success yet.

@amitassaraf You can use Layer=>Feature instead Marker, zoom in|out is ok with Feature)

@lkazberova Yup I ended up switching to Layers anyways :)

@alex3165 playing around with one of the demos in Chrome's devtools. Based on @simple17's observation, I moved the div holding the markers to be after the mapboxgl canvas and everything appeared to worked fine (marker click events worked as well as being able to click and scroll on the canvas in the same spot). Here's some simplified markup demonstrating what I mean:

<div class="mapboxgl-map">
  <div class="current-marker-and-cluster-container-location"></div>
  <div class="mapboxgl-canvas-container">
    <canvas>
    <div class="ideal-marker-and-cluster-container-location"></div>
  </div>
</div>

I looked at the code briefly and didn't see a simple solution for moving the container past the canvas, but I think that would fix the problem. Any ideas?

I was just reading about react Portals [[React website][react-link]] [[External blog][external-link]] and I think this might be a good way of rendering children after the canvas. Currently the children aren't rendered until the map is loaded anyway, so we would already be able to access the canvas container.

It's something new to React 16, but it could probably just detect if the createPortal function exists, and only use it if it does. Otherwise behavior would be the same as it is now, but if you're on the latest react it would fix this bug.

Another option for React 15 might be to try using ReactDOM without portals, but it might be a pretty hacky solution.

I have a fix for this that works if A) react-mapbox-gl is compiled with react 15 as a devDependency, or B) if react-mapbox-gl is compiled with react 16 as a devDependency and the app using it is also using react 16. It doesn't work for C) compiled with react 16, but used within react 15.

Does anybody know a good way to detect if the app requiring react-mapbox-gl is using react 15 or 16?

The createPortal solution is cleaner, but requires React 16. The react 15 variant uses ReactDOM.render and seems to work fine, so maybe we can just use that for backwards compatibility, then upgrade to createPortal if react-mapbox-gl stops supporting React 15?

@redbmk We could include those changes in a new major version of react-mapbox-gl 4.x.x and specify that react-mapbox-gl 4.x.x only works with react 16+, I would expect most of the users of react-mapbox-gl to be using react 16 by now.

Cool - is there a branch for 4.x.x yet, or how far away would that be?

I've been playing around with it and I was able to make a fix that seems to work with React 15+ and it just wouldn't use Portals at all, so maybe we could use that for now and upgrade to createPortal for 4.x.x. I'm not sure if there are any performance implications to using ReactDOM.render, but things seem to be working fine so far this way.

I know one advantage to using Portals is that events like onClick will still bubble up as though they were rendered as a child, but that might not matter in this case.

The Popup and Marker were using ReactDOM.render before and we moved to normal react components because with ReactDOM.render there is no way to access the context in the children components.

On the other hand, there is no 4.x.x branch, but we can start one and I can draft a roadmap with breaking changes we could also includes. I am happy to go for this approach even if it is disruptive.

Gotcha. I started a PR so you can take a look at the code I have so far. I completely forgot to run the tests and a lot of those are failing - I think it might have something to do with enzyme but I'm not sure yet. It fails with the createPortal version as well.

I was able to pass in context by rendering another component that takes map as a prop and then sets the context using that.

I also realized after some more testing that Popup is going to pass through scroll events as well. If that's not desired, we might want to only render Cluster and Marker using the portal method.

OK I found and fixed the issue with the tests. I just needed to wait until the load event to get the canvas container. It's still using the ReactDOM.render method, but I can switch it over to createPortal easily if you want to go the React 16 route. That would get rid of the extra portal.tsx component as well, which is just used to pass along the map context.

Merged into v4 branch

To whom it may concern. I'm using a workaround re-emitting wheel events on all markers. It is not bulletproof; it works only for some interactions (wheel events) and doesn't solve for example mouse and touch dragging.

onMarkerWheel = (event) => {
    event.preventDefault()

    const interactiveElement = mapElement.querySelector('.mapboxgl-interactive') // mapElement can be any parent of the .mapboxgl-interactive created by the library (even body)
    if (interactiveElement) {
        const { nativeEvent } = event
        const eventCopy = new nativeEvent.constructor(nativeEvent.type, nativeEvent)
        interactiveElement.dispatchEvent(eventCopy)
    }
}

renderMarker = (content) => {
    <Marker
        coordinates={[0, 0]}
    >
        <div onWheel={this.onMarkerWheel}>
            {content}
        </div>
    </Marker>
}

@Onset Does the v4 branch work for you? There's a fix for this but it requires react 16, so it will be in the next major version.

@alex3165 would you mind to pre-release v4 on npm?

I compiled it myself and it seems to work even for Marker :)

EDIT: notice that containerStyle has been renamed to style and style is renamed to mapStyle

Yeah, that was in response to #498.

And I agree it would be cool to be able to do yarn add react-mapbox-gl@next to get v4.

Just one note: the onClick on Mapbox.Marker fires even if dragging took place. It would be probably better to fire onClick only if onDragStart didn't happen.

Any progresss on this? Was it fixed in v4? If so, how to fetch the newest v4 lib? react-mapbox-gl@next points to v3.

@alex3165 would you be able to add the v4 branch to npm so people can start using it? Are there any other items on the roadmap for v4 that need to be addressed before an official 4.0.0 is released?

Any progress on this? v4 has been released, however we still can't zoom when hovering e.g. marker. Looking forward for it. Thanks.

Hello, any update? The fix is ready, can you push a version on npm please?

For those like me finding this thread on google.. you can now have scroll events pass through the Marker components with:

<Map renderChildrenInPortal={true} ... />

Was this page helpful?
0 / 5 - 0 ratings