如何居中和d3js中的比例映射(使用projection.center/translate/rotate?)

时间:2016-10-26 14:41:12

标签: d3.js maps visualization map-projections

鉴于我有给定地理特征和特定投影的topoJSON数据。

我应该如何居中和缩放地图以适合其父对象?

似乎我可以使用projection.rotate(),projection.translate()或projection.center()来映射地图:

https://github.com/d3/d3-3.x-api-reference/blob/master/Geo-Projections.md

有什么区别以及规模如何影响不同的功能?

2 个答案:

答案 0 :(得分:3)

实际上,它是两者的混合体。根据API,投影 .center:

  

将投影的中心设置为指定位置,经度和纬度的双元素数组(以度为单位)并返回投影。

因此,它用于设置地图的中心。关于投影 .translate:

  

如果指定了point,则将投影的平移偏移设置为指定的双元素数组[x,y]并返回投影。如果未指定point,则返回当前平移偏移,默认为[480,250]。平移偏移确定投影中心的像素坐标。默认平移偏移将⟨0°,0°places置于960×500区域的中心。

如您所见,投影 .translate取决于投影 .center(“平移偏移决定了投影中心的像素坐标”)。因此,两个值都将决定地图在容器中的位置

这是一个演示,显示日本地图(此代码不是我的)在一个较小的SVG,500x500。在这一个中,我们将把翻译设置为SVG的中间位置:

.translate([width/2, height/2]);

查看演示:

var topoJsonUrl = "https://dl.dropboxusercontent.com/u/1662536/topojson/japan.topo.json";

var width = 500,
    height = 500,
    scale = 1;

d3.select("body").append("svg")
	.attr("width", width)
	.attr("height", height)
    .append("g").attr("id", "all-g");

var projection = d3.geo.mercator()
		.center([138, 38])
		.scale(1000)
		.translate([width / 2, height / 2]);
    
d3.json(topoJsonUrl, onLoadMap);

function onLoadMap (error, jpn) {
    var path = d3.geo.path()
        		.projection(projection);
	var features = topojson.object(jpn, jpn.objects.japan);
  
  var mapJapan = features;
  

	d3.select("#all-g")
        .append("g").attr("id", "path-g").selectAll("path")
            .data(features.geometries)
            .enter()
            .append("path")
            .attr("fill", "#f0f0f0")
            .attr("id", function(d,i){ return "path" + i})
            .attr("stroke", "#999")
            .attr("stroke-width", 0.5/scale)
            .attr("d", path);

}
path {
  stroke: black;
  stroke-width: 1.5;
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://d3js.org/topojson.v0.min.js"></script>

而且,在这一个中,在左边:

.translate([width/4, height/2]);

查看演示:

var topoJsonUrl = "https://dl.dropboxusercontent.com/u/1662536/topojson/japan.topo.json";

var width = 500,
    height = 500,
    scale = 1;

d3.select("body").append("svg")
	.attr("width", width)
	.attr("height", height)
    .append("g").attr("id", "all-g");

var projection = d3.geo.mercator()
		.center([138, 38])
		.scale(1000)
		.translate([width / 4, height / 2]);
    
d3.json(topoJsonUrl, onLoadMap);

function onLoadMap (error, jpn) {
    var path = d3.geo.path()
        		.projection(projection);
	var features = topojson.object(jpn, jpn.objects.japan);
  
  var mapJapan = features;
  

	d3.select("#all-g")
        .append("g").attr("id", "path-g").selectAll("path")
            .data(features.geometries)
            .enter()
            .append("path")
            .attr("fill", "#f0f0f0")
            .attr("id", function(d,i){ return "path" + i})
            .attr("stroke", "#999")
            .attr("stroke-width", 0.5/scale)
            .attr("d", path);

}
path {
  stroke: black;
  stroke-width: 1.5;
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://d3js.org/topojson.v0.min.js"></script>

但是,在这两种情况下,更改投影 .center都会将地图移动到其容器中。

答案 1 :(得分:1)

在v4中使用projection.fitExtent()DocumentationExample

fitExtent有两个参数:

  1. extent 是投影的左上角和右下角,由两个数组的数组表示 - 例如[[0, 0], [width, height]]
  2. object 是一个GeoJSON对象。
  3. 如果投影的左上角是[0, 0],您可以使用便捷方法projection.fitSize(),只传递extent的右下角,由单个词组成两个项目的数组 - 例如[width, height]