5

マウスでズームすると、に接続されている次の関数myZoomが実行されます。

myZoom.on('zoom', function() {

    someElement.attr('transform', 'translate(' + d3.event.translate[0] + ',' + d3.event.translate[1] + ') scale(' + d3.event.scale + ')');

....
// redraw axes, which should stay where they are at.
....

}

マウスやその他のポインティングデバイスを使用せずにズームをシミュレートするには、上記の属性「transform」の値を変更するだけです。簡単。

しかし、問題はこの関数にあります。実際に軸を再描画します。軸のスケールは自動的に再計算されます。d3の次の公式ドキュメントを参照してください。

Zoom.y([y])

ズーム時にドメインを自動的に調整するYスケールを指定します。指定しない場合、現在のyスケールを返します。デフォルトはnullです。スケールのドメインがプログラムで変更された場合は、ズーム動作に再割り当てする必要があります。

プログラムでズームする必要があります(おそらくズームボタンを使用)。ズームイベントを発生させて、軸のスケールが自動的に再計算されるようにするにはどうすればよいですか?

4

4 に答える 4

6

D3 のズームはマウス イベントと密接に関係しているため、プログラムによるズームは D3 ライブラリでは困難な作業のようです。プログラムによるズームの一般的な例は、スライダー コントロールを使用したズームインまたはズームアウトです。驚いたことに、D3 ズームをスライダー コントロールで機能させる方法の実用的な例を 1 つも見つけることができませんでした。時間と労力を費やした後、この動作するデモを開発しました。これはD3SliderZoomにあります。重要な点は、スライダーによってスローされたスケール値を使用して、「<svg>」要素に埋め込まれた「<g>」SVGElement の変換属性を変更することです。

function zoomWithSlider(scale) {
    var svg = d3.select("body").select("svg");
    var container = svg.select("g");
    var h = svg.attr("height"), w = svg.attr("width");

    // Note: works only on the <g> element and not on the <svg> element
    // which is a common mistake
    container.attr("transform",
            "translate(" + w/2 + ", " + h/2 + ") " +
            "scale(" + scale + ") " +
            "translate(" + (-w/2) + ", " + (-h/2) + ")");

}

このメソッドは、次に示すように、スライダーの変更イベントから呼び出す必要があります。

$(function() {
$( "#slider-vertical" ).slider({
    orientation: "vertical",
    range: "min",
    min: 1000,
    max: 10000,
    value: 1000,
    slide: function( event, ui ) {
        zoomWithSlider(ui.value/1000);
    }
});

});

このソリューションは、疑似マウス スクロール イベントを生成するよりもはるかに洗練されています。

于 2013-11-13T18:38:06.237 に答える
2

残念ながら、 @Debasis の答えはうまくいきませんでした。これは、 force layoutで既に使用していたズーム動作でこれを達成したかったからです。2日間の必死の後、私は最終的にこのスレッドで解決策を見つけました:

https://groups.google.com/forum/#!msg/d3-js/qu4lX5mpvWY/MnnRMLz_cnUJ

function programmaticZoom ($svg, $zoomContainer, zoomBehavior, factor) {

    var width = $svg.attr('width');
    var height = $svg.attr('height');

    var newScale = zoomBehavior.scale() * factor;
    var newX = (zoomBehavior.translate()[0] - width / 2) * factor + width / 2;
    var newY = (zoomBehavior.translate()[1] - height / 2) * factor + height / 2;

    zoomBehavior
      .scale(newScale)
      .translate([newX,newY])
      .event($zoomContainer);
}
于 2014-10-10T13:13:23.747 に答える
2

新しいズームレベルの新しいドメインを自分で計算することになりました。この新しいドメインで、2 つの y 軸を再描画できました。同じ問題を抱えている人のために、コードを投稿します。私のプロジェクトに非常に固有のものなので、理解するのは難しいかもしれません。あなたの興味のために。

wr.zoomSim = function(sNew) {

    var s = wr.zoom.scale(),
        tx = wr.zoom.translate()[0],
        ty = wr.zoom.translate()[1],
        sReal = sNew / s,
        dtx = wr.width / 2 * (1 - sReal),
        dty = wr.height / 2 * (1 - sReal),
        txNew = sReal * tx + dtx,
        tyNew = sReal * ty + dty,

        a = wr.scaleYBZoom.domain()[0],
        b = wr.scaleYBZoom.domain()[1],
        c = wr.scaleYBZoom.range()[0],
        d = wr.scaleYBZoom.range()[1],
        r = (b-a)/(d-c);

    wr.scaleYBZoom.domain([a + r * ( (c - dty) / sReal - c), a + r * ( (d - dty) / sReal - c)]);

    wr.zoom.scale(sNew);
    wr.zoom.translate([txNew, tyNew]);

    wr.svg2.select('g#bar')
            .attr('transform', 'translate(' + txNew + ',' + tyNew + ') scale(' + sNew + ')');

    wr.svg2.select('g#axisl')
            .call(d3.svg.axis().scale(wr.scaleYBZoom).orient('left'))
        .selectAll('line.tick')
            .attr('x2', wr.width - wr.bar.left - wr.bar.right + 2 * wr.padding);
    wr.svg2.select('g#axisr')
            .call(d3.svg.axis().scale(wr.scaleYBZoom).orient('right'))
        .selectAll('line')
            .remove();

};
于 2012-11-07T11:46:09.760 に答える