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>
Advertisement
Answer
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>