轻轻放大到 D3 地图的中心

Zoom softly into the center of a D3 map

我创建了一个 interactive map。该地图可以通过按钮缩放。这些按钮已经可以使用,但我不喜欢当前的样式。当点击按钮时地图有点晃动时,感觉不友好。我想轻轻地放大到地图的中心。

此处放大代码按钮:

d3.select('#zoomplusbutton').on('click', function () {
    ardamap.zoomByFactor(1.3);
});

这里是函数代码,带有奇怪的缩放:

zoomByFactor: function (factor) {
                d3.event.preventDefault();
                var scale = zoom.scale();
                var extent = zoom.scaleExtent();
                var newScale = scale * factor;
                if (extent[0] <= newScale && newScale <= extent[1]) {
                    var t = zoom.translate();
                    var c = [width / 2, height / 2];
                    zoom
                        .scale(newScale)
                        .translate([c[0] + (t[0] - c[0]) / scale * newScale, c[1] + (t[1] - c[1]) / scale * newScale])
                        .event(g.transition());
                }
            }

我真的不知道我从哪里得到这个缩放代码了。

那么怎样才能真正柔和地缩放到地图的中心呢?随意更改网站上的 JS 代码。

几个小时后,现在想出了一个 'OK' 解决方案。它不是完美的中心,但最后没有晃动和任何其他不良行为:

zoomButton: function (zoom_in) {
            var scale = zoom.scale(),
                extent = zoom.scaleExtent(),
                translate = zoom.translate(),
                x = translate[0], y = translate[1],
                factor = zoom_in ? 1.3 : 1/1.3,
                target_scale = scale * factor;
            if (target_scale === extent[0] || target_scale === extent[1] || target_scale > extent[1] || target_scale < extent[0]) { return false; }
            var clamped_target_scale = Math.max(extent[0], Math.min(extent[1], target_scale));
            if (clamped_target_scale != target_scale){
                target_scale = clamped_target_scale;
                factor = target_scale / scale;
            }
            x = (x - center[0]) * factor + center[0];
            y = (y - center[1]) * factor + center[1];
            if (zoom_in){
                x = x - 500;
            }else{
                x = x + 500;
            }
            d3.transition().duration(450).tween("zoom", function () {
                var interpolate_scale = d3.interpolate(scale, target_scale),
                    interpolate_trans = d3.interpolate(translate, [x,y]);
                return function (t) {
                    zoom.scale(interpolate_scale(t))
                        .translate(interpolate_trans(t));
                    ardamap.zoomedButton();
                };
            });
        }

这些计算非常有效。这里有两个按钮提升事件:

d3.select('#zoomplusbutton').on('click', function(){
    ardamap.zoomButton(true);
});
d3.select('#zoomminusbutton').on('click', function () {
    ardamap.zoomButton(false);
});

您也可以在 arda-maps.org 上找到代码更新。如果您已经修复了真正进入当前地图中心的问题,请随时编辑我的答案。我仍然有兴趣改进它!