gpt4 book ai didi

javascript - D3 - Sunburst 图中的过渡弧

转载 作者:可可西里 更新时间:2023-11-01 02:46:25 26 4
gpt4 key购买 nike

我有一张用 D3 制作的旭日图。每个“花瓣”代表一个数据子集。当用户点击其中一个“花瓣”时,我希望它进行转换,散开以仅显示该子集(见图):

enter image description here

我无法让代码正确转换。

单击时,所有“花瓣”(除了选定的花瓣)都应消失,其余路径应沿圆圈设置动画(使用 attrTween、arcTween 和插值?)。将要更改的主要值是 angleSize(var angleSize = (2 * Math.PI)/theData.length;)。

我试过使用 this , this , this , 和 this作为引用没有太大的成功。处理动画的最佳方式是什么?

感谢您的宝贵时间!

--> 参见 Plunker Here . <--

代码如下:

  var colors = {
'Rank1' : '#3FA548',
'Rank2' : '#00B09E',
'Rank3' : '#8971B3',
'Rank4' : '#DFC423',
'Rank5' : '#E74341'
};

var $container = $('.chart'),
m = 40,
width = $container.width() - m,
height = $container.height() - m,
r = Math.min(width, height) / 2;

var study = null;
var arc = d3.svg.arc();

d3.csv('text.csv', ready);

function ready(err, data) {
if (err) console.warn('Error', err);

var svg = d3.select('.chart')
.append('svg')
.attr({
'width' : (r + m) * 2,
'height' : (r + m) * 2,
'class' : 'container'
})
.append('g')
.attr('transform', 'translate(' + (width / 4) + ', ' + (height / 2) + ' )');

var slice = svg.selectAll('.slice');

function updateChart(study) {
if (study) {
var theData = data.filter(function(d) {
return d.study_name === study;
});
} else {
var theData = data;
}

slice = slice.data(theData);

slice.enter()
.append('g')
.attr('class', 'slice');

var angleSize = (2 * Math.PI) / theData.length;

var startRadArr = [],
endRadArr = [];

for ( var i = 0; i < data.length; i++ ) {
var startRadius = (width / 20),
endRadius = startRadius;

for ( var x = 0; x < 4; x++ ) {
startRadArr.push(startRadius);

if ( x == 0 ) {
endRadius += Number(data[i].group1_score) * (width / 500);
} else if ( x == 1 ) {
endRadius += Number(data[i].group2_score) * (width / 500);
} else if ( x == 2 ) {
endRadius += Number(data[i].group3_score) * (width / 500);
} else {
endRadius += Number(data[i].group4_score) * (width / 500);
}

endRadArr.push(endRadius);
startRadius = endRadius + 0.3;
}
}

var startRadGroup = [],
endRadGroup = [];

for (i = 0; i < startRadArr.length; i += 4) {
startRadGroup.push(startRadArr.slice(i, i + 4));
}

for (i = 0; i < endRadArr.length; i += 4) {
endRadGroup.push(endRadArr.slice(i, i + 4));
}

slice.selectAll('path')
.remove();

for ( var x = 0; x < 4; x++ ) {
slice.append('path')
.attr({
'class' : function(d, i) {
if ( x == 0 ) {
return d.group1_class;
} else if ( x == 1 ) {
return d.group2_class;
} else if ( x == 2 ) {
return d.group3_class;
} else {
return d.group4_class;
}
},
'company' : function(d, i) {
return d.brand_name;
},
'cat' : function(d, i) {
if ( x == 0 ) {
return 'Group1';
} else if ( x == 1 ) {
return 'Group2';
} else if ( x == 2 ) {
return 'Group3';
} else {
return 'Group4';
}
},
'study' : function(d, i) {
return d.study_name;
},
'companyid' : function(d, i) {
return d.brand_id;
},
'startradius' : function(d, i) {
return startRadGroup[i][x];
},
'endradius' : function(d, i) {
return endRadGroup[i][x];
},
'startangle' : function(d, i) {
return angleSize * i;
},
'endangle' : function(d, i) {
return angleSize * (i + 1);
}
})
.on('click', selectStudy);
}

slice.exit()
.remove();

slice.selectAll('path')
.attr({
'd' : function(d) {
return arc({
innerRadius : +d3.select(this)[0][0].attributes.startradius.nodeValue,
outerRadius : +d3.select(this)[0][0].attributes.endradius.nodeValue,
startAngle : +d3.select(this)[0][0].attributes.startangle.nodeValue,
endAngle : +d3.select(this)[0][0].attributes.endangle.nodeValue
})
}
});
}

function selectStudy(d) {
study = $(this).attr('study');
updateChart(study);
}

updateChart();
}

编辑
更新了代码(基于 this )以包含正常工作的进入、更新和退出模式。但是仍然不确定过渡。我链接的大多数示例使用类似于 d3.interpolate(this._current, a); 的东西,在不同数据之间进行补间。

在这个图表中,this._current和a是一样的,angleSize(var angleSize = (2 * Math.PI)/theData.length;),startAngle,endAngle是唯一的那改变了。

最佳答案

你的问题是你并没有真正将数据绑定(bind)到元素,因此转换是不可能的。我稍微修改了您的代码,以便数据包含有关起始 Angular 和结束 Angular 的所有嵌套信息,以便它可以绑定(bind)到每个切片内的路径。

看看这个 Plunker:https://plnkr.co/edit/a7cxRplzy66Pc1arM2a9?p=preview

修改后的版本列表如下:

var colors = {
Rank1: '#3FA548',
Rank2: '#00B09E',
Rank3: '#8971B3',
Rank4: '#DFC423',
Rank5: '#E74341'
};

// Configuration
var $container = $('.chart'),
m = 40,
width = $container.width() - m,
height = $container.height() - m,
r = Math.min(width, height) / 2;

var study = null;

var arc = d3.svg.arc();

// Load data
d3.csv('text.csv', ready);

// Data loaded callback
function ready(err, data) {
if (err) console.warn('Error', err);

var svg = d3.select('.chart')
.append('svg')
.attr({
'width': (r + m) * 2,
'height': (r + m) * 2,
'class': 'container'
})
.append('g')
.attr('transform', 'translate(' + (width / 4) + ', ' + (height / 2) + ' )');

var slices = svg.selectAll('.slice');

function updateChart(study) {
var theData = data;

if (study) {
theData = data.filter(function (d) {
return d.study_name === study;
});
}

var angleSize = (2 * Math.PI) / theData.length;

theData.forEach(function (item, i) {
var startRadius = (width / 20),
endRadius = startRadius,
groupName;

item.paths = [];

for (var g = 0; g < 4; g++) {
item.paths[g] = {};

item.paths[g].startRadius = startRadius;

groupName = 'group' + (g + 1) + '_score';

endRadius += Number(item[groupName]) * (width / 500);

item.paths[g].endRadius = endRadius;

startRadius = endRadius + 0.3;
}
});

// Set the data
slices = slices.data(theData);

// Enter
slices.enter()
.append('g')
.attr('class', 'slice');

// Exit
slices.exit()
.remove();

// Update
slices
.transition()
.duration(750)
.each(function (dSlice, iSlice) {
var slice = d3.select(this);

var paths = slice.selectAll('path');

// Set data
paths = paths.data(dSlice.paths);

// Exit
paths.exit()
.remove();

// Enter
paths.enter()
.append('path')
.attr('class', 'path');

// Update
paths
.transition()
.attr({
'class': function (d, i) {
return dSlice['group' + (i + 1) + '_class'];
},
'company': dSlice.brand_name,
'cat': function (d, i) {
return 'Group' + (i + 1);
},
'study': function (d, i) {
return dSlice.study_name;
},
'companyid': function (d, i) {
return dSlice.brand_id;
},
'startradius': function (d, i) {
return d.startRadius;
},
'endradius': function (d, i) {
return d.endRadius;
},
'startangle': function (d, i) {
return angleSize * iSlice;
},
'endangle': function (d, i) {
return angleSize * (iSlice + 1);
},
'd': function (d) {
return arc({
innerRadius: +d.startRadius,
outerRadius: +d.endRadius,
startAngle: +angleSize * iSlice,
endAngle: +angleSize * (iSlice + 1)
})
}
})
.duration(750);

paths.on('click', selectStudy);
});

function selectStudy(d, i) {
study = $(this).attr('study');

updateChart(study);
}
}

updateChart();
}

如您所见,关键是正确准备数据(假设您的示例 .tsv 文件中的格式不是最佳选择,但有时我们无法选择数据源。 ..)

然后,通过将用于路径生成的代码放在切片上的 .each 调用中,可以从 function (d, i) { ... 回调,每个元素恰好接收到相应的数据。

另一个技巧是在路径的回调中使用切片数据(通过 dSliceiSlice 变量在 .each 函数中访问) .这样,路径可以出于自己的目的使用此数据。在本例中,companystudy_name 属性。

现在为了调整过渡并使其更准确,起始属性可以更改。您可以尝试在 .enter() 阶段为路径设置一些属性。

关于javascript - D3 - Sunburst 图中的过渡弧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39024805/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com