I am having a reactjs project to create a arc diagram using D3js. Here is the template I'm using. The first problem is in (d) => `translate(${x(d.id)},${height - 15}) rotate(-45). It says ${x(d.id)} is undefined. The second problem is even when I comment all the labels and the nodes hover below, the graph still not render anything and no error in the console.
/* eslint-disable no-alert */
/* eslint-disable no-use-before-define */
/* eslint-disable react/prop-types */
import useD3 from '../../hooks/useD3';
import * as d3 from 'd3';
import { useState, useEffect } from 'react';
import graph1 from './graph1.json';
export default function ArcDiagram({ nodes, links }) {
const ref = useD3((svg) => {
// set the dimensions and margins of the graph
const margin = { top: 0, right: 30, bottom: 50, left: 60 };
const width = 650 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;
// append the svg object to the body of the page
svg = d3
.select('.chart')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
// List of node id
const allNodes = nodes.map((d) => d.id);
console.log('allNodes', allNodes);
// List of groups
const allGroups = nodes.map((d) => d.group);
console.log('allGroups', allGroups);
// A color scale for groups:
const color = d3.scaleOrdinal().domain(allGroups).range(d3.schemeSet3);
// A linear scale for node size
const size = d3.scaleLinear().domain([1, 10]).range([2, 10]);
// A linear scale to position the nodes on the X axis
const x = d3.scalePoint().domain(allNodes).range([0, width]);
console.log(x('A00625243BI8W1SSZNLMD'));
// // In my input data, links are provided between nodes -id-, NOT between node names.
// // So I have to do a link between this id and the name
// const idToNode = {};
// nodes.forEach((n) => {
// idToNode[n.id] = n;
// });
// Add the links
links = svg
.selectAll('line')
.data(links)
.enter()
.append('g')
.attr('d', (d) => {
const start = x(d.source); // X position of start node on the X axis
const end = x(d.target); // X position of end node
return [
'M',
start,
height - 30, // the arc starts at the coordinate x=start, y=height-30 (where the starting node is)
'A', // This means we're gonna build an elliptical arc
(start - end) / 2,
',', // Next 2 lines are the coordinates of the inflexion point. Height of this point is proportional with start - end distance
(start - end) / 2,
0,
0,
',',
start < end ? 1 : 0,
end,
',',
height - 30
] // We always want the arc on top. So if end is before start, putting 0 here turn the arc upside down.
.join(' ');
})
.style('fill', 'none')
.attr('stroke', 'grey')
.style('stroke-width', 1);
// Add the circle for the nodes
nodes = svg
.selectAll('circle')
.data(nodes.sort((a, b) => +b.weight - +a.weight))
.enter()
.append('g')
.attr('cx', (d) => x(d.id))
.attr('cy', height - 30)
.attr('r', (d) => size(d.weight))
.style('fill', (d) => color(d.group))
.attr('stroke', 'white');
// And give them a label
const labels = svg
.selectAll('mylabels')
.data(nodes)
.enter()
.append('text')
.attr('x', 0)
.attr('y', 0)
.text((d) => d.id)
.style('text-anchor', 'end')
.attr('transform', (d) => `translate(${x(d.id)},${height - 15}) rotate(-45)`)
.style('font-size', 6);
// Add the highlighting functionality
nodes
.on('mouseover', function (d) {
// Highlight the nodes: every node is green except of him
nodes.style('opacity', 0.2);
d3.select(this).style('opacity', 1);
// Highlight the connections
links
.style('stroke', (dLink) => (dLink.source === d.id || dLink.target === d.id ? color(d.group) : '#b8b8b8'))
.style('stroke-opacity', (dLink) => (dLink.source === d.id || dLink.target === d.id ? 1 : 0.2))
.style('stroke-width', (dLink) => (dLink.source === d.id || dLink.target === d.id ? 4 : 1));
labels.style('font-size', (dLabel) => (dLabel.id === d.id ? 16 : 2)).attr('y', (dLabel) => (dLabel.name === d.id ? 10 : 0));
})
.on('mouseout', (d) => {
nodes.style('opacity', 1);
links.style('stroke', 'grey').style('stroke-opacity', 0.8).style('stroke-width', '1');
labels.style('font-size', 6);
});
}, []);
return (
<div>
<div className="chartContainer">
<svg className="chart" ref={ref} />
</div>
</div>
);
}
{
"directed": false,
"multigraph": false,
"graph": {},
"nodes": [
{
"id": "A00625243BI8W1SSZNLMD",
"weight": 8,
"group": 1
},
{
"id": "A13IKQCJKFAP5S",
"weight": 14,
"group": 1
},
{
"id": "A15TYOEWBQYF0X",
"weight": 38,
"group": 1
},
{
"id": "A102MU6ZC9H1N6",
"weight": 6,
"group": 1
},
{
"id": "A10FM4ILBIMJJ7",
"weight": 8,
"group": 2
},
{
"id": "A19Q4B515ENF9C",
"weight": 6,
"group": 1
},
{
"id": "A11INIL2YFJ137",
"weight": 7,
"group": 3
},
{
"id": "A19WXFFQMKES6O",
"weight": 8,
"group": 3
},
{
"id": "A12O5B8XNKNBOL",
"weight": 12,
"group": 4
},
{
"id": "A136IQFGB01KQB",
"weight": 8,
"group": 4
},
{
"id": "A164BJ2NU1NSJZ",
"weight": 13,
"group": 4
},
{
"id": "A18X90KMZ6KZ3H",
"weight": 7,
"group": 1
},
{
"id": "A1DZDG9AT98298",
"weight": 12,
"group": 1
},
{
"id": "A13T4T3QOSII3I",
"weight": 9,
"group": 5
},
{
"id": "A15N5RY4YGRQRQ",
"weight": 10,
"group": 5
},
{
"id": "A149F91FB9WTW6",
"weight": 7,
"group": 1
},
{
"id": "A18MMME07XZLYO",
"weight": 9,
"group": 1
},
{
"id": "A14BICJ93WO926",
"weight": 10,
"group": 1
},
{
"id": "A14CQY582WMP7O",
"weight": 6,
"group": 1
},
{
"id": "A14PY68SX7D5DV",
"weight": 8,
"group": 6
},
{
"id": "A1CUB195YB9XKO",
"weight": 8,
"group": 5
},
{
"id": "A15BHBF0L0HV1F",
"weight": 8,
"group": 1
},
{
"id": "A15WZCSME5X74S",
"weight": 14,
"group": 1
},
{
"id": "A16Z3HTUIYPDH8",
"weight": 13,
"group": 1
},
{
"id": "A1AUDW7X02EEPJ",
"weight": 7,
"group": 1
},
{
"id": "A1AWXXBQRQN13I",
"weight": 7,
"group": 1
},
{
"id": "A1CL807EOUPVP1",
"weight": 19,
"group": 5
},
{
"id": "A1DVUFG2QSJ6IK",
"weight": 24,
"group": 1
},
{
"id": "A1CF9IF5FWYNU0",
"weight": 6,
"group": 3
}
],
"links": [
{
"weight": 4,
"source": "A00625243BI8W1SSZNLMD",
"target": "A13IKQCJKFAP5S"
},
{
"weight": 4,
"source": "A00625243BI8W1SSZNLMD",
"target": "A15TYOEWBQYF0X"
},
{
"weight": 3,
"source": "A13IKQCJKFAP5S",
"target": "A18X90KMZ6KZ3H"
},
{
"weight": 3,
"source": "A13IKQCJKFAP5S",
"target": "A1DZDG9AT98298"
},
{
"weight": 4,
"source": "A15TYOEWBQYF0X",
"target": "A102MU6ZC9H1N6"
},
{
"weight": 3,
"source": "A15TYOEWBQYF0X",
"target": "A10FM4ILBIMJJ7"
},
{
"weight": 4,
"source": "A15TYOEWBQYF0X",
"target": "A136IQFGB01KQB"
},
{
"weight": 3,
"source": "A15TYOEWBQYF0X",
"target": "A149F91FB9WTW6"
},
{
"weight": 3,
"source": "A15TYOEWBQYF0X",
"target": "A14BICJ93WO926"
},
{
"weight": 3,
"source": "A15TYOEWBQYF0X",
"target": "A14CQY582WMP7O"
},
{
"weight": 3,
"source": "A15TYOEWBQYF0X",
"target": "A15BHBF0L0HV1F"
},
{
"weight": 3,
"source": "A15TYOEWBQYF0X",
"target": "A16Z3HTUIYPDH8"
},
{
"weight": 4,
"source": "A15TYOEWBQYF0X",
"target": "A18MMME07XZLYO"
},
{
"weight": 3,
"source": "A15TYOEWBQYF0X",
"target": "A1AUDW7X02EEPJ"
},
{
"weight": 3,
"source": "A15TYOEWBQYF0X",
"target": "A1AWXXBQRQN13I"
},
{
"weight": 4,
"source": "A15TYOEWBQYF0X",
"target": "A1CL807EOUPVP1"
},
{
"weight": 3,
"source": "A15TYOEWBQYF0X",
"target": "A1DVUFG2QSJ6IK"
},
{
"weight": 3,
"source": "A15TYOEWBQYF0X",
"target": "A1DZDG9AT98298"
},
{
"weight": 3,
"source": "A10FM4ILBIMJJ7",
"target": "A19Q4B515ENF9C"
},
{
"weight": 3,
"source": "A11INIL2YFJ137",
"target": "A19WXFFQMKES6O"
},
{
"weight": 3,
"source": "A19WXFFQMKES6O",
"target": "A1CF9IF5FWYNU0"
},
{
"weight": 3,
"source": "A12O5B8XNKNBOL",
"target": "A136IQFGB01KQB"
},
{
"weight": 4,
"source": "A12O5B8XNKNBOL",
"target": "A164BJ2NU1NSJZ"
},
{
"weight": 3,
"source": "A13T4T3QOSII3I",
"target": "A15N5RY4YGRQRQ"
},
{
"weight": 3,
"source": "A15N5RY4YGRQRQ",
"target": "A14PY68SX7D5DV"
},
{
"weight": 3,
"source": "A15N5RY4YGRQRQ",
"target": "A15WZCSME5X74S"
},
{
"weight": 3,
"source": "A149F91FB9WTW6",
"target": "A18MMME07XZLYO"
},
{
"weight": 3,
"source": "A14PY68SX7D5DV",
"target": "A1CUB195YB9XKO"
},
{
"weight": 3,
"source": "A15WZCSME5X74S",
"target": "A1CL807EOUPVP1"
}
]
}