戦略は、チャートがレンダリングされるたびに再評価されています。通常、最初のチャートのレンダリングには100msのレンダリング時間は問題ありませんが、滑らかなパン/ズームが必要な場合は問題になります。
私が思いついた解決策は、レイアウトの結果をキャッシュして、チャートが拡大されている間に再評価されないようにすることです。ただし、ズーム操作が終了すると、レイアウトが再評価されて衝突が取り除かれます。
まず、ズームイベントはオン/オフキャッシュの動作を有効に処理されます。
var returnCachedLayout = false;
var zoomBeh = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([0, 500])
.on("zoomstart", function() {
returnCachedLayout = true;
zoom()
})
.on("zoom", zoom)
.on("zoomend", function() {
returnCachedLayout = false;
zoom()
})
その後の戦略は、キャッシュを利用するように適合されている:
var strategyCache = function (strategy) {
var cachedLayout;
var cache = function(layout) {
if (!returnCachedLayout) {
cachedLayout = strategy(layout);
// determine the offset applied by the layout
for (var i = 0; i< layout.length; i++) {
cachedLayout[i].dx = layout[i].x - cachedLayout[i].x;
cachedLayout[i].dy = layout[i].y - cachedLayout[i].y;
}
} else {
// update the location of each label, including the offset
for (var i = 0; i< layout.length; i++) {
cachedLayout[i].x = layout[i].x - cachedLayout[i].dx;
cachedLayout[i].y = layout[i].y - cachedLayout[i].dy;
}
}
return cachedLayout;
};
return cache;
};
// construct a strategy that uses the "greedy" algorithm for layout, wrapped
// by a strategy that removes overlapping rectangles.
var strategy = strategyCache(fc.layout.strategy.removeOverlaps(fc.layout.strategy.greedy()));
それは少しトリッキーですズーム動作によってこれらのポイントが移動するため、キャッシュからラベルを再レンダリングできないためです。このため、オフセットは新しい位置のラベルに再適用できるように保存されています。
とにかく、ここでは完全な例です:
https://jsfiddle.net/qrpr0wre/
私はすぐにd3fcラベルレイアウトのこの「最初のクラスの機能を作るために見ていきます。
あなたの問題を示すより完全で実行可能な例を提供できますか? – ColinE
こんにちは@ColinE - より大きなSencha ExtJS UIシステムに埋め込まれているので、実際のコードを公開することはできませんが、d3fsの使い方を示すコードの簡略版を提示しようとしました。助けてくれてありがとう! –
これは整理するために少し作業が必要になると思います。レイアウトの計算には約100msかかりますが、これは常にズームを「不安定」にします。私はここ(https://github.com/d3fc/d3fc-label-layout/issues/24)の問題を提起し、まともな解決策を見つけることを試みるでしょう。 – ColinE