在D3中将地理形状缩放到相似的大小

时间:2012-12-14 10:45:27

标签: javascript math d3.js computational-geometry cartogram

我正在使用D3的world-countries.json文件创建一个世界国家的墨卡托地图,然后我将绑定到一些非连续制图的数据。唉,加拿大,美国,澳大利亚等规模要大得多,意味着这些国家的一个单位是马耳他的几个单位的空间等价物。

我认为我需要做的是将geojson形状标准化,以便加拿大和马耳他在开始时的大小相同。

知道我该怎么做吗?

谢谢!

更新:我已经尝试将所有路径的宽度和高度明确地设置为一个小整数,但这似乎只是稍后被变换覆盖。代码如下:

// Our projection.
var xy = d3.geo.mercator(),
    path = d3.geo.path().projection(xy);

var states = d3.select("body")
  .append("svg")
  .append("g")
    .attr("id", "states");

function by_number() {

 function compute_by_number(collection, countries) {

    //update
     var shapes = states
            .selectAll("path")
              .data(collection.features, function(d){ return d.properties.name; });
    //enter       
         shapes.enter().append("path")
              .attr("d", path)
              .attr("width", 5) //Trying to set width here; seems to have no effect.
              .attr("height", 5) //Trying to set height here; seems to have no effect.
              .attr("transform", function(d) { //This works.
                var centroid = path.centroid(d),
                x = centroid[0],
                y = centroid[1];
                return "translate(" + x + "," + y + ")"
                + "scale(" + Math.sqrt(countries[d.properties.name] || 0) + ")"
                + "translate(" + -x + "," + -y + ")";
              })
            .append("title")
              .text(function(d) { return d.properties.name; });
    //exit
 }

 d3.text("../data/country_totals.csv", function(csvtext){
    var data = d3.csv.parse(csvtext);
    var countries = [];
    for (var i = 0; i < data.length; i++) {
        var countryName = data[i].country.charAt(0).toUpperCase() + data[i].country.slice(1).toLowerCase();
        countries[countryName] = data[i].total;
    }

    if (typeof window.country_json === "undefined") {
        d3.json("../data/world-countries.json", function(collection) {          
            window.country_json = collection;
            compute_by_number(collection, countries);           


        });
    } else {
            collection = window.country_json;
            compute_by_number(collection, countries);
    }

  });
} //end by_number

by_number();

1 个答案:

答案 0 :(得分:3)

您可以使用我在此处发布的帮助函数:https://gist.github.com/1756257

这会缩放投影以使给定的GeoJSON对象适合给定的边界框。缩放投影而不是使用变换来缩放整个路径的一个优点是笔划可以在地图上保持一致。

另一个更简单的选项可能是:

  1. 投射路径;
  2. 使用path.getBBox()获取每个边界框({​​{1}}是原生SVG函数,而不是D3方法)
  3. 在路径上设置变换,类似于现在的操作,缩放和平移路径以适合您的边界框。
  4. 这有点简单,因为它不涉及投影,但你需要通过反向(.getBBox())来缩放笔划以保持它们的一致性(因此你将无法用CSS设置笔画值。它还需要首先实际渲染路径,然后缩放它 - 这可能会影响复杂几何的性能。