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

When fitBounds() is called with nonzero bearing, rotate padding #9821

Merged
merged 6 commits into from
Aug 26, 2020
Merged
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
10 changes: 7 additions & 3 deletions src/ui/camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ class Camera extends Evented {
* in the viewport. LngLatBounds represent a box that is always axis-aligned with bearing 0.
* @param options Options object
* @param {number | PaddingOptions} [options.padding] The amount of padding in pixels to add to the given bounds.
* @param {number} [options.bearing=0] Desired map bearing at end of animation, in degrees.
* @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 camera would transition to the specified bounds.
* @returns {CameraOptions | void} If map is able to fit to provided bounds, returns `CameraOptions` with
Expand All @@ -492,7 +493,8 @@ class Camera extends Evented {
*/
cameraForBounds(bounds: LngLatBoundsLike, options?: CameraOptions): void | CameraOptions & AnimationOptions {
bounds = LngLatBounds.convert(bounds);
return this._cameraForBoxAndBearing(bounds.getNorthWest(), bounds.getSouthEast(), 0, options);
const bearing = options && options.bearing || 0;
return this._cameraForBoxAndBearing(bounds.getNorthWest(), bounds.getSouthEast(), bearing, options);
}

/**
Expand Down Expand Up @@ -570,10 +572,12 @@ class Camera extends Evented {
const zoom = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), options.maxZoom);

// Calculate center: apply the zoom, the configured offset, as well as offset that exists as a result of padding.
const offset = Point.convert(options.offset);
const offset = (typeof options.offset.x === 'number') ? new Point(options.offset.x, options.offset.y) : Point.convert(options.offset);
const paddingOffsetX = (options.padding.left - options.padding.right) / 2;
const paddingOffsetY = (options.padding.top - options.padding.bottom) / 2;
const offsetAtInitialZoom = new Point(offset.x + paddingOffsetX, offset.y + paddingOffsetY);
const paddingOffset = new Point(paddingOffsetX, paddingOffsetY);
const rotatedPaddingOffset = paddingOffset.rotate(bearing * Math.PI / 180);
const offsetAtInitialZoom = offset.add(rotatedPaddingOffset);
const offsetAtFinalZoom = offsetAtInitialZoom.mult(tr.scale / tr.zoomScale(zoom));

const center = tr.unproject(p0world.add(p1world).div(2).sub(offsetAtFinalZoom));
Expand Down
44 changes: 42 additions & 2 deletions test/unit/ui/camera.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1797,7 +1797,7 @@ test('camera', (t) => {
});

t.test('#cameraForBounds', (t) => {
t.test('no padding passed', (t) => {
t.test('no options passed', (t) => {
const camera = createCamera();
const bb = [[-133, 16], [-68, 50]];

Expand All @@ -1807,6 +1807,28 @@ test('camera', (t) => {
t.end();
});

t.test('bearing positive number', (t) => {
const camera = createCamera();
const bb = [[-133, 16], [-68, 50]];

const transform = camera.cameraForBounds(bb, {bearing: 175});
t.deepEqual(fixedLngLat(transform.center, 4), {lng: -100.5, lat: 34.7171}, 'correctly calculates coordinates for new bounds');
t.equal(fixedNum(transform.zoom, 3), 2.558);
t.equal(transform.bearing, 175);
t.end();
});

t.test('bearing negative number', (t) => {
const camera = createCamera();
const bb = [[-133, 16], [-68, 50]];

const transform = camera.cameraForBounds(bb, {bearing: -30});
t.deepEqual(fixedLngLat(transform.center, 4), {lng: -100.5, lat: 34.7171}, 'correctly calculates coordinates for new bounds');
t.equal(fixedNum(transform.zoom, 3), 2.392);
t.equal(transform.bearing, -30);
t.end();
});

t.test('padding number', (t) => {
const camera = createCamera();
const bb = [[-133, 16], [-68, 50]];
Expand All @@ -1826,7 +1848,7 @@ test('camera', (t) => {
t.end();
});

t.test('asymetrical padding', (t) => {
t.test('asymmetrical padding', (t) => {
const camera = createCamera();
const bb = [[-133, 16], [-68, 50]];

Expand All @@ -1835,6 +1857,15 @@ test('camera', (t) => {
t.end();
});

t.test('bearing and asymmetrical padding', (t) => {
const camera = createCamera();
const bb = [[-133, 16], [-68, 50]];

const transform = camera.cameraForBounds(bb, {bearing: 90, padding: {top: 10, right: 75, bottom: 50, left: 25}, duration: 0});
t.deepEqual(fixedLngLat(transform.center, 4), {lng: -103.3761, lat: 31.7099}, 'correctly calculates coordinates for bounds with bearing and padding option as object applied');
t.end();
});

t.test('offset', (t) => {
const camera = createCamera();
const bb = [[-133, 16], [-68, 50]];
Expand Down Expand Up @@ -1862,6 +1893,15 @@ test('camera', (t) => {
t.end();
});

t.test('bearing, asymmetrical padding, and offset', (t) => {
const camera = createCamera();
const bb = [[-133, 16], [-68, 50]];

const transform = camera.cameraForBounds(bb, {bearing: 90, padding: {top: 10, right: 75, bottom: 50, left: 25}, offset: [0, 100], duration: 0});
t.deepEqual(fixedLngLat(transform.center, 4), {lng: -103.3761, lat: 43.0929}, 'correctly calculates coordinates for bounds with bearing, padding option as object, and offset applied');
t.end();
});

t.end();
});

Expand Down