DC.jsキャンバスチャートにカーソルを合わせ、カーソルを合わせたポイントを使用して別のチャートに変更を適用したいと思います(つまり、そのポイントに関する情報を別のチャートに表示します)。
合併症:
このようなレンダーレットになると思いますが、キャンバスプロットなのでかなり注意が必要です。
このブロックのように、キャンバスであるために非表示の要素を使用する必要があると思います
必要な動作がオレンジと緑のプロットをホバリングする場所にStackblitzを配置しました。他のスキャッターは、それぞれのグループポイントに対していくつかの(この例では任意の)プロパティが変更されています
涼しい!あなたがこれを理解し、あなたの答えを発表してくれてうれしいです。これは他の人にも役立ちます。
あなたの本能は、内部ループ内で高価な初期化を行わないのは正しいことです。
レンダーレットハンドラーで作業を行うのは問題ありません。これは、グラフがレンダリングまたは再描画されたとき、およびデータが変更されたときに発生するため、理にかなっています。
ただし、mousemoveリスナー内でクアッドツリーを計算するような高価な計算はインタラクティブであるため、お勧めできません。
速度は完全に良いように見えますが、私はまともなiMacを持っており、ローエンドのマシンではパフォーマンスが厄介かもしれません。
私は次のようにコードを構成します:
eventScatterChart.on("renderlet", c => {
// 0
const xScale = c.x();
const yScale = c.y();
const data = c.group().all() // 1
.filter(({value}) => value) // 2
.map(({key}) => key); // 3
// 4
const overlayPos = c.select('.overlay').node().getBBox();
const tree = d3
.quadtree()
.extent([
[xScale.invert(overlayPos.x), yScale.invert(overlayPos.y)],
[xScale.invert(overlayPos.width), yScale.invert(overlayPos.height)]
])
.addAll(data);
c.select(".overlay").on("mousemove.eventID", function(event) {
// 5
const cursorX = d3.pointer(event)[0];
const cursorY = d3.pointer(event)[1];
const closestPoint = tree.find(
xScale.invert(cursorX),
yScale.invert(cursorY)
);
console.log(closestPoint);
});
});
レンダーレットは、初期化を行うのに適した場所です。また、チャートが描かれるまで、xとyのスケールが定義されていないこともわかりました。
ディメンションではなくグループからデータをフェッチして、他のディメンションのフィルターを監視するようにします。
ポイントが「フィルターで除外」された場合でもエントリvalue
はありますが、0なので、それらを削除します。非表示のポイントにカーソルを合わせると、最も近い表示ポイントが選択されます。
グループのキーは、次元キーを次のように定義したため、最初の要素としてx、yを含む配列です。
const dimension = ndx.dimension(d => [
d.changePointTime,
d.photonCountsMean,
d.transitionDirection === -1 ? "BG" : "Signal"
]);
前とまったく同じようにクアッドツリーを初期化します。
これで、mousemoveイベントハンドラーは本当にシンプルになり、ルックアップのみを実行します。かなり効率的であるはずです!
私はそれがCPU使用率を助けないことを発見しました(それでも1つのプロセッサをペグします)、しかし数字はブラウザコンソールではるかに速く飛んでいました。パフォーマンスをさらに向上させたい場合は、mousemoveイベントを調整できます。(ブラウザーは1秒あたり数百を生成できます。)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加