4

ズーム機能を備えたグラフがあります。私の主な観察結果は、x 軸が現在のズーム レベルに基づいてスケールを更新したことです。私はy軸にもこれをさせたかったので、有効zoom.y(y)にしました。望ましくない副作用は、ユーザーがグラフの「下」の負の値であっても、すべての方向にズームアウトできることです。

http://jsfiddle.net/ericps/xJ3Ke/5/

var zoom = d3.behavior.zoom().scaleExtent([0.2, 5]) .on("zoom", draw);y 軸を実際に考慮していないようです。また、ユーザーはグラフを任意の方向に無限にドラッグできます。

私が考えたアイデアの 1 つは、zoom.y(y) を有効にすることとは関係なく、現在表示されている範囲にあるものに基づいて y 軸を再描画する必要があるだけです。X 軸の位置のみに基づいたある種の再描画のように。今は上下スクロールは一切したくない、左右だけにしたい

コメントアウトする以外に、//zoom.y(y)これはどのように行われますか?洞察力に感謝します。

4

1 に答える 1

12

draw メソッドで y スケール ドメインを更新するだけです。

ズーム機能は、関連付けられたスケールを変更し、ズームをシミュレートするようにドメインを設定します。したがって、たとえば x.invert(0) および x.invert(width) を実行することで、x の可視データ境界を取得できます。文字列の代わりに日付を使用するようにデータを変換した場合、これを使用してフィルタリングすることをお勧めします。おそらくより効率的です。

ただし、x スケールを使用して可視データをフィルタリングし、それらの値の y 軸の範囲を見つけ、それに応じて一致するように y スケール ドメインを設定することができます。実際、これらすべてをわずか数行で実行できます (ズーム更新コールバック内):

var yExtent = d3.extent(data.filter(function(d) { 
    var dt = x(d.date);
    return dt > 0 && dt < width;
}), function(d) { return d.value; });
y.domain(yExtent).nice(); 

ここで試すことができます

何が起こっているのかをよりよく説明するには:

ズーム動作はマウス イベントをリッスンし、関連付けられたスケールの範囲を変更します。

スケールは、目盛り付きの線として描画する軸によって使用されます。スケールは、コールバックで設定したパスとエリアに関連付けられたデータによっても使用されます。

したがって、ズームが変更されるとコールバックが発生し、基本的なメソッドは次のとおりです。

svg.select("g.x.axis").call(xAxis);
svg.select("g.y.axis").call(yAxis);
svg.select("path.area").attr("d", area);
svg.select("path.line").attr("d", line);

新しく更新されたドメインで x 軸と y 軸を再描画し、新しくドメイン化された x スケールと y スケールで領域と線を再描画 (再計算) します。

したがって、必要な動作を実現するために、y スケールのデフォルトのズーム動作を取り除き、代わりに、ズームまたはパンを取得するたびに y スケール ドメインを自分で変更します。便利なことに、ズーム動作のために、これらのアクションのコールバックが既にあります。 .

y スケールのドメインを計算する最初のステップは、どのデータ値が表示されているかを把握することです。x 軸は 0 から幅の範囲に出力するように構成されており、ズーム動作によって x スケールのドメインが更新されたため、元のドメインのサブセットのみがこの範囲に出力されます。したがって、javascript 配列のフィルター メソッドを使用して、マッピングによって可視範囲内にあるデータ オブジェクトのみを抽出します。

data.filter(function(d) { 
    var dt = x(d.date);
    return dt > 0 && dt < width;
}

次に、便利な d3 エクステント メソッドを使用して、最小値と最大値を配列で返します。しかし、配列はすべてオブジェクトであるため、extents メソッドが実際に比較するいくつかの数値を持つように、アクセサー関数が必要です (これは D3 の一般的なパターンです)。

d3.extents(filteredData, function(d) { return d.value; });

これで、現在の x スケールで描画されるすべてのデータ ポイントの最小値と最大値がわかります。最後のビットは、y スケールのドメインを設定し、通常どおり続行することです。

y.domain(yExtent).nice(); 

私がAPIで見つけた素敵な方法は、スケールでやりたいことであり、d3はしばしばあなたがやりたいことをしてくれるからです。

このようなことのいくつかを理解するための優れたチュートリアルは次のとおり です。

于 2013-03-05T19:03:46.107 に答える