用D3.js计算SVG路径质心

时间:2012-08-21 20:29:56

标签: javascript svg d3.js

我在项目中使用位于http://upload.wikimedia.org/wikipedia/commons/3/32/Blank_US_Map.svg的SVG并使用d3.js与其进行交互。我想创建一个单击缩放效果,如http://bl.ocks.org/2206590,但该示例依赖于存储在JSON对象中的路径数据来计算质心。有没有办法从现有的SVG加载d3中的路径数据来获得质心?

到目前为止我的(hackish)尝试:

  function get_centroid(sel){
    var coords = d3.select(sel).attr('d');
    coords = coords.replace(/ *[LC] */g,'],[').replace(/ *M */g,'[[[').replace(/ *z */g,']]]').replace(/ /g,'],[');
    return d3.geo.path().centroid({
      "type":"Feature",
      "geometry":{"type":"Polygon","coordinates":JSON.parse(coords)}
    });
  }

这似乎适用于密苏里州等一些州,但像华盛顿这样的其他州也失败了,因为我的SVG数据解析非常简陋。 d3本身是否支持这样的东西?

2 个答案:

答案 0 :(得分:54)

D3函数似乎都假设您从GeoJSON开始。但是,我实际上并不认为你需要质心 - 你真正需要的是边界框,幸运的是这可以直接从SVG DOM界面获得:

function getBoundingBoxCenter (selection) {
  // get the DOM element from a D3 selection
  // you could also use "this" inside .each()
  var element = selection.node();
  // use the native SVG interface to get the bounding box
  var bbox = element.getBBox();
  // return the center of the bounding box
  return [bbox.x + bbox.width/2, bbox.y + bbox.height/2];
}

实际上,为了缩放,这实际上比真正的质心略好,因为它避免了一些您可能遇到的投影问题。

答案 1 :(得分:0)

来自here

解决方案是在选择项上使用.datum()方法。

var element = d3.select("#element");
var centroid = path.centroid(element.datum());