3

マップをD3のv3にアップグレードし、ここにあるD3サンプルコードで概説されているクリックしてズームする変換を使用しています。

私のコードは、マップのサイズがわずかに小さい(960x500ではなく564x300)ことを除いて、ほぼ同じです。さらに、マップをdiv内にネストし、ページの左上に配置しています(ただし、これは重要ではないと思います)。

マップロードの初期ロードは問題ありません(現在、区別のために黒い背景を使用しています)

// Clear existing map in case there is remnant data.
$("#map").html(null);

var mapWidth = 564;
var mapHeight = 300;

var projection = d3.geo.albersUsa()
                          .scale(mapWidth)
                          .translate([0, 0]);   

var path = d3.geo.path()
                 .projection(projection);

var svg = d3.select("#map")
               .append("svg")
               .attr("id", "map-svg")
               .attr("width", mapWidth)
               .attr("height", mapHeight);

   svg.append("rect")
    .attr("id", "map-background")
    .attr("class", "background")
    .attr("width", mapWidth)
    .attr("height", mapHeight)
    .on("click", click);

   // Create placeholders for shapes and labels
   var states = svg.append("g")
                   .attr("transform", "translate(" + mapWidth / 2 + "," + mapHeight / 2 + ")")
                   .attr("id", "states");

ここに画像の説明を入力してください

ただし、状態がクリックされ、クリック関数が実行されると、変換がオフになっているように見えます。私の場合、アーカンソー州をクリックしました(青い陰影で示されています)

function click(d)
{
   var x = 0,
       y = 0,
       k = 1;

   if (d && centered !== d)
   {
      var centroid = path.centroid(d);
      x = -centroid[0];
      y = -centroid[1];
      k = 4;
      centered = d;      
   }
   else
   {
      centered = null;
   }

   d3.select("#states").selectAll("path")
       .classed("active", centered && function (d) { return d === centered; });

   d3.select("#states").transition()
       .duration(1000)
       .attr("transform", "scale(" + k + ")translate(" + x + "," + y + ")")
       .style("stroke-width", 1.5 / k + "px");
}

ここに画像の説明を入力してください

私の唯一の考えは、マップのサイズを小さくしたり、位置を変えたりするために、重心の計算をわずかに調整する必要があるということですが、これも正しくないようです。

適切な調整を行うにはどうすればよいですか?

編集:変換の最後に「負の平行移動」を追加すると(translate( "+ -x +"、 "+ -y +"))、ズームを適切に中心に近づけることがわかりましたが、そうではありません完全に

4

1 に答える 1

8

から2つの変換のうちの1つが欠落しています。しかし、より簡単な解決策を読んでください。

使用している例には、2つのネストされた変換があります。まず、外側のG要素の静的変換:

var g = svg.append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
  .append("g")
    .attr("id", "states");

この変換は、 projection.translateが通常行うのと同じ目的を果たしますが、例ではtranslate([0、0])を使用しています。(私が言ったように、より簡単な解決策があるでしょう…)

2番目の変換は、内側のG(id "states")で動的に設定され、次のようにズームインします。

g.transition()
    .attr("transform", "scale(" + k + ")translate(" + x + "," + y + ")");

var gここでは、内側のG要素を参照していることに注意してください。これは、定義されたときにg、 2番目の;append("g")でチェーンされた要素があったためです。append("g")したがって、変数は、最初の外側のGではなく、2番目の内側のGとして定義されます。

結果のSVGは次のようになります。

<g transform="translate(480,250)">
  <g id="states" transform="translate(75.746,-439.514)scale(4,4)">
    …
  </g>
</g>

派生にネストされた内側のGがありません。したがって、#states G要素に「transform」属性を設定すると、外側の変換が上書きされ、次のようになります。

<g id="states" transform="scale(4)translate(18.936679862557288,-109.8787070159044)">
  …
</g>

したがって、静的変換「translate(480,250)」がありません。

これらの変換を組み合わせることをお勧めします。次に、外側のGは必要ありません。次のことができます。

g.transition()
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"
        + "scale(" + k + ")"
        + "translate(" + x + "," + y + ")");

これにより、投影の変換を[0、0]に設定する必要もなくなるため、代わりに標準の変換[width / 2、height/2]を使用できます。まさにそれを行うために例を更新しました!

于 2013-03-21T01:48:41.667 に答える