【问题标题】:D3.js - how to add zoom button with the default wheelmouse zoom behaviorD3.js - 如何添加具有默认滚轮鼠标缩放行为的缩放按钮
【发布时间】:2026-01-23 10:20:06
【问题描述】:

所以我使用默认的 d3.behavior.zoom() 和限制以防止地图被完全拖出页面,得到了一个带有鼠标缩放的世界地图。开始工作很痛苦,但现在可以工作了。

我现在的问题是这个项目还需要界面中无用的缩放 + 和 - 按钮,我找不到具有两种缩放类型的示例。它要么是鼠标缩放,要么是一个糟糕的按钮缩放。

我尝试简单地调用 zoom.scale(newScale);但它不更新任何东西。我似乎在正确的轨道上,因为在控制台中您可以看到比例已更新,但没有更新,当我用鼠标缩放时,它突然跳到使用按钮定义的比例。但似乎我还需要更新翻译,我不确定如何获得地图中心并计算缩放到那里所需的翻译。

我还需要知道在调用 zoom.scale(newScale); 之后如何更新投影如果这是这样做的方法。

我用缩放按钮做了一个简化的演示,显然现在不能正常工作。 http://bl.ocks.org/jfmmm/f5c62bc056e557b80447

谢谢!

编辑: 现在如此接近,它缩放到地图的中心,因为我使用了与计算屏幕中间相同的计算方法,但使用了新的比例。问题是我希望它放大屏幕中间的对象,而不是地图中间的国家。

function zoomBtn(action) {
    var currentZoom = zoom.scale();

    if( action == 'in' ){
        if(currentZoom < options.maxZoomLevel){
            var newScale = Math.floor(currentZoom) + 1;

            var b = path.bounds(mapFeatures);
            var t = [(width - newScale * (b[1][0] + b[0][0])) / 2, (height - newScale * (b[1][1] + b[0][1])) / 2];

            zoom.scale(newScale)
                .translate(t)
                .event(svg);
        }
    }else{
        if(currentZoom > options.minZoomLevel){
            var newScale = Math.floor(currentZoom) - 1;

            var b = path.bounds(mapFeatures);
            var t = [(width - newScale * (b[1][0] + b[0][0])) / 2, (height - newScale * (b[1][1] + b[0][1])) / 2];

            zoom.scale(newScale)
                .translate(t)
                .event(svg);
        }
    }
}

我会在几分钟内更新我的示例。

【问题讨论】:

  • 您可以使用 zoom.event(svg) 更新投影。见github.com/mbostock/d3/wiki/Zoom-Behavior#event
  • 这对于缩放非常有效!
  • 现在我的问题是它缩放到地图的左上角。如何将其设置为缩放到中心? zoom.translate 还是 zoom.center?以及如何获得中心位置。
  • mbostock 现在有一个缩放按钮的示例,该按钮聚焦在此处的中心(2015 年 4 月 9 日):bl.ocks.org/mbostock/7ec977c95910dd026812

标签: javascript d3.js geojson topojson world-map


【解决方案1】:

放大到屏幕中心而不是向左上角或 0lat/0lon 放大的数学计算是相当棘手的。我从Wil Linssen's example 复制它,并将其移植到 Mike Bostock 的Map Pan & Zoom I 上。重要的是,该示例使用 SVG 变换来重新渲染地图,而不是不断地重新计算投影。您可能希望按钮通过以下几种方式工作:

  • Zoom Buttons I - 按下按钮会导致转换到新视图。按住按钮不会重新开始转换。

  • Zoom Buttons II - 按住按钮会导致新视图立即更新,每 40 毫秒。这会导致令人不快的跳跃,尤其是在反复单击按钮时。

  • Zoom Buttons III - 持续 100 毫秒的链式转换,直到不再按住按钮或达到 scaleExtent。控制逻辑防止任何不需要的即时平移。这是要使用的。

再次重申,正确获取详细信息很棘手,这就是我提供完整示例的原因。但令人满意的是,核心逻辑确实是有道理的。您正在对向量进行归零、拉伸和取消归零:

x = (x - center[0]) * factor + center[0];
y = (y - center[1]) * factor + center[1];

【讨论】:

  • 当我尝试这个时,我得到“ReferenceError: center is not defined”
  • 查看示例以了解它是如何定义的。最后两行是摘录。
  • 嗯,我现在正在使用来自 Ilya 的 *.com/questions/18488972/…,它在没有中心的情况下工作。所以没关系=)
  • 是的,他叫它c,我叫它center
  • 啊,好吧,你在最上面声明了它。好的,没看到,抱歉。