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

Fit Camera to Feature #6208

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions debug/query_features.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"source": "queried",
"paint": {
"line-color": "#8D8DEC",
"line-width": {base: 1.5, stops: [[5, 0.75], [18, 32]]}
"line-width": {base: 1.5, stops: [[5, 0.75], [18, 24]]}
}
}, 'country-label-sm');

Expand Down Expand Up @@ -79,7 +79,7 @@
var results = map.queryRenderedFeatures(box, {});
map.getSource('queried').setData({
type: 'FeatureCollection',
features: results
features: [ results[0] ]
});

map.getSource('boxsource').setData({
Expand All @@ -93,6 +93,8 @@
}
}]
});

map.fitFeature(results[0]);
}
});

Expand Down
59 changes: 59 additions & 0 deletions src/ui/camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,65 @@ class Camera extends Evented {
return this;
}

/**
* Pans and zooms the map to contain its visible area within the geographical bounds of the feature geometry.
* This function will also reset the map's bearing to 0 if bearing is nonzero.
Copy link
Collaborator

Choose a reason for hiding this comment

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

does this mean fit to feature is pitch aware and will retain the existing pitch?

Copy link
Collaborator

Choose a reason for hiding this comment

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

This function will also reset the map's bearing to 0 if bearing is nonzero.

What are the implications of this for backwards compatibility? In the future if we can support retaining the bearing as part of fitFeature would it just be a breaking change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It does not alter the pitch, but it also doesn't account for it and will not give the correct result.
There is no resolution yet for the pitch aware fitting.

There is more work needed to maintain the bearing or change it to some other value as part of the fitting operation.

*
* @memberof Map#
* @param feature Center the bounds of the feature's geometry in the viewport and use the highest
* zoom level up to and including `Map#getMaxZoom()` that fits it in the viewport.
* @param options
* @param {number | PaddingOptions} [options.padding] The amount of padding in pixels to add to the given bounds.
* @param {boolean} [options.linear=false] If `true`, the map transitions using
* {@link Map#easeTo}. If `false`, the map transitions using {@link Map#flyTo}. See
* those functions and {@link AnimationOptions} for information about options available.
* @param {Function} [options.easing] An easing function for the animated transition. See {@link AnimationOptions}.
* @param {PointLike} [options.offset=[0, 0]] The center of the given bounds relative to the map's center, measured in pixels.
* @param {number} [options.maxZoom] The maximum zoom level to allow when the map view transitions to the specified bounds.
* @param eventData Additional properties to be added to event objects of events triggered by this method.
* @fires movestart
* @fires moveend
* @returns {Map} `this`
* @example
* var results = map.getRenderedFeatures(pt, {});
* map.fitFeature(results[0], {
* padding: {top: 10, bottom:25, left: 15, right: 5}
* });
*/
fitFeature(feature: Object, options?: AnimationOptions & CameraOptions, eventData?: Object) {
if (!feature || !feature._geometry) {
return;
}
const se = new Point(Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY);
const nw = new Point(Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY);
const tr = this.transform;

function boundsForArray(arr) {
arr.forEach((coords) => {
const pt = tr.project(LngLat.convert(coords));
se.x = Math.max(se.x, pt.x);
se.y = Math.min(se.y, pt.y);
nw.x = Math.min(nw.x, pt.x);
nw.y = Math.max(nw.y, pt.y);
});

}

const coordinates = feature._geometry.coordinates;
if (feature._geometry.type === "LineString") {
boundsForArray(coordinates);
} else if (feature._geometry.type === "Point") {
boundsForArray([ coordinates ]);
} else if (feature._geometry.type === "MultiPolygon") {
coordinates.forEach((arr) => {
arr.forEach(boundsForArray);
});
} else {
coordinates.forEach(boundsForArray);
}

return this.fitBounds([ this.transform.unproject(nw), this.transform.unproject(se)], options, eventData);
}

/**
* Pans and zooms the map to contain its visible area within the specified geographical bounds.
Expand Down