Skip to content

Commit 360bfd2

Browse files
authored
Respect padding in cameraForBounds on Globe (#13126) (h/t @jonasnoki)
1 parent 541c310 commit 360bfd2

File tree

2 files changed

+50
-32
lines changed

2 files changed

+50
-32
lines changed

src/ui/camera.js

+41-32
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,8 @@ class Camera extends Evented {
705705

706706
aabb = Aabb.applyTransform(aabb, mat4.multiply([], worldToCamera, aabbOrientation));
707707

708+
aabb = this._extendAABBWithPaddings(aabb, eOptions, tr, bearing);
709+
708710
vec3.transformMat4(center, center, worldToCamera);
709711

710712
const aabbHalfExtentZ = (aabb.max[2] - aabb.min[2]) * 0.5;
@@ -740,6 +742,42 @@ class Camera extends Evented {
740742
return {center: tr.center, zoom, bearing, pitch};
741743
}
742744

745+
_extendAABBWithPaddings(aabb: Aabb, eOptions: FullCameraOptions, tr: Transform, bearing: number): Aabb {
746+
const size = vec3.sub([], aabb.max, aabb.min);
747+
748+
const screenPadL = tr.padding.left || 0;
749+
const screenPadR = tr.padding.right || 0;
750+
const screenPadB = tr.padding.bottom || 0;
751+
const screenPadT = tr.padding.top || 0;
752+
753+
const {left: padL, right: padR, top: padT, bottom: padB} = eOptions.padding;
754+
755+
const halfScreenPadX = (screenPadL + screenPadR) * 0.5;
756+
const halfScreenPadY = (screenPadT + screenPadB) * 0.5;
757+
758+
const scaleX = (tr.width - (screenPadL + screenPadR + padL + padR)) / size[0];
759+
const scaleY = (tr.height - (screenPadB + screenPadT + padB + padT)) / size[1];
760+
761+
const zoomRef = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), eOptions.maxZoom);
762+
763+
const scaleRatio = tr.scale / tr.zoomScale(zoomRef);
764+
765+
aabb = new Aabb(
766+
[aabb.min[0] - (padL + halfScreenPadX) * scaleRatio, aabb.min[1] - (padB + halfScreenPadY) * scaleRatio, aabb.min[2]],
767+
[aabb.max[0] + (padR + halfScreenPadX) * scaleRatio, aabb.max[1] + (padT + halfScreenPadY) * scaleRatio, aabb.max[2]]);
768+
769+
const centerOffset = (typeof eOptions.offset.x === 'number' && typeof eOptions.offset.y === 'number') ?
770+
new Point(eOptions.offset.x, eOptions.offset.y) :
771+
Point.convert(eOptions.offset);
772+
773+
const rotatedOffset = centerOffset.rotate(-degToRad(bearing));
774+
775+
aabb.center[0] -= rotatedOffset.x * scaleRatio;
776+
aabb.center[1] += rotatedOffset.y * scaleRatio;
777+
778+
return aabb;
779+
}
780+
743781
/** @section {Querying features} */
744782

745783
/**
@@ -773,6 +811,7 @@ class Camera extends Evented {
773811
* the highest zoom level up to and including `Map#getMaxZoom()` that fits
774812
* the points in the viewport at the specified bearing.
775813
* @memberof Map#
814+
* @param transform The current transform
776815
* @param {LngLatLike} p0 First point
777816
* @param {LngLatLike} p1 Second point
778817
* @param {number} bearing Desired map bearing at end of animation, in degrees
@@ -799,7 +838,6 @@ class Camera extends Evented {
799838

800839
const tr = transform.clone();
801840
const eOptions = this._extendCameraOptions(options);
802-
const edgePadding = tr.padding;
803841

804842
tr.bearing = bearing;
805843
tr.pitch = pitch;
@@ -829,29 +867,9 @@ class Camera extends Evented {
829867

830868
aabb = Aabb.applyTransform(aabb, worldToCamera);
831869

832-
const size = vec3.sub([], aabb.max, aabb.min);
833-
834-
const screenPadL = edgePadding.left || 0;
835-
const screenPadR = edgePadding.right || 0;
836-
const screenPadB = edgePadding.bottom || 0;
837-
const screenPadT = edgePadding.top || 0;
838-
839-
const {left: padL, right: padR, top: padT, bottom: padB} = eOptions.padding;
840-
841-
const halfScreenPadX = (screenPadL + screenPadR) * 0.5;
842-
const halfScreenPadY = (screenPadT + screenPadB) * 0.5;
843-
844-
const scaleX = (tr.width - (screenPadL + screenPadR + padL + padR)) / size[0];
845-
const scaleY = (tr.height - (screenPadB + screenPadT + padB + padT)) / size[1];
846-
847-
const zoomRef = Math.min(tr.scaleZoom(tr.scale * Math.min(scaleX, scaleY)), eOptions.maxZoom);
848-
849-
const scaleRatio = tr.scale / tr.zoomScale(zoomRef);
850-
851-
aabb = new Aabb(
852-
[aabb.min[0] - (padL + halfScreenPadX) * scaleRatio, aabb.min[1] - (padB + halfScreenPadY) * scaleRatio, aabb.min[2]],
853-
[aabb.max[0] + (padR + halfScreenPadX) * scaleRatio, aabb.max[1] + (padT + halfScreenPadY) * scaleRatio, aabb.max[2]]);
870+
aabb = this._extendAABBWithPaddings(aabb, eOptions, tr, bearing);
854871

872+
const size = vec3.sub([], aabb.max, aabb.min);
855873
const aabbHalfExtentZ = size[2] * 0.5;
856874
const frustumDistance = this._minimumAABBFrustumDistance(tr, aabb);
857875

@@ -863,15 +881,6 @@ class Camera extends Evented {
863881
const offset = vec3.scale([], normalZ, frustumDistance + aabbHalfExtentZ);
864882
const cameraPosition = vec3.add([], aabb.center, offset);
865883

866-
const centerOffset = (typeof eOptions.offset.x === 'number' && typeof eOptions.offset.y === 'number') ?
867-
new Point(eOptions.offset.x, eOptions.offset.y) :
868-
Point.convert(eOptions.offset);
869-
870-
const rotatedOffset = centerOffset.rotate(-degToRad(bearing));
871-
872-
aabb.center[0] -= rotatedOffset.x * scaleRatio;
873-
aabb.center[1] += rotatedOffset.y * scaleRatio;
874-
875884
vec3.transformMat4(aabb.center, aabb.center, cameraToWorld);
876885
vec3.transformMat4(cameraPosition, cameraPosition, cameraToWorld);
877886

test/unit/ui/camera.test.js

+9
Original file line numberDiff line numberDiff line change
@@ -2299,6 +2299,15 @@ describe('camera', () => {
22992299
expect(fixedLngLat(transform.center, 4)).toEqual({lng: 180, lat: 80});
23002300
expect(fixedNum(transform.zoom, 3)).toEqual(1.072);
23012301
});
2302+
2303+
test('entire longitude range: -180 to 180 with asymmetrical padding', () => {
2304+
const camera = createCamera({projection: {name: 'globe'}});
2305+
const bb = [[-180, 10], [180, 50]];
2306+
2307+
const transform = camera.cameraForBounds(bb, {padding:{top: 10, right: 75, bottom: 50, left: 25}});
2308+
expect(fixedLngLat(transform.center, 4)).toEqual({lng: 180, lat: 80});
2309+
expect(fixedNum(transform.zoom, 3)).toEqual(0.892);
2310+
});
23022311
});
23032312

23042313
describe('#fitBounds', () => {

0 commit comments

Comments
 (0)