2016-10-06 7 views
2

thisのようなものを実装して、D3の線の遷移については、this postによく従っています。D3 Y軸のスケーリングとパスの切り替え

最後の目標は、リアルタイムのデータポイントを表示することです。

私はそうのように、軸を定義している:

var x = d3.time.scale() 
    .domain([now - (n - 2) * duration, now - duration]) 
    .range([0, width]); 

var y = d3.scale.linear() 
    .range([height, 0]) 
    .domain([0, 100]) 

var axisx = svg.append('g') 
    .attr('class', 'x axis') 
    .attr('transform', `translate(0, ${height})`) 
    .call(x.axis = d3.svg.axis().scale(x).orient('bottom').tickPadding(10)); 

var axisy = svg.append('g') 
    .attr('class', 'y axis') 
    .attr('transform', `translate(${width}, 0)`) 
    .call(y.axis = d3.svg.axis().scale(y).orient('right').tickPadding(10)); 

そしてそうのような行:

var line = d3.svg.line() 
    .interpolate('basis') 
    .x(function(d, i) { return x(now - (n - 1 - i) * duration); }) 
    .y(function(d, i) { return y(d); }); 

私は水平にポイントを移行しようとしてリンクポストの話のような遷移関数を追加しています時間の経過とともに:

(function tick() { 

    transition = transition.each(function() { 

     // Update the domain of the x-axis 
     now = new Date(); 
     x.domain([now - (n - 2) * duration, now - duration]); 

     // Push the new data point 
     data.push(temperature); 

     // Redraw the line 
     svg.select('.line') 
      .attr('d', line) 
      .attr('transform', null); 

     // Slide the x-axis left 
     axisx.call(x.axis); 

     // Slide the line left 
     path.transition() 
      .attr('transform', `translate(${x(now - (n - 1) * duration)})`); 

     // Pop the old data point off the front 
     data.shift(); 

    }).transition().each('start', tick); 
})(); 

これまでのところ、Y軸ドメインが固定されていると大変効果があります。私は、動的にY軸のドメインとラベルのサイズを変更したかったので、私は遷移関数に次を追加しました:

y.domain([ 
    Math.min.apply(Math, data) - 10, 
    Math.max.apply(Math, data) + 10 
]) 
axisy.call(y.axis); 

そして、y軸のスケールが正しく調整すると思われる一方でたときに、この顕著なグリッチ効果があります

Chart Redraw Glitch

明らかに、問題は、私は相間のラインの垂直方向の動きをアニメーションではないよということです:行は(ない各遷移関数目盛り間の)遷移関数がリコールされるたびに再描画されます。だから、最初の質問は、これを行うD3の簡単な方法はありますか?

データの最大値と最小値に基づいてドメインを設定することは、もはやデータが一貫して遷移していないため、スケーリングでもあることに気付きました。

だから、私はおそらくそうのようなドメインを設定することで和解するので終わるだろうと思う:ウィンドウが固定されている

y.domain([temperature - 10, temperature + 10]); 

。そして、私はそれが属性を持っているように、トランジションを変更する必要がありますと思う:

.attr('transform', `translate(${x(now - (n - 1) * duration)}, ${y(data[1] - data[0]}))`); 

私はこのtransformlineに関連するy関数を呼び出しますことがわかりますが、私はそれを再定義する必要がありますかどうかはわかりません。私は試しました:

.y(function(d, i) { return y(d/i); }); 

しかし、それは動作していないようです。

これらのライントランジションをどのように機能させることができますか?ご協力いただきありがとうございます。私はこのような深くて長い質問に対して謝罪します。

Link to full gist of code.

+0

こんにちはJamesさん、素敵な例です。この質問を投稿してからあなたの要点を修正しましたか?私はコピーしてあなたのコードを貼り付けて、あなたの質問に記述している問題に遭遇しないでください。あなた自身のために見てください(醜いCSSスタイルには申し訳ありません):https://bl.ocks.org/phvaillant/ff9135e0b03d76d67c368b5c7477f402 –

+0

返信いただきありがとうございます!私は何が起こっているのかを説明するのに悪い仕事をしたと思います。あなたと同じ要点をとり、 'y.domain([Math.min.apply(Math、data) - 10、Math.max.apply(Math、data)+ 10])を追加します。 axisy.call(y.axis); '遷移/アニメーションループで、私が話している問題が見えます。私が提供した要点は、単にy軸のドメインが変化する(それ自体がスムーズな遷移を持つ)ように垂直に線をアニメーション化するために様々なことを試しているベースコードです。 –

+0

私は、私の悪いを参照してください。私は誰かが(質問をupvoted)1つを見つける場合は、答えにも同様に興味があります。このグリッチ効果はすべての私の試みに抵抗しています。 –

答えて

0

編集:私は私の古い方法は、多くの場合、間違っていた実現、およびサンプルコード/計算を削除しました。私は何が間違っていたのか把握できるときに更新します...

これはクールな問題です。リンク先の例(Mike Bostock's)は、X方向の平行移動を補間するだけで、曲線が更新されたときにスムーズに左に移動します。しかし、あなたの例では、でもはY軸のスケールをリアルタイムで変更したいと思っています -

これについて考えると、曲線を左に移動することに加えてX方向)、我々はでも(Y方向のスケール変換を介して)それを少し踏み出す必要があります。それをY方向にスケーリングすることに加えて、y軸の新しい位置を補うために少し翻訳する必要があります。

[SVG行列変換] [1]でこれをすべて行うことができます。あなたはあなたの定数が何であるかを理解する必要があります(a、b、c、d、e、f)。これらは、あなたの古いスケールと新しいスケールを使って計算できます。

+0

私は本当にあなたの応答に感謝します!私は行列変換を調べます。あなたが提供したコードサンプルをチェックしたところ、彼らはうまくいくように見えたので、計算が間違っていることに気付いていませんでした。私はこれをもう少し詳しく説明します。 –

+0

翻訳が正しく動作しているように見えましたが、スケーリングがオフで、最初に見たものと同様のアーティファクトが発生していました。私は元のサンプルがY軸をスケーリングしていなかったので動作していたようだと思っています。 – Joel

関連する問題