I'm trying to update chord diagram according to the changes in data.
I created groups for each element and updated the data binding. However, for some reason, it updates the data accordingly, only when I go with 'select' instead of 'selectAll' which feels quite odd for me because everytime I update data binding I have used selectAlll only to update every element related.
My code is as below.
-Creating initial diagram-
var g = svg.selectAll('g.groups')
.data(figureCalculation.groups)
.join('g')
.attr('class', (d, i) => { return `group ${nameArray[i]}` })
g.append('path')
.attr('class', (d) => { return `arc ${d.value}` })
.attr('d', arc)
.style('fill', 'grey')
.style('stroke', 'pink')
.style("opacity", 0)
.transition().duration(1000)
.style("opacity", 0.8);
var chords = svg.append('g')
.selectAll('path')
.data(figureCalculation.chords)
.join('path')
.attr('class', 'chords')
.attr('d', d3.ribbon().radius(innerRadius))
.style('fill', 'green')
.style('stroke', 'red')
-update the data binding-
setTimeout(updateData, 2500)
function updateData() {
figureCalculation = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending)(matrix1)
figureCalculation.chords = [];
figureCalculation.forEach((d) => {
figureCalculation.chords.push(d)
})
g.select('path').data(figureCalculation.groups)
.join('path').attr('d', arc)
.style('fill', 'grey')
.style('stroke', 'pink')
chords.select('path').data(figureCalculation.chords)
.join('path')
.attr('d', d3.ribbon().radius(innerRadius))
.style('fill', 'green')
.style('stroke', 'red')
}
The full code is in the following link.
Your SVG
is structured strangely.
First, for your groups, you create a g
with one child of path
. Your update doesn't work because you do a selectAll
of paths on the g
with only one child.
Then for your chords that variable is already a collection of path
. You are treating it like it's the g
element holding the path
.
I'd rewrite your code like this:
let margin = { top: 50, bottom: 50, left: 20, right: 20 }
let width = 600 - margin.left - margin.right;
let height = 600 - margin.top - margin.bottom;
let innerRadius = Math.min(width, height) * 0.4;
let outterRadius = innerRadius * 1.2
let svg = d3.select('#graph').append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', `translate(${width / 2 + margin.left}, ${height / 2 + margin.top})`)
var nameArray = ['A', 'B', 'C', 'D'];
var matrix = [
[11975, 5871, 8916, 2868],
[1951, 10048, 2060, 6171],
[8010, 16145, 8090, 8045],
[1013, 990, 940, 6907]
];
var matrix1 = [
[175, 571, 916, 868],
[1951, 1248, 2060, 5471],
[8010, 14145, 4390, 4245],
[1213, 990, 540, 1207]
];
let figureCalculation = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending)(matrix)
figureCalculation.chords = [];
figureCalculation.forEach((d) => {
figureCalculation.chords.push(d)
})
var arc = d3.arc().innerRadius(innerRadius).outerRadius(outterRadius)
svg
.append('g')
.attr('class', 'groups')
.selectAll('path')
.data(figureCalculation.groups)
.join('path')
.attr('class', (d, i) => { return `group ${nameArray[i]}` })
.attr('d', arc)
.style('fill', 'grey')
.style('stroke', 'pink')
.style("opacity", 0)
.transition().duration(1000)
.style("opacity", 0.8);
svg
.append('g')
.attr('class', 'chords')
.selectAll('path')
.data(figureCalculation.chords)
.join('path')
.attr('class', 'chords')
.attr('d', d3.ribbon().radius(innerRadius))
.style('fill', 'green')
.style('stroke', 'red')
function updateData() {
figureCalculation = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending)(matrix1)
figureCalculation.chords = [];
figureCalculation.forEach((d) => {
figureCalculation.chords.push(d)
})
svg.select('.groups')
.selectAll('path').data(figureCalculation.groups)
.join('path').attr('d', arc)
.style('fill', 'grey')
.style('stroke', 'pink')
svg.select('.chords')
.selectAll('path').data(figureCalculation.chords)
.join('path')
.attr('d', d3.ribbon().radius(innerRadius))
.style('fill', 'green')
.style('stroke', 'red')
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.3.1/d3.min.js"></script>
<button onclick="updateData()">Update Data</button>
<div id="graph"></div>