2014-01-13 42 views
0

點擊一個按鈕,我想添加一個新的數據集到我的圓環圖並讓它轉換新的數據集。我寫過的代碼就是這樣做的,但是當數據集中的個體數據數量與之前的數據數量不同時(即從[1,2]到[1,2,3,4]),它會遇到問題。圓環圖與數據集變化與d3,js

我認爲問題是我需要創建一個新的路徑,每當有新的數據集有更多的數據,並刪除路徑,只要它少。但是,當我嘗試在我的點擊功能中追加數據時,它會追加它而不刪除舊路徑,並會在圖表上重疊。

這裏是沒有追加,其中arctween將工作,但會出現空派弧,因爲我不追加路徑(arctween工作一半時間)的一個版本: http://jsfiddle.net/njrPF/1/

var pieW = 500; 
var pieH = 500; 
var innerRadius = 100; 
var outerRadius = 200; 

var results_pie = d3.layout.pie() 
    .sort(null); 
var pie_arc = d3.svg.arc() 
    .innerRadius(innerRadius) 
    .outerRadius(outerRadius); 

var svg_pie = d3.select("#pieTotal") 
    .attr("width", pieW) 
    .attr("height", pieH) 
    .append("g") 
    .attr("transform", "translate(" + pieW/2 + "," + pieH/2 + ")") 
    .attr("class", "piechart"); 

var pie_path = svg_pie.selectAll("path").data(results_pie([1, 2])) 
    .enter().append("path") 
    .attr("d", pie_arc) 
    .each(function (d) { 
    this._current = d; 
}) // store the initial values 
.attr("class", "vote_arc") 
    .attr("value", function (d, i) { 
    return (i - 1); 
}); 


var pie_votes = [1, 2]; 
var pie_colors = ["#0f0", "#f00"]; 
$(svg_pie).bind("monitor", worker); 
$(svg_pie).trigger("monitor"); 

function worker(event) { 
    pie_path = pie_path.data(results_pie(pie_votes)) 
     .attr("fill", function (d, i) { 
     return pie_colors[i]; 
    }); 

    pie_path.transition().duration(500).attrTween("d", arcTween).each('end', function (d) { 
     if (d.value <= 0) { 
      this.remove(); 
     } 
    }); 
    setTimeout(function() { 
     $(svg_pie).trigger("monitor"); 
    }, 500); 
} 

function arcTween(a) { 
    var i = d3.interpolate(this._current, a); 
    this._current = i(0); 
    return function (t) { 
     return pie_arc(i(t)); 
    }; 
} 

$('button').click(function() { 
    pie_votes = []; 
    pie_colors = []; 
    for (var i = 0; i < Math.floor(Math.random() * 6); i++) { 
     //sets new values on pie arcs 
     pie_votes.push(Math.floor(Math.random() * 10)); 
     pie_colors.push("#" + (Math.floor(Math.random() * 16777215)).toString(16)); 
    } 
    pie_path = pie_path.data(results_pie(pie_votes)) 
     .attr("fill", function (d, i) { 
     return pie_colors[i] 
    }); 

    pie_path.transition().duration(500).attrTween("d", arcTween).each('end', function (d) { 
     if (d.value <= 0) { 
      this.remove(); 
     } 
    }); 
}); 

這裏是一個版本在那裏我嘗試添加新的路徑,但它們重疊:提前 http://jsfiddle.net/njrPF/3/

var pieW = 500; 
var pieH = 500; 
var innerRadius = 100; 
var outerRadius = 200; 

var results_pie = d3.layout.pie() 
    .sort(null); 
var pie_arc = d3.svg.arc() 
    .innerRadius(innerRadius) 
    .outerRadius(outerRadius); 

var svg_pie = d3.select("#pieTotal") 
    .attr("width", pieW) 
    .attr("height", pieH) 
    .append("g") 
    .attr("transform", "translate(" + pieW/2 + "," + pieH/2 + ")") 
    .attr("class", "piechart"); 

var pie_path = svg_pie.selectAll("path").data(results_pie([1, 2])) 
    .enter().append("path") 
    .attr("d", pie_arc) 
    .each(function (d) { 
    this._current = d; 
}) // store the initial values 
.attr("class", "vote_arc") 
    .attr("value", function (d, i) { 
    return (i - 1); 
}); 

function arcTween(a) { 
    var i = d3.interpolate(this._current, a); 
    this._current = i(0); 
    return function (t) { 
     return pie_arc(i(t)); 
    }; 
} 

$('button').click(function() { 
    pie_votes = []; 
    pie_colors = []; 
    for (var i = 0; i < Math.floor(Math.random() * 10); i++) { 
     //sets new values on pie arcs 
     pie_votes.push(Math.floor(Math.random() * 10)); 
     pie_colors.push("#" + (Math.floor(Math.random() * 16777215)).toString(16)); 
    } 
    pie_path = pie_path.data(results_pie(pie_votes)) 
     .enter().append("path") 
     .attr("d", pie_arc) 
     .each(function (d) { 
     this._current = d; }) // store the initial values 
    .attr("class", "vote_arc") 
     .attr("value", function (d, i) { 
     return (i - 1); 
    }); 
    pie_path.attr("fill", function (d, i) { 
     return pie_colors[i] 
    }); 

    pie_path.transition().duration(500).attrTween("d", arcTween).each('end', function (d) { 
     if (d.value <= 0) { 
      this.remove(); 
     } 
    }); 
}); 

感謝。

回答

1

您需要處理進入和退出選擇以及更新選擇。例如參見this tutorial。在你的情況下的相關代碼將是

pie_path = pie_path.data(results_pie(pie_votes)); 

pie_path.enter().append("path") 
    .attr("d", pie_arc) 
    .each(function (d) { 
     this._current = d; 
    }) // store the initial values 
    .attr("class", "vote_arc") 
     .attr("value", function (d, i) { 
     return (i - 1); 
    }); 

pie_path.exit().remove(); 

完整的示例here

+0

謝謝。有沒有辦法在remove()之後進行回調?它會像刪除(回調)? – PGT

+1

你想在回調中做什麼? '.remove()'應該是最後一件事。 –

+0

基本上我把餅圖數據的改變放在一個函數中,我傳入數據和顏色。我希望它的動畫方式是,如果你推入一組全新的數據(數據數組中的長度不同),它將首先將所有內容設置爲0來處理它(所以它會像arctween是'清空'),刪除數據,初始化新的數據集,然後爲新數據設置動畫。所以這基本上需要4次調用上述代碼的改變版本來操縱餅圖的移動。 – PGT