22

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

到目前为止,我的(骇人听闻的)尝试:

  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 是否本机支持这样的东西?

4

3 回答 3

59

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];
}

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

于 2012-08-21T21:53:28.960 回答
4

接受的答案对我来说非常有用,直到我在 Edge 中进行测试。我无法发表评论,因为我没有足够的业力或其他任何东西,但正在使用此解决方案并发现 Microsoft Edge 存在问题,它不使用 x 或 y,仅使用上/左/下/右等。

所以上面的代码应该是:

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.left + bbox.width/2, bbox.top + bbox.height/2];
}
于 2017-11-30T10:32:25.233 回答
0

这里

解决方案是对选择使用 .datum() 方法。

var element = d3.select("#element");
var centroid = path.centroid(element.datum());
于 2020-04-02T20:24:40.763 回答