web-dev-qa-db-ja.com

d3.jsバージョン4でのズームの例の書き換え

ドラッグアンドドロップの例

上記の例の一部を、コードで使用するように書き直そうとしています。具体的には次の部分です。

function centerNode(source) {
        scale = zoomListener.scale();
        x = -source.y0;
        y = -source.x0;
        x = x * scale + viewerWidth / 2;
        y = y * scale + viewerHeight / 2;
        d3.select('g').transition()
            .duration(duration)
            .attr("transform", "translate(" + x + "," + y + ")scale(" + scale + ")");
        zoomListener.scale(scale);
        zoomListener.translate([x, y]);
    }

しかし、v4パッケージがかなり変更されているため、行き詰まっています。 zoomListener関数を次のように記述しました

    var zoomListener = d3.zoom()
                 .scaleExtent([0.3,2])
                 .on("zoom", zoomed);

    function zoomed() {
       transform = d3.event.transform;
       console.log(d3.event);
         svg.attr("transform", transform);
    } 

function centerNode(source){
  t = transform;
  console.log(t);
  x = t.x*t.k; //I only want things to be centered vertically
  y = (t.y + -source.x0)*t.k + (viewerHeight)/2 ;
  svg.transition()
     .duration(duration)
     .attr("transform","translate(" + x + "," + y +")scale(" + t.k + ")");

  transform.scale(t.k); //DOES NOT WORK
  transform.translate([x, y]); //DOES NOT WORK

}

そして、私はドキュメントに従って物事が変更され、情報が私のzoomListenerとなるものに保存されなくなったことを知っています ズームに関するD3 V4リリースノート 新しいバージョンでそれを。 centerNode関数の最後の数行が機能しないため、ノードを中央に配置すると、ズームとパンがリセットされます...

なにか提案を?

14
Tekill

それで、多くの掘り起こしと試行錯誤の後で、私は私の目的のためにかなりうまくいく答えを思いつきました。以下のこのコードはコード全体ではなく、コードの関連部分にすぎないことに注意してください。特定の変数は自明であり、それらを含めませんでした。 ALSO THIS IS IN VERSION 4 of d3.js。

_var zoom = d3.zoom()
             .scaleExtent([0.3,2])
             .on("zoom", zoomed);


var svg = d3.select("body")
            .append("svg")
              .attr("width", viewerWidth)
              .attr("height", viewerHeight);

var zoomer = svg.append("rect")
                .attr("width", viewerWidth)
                .attr("height", viewerHeight)
                .style("fill", "none")
                .style("pointer-events", "all")
                .call(zoom);

var g = svg.append("g");

zoomer.call(zoom.transform, d3.zoomIdentity.translate(150,0)); //This is to pad my svg by a 150px on the left hand side

function zoomed() {
  g.attr("transform", d3.event.transform);//The zoom and panning is affecting my G element which is a child of SVG
}

function centerNode(source){

  t = d3.zoomTransform(zoomer.node());
  console.log(t);

  x =  t.x;
  y = source.x0;

  y = -y *t.k + viewerHeight / 2;

  g.transition()
   .duration(duration)
   .attr("transform", "translate(" + x + "," + y + ")scale(" + t.k + ")")
   .on("end", function(){ zoomer.call(zoom.transform, d3.zoomIdentity.translate(x,y).scale(t.k))});


}
_

D3.jsページのv4の例のように、長方形を使用してズームを適用しました

ズーム動作は、SVG要素をオーバーレイする非表示の四角形に適用されます。これにより、入力が確実に受け取られ、ポインターの座標がズーム動作の変換の影響を受けなくなります。 パンとズームの例

Centerノード関数では、d3.zoomTransform(zoomer.node());を使用して、ページに適用されている現在の変換を取得しています。この関数の目的は、折りたたみ可能なツリーを水平ではなく垂直に中央揃えすることだけなので、現在のtransform.x(ここでは_t.x_)を同じに保ちます。私のsvgの座標は反転しているので、なぜ_y= source.x0_、sourceは、折りたたみツリーでクリックされたノードです。 (「私がバージョン4に変換しようとしているものを理解するには、このスレッドの上部にある例を参照してください)

私はG要素に変換を適用してから、これらの変更をズーム変換にコミットしたいので、.on("end", function(){})を使用します。変換の現在の状態を設定しています。

_zoomer.call(zoom.transform, d3.zoomIdentity.translate(x,y).scale(t.k))
_

上記のこの行は、xとyの変換と現在の状態に等しいスケールを識別行列に適用して、Gの新しい変換を取得する必要があります。次に、それをzoomerに適用します。これは、以前にzoomと呼んだ要素です。

これは私にとって魅力のように働きました!

18
Tekill

transform.scaleおよびtransform.translateを呼び出すと、新しい変換が返され、何も変更されません。したがって:

transform = transform.translate([x, y]).scale(k)

svg.call(zoomListener.transform, newTransform)

(現時点ではzoomListenerはかなり不正確な名前ですが、関係ありません...)

kx、およびysourceから派生する可能性があります。表示されているとおりですが、よくわかりません。 sourceとはしかし、私にとって、t.x*t.kは、既存の変換xにそのスケールを乗算しているため、疑わしく見えます。フィードバックループが発生するようです。

V4のズームインの詳細については、 この関連するStackOverflowポスト 、または この例はmbostock をチェックして、要素(この場合はキャンバス)のズーム変換に対するプログラムによる制御を示します。 )および遷移が含まれます。

0
meetamit