我有一个圆环图,它被用作显示进展的一种方式。我没有办法向您展示圆环图,但代码很简单,可以复制和粘贴。
我添加了代码来向您展示一个示例。我尝试了各种不合理的方法来使过渡工作第一次。但由于某种原因,它仍然无法正常工作。网上的所有例子都非常相似,所以我不确定为什么会这样。
var data = [95, 5];
var pie = d3.pie().sort(null);
var svg = d3.select("svg"),
width = svg.attr("width"),
height = svg.attr("height"),
radius = Math.min(width, height) / 2;
var arc = d3.arc()
.innerRadius(60)
.outerRadius(radius);
function createdonut() {
g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
//Inner SVG Circle
svg.append("svg:circle")
.attr("cx", width / 2)
.attr("cy", height / 2)
.attr("r", 60)
.style("fill", "#ead4d4")
.append("g");
var color = d3.scaleOrdinal(['#4daf4a', '#377eb8', '#ff7f00', '#984ea3', '#e41a1c']);
//Generate groups
var arcs = g.selectAll("arc")
.data(pie(data))
.enter()
.append("g")
.attr("class", "arc")
//Draw arc paths
arcs.append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc)
.on('mouseover', mouseover);
function mouseover(d, i) {
$('#percentage').html(i.data + ' units');
}
}
function updateDoNut(update) {
data[0] = data[0] - update;
data[1] = data[1] + update;
var path = d3.select("svg").selectAll("path").data(pie(data));
/*path.enter().append("path")
.attr("fill", function (d, i) {
return color[i];
})
.attr("d", arc);*/
path.transition().duration(100).attrTween("d", arcTween);
}
function arcTween(a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function (t) {
return arc(i(t));
};
}
createdonut();
//updateDoNut(0);
var inter = setInterval(function () { updateDoNut(5); }, 3000);Run Code Online (Sandbox Code Playgroud)
<script src="https://d3js.org/d3.v6.min.js"></script>
<div id="my_dataviz">
<svg width="300" height="200"> </svg>
<div id="percentage">0 units</div>
</div>Run Code Online (Sandbox Code Playgroud)
如果我们查看你的补间函数,我们会发现一个问题:
var i = d3.interpolate(this._current, a);
this._current = i(0);
Run Code Online (Sandbox Code Playgroud)
this.current当您第一次开始转换时未定义 - 那么 D3 如何在未定义和包含弧属性的对象之间进行插值?事实并非如此。导致您看到的非转换。this._current附加圆弧时设置:
arcs.append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc)
.each(function(d) {
this._current = d;
})
.on('mouseover', mouseover);
Run Code Online (Sandbox Code Playgroud)
现在,当您更新圆时,插值器有一个有效的起点,您应该看到一个过渡:
var i = d3.interpolate(this._current, a);
this._current = i(0);
Run Code Online (Sandbox Code Playgroud)
arcs.append("path")
.attr("fill", function (d, i) {
return color(i);
})
.attr("d", arc)
.each(function(d) {
this._current = d;
})
.on('mouseover', mouseover);
Run Code Online (Sandbox Code Playgroud)
为什么未定义和对象之间的插值不会生成错误?那么 D3-interpolate 会非常努力地尝试插值。在这种情况下,在 undefined 和对象之间,它将使用 d3-interpolateObject,它将按如下方式插值:
对于 b 中的每个属性,如果 a 中存在相应的属性,则使用 interpolate 为这两个元素创建通用插值器。如果没有这样的属性,则在模板中使用 b 的静态值。(文档)
因此,由于未定义中没有属性,插值器仅对插值中的每个点使用静态值,因此在第一次更新时缺乏转换:每个插值点都是相同的:终点值。