d3:使用 arcTween 平滑地补间圆环图?
d3: smoothly tween a donut chart using arcTween?
我正在使用 D3.js 版本 4 构建圆环图。我想移动它并使其变小,两者都很顺利。我可以移动它,但我不能让它变小。
JSFiddle here:https://jsfiddle.net/5sar7yp9/ - 单击文本以查看大小如何突然从大跳到小。
我怀疑这与我对 arcTween
的定义有关,但我不确定到底是什么。也许我需要内联它?
完整代码:
function updateDataPoints(series, scales) {
var padAngle = 0.015,
cornerRadius = 3,
floatFormat = d3.format('.4r'),
radius = Math.min(scales.w, scales.h) / 2;
var outerRadius = radius * 0.8, innerRadius = radius * 0.6;
var tPie = d3.pie()
.value(function(d) { return floatFormat(d.y); })
.sort(null);
var tArc = d3.arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius)
.cornerRadius(cornerRadius)
.padAngle(padAngle);
function arcTween(d) {
var i = d3.interpolate(this._current, d);
this._current = i(0);
return function(t) { return tArc(i(t)); };
}
var points = series.select(".data-points")
.selectAll("path.data-point")
.data(function(d) { return tPie(d.data_points); });
var points_enter = points.enter()
.append("path")
.each(function(d, i) { this._current = d; })
.attr("class", "data-point arc")
.attr("opacity", 0)
.attr("d", tArc)
.attr("transform", 'translate(' + scales.w / 2 + ',' + scales.h/2 + ")")
.transition().duration(1000)
.attr("fill", function(d) { return 'red'; });
var points_update = points.merge(points_enter);
points_update
.attr("fill", function(d) { return 'red'; })
.transition().duration(1000)
.attr("transform", 'translate(' + scales.w / 2 + ',' + scales.h/2 + ")")
.attr("opacity", 0.8)
.transition().duration(1000)
.attrTween('d', arcTween);
points.exit().transition()
.duration(1000)
.attrTween("d", arcTween)
.remove();
}
function updateSeries(chart_data, plot, scales) {
var series_data = [chart_data.series[0]];
var series = plot.selectAll(".series").data(series_data);
var series_enter = series.enter().append("g").attr("class", "series");
series_enter.append("g").attr("class", "data-points");
var series_update = series.merge(series_enter);
series.exit().remove();
updateDataPoints(series_update, scales);
}
var svg = d3.select("#chart").append("svg")
.attr("width", 300)
.attr("height", 300)
.append("g")
.attr("transform", "translate(100,100)");
var scales = { w: 100, h: 100},
chart_data = {
'series': [{
'data_points': [
{ x: 1999, y: 20000},
{ x: 2000, y: 12000},
{ x: 2001, y: 14000}
]
}]
},
plot = svg.append('g').attr('class', 'plot');
updateSeries(chart_data, plot, scales);
d3.select('#update').on('click', function() {
scales.w = 50;
scales.h = 50;
updateSeries(chart_data, plot, scales);
});
我认为你把它复杂化了。您的补间函数看起来像是在尝试动态缩小 grow/shrink 甜甜圈的各个部分。如果你只想平滑地调整它们的大小,你可以只转换路径的 d
属性本身:
points_update
.attr("fill", function(d) { return 'red'; })
.transition().duration(1000)
.attr("transform", 'translate(' + scales.w / 2 + ',' + scales.h/2 + ")")
.attr("opacity", 0.8)
.transition().duration(1000)
.attr('d', function(d){
return tArc(d);
});
运行代码:
function updateDataPoints(series, scales) {
var padAngle = 0.015,
cornerRadius = 3,
floatFormat = d3.format('.4r'),
radius = Math.min(scales.w, scales.h) / 2;
var outerRadius = radius * 0.8, innerRadius = radius * 0.6;
var tPie = d3.pie()
.value(function(d) { return floatFormat(d.y); })
.sort(null);
var tArc = d3.arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius)
.cornerRadius(cornerRadius)
.padAngle(padAngle);
var points = series.select(".data-points")
.selectAll("path.data-point")
.data(function(d) { return tPie(d.data_points); });
var points_enter = points.enter()
.append("path")
.each(function(d, i) { this._current = d; })
.attr("class", "data-point arc")
.attr("opacity", 0)
.attr("d", tArc)
.attr("transform", 'translate(' + scales.w / 2 + ',' + scales.h/2 + ")")
.transition().duration(1000)
.attr("fill", function(d) { return 'red'; });
var points_update = points.merge(points_enter);
points_update
.attr("fill", function(d) { return 'red'; })
.transition().duration(1000)
.attr("transform", 'translate(' + scales.w / 2 + ',' + scales.h/2 + ")")
.attr("opacity", 0.8)
.transition().duration(1000)
.attr('d', function(d){
return tArc(d);
});
points.exit().transition()
.duration(1000)
.attr("d", "")
.remove();
}
function updateSeries(chart_data, plot, scales) {
var series_data = [chart_data.series[0]];
console.log('series', series_data);
var series = plot.selectAll(".series").data(series_data);
var series_enter = series.enter().append("g").attr("class", "series");
console.log('updateSeries series_enter', series_enter.size());
series_enter.append("g").attr("class", "data-points");
var series_update = series.merge(series_enter);
series.exit().remove();
console.log('updateSeries series_update', series_update.size());
updateDataPoints(series_update, scales);
}
var svg = d3.select("#chart").append("svg")
.attr("width", 300)
.attr("height", 300)
.append("g")
.attr("transform", "translate(100,100)");
var scales = { w: 100, h: 100},
chart_data = {
'series': [{
'data_points': [
{ x: 1999, y: 20000},
{ x: 2000, y: 12000},
{ x: 2001, y: 14000}
]
}]
},
plot = svg.append('g').attr('class', 'plot');
updateSeries(chart_data, plot, scales);
d3.select('#update').on('click', function() {
scales.w = 50;
scales.h = 50;
updateSeries(chart_data, plot, scales);
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="update">click text to tween...</div>
<div id="chart"></div>
我正在使用 D3.js 版本 4 构建圆环图。我想移动它并使其变小,两者都很顺利。我可以移动它,但我不能让它变小。
JSFiddle here:https://jsfiddle.net/5sar7yp9/ - 单击文本以查看大小如何突然从大跳到小。
我怀疑这与我对 arcTween
的定义有关,但我不确定到底是什么。也许我需要内联它?
完整代码:
function updateDataPoints(series, scales) {
var padAngle = 0.015,
cornerRadius = 3,
floatFormat = d3.format('.4r'),
radius = Math.min(scales.w, scales.h) / 2;
var outerRadius = radius * 0.8, innerRadius = radius * 0.6;
var tPie = d3.pie()
.value(function(d) { return floatFormat(d.y); })
.sort(null);
var tArc = d3.arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius)
.cornerRadius(cornerRadius)
.padAngle(padAngle);
function arcTween(d) {
var i = d3.interpolate(this._current, d);
this._current = i(0);
return function(t) { return tArc(i(t)); };
}
var points = series.select(".data-points")
.selectAll("path.data-point")
.data(function(d) { return tPie(d.data_points); });
var points_enter = points.enter()
.append("path")
.each(function(d, i) { this._current = d; })
.attr("class", "data-point arc")
.attr("opacity", 0)
.attr("d", tArc)
.attr("transform", 'translate(' + scales.w / 2 + ',' + scales.h/2 + ")")
.transition().duration(1000)
.attr("fill", function(d) { return 'red'; });
var points_update = points.merge(points_enter);
points_update
.attr("fill", function(d) { return 'red'; })
.transition().duration(1000)
.attr("transform", 'translate(' + scales.w / 2 + ',' + scales.h/2 + ")")
.attr("opacity", 0.8)
.transition().duration(1000)
.attrTween('d', arcTween);
points.exit().transition()
.duration(1000)
.attrTween("d", arcTween)
.remove();
}
function updateSeries(chart_data, plot, scales) {
var series_data = [chart_data.series[0]];
var series = plot.selectAll(".series").data(series_data);
var series_enter = series.enter().append("g").attr("class", "series");
series_enter.append("g").attr("class", "data-points");
var series_update = series.merge(series_enter);
series.exit().remove();
updateDataPoints(series_update, scales);
}
var svg = d3.select("#chart").append("svg")
.attr("width", 300)
.attr("height", 300)
.append("g")
.attr("transform", "translate(100,100)");
var scales = { w: 100, h: 100},
chart_data = {
'series': [{
'data_points': [
{ x: 1999, y: 20000},
{ x: 2000, y: 12000},
{ x: 2001, y: 14000}
]
}]
},
plot = svg.append('g').attr('class', 'plot');
updateSeries(chart_data, plot, scales);
d3.select('#update').on('click', function() {
scales.w = 50;
scales.h = 50;
updateSeries(chart_data, plot, scales);
});
我认为你把它复杂化了。您的补间函数看起来像是在尝试动态缩小 grow/shrink 甜甜圈的各个部分。如果你只想平滑地调整它们的大小,你可以只转换路径的 d
属性本身:
points_update
.attr("fill", function(d) { return 'red'; })
.transition().duration(1000)
.attr("transform", 'translate(' + scales.w / 2 + ',' + scales.h/2 + ")")
.attr("opacity", 0.8)
.transition().duration(1000)
.attr('d', function(d){
return tArc(d);
});
运行代码:
function updateDataPoints(series, scales) {
var padAngle = 0.015,
cornerRadius = 3,
floatFormat = d3.format('.4r'),
radius = Math.min(scales.w, scales.h) / 2;
var outerRadius = radius * 0.8, innerRadius = radius * 0.6;
var tPie = d3.pie()
.value(function(d) { return floatFormat(d.y); })
.sort(null);
var tArc = d3.arc()
.outerRadius(outerRadius)
.innerRadius(innerRadius)
.cornerRadius(cornerRadius)
.padAngle(padAngle);
var points = series.select(".data-points")
.selectAll("path.data-point")
.data(function(d) { return tPie(d.data_points); });
var points_enter = points.enter()
.append("path")
.each(function(d, i) { this._current = d; })
.attr("class", "data-point arc")
.attr("opacity", 0)
.attr("d", tArc)
.attr("transform", 'translate(' + scales.w / 2 + ',' + scales.h/2 + ")")
.transition().duration(1000)
.attr("fill", function(d) { return 'red'; });
var points_update = points.merge(points_enter);
points_update
.attr("fill", function(d) { return 'red'; })
.transition().duration(1000)
.attr("transform", 'translate(' + scales.w / 2 + ',' + scales.h/2 + ")")
.attr("opacity", 0.8)
.transition().duration(1000)
.attr('d', function(d){
return tArc(d);
});
points.exit().transition()
.duration(1000)
.attr("d", "")
.remove();
}
function updateSeries(chart_data, plot, scales) {
var series_data = [chart_data.series[0]];
console.log('series', series_data);
var series = plot.selectAll(".series").data(series_data);
var series_enter = series.enter().append("g").attr("class", "series");
console.log('updateSeries series_enter', series_enter.size());
series_enter.append("g").attr("class", "data-points");
var series_update = series.merge(series_enter);
series.exit().remove();
console.log('updateSeries series_update', series_update.size());
updateDataPoints(series_update, scales);
}
var svg = d3.select("#chart").append("svg")
.attr("width", 300)
.attr("height", 300)
.append("g")
.attr("transform", "translate(100,100)");
var scales = { w: 100, h: 100},
chart_data = {
'series': [{
'data_points': [
{ x: 1999, y: 20000},
{ x: 2000, y: 12000},
{ x: 2001, y: 14000}
]
}]
},
plot = svg.append('g').attr('class', 'plot');
updateSeries(chart_data, plot, scales);
d3.select('#update').on('click', function() {
scales.w = 50;
scales.h = 50;
updateSeries(chart_data, plot, scales);
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="update">click text to tween...</div>
<div id="chart"></div>