Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a way to set initial map bounds #1970

Closed
peckjon opened this issue Jan 22, 2016 · 27 comments
Closed

Add a way to set initial map bounds #1970

peckjon opened this issue Jan 22, 2016 · 27 comments

Comments

@peckjon
Copy link
Contributor

peckjon commented Jan 22, 2016

Is there no way to set the initial bounds of a Map?

options.maxBounds allows one to set the initial bounding box, but also permanently constrains the view to this box.

A combination of .center and .zoom would effectively allow one to set initial bounds, but also requires some computation, and is inexact.

Is there an easy way to set an initial options.bounds ?

@ravraponi
Copy link

+1

On Fri, Jan 22, 2016 at 2:12 AM, Jon Peck notifications@github.com wrote:

Is there no way to set the initial bounds of a Map?

optionsmaxBounds https://wwwmapboxcom/mapbox-gl-js/api/#Map allows one
to set the initial bounding box, but also permanently constrains the view
to this box

A combination of center and zoom would effectively allow one to set
initial bounds, but also requires some computation, and is inexact

Is there an easy way to set an initial optionsbounds ?


Reply to this email directly or view it on GitHub
#1970.

@lucaswoj
Copy link
Contributor

You are correct. That feature does not exist but should 👍

@lucaswoj lucaswoj changed the title No way to set initial Bounds? Add a way to set initial map bounds Jan 22, 2016
@mourner mourner added the api label Jan 22, 2016
@ryanbaumann
Copy link
Contributor

To get around this at the moment, I've used the 'geojsonExtent' mapbox.js library to facilitate zooming to bounds. Agreed it would be great to have as a standard feature in the API.

<script src='https://api.mapbox.com/mapbox.js/plugins/geojson-extent/v0.0.1/geojson-extent.js'></script>
function fit() {
    //fit gl map to a geojson file bounds
    try {
        map.fitBounds(geojsonExtent( geojson_data ));
    }
    catch (err) {
        console.log(err);
    }
}

@averas
Copy link
Contributor

averas commented Jan 26, 2016

@ryanbaumann I think there's a misunderstand there. I believe what @peckjon is asking for is not a method to to zoom to a bounding box (Map#fitBounds) per se, because this is actually already part of the library. The problem is that the current function is animated so you can't instantly change the center/zoom of a map like you can with Map#jumpTo, using a bounding box. What this ticket asks for is a fitBounds without a transition (and possibly also as input when instantiating the map).

Also, getting the bounding box for a geometry I would argue is out of scope for the library, but can easily done with for example turf.js (http://turfjs.org/static/docs/module-turf_extent.html).

@jfirebaugh
Copy link
Contributor

Unanimated Map#fitBounds is #1473. This issue is about bounds-based map initialization.

@averas
Copy link
Contributor

averas commented Jan 26, 2016

@jfirebaugh Gotcha, but I still got the impression that @ryanbaumann was asking for functionality in the API to actually calculate the bounds for you based on a given geometry, i.e. something like "Map#fitGeojson(geojson)"

@ryanbaumann
Copy link
Contributor

@averas I was off-topic on my comment. Apologies.

My intent was to communicate that from a user perspective, I want to initialize a map to fit the bounds of a data layer. Zooming to bounds after the data layer is added to the map is acceptable.

@anx-ckreuzberger
Copy link

This is missing for my project too!
I am calculating the bounds from an existing list of coordinates, e.g., like this:

var devicesBounds = new mapboxgl.LngLatBounds();

// iterate over all markers
for (var i = 0; i < devices.length; i++)
{
    var device = devices[i];

    // add the current coordinates to the bounds array, so we can fit the map extent to the bounds of all markers
    devicesBounds.extend([
        device.longitude,
        device.latitude
    ]);
}

And then I am setting the map config parameters like this

mapboxConfig.center = devicesBounds.getCenter();
mapboxConfig.zoom = 14;

However, this is far from optimal, as the zoom level is static. I would like to do it like this:

mapboxConfig.initialBounds = devicesBounds;

@lucaswoj
Copy link
Contributor

Closely related to #4029

@jwangler
Copy link

+1

Being able to specify an initial bounds when the map is instantiated would be very convenient - we definitely have a need for that. Currently I will work around this by calculating the center pt and zoom based on the bounding box and the div dimensions, but even better to have this built in to the api. Bonus points for integrating with the camera options and setting the center & zoom from the bounds, and the bearing and pitch from the camera options.

@ryanbaumann
Copy link
Contributor

ryanbaumann commented Apr 26, 2017

A workaround to initialize a map to a bounding box is possible using the geo-viewport library.

Pass a bounding box and the map HTML element dimensions to the geoViewport.viewport() function. Use the returned center and zoom level to initialize the map.

const mapboxgl = require('mapbox-gl');
const geoViewport = require('@mapbox/geo-viewport');

var mapEl = document.getElementById('map').getBoundingClientRect();  
var bounds = [-123.749, 28.613, -61.1718, 48.69096];
var mapDim = [mapEl.height, mapEl.width];
var newbounds = geoViewport.viewport(bounds, mapDim, 0, 20, 512);

mapboxgl.accessToken = 'my-token';
var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/light-v9',
    center: newbounds.center,
    zoom: newbounds.zoom
});

@jwangler
Copy link

Thanks Ryan, looks like a good option.

@anx-ckreuzberger
Copy link

That is very similar to what I am doing, except I am setting a "default" zoom level.

@eltonjuan
Copy link

I think this can be closed if I'm not mistaken?

I was able to accomplish this by doing:
map.fitBounds(bbox, { duration: 0 })

Technically that is a Map#fitBounds without transition, but still accomplishes the task at hand (albeit not the smoothest transition in the world)...

@iplanwebsites
Copy link

I think it'd make more sense to supply the bounds on init.
It's a very common need and feels quite messy to set an arbitrary zoom and center to just jump via fitBounds.

@anx-ckreuzberger
Copy link

@iplanwebsites exactly. The solution provided by @eltonjuan is the temporary fix for the problem. It solves the task at hand, but it makes the map "jump" after initialiation, which I (and many others) consider as poor user experience.

@iplanwebsites
Copy link

Thanks @anx-ckreuzberger. Upon coding an ugly workaround, I realized that firBounds doesn't even work with bounds over the dateline. Unless I'm mistaken, it seems impossible to fit the bounds of Alaska or a flight from HK to SF. I'm debating coding a workaround making use of a center point and a custom zoom-level but it feel so counter-productive to do so much ground work for such a basic need. Do you know if the Google-maps API has figured this out?

@benmcginnis
Copy link

here's the forked pen with the fix: https://codepen.io/mcginnisb/pen/Jrxowe?editors=0011

@jaapster
Copy link

A related fundamental issue is that it is impossible to correctly render a geometry that crosses the dateline.

@igal1c0de4n
Copy link

igal1c0de4n commented Jan 9, 2018

Connecting the dots, I came up with the following "workaround":

// init the map _without_ a center (it defaults to [0,0])
var map = new mapboxgl.Map({...})

// immediately after, not after the `load` event
// the goal is for the map to load at the specified bounds, 
// without loading any unrelated resources related to [0,0] 
map.fitBounds(myBounds, {linear: true, duration: 0})

I'm not sure this is officially supported, also then the console shows:

Uncaught TypeError: Cannot read property 'transition' of undefined
    at e._render (map.js:1484)
    at map.js:1569

(happens when using mapboxgl v0.43.0)

My questions:

  1. Is this error safe to ignore?
  2. Would any of you say my hack is acceptable/reasonable? (or am I voiding the warranty by not waiting for the map to fully load first)

@morgant
Copy link

morgant commented Jan 19, 2018

We are running into this issue as well. There are a lot of comments that do not seem to grasp the importance of initializing to a bounding box instead of initializing and then immediately calling fitBounds() (animated or not), so please consider:

  • Load performance from the user’s perspective (everyone’s highest priority, correct? Even if immediately calling fitBounds(), there can be a delay)
  • Efficient use of network resources (reducing the number of tilesets fetched)
  • Code reduction & performance (Less client side JS is better, plus fewer calculations & redraws; in our case, we actually work exclusively with bboxes)
  • Reduced MapBox API use & reduction of map views (we pay more because it costs MapBox more)

@ryanbaumann’s workaround using geo-viewport is the most appropriate, but is still additional code that shouldn’t be required.

@sharkinsspatial
Copy link

If @ryanbaumann map.fitBounds approach is not appropriate for your use case, you can use the excellent viewport-mercator-project. It contains a fitBounds method which returns center and zoom. These can then be used to initialize your map. It also contains handy padding and offset options.

@morgant
Copy link

morgant commented Jan 20, 2018

@sharkinsspatial Just to clarify, @ryanbaumann’s solution uses geoViewport.viewport() instead of fitBounds() (just for initialization) and hence is avoids calling fitBounds() post initialization.

Thanks for pointing out viewport-mercator-project. I’d personally lean towards @ryanbaumann’s solution using geo-viewport as it is developed & supported by MapBox, plus is <5K (minimized; viewport-mercator-project is significantly larger).

@iplanwebsites
Copy link

Any timeline on this issue?

stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Jul 25, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Jul 25, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Jul 25, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Jul 25, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Jul 25, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Jul 25, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Aug 9, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Aug 9, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Aug 9, 2018
@peckjon
Copy link
Contributor Author

peckjon commented Aug 20, 2018

See #1473 (comment)

stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Oct 8, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Oct 8, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Oct 8, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Oct 8, 2018
stepankuzmin added a commit to stepankuzmin/mapbox-gl-js that referenced this issue Oct 8, 2018
mourner pushed a commit that referenced this issue Oct 8, 2018
* add initial bounds as map constructor option #1970

* fix map initial bounds test #1970

* resize map before setting initial view #1970

* move this.resize() back to conditional #1970

* fix expected zoom value for initial bounds test #1970
@korywka
Copy link
Contributor

korywka commented Oct 18, 2018

duration 0 is not a good solution:

  1. you still see jumping map after load
  2. you pay for extra tiles 💸 💸 💸

@mourner
Copy link
Member

mourner commented Oct 18, 2018

This was fixed in #5518

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests