Mapbox-gl-js: Map resize fires "movestart", "move", and "moveend" events.

Created on 13 Apr 2018  路  10Comments  路  Source: mapbox/mapbox-gl-js

Mapboxgl, current version.

https://github.com/mapbox/mapbox-gl-js/blob/6997943681e50b6563f98f20887cf83c6e0ddfbf/src/ui/map.js#L428-L442

The resize function fires movestart, move, and moveend. This is nonsensical, during a resize the map has not moved. This is causing those event handlers to fire unnecessarily, and I don't see any way to distinguish the "source" of the event.

api needs discussion

Most helpful comment

Not sure if my solution counts as elegant... :)

When you set up the map, you can configure a trackResize property. It's true by default, but I set it to false. Then, I added my own resize handler to redraw the map, passing along extra metadata that I can check for elsewhere:

window.addEventListener('resize', () => myMap.resize({ programmatic: true }));

That {programmatic: true} flag gets passed into all of the other events triggered by resize, so in my handlers for e.g. map.on("moveend", evt => ...), I can check for evt.programmatic and handle the event differently. This is very similar to your check for originalEvent.type, but it offers me a little extra control (e.g. I can pass a programmatic flag from other non-user-triggered move events, which allows me to only re-fetch data when the user would expect it).

So again... elegant? Hardly. But it works well enough for me to only do "moveend" things when the map has actually been moved.

All 10 comments

Indeed, if you have the map set to listen for window resizes (which I think is the default behavior), this causes many moveend events to fire repeatedly when the browser window is resized. Since I'm trying to load updated data when the user repositions the map, this is hitting my server with lots of garbage requests.

Is there an easy way to tell which move* events were triggered by the user vs which ones were programmatic?

@mlms13 I have a hacky solution but not sure if it works for you, but there is actually a public variable called "_moving" which will be true if the map is being dragged around. If map resize is being called this variable remains false.

mapobj.on('move', function(){ if(mapobject._moving){ console.log('has moved'); } })

Thanks @jovanjay, I'll have to play around with this.

A closely related problem I'm running into:

  • User scrolls down on a mobile browser (hiding the URL bar)
  • Browser fires a resize event
  • Mapbox redraws on window resize and claims a moveend occurred

Having the same issue.... :(

no solution fo this then?

Any solutions for this? I'm having the same issue

I've been banging my head on this issue for hours, at least now I know what's causing it. Did anyone found an elegant solution to this? Any way to know what triggered the moveend event?

EDIT: I was able to solve my issue by checking the originalEvent.type property. It does not say if the resize originates from a user interaction specifically but in my case it was good enough. Hope this helps!

this.map.on('moveend', (eventData)=> {
  let sendAction = true;
  if (eventData && eventData.originalEvent && eventData.originalEvent.type === 'resize') {
    sendAction = false;
  }

  if (sendAction) {
    // do the thing
  }
}

Not sure if my solution counts as elegant... :)

When you set up the map, you can configure a trackResize property. It's true by default, but I set it to false. Then, I added my own resize handler to redraw the map, passing along extra metadata that I can check for elsewhere:

window.addEventListener('resize', () => myMap.resize({ programmatic: true }));

That {programmatic: true} flag gets passed into all of the other events triggered by resize, so in my handlers for e.g. map.on("moveend", evt => ...), I can check for evt.programmatic and handle the event differently. This is very similar to your check for originalEvent.type, but it offers me a little extra control (e.g. I can pass a programmatic flag from other non-user-triggered move events, which allows me to only re-fetch data when the user would expect it).

So again... elegant? Hardly. But it works well enough for me to only do "moveend" things when the map has actually been moved.

You can use dragstart

Still no working solution out of the box for this?
Oh, my.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

muesliq picture muesliq  路  3Comments

rigoneri picture rigoneri  路  3Comments

mollymerp picture mollymerp  路  3Comments

foundryspatial-duncan picture foundryspatial-duncan  路  3Comments

BernhardRode picture BernhardRode  路  3Comments