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

Allow user to specify n, s, e, w padding options for fitBounds #3890

Merged
merged 14 commits into from
Feb 13, 2017

Conversation

mollymerp
Copy link
Contributor

@mollymerp mollymerp commented Jan 4, 2017

Launch Checklist

Continuing on @tristen's PR from #1682.
In order to have separate padding pixels on each side of the map bounds. Right now its set up as [n,e,s,w] but I'm not sure this makes the most sense. Should we be consistent with the offset option and take 2 Points (one for each corner of the bounds)?

Testing the debug page is showing me I'm slightly off on the adjustments right now so I have to figure out what I did wrong in adjusting the camera function. flipped x, y 😭

cc @lucaswoj
closes #1339

  • briefly describe the changes in this PR
  • write tests for all new functionality
  • document any changes to public APIs
  • post benchmark scores
  • manually test the debug page

@mollymerp mollymerp changed the title Allow an array to be passed for fitBounds padding option Allow user to specify n, s, e, w padding options for fitBounds Jan 5, 2017
@mollymerp
Copy link
Contributor Author

ready for your 👀 @lucaswoj

js/ui/camera.js Outdated
@@ -303,32 +303,58 @@ class Camera extends Evented {
* {@link Map#easeTo}. If `false`, the map transitions using {@link Map#flyTo}. See
* {@link Map#flyTo} for information about the options specific to that animated transition.
* @param {Function} [options.easing] An easing function for the animated transition.
* @param {number} [options.padding=0] The amount of padding, in pixels, to allow around the specified bounds.
* @param {number|Object} [options.padding] Sets padding around the given bounds on each side in pixels. Accepts a number for all padding edges or an object with padding for each compass direction (north, south, east, and west)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can provide a more specific type definition by creating a PaddingOptions @typdef for {north: Number; east: Number; south: Number; west: Number;}.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok! will investigate

js/ui/camera.js Outdated
@@ -303,32 +303,58 @@ class Camera extends Evented {
* {@link Map#easeTo}. If `false`, the map transitions using {@link Map#flyTo}. See
* {@link Map#flyTo} for information about the options specific to that animated transition.
* @param {Function} [options.easing] An easing function for the animated transition.
* @param {number} [options.padding=0] The amount of padding, in pixels, to allow around the specified bounds.
* @param {number|Object} [options.padding] Sets padding around the given bounds on each side in pixels. Accepts a number for all padding edges or an object with padding for each compass direction (north, south, east, and west)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are your thoughts about providing geographic padding options (north, east, ...) vs screen padding options (top, left, ...)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think screen padding options make more sense but would be more complicated to implement... 😬

Copy link
Contributor

@lucaswoj lucaswoj Jan 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just did a little experimentation with this PR and discovered that Map#fitBounds always resets the bearing to 0 when it is called. 🤔

We may be able to rename these properties, ship this PR as-is, and open a separate issue about preserving bearing during a Map#fitBounds operation.

js/ui/camera.js Outdated
* @see [Fit a map to a bounding box](https://www.mapbox.com/mapbox-gl-js/example/fitbounds/)
*/
fitBounds(bounds, options, eventData) {

options = util.extend({
padding: 0,
padding: {
north: 0,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes more sense to name these top, right, bottom and left. It's more consistent with Leaflet and Google Maps APIs.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. If fitBounds is called on a (potentially) rotated map n, s, e and w don't make sense as you would want the padding to be applied to the viewport, not the feature.

@mollymerp
Copy link
Contributor Author

I updated the approach to one @lucaswoj and I discussed a couple weeks ago where we separate the padding out into two parts: the part that does not alter the center of the map (i.e. equal padding amts on top/bottom and left/right) and the part that does (any left over padding from the first part) and the latter part gets added to the offset object which is handled in subsequent calls to flyTo or easeTo.

So if you pass a padding object like {padding: {top: 10, bottom: 20, right: 50, left: 75}} this will get broken into {lateralPadding: 50, verticalPadding: 10, offset: [25, -10]}

This was a compromise to get accurate results without completely refactoring the camera 😅 -- the same results are achievable with the current API, but hopefully this option will be more clear to users going forward.

@mollymerp
Copy link
Contributor Author

@lucaswoj I also added a typedef for the PaddingOptions, but I kind of think this makes our docs less clear (i.e. users have to click through to find out how to add padding) and since padding is only used in this one function we don't end up saving a ton of space. What do you think?

screen shot 2017-01-31 at 7 09 31 pm

@lucaswoj
Copy link
Contributor

lucaswoj commented Feb 1, 2017

@mollymerp 👍 on the typedef. The typedef is the most semantically correct. I hope we'll have an oppurtunity to refactor when we hit #2801. I also hope we'll add better support for {inline: declarations} soon.

Copy link
Contributor

@lucaswoj lucaswoj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure about the need to support both offset and padding. The relationship between the two is a little confusing. padding alone should be functionally sufficient.

Could we deprecate offset and remove it in a future release?

src/ui/camera.js Outdated
console.log(Object.keys(options.padding).sort((a, b)=> {
if (a < b) return -1;
if (a > b) return 1;
return 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

accidental console.log?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As best I can tell, these lines are equivalent to .sort((a, b)=> a - b)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙈

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I don't think they're equivalent... according to the docs the approach you suggest can be used for comparing numeric values, but not for strings.

@mollymerp
Copy link
Contributor Author

offset is an AnimationOptions property (should really be a Camera option I think), while padding is only an option on Map#fitBounds. If we deprecate one of them it should be padding I think.

Given that this is one of the most requested features, maybe we should merge and this in advance of a larger refactor of the Camera API + documentation?

Copy link
Contributor

@anandthakker anandthakker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great to me, barring a couple of minor suggestions.

Regarding the redundancy between offset and padding: while I agree that the redundancy could be confusing, this is a case where parsimony might be more confusing, because while they're functionally redundant, they represent distinct use cases, and it's hard (or at least annoying) to convert between them.

src/ui/camera.js Outdated
*
* @memberof Map#
* @param {LngLatBoundsLike} bounds Center these bounds in the viewport and use the highest
* zoom level up to and including `Map#getMaxZoom()` that fits them in the viewport.
* @param {Object} [options]
* @param {AnimationOptions | CameraOptions | PaddingOptions} [options]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way I read this, it makes me think that top, bottom, etc. are properties that can go directly on options. Since these should actually be sub-properties of options.padding, should this be @param {number|PaddingOptions} [options.padding=0] The amount of padding to allow around the given bounds. (or something less stilted-sounding heh)

const bb = [[-133, 16], [-68, 50]];

camera.fitBounds(bb, {duration:0});
t.deepEqual(fixedLngLat(camera.getCenter()), { lng: -100.5, lat: 34.717077774 }, 'pans to coordinates based on fitBounds');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small preemptive suggestion: should we round the latitude before comparing it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixedLngLat does round to a default precision of 9 decimal places – that is rather precise, though, so it might be a good idea to reduce precision a bit

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh whoops 🙈 totally didn't see that!

@lucaswoj
Copy link
Contributor

Per chat with @mollymerp today, we're going to 🚢 this API and look to make simplifying + breaking changes in conjunction with #2801

@mollymerp mollymerp merged commit 74a4456 into master Feb 13, 2017
@mollymerp mollymerp deleted the fitbounds-padding-options branch February 13, 2017 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow each edge to have different padding when fitting to bounds
6 participants