d3美国地图缩放到标记状态

时间:2017-12-11 09:51:43

标签: javascript angularjs d3.js

美国地图与d3.v3使用Mike Bostock的例子:

US map with d3.v3 using mike bostock's example

我希望地图在页面加载时最初放大到标记的位置,但是应该渲染整个地图,以便用户可以根据需要缩小。

var w = 300;
var h = 280;
//Define map projection
var projection = d3.geo.albersUsa()
                   .translate([w/2, h/2])
                   .scale([300]);

//Define path generator
var path = d3.geo.path()
             .projection(projection);



//Create SVG element
var svg = d3.select("#map1").append("svg")
                        .attr("width", w)
                        .attr("height", h)
var g = svg.append("g");

var tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "1000")
.style('opacity', 0)
.style("font-family", "sans-serif")
.style("background-color", "white")
.style("border-radius", "5px")
.style("padding", "10px")
.style('color', '#000')
.style("font-size", "12px");

//Load in GeoJSON data
d3.json("us-states.json", function(json) {
        d3.csv("cities.csv", function(error, data) {    
            g.selectAll("circle")
                .data(data)
                .enter()
               .append("circle")
                .attr("cx", function(d) {
                    return projection([d.longi, d.lati])[0];
                })
                .attr("cy", function(d) {
                    return projection([d.longi, d.lati])[1];
                })
                .attr("r", 4)
                .style("fill", "#4F6D88")
                .on("mouseover", function(d){
                    tooltip.transition().style("opacity", 0.9)
                    .style('left', (d3.event.pageX) + 'px')
                    .style('top', (d3.event.pageY) + 'px')
                    .text(d.city)
                })
                .on("mousemove", function(event){
                    tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");
                })
                .on("mouseout", function(){
                    tooltip.transition().delay(500).style("opacity", 0);
                });
        });

        //Bind data and create one path per GeoJSON feature
        g.selectAll("path")
           .data(json.features)
           .enter()
           .append("path")
           .attr("d", path);

});
    var zoom = d3.behavior.zoom()
    .scaleExtent([1, 50])
    .on("zoom", function() {
      var e = d3.event,
          tx = Math.min(0, Math.max(e.translate[0], w - w * e.scale)),
          ty = Math.min(0, Math.max(e.translate[1], h - h * e.scale));
      zoom.translate([tx, ty]);
      g.attr("transform", [
        "translate(" + [tx, ty] + ")",
        "scale(" + e.scale + ")"
      ].join(" "));
    });
svg.call(zoom)

我有使用我上面粘贴的滚动放大的代码,但我想让它放大到那些特定位置的负载。我希望如何:

How i want it to be

1 个答案:

答案 0 :(得分:0)

在d3中缩放地图有两种主要方法:

  • 修改将重新绘制路径的投影,或
  • 使用比例和变换修改绘制的路径。

使用fitSize或fitExtent在d3v4中修改投影最简单 - 尽管您需要将您的点转换为geojson。您还可以手动计算翻译和缩放值以更新预测(请参阅Mike Bostock的this answer,其中解释了这种常见的d3v3方法)。

或者,您可以通过调用缩放功能来修改绘制的路径 - this question昨天提到的一个很好的例子(在d3v4中)。或者,您可以手动计算和应用缩放,然后更新缩放以指示当前比例和平移。我将使用修改上述d3v3投影的常用方法(使用Mike的答案)并将其应用于路径上的变换 - 而不是修改投影。 虽然不难看出如何更改我的答案以修改投影。

首先,您需要确定点的x和y坐标之间的最大差异。如果处理两点,这将是相当容易的:

var data = [[-100,45],[-110,45]];
var p1 = projection(data[0]);
var p2 = projection(data[1]);

var dx = Math.abs(p1[0] - p2[0]);
var dy = Math.abs(p1[1] - p2[1]);

为了缩短答案,我假设一种简单的数据格式。此外,如果处理许多点,这将会更复杂一些。一个可能的选择是将你的积分放在geojson中并获得积分的边界框。

现在我们需要找出点的质心 - 在两点的情况下,这只是x和y值的平均值:

var x = (p1[0] + p2[0])/2;
var y = (p1[1] + p2[1])/2;

接下来,我们需要计算一个新的比例,同时还要确定比例是否受坐标x值的差异或坐标的y值差异的限制:

var scale = 0.9 / Math.max( dx/w , dy/h );

0.9会略微缩小比例,与0.9 * scale相同,并允许可变数量的保证金。 dx/w返回的值是我们在svg容器宽度上拉伸差异所需的比例值。

(它可能更有意义地写成:var scale = 0.9 * Math.min(w/dx,h/dy); - 我们希望将缩放限制为最低比例值并将其乘以某个百分比以给出边距。但另一种表示无处不在在线示例)

现在我们有一个比例,我们只需要确定一个翻译。为此,我们要了解我们需要在多远的位置重新定位xy变量中的值,以便将这些值置于中心位置:

var translate = [w/2 - scale * x, h/2-scale*y];

现在您可以设置地图的初始比例和平移:

g.attr("transform", "translate("+translate+")scale("+scale+")");

但是,您可能希望更新页面加载时的缩放参数以反映初始缩放和翻译:

zoom.translate(translate);
zoom.scale(scale);

这样,当您从初始视图放大或缩小时,更改与初始缩放相关。

现在,您只需在添加点时包含上述代码即可。请注意,如果要返回初始位置,可能需要对此技术进行一些修改。