I migrated this https://bl.ocks.org/nbremer/d2720fdaab1123df73f4806360a09c9e D3 Chord layout to D3v7. My current problem is, I want to utilize the color attribute from var objects to fill the individual paths. Those are currently grey.
I managed to get it done for the outer circle with
.style("fill", function (d) {
return objects[d.index].color
])
I thought I could use the same line of code to display the respected color for the paths but I receive the error that objects[d.index].color is undefined, which confuse me. I assume I did not understood the path procedure fully, which makes me believe I do everything correct.. pathetic.
I appreciate any help.
// Setup
var objects = [
{ id: 0, name: "Black Widow", color: "#301E1E" },
{ id: 1, name: "Captian America", color: "#083E77" },
{ id: 2, name: "Hawkeye", color: "#342350" },
{ id: 3, name: "The Hulk", color: "##567235" },
{ id: 4, name: "Iron Man", color: "#8B161C" },
{ id: 5, name: "Thor", color: "#DF7C00" }
]
var flows = [
{ from: 0, to: 0, quantity: 0 },
{ from: 0, to: 1, quantity: 4 },
{ from: 0, to: 2, quantity: 3 },
{ from: 0, to: 3, quantity: 2 },
{ from: 0, to: 4, quantity: 5 },
{ from: 0, to: 5, quantity: 2 },
{ from: 1, to: 0, quantity: 4 },
{ from: 1, to: 1, quantity: 0 },
{ from: 1, to: 2, quantity: 3 },
{ from: 1, to: 3, quantity: 2 },
{ from: 1, to: 4, quantity: 4 },
{ from: 1, to: 5, quantity: 3 },
{ from: 2, to: 0, quantity: 3 },
{ from: 2, to: 1, quantity: 3 },
{ from: 2, to: 2, quantity: 0 },
{ from: 2, to: 3, quantity: 2 },
{ from: 2, to: 4, quantity: 3 },
{ from: 2, to: 5, quantity: 3 },
{ from: 3, to: 0, quantity: 2 },
{ from: 3, to: 1, quantity: 2 },
{ from: 3, to: 2, quantity: 2 },
{ from: 3, to: 3, quantity: 0 },
{ from: 3, to: 4, quantity: 3 },
{ from: 3, to: 5, quantity: 3 },
{ from: 4, to: 0, quantity: 5 },
{ from: 4, to: 1, quantity: 4 },
{ from: 4, to: 2, quantity: 3 },
{ from: 4, to: 3, quantity: 3 },
{ from: 4, to: 4, quantity: 0 },
{ from: 4, to: 5, quantity: 2 },
{ from: 5, to: 0, quantity: 2 },
{ from: 5, to: 1, quantity: 3 },
{ from: 5, to: 2, quantity: 3 },
{ from: 5, to: 3, quantity: 3 },
{ from: 5, to: 4, quantity: 2 },
{ from: 5, to: 5, quantity: 0 },
]
var matrix = [];
// Map flows data to valid matrix
flows.forEach(function (flow) {
//initialize sub-array if not yet exists
if (!matrix[flow.to]) {
matrix[flow.to] = [];
}
matrix[flow.to][flow.from] = flow.quantity;
})
const width = window.innerWidth
const height = window.innerHeight
const svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" width/2 "," height/2 ")")
// Übergibt die Daten-Matrix zu d3.chord()
const root = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending)(matrix)
// Fügt die Gruppen für den inneren Kreis hinzu
svg
.datum(root)
.append("g")
.selectAll("g")
.data(d => d.groups)
.join("g")
.append("path")
.style("fill", "grey")
.style("stroke", "black")
.attr("d", d3.arc()
.innerRadius(width/2 - 210)
.outerRadius(width/2 - 200)
)
.style("fill", function (d) {
return objects[d.index].color
})
// Fügt Verlinkungen zwischen den Gruppen hinzu
svg
.datum(root)
.append("g")
.selectAll("path")
.data(d => d)
.join("path")
.attr("d", d3.ribbon()
.radius(width/2 - 220)
)
.style("fill", function (d) {
return objects[d.index].color
})
//.style("fill", "grey")
.style("stroke", "black")
body {
font-size: 12px;
font-family: 'Lato', sans-serif;
text-align: center;
fill: #2B2B2B;
cursor: default;
overflow: hidden;
}
@media (min-width: 600px) {
#chart {
font-size: 16px;
}
}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Step 1 - Collaborations between MCU Avengers</title>
<!-- D3.js -->
<script src="https://d3js.org/d3.v7.js"></script>
</head>
<body>
</body>
</html>
CodePudding user response:
TL;DR:
Lines 92 through 94:
.style("fill", function (d) {
return objects[d.index].color
})
... become:
.style('fill', ({ index }) => objects.find(({ id }) => id === index).color)
And lines 107 through 109:
.style("fill", function (d) {
return objects[d.index].color
})
... become:
.style('fill', ({ source: { index } }) => objects.find(({ id }) => id === index).color)
Explanation
You have two problems:
- Your items
d
in the second method actually contain both "source" and "target", for instance:
{
"source": {
"index": 0,
"startAngle": 0.3399537106352038,
"endAngle": 0.6119166791433668,
"value": 4
},
"target": {
"index": 1,
"startAngle": 1.1378518740326522,
"endAngle": 1.4098148425408152,
"value": 4
}
}
... and you therefore need to dig into either "source" or "target" before having access to an "index" attribute.
- your
objects
Array contains references to items that are apparently ordered such that their "id" attribute corresponds to their index in theobjects
Array, but I presume it to be either an unreliable coincidence or an inadvertent oversight.
In any case, you seem to be disregarding the index
property entirely, while I believe you meant to use it to identify each item. I suggest you use Array#find here!
Updated Code Snippet
// Setup
var objects = [
{ id: 0, name: "Black Widow", color: "#301E1E" },
{ id: 1, name: "Captian America", color: "#083E77" },
{ id: 2, name: "Hawkeye", color: "#342350" },
{ id: 3, name: "The Hulk", color: "##567235" },
{ id: 4, name: "Iron Man", color: "#8B161C" },
{ id: 5, name: "Thor", color: "#DF7C00" }
]
var flows = [
{ from: 0, to: 0, quantity: 0 },
{ from: 0, to: 1, quantity: 4 },
{ from: 0, to: 2, quantity: 3 },
{ from: 0, to: 3, quantity: 2 },
{ from: 0, to: 4, quantity: 5 },
{ from: 0, to: 5, quantity: 2 },
{ from: 1, to: 0, quantity: 4 },
{ from: 1, to: 1, quantity: 0 },
{ from: 1, to: 2, quantity: 3 },
{ from: 1, to: 3, quantity: 2 },
{ from: 1, to: 4, quantity: 4 },
{ from: 1, to: 5, quantity: 3 },
{ from: 2, to: 0, quantity: 3 },
{ from: 2, to: 1, quantity: 3 },
{ from: 2, to: 2, quantity: 0 },
{ from: 2, to: 3, quantity: 2 },
{ from: 2, to: 4, quantity: 3 },
{ from: 2, to: 5, quantity: 3 },
{ from: 3, to: 0, quantity: 2 },
{ from: 3, to: 1, quantity: 2 },
{ from: 3, to: 2, quantity: 2 },
{ from: 3, to: 3, quantity: 0 },
{ from: 3, to: 4, quantity: 3 },
{ from: 3, to: 5, quantity: 3 },
{ from: 4, to: 0, quantity: 5 },
{ from: 4, to: 1, quantity: 4 },
{ from: 4, to: 2, quantity: 3 },
{ from: 4, to: 3, quantity: 3 },
{ from: 4, to: 4, quantity: 0 },
{ from: 4, to: 5, quantity: 2 },
{ from: 5, to: 0, quantity: 2 },
{ from: 5, to: 1, quantity: 3 },
{ from: 5, to: 2, quantity: 3 },
{ from: 5, to: 3, quantity: 3 },
{ from: 5, to: 4, quantity: 2 },
{ from: 5, to: 5, quantity: 0 },
]
var matrix = [];
// Map flows data to valid matrix
flows.forEach(function (flow) {
//initialize sub-array if not yet exists
if (!matrix[flow.to]) {
matrix[flow.to] = [];
}
matrix[flow.to][flow.from] = flow.quantity;
})
const width = window.innerWidth
const height = window.innerHeight
const svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" width/2 "," height/2 ")")
// Übergibt die Daten-Matrix zu d3.chord()
const root = d3.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending)(matrix)
// Fügt die Gruppen für den inneren Kreis hinzu
svg
.datum(root)
.append("g")
.selectAll("g")
.data(d => d.groups)
.join("g")
.append("path")
.style("fill", "grey")
.style("stroke", "black")
.attr("d", d3.arc()
.innerRadius(width/2 - 210)
.outerRadius(width/2 - 200)
)
.style("fill", function ({ index }) {
return objects.find(({ id }) => id === index).color;
})
// Fügt Verlinkungen zwischen den Gruppen hinzu
svg
.datum(root)
.append("g")
.selectAll("path")
.data(d => d)
.join("path")
.attr("d", d3.ribbon()
.radius(width/2 - 220)
)
.style("fill", function ({ source: { index } }) {
return objects.find(({ id }) => id === index).color;
})
//.style("fill", "grey")
.style("stroke", "black")
body {
font-size: 12px;
font-family: 'Lato', sans-serif;
text-align: center;
fill: #2B2B2B;
cursor: default;
overflow: hidden;
}
@media (min-width: 600px) {
#chart {
font-size: 16px;
}
}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Step 1 - Collaborations between MCU Avengers</title>
<!-- D3.js -->
<script src="https://d3js.org/d3.v7.js"></script>
</head>
<body>
</body>
</html>