From a872c0ee6dce0f9887b7e710e5c6383c23800523 Mon Sep 17 00:00:00 2001 From: Quincy Morgan Date: Sun, 13 Oct 2019 17:59:03 +0200 Subject: [PATCH] Zoom toward the mouse pointer instead of the map center (#75) --- README.md | 1 - src/Mapscii.js | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5f049ef..4e8b28f 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,6 @@ If your terminal supports mouse events you can drag the map and use your scroll * [ ] mouse control * [ ] hover POIs/labels * [ ] hover maybe even polygons/-lines? - * [ ] zoom into mouse pos * Styler * [ ] respect zoom based style ranges diff --git a/src/Mapscii.js b/src/Mapscii.js index e02459b..541e3d2 100644 --- a/src/Mapscii.js +++ b/src/Mapscii.js @@ -110,10 +110,10 @@ class Mapscii { this.renderer.setSize(this.width, this.height); } - _updateMousePosition(event) { + _colrow2ll(x, y) { const projected = { - x: (event.x-0.5)*2, - y: (event.y-0.5)*4, + x: (x-0.5)*2, + y: (y-0.5)*4, }; const size = utils.tilesizeAtZoom(this.zoom); @@ -122,7 +122,11 @@ class Mapscii { const z = utils.baseZoom(this.zoom); const center = utils.ll2tile(this.center.lon, this.center.lat, z); - this.mousePosition = utils.normalize(utils.tile2ll(center.x+(dx/size), center.y+(dy/size), z)); + return utils.normalize(utils.tile2ll(center.x+(dx/size), center.y+(dy/size), z)); + } + + _updateMousePosition(event) { + this.mousePosition = this._colrow2ll(event.x, event.y); } _onClick(event) { @@ -142,8 +146,33 @@ class Mapscii { _onMouseScroll(event) { this._updateMousePosition(event); - // TODO: handle .x/y for directed zoom + + // the location of the pointer, where we want to zoom toward + const targetMouseLonLat = this._colrow2ll(event.x, event.y); + + // zoom toward the center this.zoomBy(config.zoomStep * (event.button === 'up' ? 1 : -1)); + + // the location the pointer ended up after zooming + const offsetMouseLonLat = this._colrow2ll(event.x, event.y); + + const z = utils.baseZoom(this.zoom); + // the projected locations + const targetMouseTile = utils.ll2tile(targetMouseLonLat.lon, targetMouseLonLat.lat, z); + const offsetMouseTile = utils.ll2tile(offsetMouseLonLat.lon, offsetMouseLonLat.lat, z); + + // the projected center + const centerTile = utils.ll2tile(this.center.lon, this.center.lat, z); + + // calculate a new center that puts the pointer back in the target location + const offsetCenterLonLat = utils.tile2ll( + centerTile.x - (offsetMouseTile.x - targetMouseTile.x), + centerTile.y - (offsetMouseTile.y - targetMouseTile.y), + z + ); + // move to the new center + this.setCenter(offsetCenterLonLat.lat, offsetCenterLonLat.lon); + this._draw(); }