Skip to content

Commit c2b23ea

Browse files
committed
Use local variables for calculating zoom button actions
1 parent 4f6f122 commit c2b23ea

1 file changed

Lines changed: 17 additions & 9 deletions

File tree

src/components/modebar/buttons.js

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,8 @@ modeBarButtons.hoverClosestGeo = {
594594
click: toggleHover
595595
};
596596

597+
const ZOOM_STEP_GEO = 2;
598+
597599
function handleGeo(gd, ev) {
598600
const button = ev.currentTarget;
599601
const attr = button.getAttribute('data-attr');
@@ -603,30 +605,36 @@ function handleGeo(gd, ev) {
603605

604606
for (const id of geoIds) {
605607
const geoLayout = fullLayout[id];
608+
const geoSubplot = geoLayout._subplot;
606609

607610
if (attr === 'zoom') {
608-
const { minscale, scale } = geoLayout.projection;
611+
// Under fitbounds, geoLayout.projection.scale is undefined; read the
612+
// effective view from the D3 projection state instead
613+
const projection = geoSubplot.projection;
614+
const effectiveScale = projection.scale() / geoSubplot.fitScale; // Convert to schema format (multiples of original scale)
615+
const [rotationLon, rotationLat] = projection.rotate().map((d) => -d); // Flip sign because D3 rotation is opposite of ours
616+
const [centerLon, centerLat] = projection.invert(geoSubplot.midPt);
617+
618+
const { minscale } = geoLayout.projection;
609619
const maxscale = geoLayout.projection.maxscale ?? Infinity;
610620
// swap if user supplied min > max so clamping is well-defined
611621
const min = Math.min(minscale, maxscale);
612622
const max = Math.max(minscale, maxscale);
613-
let newScale = val === 'in' ? 2 * scale : 0.5 * scale;
623+
let newScale = val === 'in' ? ZOOM_STEP_GEO * effectiveScale : (1 / ZOOM_STEP_GEO) * effectiveScale;
614624

615625
// clamp to [min, max]
616626
if (newScale > max) newScale = max;
617627
else if (newScale < min) newScale = min;
618628

619-
if (newScale !== scale) {
629+
if (newScale !== effectiveScale) {
620630
// Persist the currently-effective view attrs with the new scale; turn
621631
// off fitbounds so auto-fit doesn't overwrite them on the ensuing replot
622-
const { rotation } = geoLayout.projection;
623-
const { center } = geoLayout;
624632
Registry.call('_guiRelayout', gd, {
625633
[id + '.projection.scale']: newScale,
626-
[id + '.projection.rotation.lon']: rotation.lon,
627-
[id + '.projection.rotation.lat']: rotation.lat,
628-
[id + '.center.lon']: center.lon,
629-
[id + '.center.lat']: center.lat,
634+
[id + '.projection.rotation.lon']: rotationLon,
635+
[id + '.projection.rotation.lat']: rotationLat,
636+
[id + '.center.lon']: centerLon,
637+
[id + '.center.lat']: centerLat,
630638
[id + '.fitbounds']: false
631639
});
632640
}

0 commit comments

Comments
 (0)