2013-05-30 53 views
6

在bl.ocks網站不更新「到位」的元素餅圖更新例如:是否可以創建具有對象一致性的餅圖?

http://bl.ocks.org/j0hnsmith/5591116

function change() { 
    clearTimeout(timeout); 
    path = path.data(pie(dataset[this.value])); // update the data 
    // set the start and end angles to Math.PI * 2 so we can transition 
    // anticlockwise to the actual values later 
    path.enter().append("path") 
     .attr("fill", function (d, i) { 
     return color(i); 
     }) 
     .attr("d", arc(enterAntiClockwise)) 
     .each(function (d) { 
     this._current = { 
      data: d.data, 
      value: d.value, 
      startAngle: enterAntiClockwise.startAngle, 
      endAngle: enterAntiClockwise.endAngle 
     }; 
     }); // store the initial values 

    path.exit() 
     .transition() 
     .duration(750) 
     .attrTween('d', arcTweenOut) 
     .remove() // now remove the exiting arcs 

    path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs 
} 

相反,它只是把價值的新數組作爲全新的數據並相應調整圖表的大小。

我創建了一個小提琴演示該問題很乾脆:

http://jsfiddle.net/u9GBq/23/

如果按「添加」,它隨機INT添加到陣列中:這個按預期工作。

如果按'刪除',則唯一被轉出的元素始終是進入餅圖的最後一個元素。總之,它的行爲就像一個LIFO堆棧。 預期的行爲是相關的派生弧被轉換出來。

是否可以應用對象一致性派?我也嘗試添加一個關鍵函數(沒有演示在小提琴上),但它只是打破了(奇怪的是,它適用於我的堆積圖)。

謝謝。

+0

你可以提供你的意思一個生動的例子 - 你會想到之前和添加新元素後,看的?我不清楚 - 一個餡餅基本上代表了100%的數據集。將新元素添加到餅圖時,所有其他元素必須按比例縮小,反之亦然。 – mccannf

+0

嗨mccannf,謝謝你的留言。如果你看看我的原始文章中的第二個鏈接的jsfiddle,你可以看到當按下'remove'時,你將從集合中刪除一個特定的隨機數據元素。我希望特定的弧線能夠轉換出來。相反,它用新顏色重新着色所有弧,並從最後一個輸入中過渡 - 不再反映底層數據集。出於這個原因,d3似乎也不保留指數。 –

+0

好的,理解。像這個例子會有幫助:http://bl.ocks.org/mbostock/3888852。這裏mbostock已經爲數據頭分配了一個顏色域,還有一個關聯的圖例。 – mccannf

回答

11

解決這個問題的最簡單的解決方案是設置缺失值爲零,而不是完全去除它們,如在Pie Chart Update一系列實施例的Part III。然後您可以免費獲得object constancy:您擁有相同數量的元素,按照相同的順序,跨越更新。

另外,如果你想有一個數據連接,如Part IV,你必須告訴D3在進入弧線應進入,並在退出的弧線應該出口。一個合理的策略是從相反的數據中找出最接近的相鄰弧:對於給定的輸入弧,在舊數據中找到最接近的相鄰弧(預過渡);同樣對於給定的退出弧,在新數據中找到最近的相鄰弧(轉換後)。

要繼續該示例,假設您顯示的是不同地區的蘋果銷售情況,並且希望切換爲顯示橙子。你可以使用下面的鍵功能,以保持恆定對象:

function key(d) { 
    return d.data.region; 
} 

(這裏假設你正在使用d3.layout.pie,它包裝自己的原始數據,並公開其作爲d.data。)

現在說,當你過渡到橘子,則有以下的舊數據和新數據:

var data0 = path.data(), // retrieve the old data 
    data1 = pie(region.values); // compute the new data 

對於在索引i(其中ddata1[i]),每個進入弧,可以依次經由前述步驟在data1數據,看看你是否能在data0找到匹配:

var m = data0.length; 
while (--i >= 0) { 
    var k = key(data1[i]); 
    for (var j = 0; j < m; ++j) { 
    if (key(data0[j]) === k) return data0[j]; // a match! 
    } 
} 

如果找到匹配的,你進入弧從匹配弧的末端開始ngle。如果您沒有找到前面的匹配項,則可以查找下面的匹配弧。如果沒有匹配,那麼兩個數據集之間沒有重疊,所以您可以從角度0°輸入弧,或者進行交叉淡入淡出。您也可以將此技術應用於退出弧。

全部放在一起,這裏的Part V

pie chart update v

+0

第五部分,只爲我:)是啊!非常感謝你的Mike !!!!!!! –

0

好的,找到了解決方案。 訣竅是要通過關鍵的是這樣的:

path = path.data(pie(dataset), function (d) {return d.data}); // this is good 

相對於不通過它,或傳遞了錯誤的方式:

path = path.data(pie(dataset, function (d) {return d.data})); // this is bad 

下面是一個更新的撥弄的工作過渡右弧! :)

http://jsfiddle.net/StephanTual/PA7WD/1/

+2

不要認爲是正確的。如果你的關鍵函數是'return d.data',那麼你所有的鍵都將是''[object Object]'',並且會發生不好的事情。請參閱我的回答,並且我還建議閱讀關鍵函數上的[對象常量教程](http://bost.ocks.org/mike/constancy/)。 – mbostock

+0

哇,我受到Mbostock自己的教育,這是一種榮幸!感謝邁克在下面的詳細答案,我會給你投票。 –

相關問題