22

プロジェクトでhttp://upload.wikimedia.org/wikipedia/commons/3/32/Blank_US_Map.svgにある SVG を使用し、d3.js とやり取りしています。http://bl.locks.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 に答える