Javascript d3美国地图加载时缩放至标记状态

Javascript d3美国地图加载时缩放至标记状态,javascript,angularjs,d3.js,Javascript,Angularjs,D3.js,使用Mike Bostock的示例,使用d3.v3绘制美国地图: 我希望在加载页面时,地图最初会放大到标记的位置,但应该呈现整个地图,以便用户可以在需要时缩小 var w = 300; var h = 280; //Define map projection var projection = d3.geo.albersUsa() .translate([w/2, h/2]) .scale([300]); //Defi

使用Mike Bostock的示例,使用d3.v3绘制美国地图:

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

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)
我有代码放大与滚动,我已经贴在上面,但我想它放大加载到这些特定的位置。我希望它是怎样的:


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

  • 修改将重新绘制路径的投影,或
  • 使用缩放和变换修改绘制的路径
在使用fitSize或fitExtent的d3v4中,修改投影是最简单的——尽管您需要将点转换为geojson。您还可以手动计算“平移”和“缩放”值以更新投影(请参见Mike Bostock,其中解释了这种常见的d3v3方法)

或者,您可以通过调用缩放函数来修改绘制的路径——昨天有一个很好的例子(在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*刻度相同,并允许可变的余量。
dx/w
返回的值比我们需要在svg容器的宽度上拉伸差值的比例值高一倍

(这样写可能更有意义:
var scale=0.9*Math.min(w/dx,h/dy);
-我们希望将缩放限制在最小的缩放值上,并将其乘以某个百分比以获得边距。但另一种表示形式在在线示例中随处可见)

现在我们有了一个标尺,我们只需要确定一个平移。为此,我们了解需要将
x
y
变量中的值重新定位到多大程度,以便将这些值居中:

var translate = [w/2 - scale * x, h/2-scale*y];
现在可以设置地图的初始比例和平移:

g.attr("transform", "translate("+translate+")scale("+scale+")");
但是,您可能希望在页面加载时更新缩放参数,以反映初始缩放和平移:

zoom.translate(translate);
zoom.scale(scale);
这样,当您从初始视图放大或缩小时,更改相对于初始缩放

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