From 0c3daa95a4d69338a1493921cd333b8bec1b153e Mon Sep 17 00:00:00 2001 From: Vladimir Agafonkin Date: Tue, 18 Apr 2017 19:05:10 +0300 Subject: [PATCH] anti-meridian crossing for easeTo; do not wrap if maxBounds set (#4602) - Enable anti-meridian crossing for `easeTo`-based methods for consistency with `flyTo`. - Fix #2521 by disabling anti-meridian crossing if `maxBounds` is set. --- src/ui/camera.js | 25 ++++++++++++++---------- test/unit/ui/camera.test.js | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/src/ui/camera.js b/src/ui/camera.js index a7058207ee2..716d1b62fdf 100644 --- a/src/ui/camera.js +++ b/src/ui/camera.js @@ -512,6 +512,8 @@ class Camera extends Evented { const pointAtOffset = tr.centerPoint.add(Point.convert(options.offset)); const locationAtOffset = tr.pointLocation(pointAtOffset); const center = LngLat.convert(options.center || locationAtOffset); + this._normalizeCenter(center); + const from = tr.project(locationAtOffset); const delta = tr.project(center).sub(from); const finalScale = tr.zoomScale(zoom - startZoom); @@ -695,16 +697,7 @@ class Camera extends Evented { const pointAtOffset = tr.centerPoint.add(Point.convert(options.offset)); const locationAtOffset = tr.pointLocation(pointAtOffset); const center = LngLat.convert(options.center || locationAtOffset); - - // If a path crossing the antimeridian would be shorter, extend the final coordinate so that - // interpolating between the two endpoints will cross it. - if (tr.renderWorldCopies && Math.abs(tr.center.lng) + Math.abs(center.lng) > 180) { - if (tr.center.lng > 0 && center.lng < 0) { - center.lng += 360; - } else if (tr.center.lng < 0 && center.lng > 0) { - center.lng -= 360; - } - } + this._normalizeCenter(center); const from = tr.project(locationAtOffset); const delta = tr.project(center).sub(from); @@ -868,6 +861,18 @@ class Camera extends Evented { return bearing; } + // If a path crossing the antimeridian would be shorter, extend the final coordinate so that + // interpolating between the two endpoints will cross it. + _normalizeCenter(center) { + const tr = this.transform; + if (!tr.renderWorldCopies || tr.lngRange) return; + + const delta = center.lng - tr.center.lng; + center.lng += + delta > 180 ? -360 : + delta < -180 ? 360 : 0; + } + // only used on mouse-wheel zoom to smooth out animation _smoothOutEasing(duration) { let easing = util.ease; diff --git a/test/unit/ui/camera.test.js b/test/unit/ui/camera.test.js index 0b0d51c3fac..08aafe7c40d 100644 --- a/test/unit/ui/camera.test.js +++ b/test/unit/ui/camera.test.js @@ -727,6 +727,44 @@ test('camera', (t) => { }); }); + t.test('pans eastward across the antimeridian', (t) => { + const camera = createCamera(); + camera.setCenter([170, 0]); + let crossedAntimeridian; + + camera.on('move', () => { + if (camera.getCenter().lng > 170) { + crossedAntimeridian = true; + } + }); + + camera.on('moveend', () => { + t.ok(crossedAntimeridian); + t.end(); + }); + + camera.easeTo({ center: [-170, 0], duration: 10 }); + }); + + t.test('pans westward across the antimeridian', (t) => { + const camera = createCamera(); + camera.setCenter([-170, 0]); + let crossedAntimeridian; + + camera.on('move', () => { + if (camera.getCenter().lng < -170) { + crossedAntimeridian = true; + } + }); + + camera.on('moveend', () => { + t.ok(crossedAntimeridian); + t.end(); + }); + + camera.easeTo({ center: [170, 0], duration: 10 }); + }); + t.end(); });