Reputation: 742
I am not sure why my circle nodes are not drawing in this case. My goal is to have fine-tuned control over the element being created for each node based on the node data (d). I do not always want circles.
Looking at what this code generates, I see:
circle are being added to the svg with a radius and fill color. However, they are not drawn.
But, if I do:
const node = svg
.append('g')
.attr('stroke', '#fff')
.attr('stroke-width', 1.5)
.selectAll()
.data(nodes)
.join((enter) => enter.append('circle'))
.attr('r', 16)
.attr('fill', (d) => color(d.group))
I see:
The svg code is identical. I do see that there is a circle[Attributes Style]
applied to each circle element. But, I am not sure why that is there in the second case, but not the first.
How can I use a function to create different node elements based on the node data? How does my code need to change so the circles will be drawn while still using a function passed to enter.append
so I can return an arbitrary element?
const width = 1000
const height = 400
const node_data = Array.from({ length: 5 }, () => ({
group: Math.floor(Math.random() * 3),
}))
const edge_data = Array.from({ length: 10 }, () => ({
source: Math.floor(Math.random() * 5),
target: Math.floor(Math.random() * 5),
value: Math.floor(Math.random() * 10) + 1,
}))
const links = edge_data.map((d) => ({ ...d }))
const nodes = node_data.map((d, index) => ({ id: index, ...d }))
const color = d3.scaleOrdinal(d3.schemeCategory10)
const svg = d3.select('#chart')
const simulation = d3
.forceSimulation(nodes)
.force(
'link',
d3
.forceLink(links)
.id((d) => d.id)
.distance((d) => 100)
)
.force('charge', d3.forceManyBody())
.force('center', d3.forceCenter(width / 2, height / 2))
.on('tick', ticked)
const link = svg
.append('g')
.attr('stroke', '#999')
.attr('stroke-opacity', 0.6)
.selectAll()
.data(links)
.join('line')
.attr('stroke-width', (d) => Math.sqrt(d.value))
const node = svg
.append('g')
.attr('stroke', '#fff')
.attr('stroke-width', 1.5)
.selectAll()
.data(nodes)
.join((enter) =>
enter.append((d) => {
return document.createElement('circle')
})
)
.attr('r', 16)
.attr('fill', (d) => color(d.group))
node.append('title').text((d) => `hello ${d.id}`)
function ticked() {
link
.attr('x1', (d) => d.source.x)
.attr('y1', (d) => d.source.y)
.attr('x2', (d) => d.target.x)
.attr('y2', (d) => d.target.y)
node.attr('cx', (d) => d.x).attr('cy', (d) => d.y)
}
.graph {
width: 1000px;
height: 400px;
}
<script src="https://d3js.org/d3.v7.min.js" charset="utf-8"></script>
<svg ref="chart" id="chart" class="graph"></svg>
Upvotes: 0
Views: 92
Reputation: 317
kindly update the code
.join(enter => { const elementType = d => document.createElementNS('http://www.w3.org/2000/svg', 'circle'); return enter.append(elementType); })
const width = 1000
const height = 400
const node_data = Array.from({ length: 5 }, () => ({
group: Math.floor(Math.random() * 3),
}))
const edge_data = Array.from({ length: 10 }, () => ({
source: Math.floor(Math.random() * 5),
target: Math.floor(Math.random() * 5),
value: Math.floor(Math.random() * 10) + 1,
}))
const links = edge_data.map((d) => ({ ...d }))
const nodes = node_data.map((d, index) => ({ id: index, ...d }))
const color = d3.scaleOrdinal(d3.schemeCategory10)
const svg = d3.select('#chart')
const simulation = d3
.forceSimulation(nodes)
.force(
'link',
d3
.forceLink(links)
.id((d) => d.id)
.distance((d) => 100)
)
.force('charge', d3.forceManyBody())
.force('center', d3.forceCenter(width / 2, height / 2))
.on('tick', ticked)
const link = svg
.append('g')
.attr('stroke', '#999')
.attr('stroke-opacity', 0.6)
.selectAll()
.data(links)
.join('line')
.attr('stroke-width', (d) => Math.sqrt(d.value))
const node = svg
.append('g')
.attr('stroke', '#fff')
.attr('stroke-width', 1.5)
.selectAll()
.data(nodes)
.join(enter => {
const elementType = d => document.createElementNS('http://www.w3.org/2000/svg', 'circle');
return enter.append(elementType);
})
.attr('r', 16)
.attr('fill', (d) => color(d.group))
node.append('title').text((d) => `hello ${d.id}`)
function ticked() {
link
.attr('x1', (d) => d.source.x)
.attr('y1', (d) => d.source.y)
.attr('x2', (d) => d.target.x)
.attr('y2', (d) => d.target.y)
node.attr('cx', (d) => d.x).attr('cy', (d) => d.y)
}
.graph {
width: 1000px;
height: 400px;
}
<script src="https://d3js.org/d3.v7.min.js" charset="utf-8"></script>
<svg ref="chart" id="chart" class="graph"></svg>
Upvotes: 0