From bdfe3e2ff198393acc6c1c7c56608e55f53b716c Mon Sep 17 00:00:00 2001 From: LiuBing <471071362@qq.com> Date: Thu, 14 Mar 2024 10:55:36 +0800 Subject: [PATCH] synchronize map with mouse when dragging or zooming map (#2210) --- src/map/Map.Zoom.js | 4 +++- src/map/Map.js | 16 ++++++++++++++++ src/map/handler/Map.Drag.js | 17 +++++++++++++++-- test/map/MapDragSpec.js | 21 +++++++++++++++++++++ test/map/MapScrollZoomSpec.js | 26 ++++++++++++++++++++++++-- 5 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/map/Map.Zoom.js b/src/map/Map.Zoom.js index 4d86ab11d..bc55e0bf9 100644 --- a/src/map/Map.Zoom.js +++ b/src/map/Map.Zoom.js @@ -146,7 +146,9 @@ Map.include(/** @lends Map.prototype */{ this._zoomLevel = nextZoom; this._calcMatrices(); if (origin) { - this._setPrjCoordAtContainerPoint(this._startZoomCoord, origin); + const p = this._containerPointToPoint(origin); + const offset = p._sub(this._prjToPoint(this._getPrjCenter())); + this._setPrjCoordAtOffsetToCenter(this._startZoomCoord, offset); } }, diff --git a/src/map/Map.js b/src/map/Map.js index a882c7595..c6c1be2d0 100644 --- a/src/map/Map.js +++ b/src/map/Map.js @@ -2082,6 +2082,22 @@ class Map extends Handlerable(Eventable(Renderable(Class))) { return this; } + _setPrjCoordAtOffsetToCenter(prjCoord, offset) { + const pcenter = this._pointToPrj(this._prjToPoint(prjCoord).sub(offset)); + this._setPrjCenter(pcenter); + return this; + } + + _queryTerrainAtPoint(p) { + const group = this.getLayers(layer => { + return layer.queryTerrainAtPoint; + })[0]; + if (group && group.getTerrainLayer()) { + return group.queryTerrainAtPoint(p); + } + return null; + } + _verifyExtent(prjCenter) { if (!prjCenter) { return false; diff --git a/src/map/handler/Map.Drag.js b/src/map/handler/Map.Drag.js index d9863307a..d17ec0a28 100644 --- a/src/map/handler/Map.Drag.js +++ b/src/map/handler/Map.Drag.js @@ -110,7 +110,7 @@ class MapDragHandler extends Handler { const map = this.target; map.onMoveStart(param); const p = getEventContainerPoint(map._getActualEvent(param.domEvent), map.getContainer()); - this.startPrjCoord = map._containerPointToPrj(p); + this.startPrjCoord = this._containerPointToPrj(p); } _moving(param) { @@ -119,10 +119,23 @@ class MapDragHandler extends Handler { } const map = this.target; const p = getEventContainerPoint(map._getActualEvent(param.domEvent), map.getContainer()); - map._setPrjCoordAtContainerPoint(this.startPrjCoord, p); + const point = map._prjToPoint(this._containerPointToPrj(p)); + const offset = point._sub(map._prjToPoint(map._getPrjCenter())); + map._setPrjCoordAtOffsetToCenter(this.startPrjCoord, offset); map.onMoving(param); } + _containerPointToPrj(p) { + const map = this.target; + const queryCoord = map._queryTerrainAtPoint(p); + if (queryCoord) { + const prjCoord = map.getProjection().project(queryCoord); + prjCoord.z = queryCoord.z; + return prjCoord; + } + return map._containerPointToPrj(p); + } + _moveEnd(param) { if (!this.startDragTime) { return; diff --git a/test/map/MapDragSpec.js b/test/map/MapDragSpec.js index 0df240fa2..e599d88e0 100644 --- a/test/map/MapDragSpec.js +++ b/test/map/MapDragSpec.js @@ -187,4 +187,25 @@ describe('Map.Drag', function () { expect(center2.toArray()).not.to.be.eql(center.toArray()); expect(map.isMoving()).not.to.be.ok(); }); + + it('synchronize with mouse when dragging map', (done) => { + map.setPitch(45); + //vlayer用于模拟鼠标的位置和高度 + const vlayer = new maptalks.VectorLayer('v').addTo(map); + vlayer.queryTerrainAtPoint = function(containerPoint) { + const coord = map.containerPointToCoordinate(containerPoint); + return new maptalks.Coordinate(coord.x, coord.y - 0.2, 100); + }; + vlayer.getTerrainLayer = function() { + return true; + } + map.on('moveend', function () { + expect(map.isMoving()).not.to.be.ok(); + const center = map.getCenter(); + expect(center.x).to.eql(118.84493355); + expect(center.y).to.eql(32.04882672); + done(); + }); + dragMap(100); + }); }); diff --git a/test/map/MapScrollZoomSpec.js b/test/map/MapScrollZoomSpec.js index 05226374f..498c76ec3 100644 --- a/test/map/MapScrollZoomSpec.js +++ b/test/map/MapScrollZoomSpec.js @@ -5,10 +5,12 @@ describe('Map.ScrollZoom', function () { var map; var center = new maptalks.Coordinate(118.846825, 32.046534); var delay; - function scrollMap(delta) { + function scrollMap(delta, clientX, clientY) { happen.once(container, { type: 'wheel', - detail: delta + detail: delta, + clientX: clientX || map.width / 2, + clientY: clientY || map.height / 2 }); } @@ -52,6 +54,26 @@ describe('Map.ScrollZoom', function () { map.on('zoomend', onZoomEnd); scrollMap(-100); }); + + it('synchronize with mouse when scroll zoom map', (done) => { + map.setPitch(45); + //vlayer用于模拟鼠标的位置和高度 + const vlayer = new maptalks.VectorLayer('v').addTo(map); + vlayer.queryTerrainAtPoint = function(containerPoint) { + const coord = map.containerPointToCoordinate(containerPoint); + return new maptalks.Coordinate(coord.x, coord.y - 0.2, 100); + }; + vlayer.getTerrainLayer = function() { + return true; + } + map.on('zoomend', function () { + const center = map.getCenter(); + expect(center.x.toFixed(4)).to.eql(118.8474); + expect(center.y.toFixed(4)).to.eql(32.0460); + done(); + }); + scrollMap(100, 10, 10); + }); }); describe('scrollZoom can be disable', function () {