1

データが変更されるとアニメーション化される積み上げ面グラフがあります。

データは、特定の日付範囲 (例: 12 月 10 ~ 15 日) の値を示します。以前の日付を含めるように日付範囲を拡張すると (例: 12 月 9 ~ 15 日)、データ配列の先頭に追加のデータが追加されます。

ただし、パスがアニメーション化されると、その効果は非常に奇妙で望ましくありません。

効果を示すこの jsfiddle を参照してください ([更新] ボタンをクリックします): http://jsfiddle.net/qprn9ta9/

これは、SVG 領域の前面に新しいポイントを追加し、補間によってインデックスに基づいてそれらがアニメーション化されているためと思われます。

どうすればこれを回避できますか? D3 に組み込まれている機能はありますか? で使用するキー関数のようなものを探しましたがdata()、同様のものは見つかりませんでした。他のアイデアはありますか?

4

3 に答える 3

0

だから、この質問は一晩中私を夢中にさせてきました. d3データの先頭に新しいポイントを追加するとinterpolateString、あるパスから別のパスに移動するときにメソッドがスローされることは正しいです。私が思いつく最善の (ハッキーな) 修正は、遷移が開始する前にパスにポイントを挿入することです。

// enter
var mp = svg.selectAll("path")
    .data(layers);

mp
    .enter().append("path")
    .style("fill", function(d) { return d.color; });

//update
mp
  .transition()
  .duration(2000)
  .tween("path", function(d) {
    var self = d3.select(this),
        cP = self.attr("d"),
        i = null;
    if (!cP){
      i = d3.interpolateString("", area(d.layer));
    } else {
        var idx = cP.indexOf("L"),
          fP = cP.substring(0, idx),
          lP = cP.substring(idx);          
                cP = fP + "L" + fP.slice(1) + lP;          
        i = d3.interpolateString(cP, area(d.layer));
    }
    return function(t) {
            self.attr("d", i(t));
    };
  });

完全なコード:

test_data0 = [{"0": 0.1, "1": 0.1}, {"0": 0.2, "1": 0.6}, {"0": 0.3, "1": 0.4}, {"0": 0.1, "1": 0.6}, {"0": 0.3, "1": 0.1}, {"0": 0.0, "1": 0.3}, {"0": 0.3, "1": 0.1}, {"0": 0.3, "1": 0.2}, {"0": 0.2, "1": 0.3}]
test_data1 = [{"0": 0.2, "1": 0.2}, {"0": 0.1, "1": 0.1}, {"0": 0.2, "1": 0.6}, {"0": 0.3, "1": 0.4}, {"0": 0.1, "1": 0.6}, {"0": 0.3, "1": 0.1}, {"0": 0.0, "1": 0.3}, {"0": 0.3, "1": 0.1}, {"0": 0.3, "1": 0.2}, {"0": 0.2, "1": 0.3}]

$('#update').click(function(){
    console.log('test')
    streamed_history(test_data1)
});
var width = 300,
    height = 200,
    colors = {'0': '#6ff500', '1': '#ffad0a'},
    feedbacks = [0, 1],
    stack = d3.layout.stack();
var svg = d3.select("#timeline").append("svg")
    .attr("width", width)
    .attr("height", height);
var y = d3.scale.linear()
    .domain([0, 1])
    .range([height, 0]);

streamed_history(test_data0)

function streamed_history(data) {
    data_array = feedbacks.map(function (f) {
        return data.map(function(element, i) { return {x: i, y: element[f]}; })
    }),
    layers = stack(data_array)
    layers = feedbacks.map(function (f, i) {
        return {layer: layers[i], feedback: f, color: colors[f]}
    })

    var x = d3.scale.linear()
        .domain([0, data.length - 1])
        .range([0, width]);

    var area = d3.svg.area()
        .x(function(d) { return x(d.x); })
        .y0(function(d) { return y(d.y0); })
        .y1(function(d) { return y(d.y0 + d.y); });
        
    //enter
    var mp = svg.selectAll("path")
        .data(layers);
        
    mp
        .enter().append("path")
        .style("fill", function(d) { return d.color; });

    //update
    mp
      .transition()
      .duration(2000)
      .tween("path", function(d) {
        var self = d3.select(this),
            cP = self.attr("d"),
            i = null;
        if (!cP){
          i = d3.interpolateString("", area(d.layer));
        } else {
        	var idx = cP.indexOf("L"),
              fP = cP.substring(0, idx),
              lP = cP.substring(idx);          
					cP = fP + "L" + fP.slice(1) + lP;          
        	i = d3.interpolateString(cP, area(d.layer));
        }
        return function(t) {
        		self.attr("d", i(t));
        };
      });

}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="timeline"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<button id='update'>Update</button>

于 2016-01-07T16:38:31.127 に答える
0

データセット 0 の 1 つにポイントを追加する必要があるが、データセット 1 が変更されていない場合は、「スペーサー値」を追加して、データセット 1 の最後の値を繰り返します。

配列の長さを一致させる必要があります。そうしないと、データに対応するために SVG のマークアップ構造を変更する必要があり、時間の経過とともに位置だけを変更する必要がないため、アニメーションに不具合が生じます。

前 (データセットの長さは異なります):

test_data0 = [{"0": 0.1, "1": 0.1}, {"0": 0.2, "1": 0.6}, {"0": 0.3, "1": 0.4}, {"0": 0.1, "1": 0.6}, {"0": 0.3, "1": 0.1}, {"0": 0.0, "1": 0.3}, {"0": 0.3, "1": 0.1}, {"0": 0.3, "1": 0.2}, {"0": 0.2, "1": 0.3}]
test_data1 = [{"0": 0.2, "1": 0.2}, {"0": 0.0, "1": 0.0}, {"0": 0.2, "1": 0.6}, {"0": 0.3, "1": 0.4}, {"0": 0.1, "1": 0.6}, {"0": 0.3, "1": 0.1}, {"0": 0.0, "1": 0.3}, {"0": 0.3, "1": 0.1}, {"0": 0.3, "1": 0.2}, {"0": 0.2, "1": 0.3}]

後 (2 つのデータセットで同じ長さ):

test_data0 = [{"0": 0.1, "1": 0.1}, {"0": 0.2, "1": 0.6}, {"0": 0.3, "1": 0.4}, {"0": 0.1, "1": 0.6}, {"0": 0.3, "1": 0.1}, {"0": 0.0, "1": 0.3}, {"0": 0.3, "1": 0.1}, {"0": 0.3, "1": 0.2}, {"0": 0.2, "1": 0.3}, {"0": 0.2, "1": 0.3}]
test_data1 = [{"0": 0.2, "1": 0.2}, {"0": 0.0, "1": 0.0}, {"0": 0.2, "1": 0.6}, {"0": 0.3, "1": 0.4}, {"0": 0.1, "1": 0.6}, {"0": 0.3, "1": 0.1}, {"0": 0.0, "1": 0.3}, {"0": 0.3, "1": 0.1}, {"0": 0.3, "1": 0.2}, {"0": 0.2, "1": 0.3}]

そのため、このソリューションでは、事前にデータセットをより慎重に扱う必要があります。

jsfiddle:

http://jsfiddle.net/2o372wu3/

于 2016-01-06T18:33:56.220 に答える