我一直在使用这个D3区块http://bl.ocks.org/dbuezas/9306799。
我的代码几乎就像我想要的那样。除了图表之外,仅在共享部分数据集时动画。如果数据集不包含任何共同的标签,则只需交换图表。如何让它从一开始就进行不断增长的弧转换,以便用户始终知道何时出现新数据?我正在从一个角度指令中取出这个片段,所以它可能不会独立,fyi。
var padding = 0;
var height = 350;
var width = 450;
var svg = d3.select("body")
.append("svg")
.attr('viewBox','0 0 '+ width +' '+ height)
.attr('preserveAspectRatio','xMinYMin')
.append("g")
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "labels");
svg.append("g")
.attr("class", "lines");
var radius = Math.min(width, height) / 2;
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.svg.arc()
.outerRadius(radius * 0.8)
.innerRadius(radius * 0.6);
var outerArc = d3.svg.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
svg.attr("transform", "translate(" + width / 2 + "," + element.parent().height() / 2 + ")");
var key = function(d){ return d.data.label; };
var color = d3.scale.category20b();
var dataset = [
{
label: "SUPPLY",
percentage: "22",
value: 10621
},
{
label: "FROZEN",
percentage: "22",
value: 17621
}
];
render(dataset);
function render(data) {
/* ------- PIE SLICES -------*/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data), key);
slice.enter()
.insert("path")
.style("fill", function(d) { return color(d.data.label); })
.attr("class", "slice");
slice
.transition().duration(1000)
.attrTween("d", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
return arc(interpolate(t));
};
})
slice.exit()
.remove();
/* ------- TOOLTIP -----------*/
var tooltip = d3.select(element.parent()[0])
.append('div')
.attr('class', 'donut-tip bodhi-tooltip');
tooltip.append('div')
.attr('class', 'bodhi-tooltip-text');
slice.on('mouseover', function(d) {
tooltip.select('.bodhi-tooltip-text').html(d.data.label + '</br>' + d.data[scope.tooltipKeyOne] + "%" + '</br>' + "$" + (d.data.total / 100).toFixed(2));
tooltip.style('display', 'table');
});
slice.on('mouseout', function(d) {
tooltip.style('display', 'none');
});
/* ------- TEXT LABELS -------*/
var text = svg.select(".labels").selectAll("text")
.data(pie(data), key);
text.enter()
.append("text")
.attr("dy", ".35em")
.text(function(d) {
return d.data.label;
});
function midAngle(d){
return d.startAngle + (d.endAngle - d.startAngle)/2;
}
text.transition().duration(1000)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
return "translate("+ pos +")";
};
})
.styleTween("text-anchor", function(d){
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start":"end";
};
});
text.exit()
.remove();
};
答案 0 :(得分:3)
问题的核心在于输入切片没有起点。也就是说,我真的简化了补间代码:
slice.enter()
.insert("path")
.style("fill", function(d) {
return color(d.data.label);
})
.attr("class", "slice")
.each(function(d){
this._current = { //<-- give the entering slices a starting point
startAngle: d.startAngle, //<-- have them "grow" from nothing
endAngle: d.startAngle
};
});
slice
.transition().duration(1000)
.attrTween("d", function(d) {
var endAt = { //<-- have the arc end where it's supposed to
startAngle: d.startAngle,
endAngle: d.endAngle
};
var interpolate = d3.interpolate(this._current, endAt);
this._current = endAt; //<-- store this for next cycle
return function(t) {
return arc(interpolate(t));
};
})
完整的工作代码:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<script>
var padding = 0;
var height = 350;
var width = 450;
var svg = d3.select("body")
.append("svg")
.attr('viewBox', '0 0 ' + width + ' ' + height)
.attr('preserveAspectRatio', 'xMinYMin')
.append("g")
svg.append("g")
.attr("class", "slices");
svg.append("g")
.attr("class", "labels");
svg.append("g")
.attr("class", "lines");
var radius = Math.min(width, height) / 2;
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var arc = d3.svg.arc()
.outerRadius(radius * 0.8)
.innerRadius(radius * 0.6);
var outerArc = d3.svg.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var key = function(d) {
return d.data.label;
};
var color = d3.scale.category20b();
update();
setInterval(update, 2000);
function update() {
var someData = [];
for (var i = 0; i < Math.random() * 10; i++){
someData.push({
label: "Slice " + i,
percentage: "22",
value: Math.random()
});
}
render(someData);
}
function render(data) {
/* ------- PIE SLICES -------*/
var slice = svg.select(".slices").selectAll("path.slice")
.data(pie(data), key);
slice.enter()
.insert("path")
.style("fill", function(d) {
return color(d.data.label);
})
.attr("class", "slice")
.each(function(d){
this._current = {
startAngle: d.startAngle,
endAngle: d.startAngle
};
});
slice
.transition().duration(1000)
.attrTween("d", function(d) {
var endAt = {
startAngle: d.startAngle,
endAngle: d.endAngle
};
var interpolate = d3.interpolate(this._current, endAt);
this._current = endAt;
return function(t) {
return arc(interpolate(t));
};
})
slice.exit()
.remove();
/* ------- TEXT LABELS -------*/
var text = svg.select(".labels").selectAll("text")
.data(pie(data), key);
text.enter()
.append("text")
.attr("dy", ".35em")
.text(function(d) {
return d.data.label;
});
function midAngle(d) {
return d.startAngle + (d.endAngle - d.startAngle) / 2;
}
text.transition().duration(1000)
.attrTween("transform", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
var pos = outerArc.centroid(d2);
return "translate(" + pos + ")";
};
})
.styleTween("text-anchor", function(d) {
this._current = this._current || d;
var interpolate = d3.interpolate(this._current, d);
this._current = interpolate(0);
return function(t) {
var d2 = interpolate(t);
return midAngle(d2) < Math.PI ? "start" : "end";
};
});
text.exit()
.remove();
};
</script>
</body>
</html>
&#13;