D3.js - 如何使用默认的wheelmouse缩放行为添加缩放按钮

时间:2014-08-15 19:56:55

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

所以我使用默认的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);
        }
    }
}

我会在最短的时间内更新我的例子。

1 个答案:

答案 0 :(得分:8)

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

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

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

  • Zoom Buttons III - 100ms链接转换,一直持续到按钮不再保持或达到scaleExtent为止。控制逻辑可防止任何不希望的即时平移。这是一个可以使用的。

同样,获取正确的细节是棘手的,这就是我提供完整示例的原因。但令人满意的是,核心逻辑确实有意义。你将一个向量归零,拉伸它并将其解除零:

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