javascript - d3 : smoothly tween a donut chart using arcTween?

标签 javascript d3.js tween donut-chart

我正在使用 D3.js 版本 4 构建圆环图。我想顺利地移动它并使其变小。我可以移动它,但我不能让它变小。

JSFiddle在这里: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);

});

最佳答案

我认为你把事情搞得太复杂了。您的补间函数看起来像是尝试动态收缩增长/收缩 donut 的各个部分。如果您只是想平滑地调整它们的大小,您可以直接转换路径的 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>

关于javascript - d3 : smoothly tween a donut chart using arcTween?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46495078/

相关文章:

javascript - React : Dynamic number of stateful items, 又名处理 "Rendered more hooks than during the previous render"

android - 适用于 Android 的通用补间引擎

javascript - 如何使用网络摄像头拍照并将其转换为图像文件

javascript - Vs code 使用(dist)名称自动创建文件夹

javascript - 如何使用 D3 和 JS 字典制作多个饼图?

javascript - 迭代 d3.js 中的数组元素以添加到按钮

javascript - D3 SVG 路径上的定位箭头

c# - 使用 atan2 进行延迟旋转

objective-c - iOS 核心动画值插值

php - 如何识别网页的真实访问