Ответ 1
Ваша проблема в том, что вы не являетесь обязательными данными для элементов, поэтому переход невозможен. Я немного исказил ваш код, поэтому данные содержат всю вложенную информацию о начальном и конечном углах, так что они могут быть связаны с путями внутри каждого среза.
Взгляните на этот 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) { ... }
, и каждый элемент получит соответствующие данные.
Другим трюком является использование данных срезов (доступ через функцию .each
через dSlice
и iSlice
vars) в обратных вызовах путей. Таким образом, пути могут использовать эти данные для своих целей. В этом случае свойства company
и study_name
.
Теперь, чтобы настроить переход и сделать его более точным, исходные атрибуты могут измениться. Вы можете попробовать, установив некоторые атрибуты для путей в фазе .enter()
.