You have to adapt your code slightly as it currently assumes that you're working with circle
elements, where you specify the centres using cx
and cy
, but you are now using g
elements, which use standard x
and y
coordinates.
First, remove the transform from the g
element (that's a leftover from my demo code):
const node = svg.append("g") .attr("stroke", "#fff") .attr("stroke-width", 1.5).selectAll(".circles") // note - should be .circles! .data(nodes) .enter() .append("g") .classed('circles', true)
and in the ticked()
function, change the node
updating code into a transform that works on g
elements (which don't have cx
or cy
):
node.attr('transform', d => 'translate('+ d.x +','+ d.y +')' )
Demo:
var json = {"nodes":[{"id":"0","group":0},{"id":"1","group":1},{"id":"2","group":2},{"id":"3","group":3},{"id":"4","group":4},{"id":"5","group":5},{"id":"6","group":6},{"id":"7","group":7},{"id":"8","group":8},{"id":"9","group":9},{"id":"10","group":10},{"id":"11","group":11},{"id":"12","group":12},{"id":"13","group":13},{"id":"14","group":14},{"id":"15","group":15},{"id":"16","group":16},{"id":"17","group":17},{"id":"18","group":18},{"id":"19","group":19}],"links":[{"source":"0","target":"1","value":1},{"source":"0","target":"18","value":1},{"source":"0","target":"10","value":1},{"source":"0","target":"12","value":1},{"source":"0","target":"5","value":1},{"source":"0","target":"8","value":1},{"source":"1","target":"0","value":1},{"source":"1","target":"9","value":1},{"source":"1","target":"4","value":1},{"source":"2","target":"4","value":1},{"source":"2","target":"17","value":1},{"source":"2","target":"13","value":1},{"source":"2","target":"15","value":1},{"source":"3","target":"6","value":1},{"source":"4","target":"14","value":1},{"source":"4","target":"2","value":1},{"source":"4","target":"5","value":1},{"source":"4","target":"19","value":1},{"source":"4","target":"1","value":1},{"source":"5","target":"4","value":1},{"source":"5","target":"0","value":1},{"source":"6","target":"3","value":1},{"source":"7","target":"18","value":1},{"source":"7","target":"16","value":1},{"source":"8","target":"0","value":1},{"source":"9","target":"1","value":1},{"source":"10","target":"0","value":1},{"source":"10","target":"15","value":1},{"source":"12","target":"0","value":1},{"source":"13","target":"15","value":1},{"source":"13","target":"2","value":1},{"source":"14","target":"4","value":1},{"source":"15","target":"13","value":1},{"source":"15","target":"10","value":1},{"source":"15","target":"2","value":1},{"source":"16","target":"7","value":1},{"source":"17","target":"2","value":1},{"source":"18","target":"0","value":1},{"source":"18","target":"7","value":1},{"source":"19","target":"4","value":1},{"source":"19","target":"4","value":1}]};d3.selectAll("svg > *").remove();const svg = d3.select("svg");var width = 900var height = 900svg.style("width", width +'px').style("height", height +'px');const links = json.links.map(d => Object.create(d));const nodes = json.nodes.map(d => Object.create(d));const simulation = forceSimulation(nodes, links).on("tick", ticked);var categorical = [{"name": "schemeAccent","n": 8},{"name": "schemeDark2","n": 8}, ]var color = d3.scaleOrdinal(d3[categorical[1].name]);var drag = simulation => { function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; } function dragged(d) { d.fx = d3.event.x; d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; } return d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended);}const link = svg.append("g") .attr("stroke", "#999") .attr("stroke-opacity", 0.6) .selectAll("line") .data(links) .enter().append("line") .attr("stroke-width", d => Math.sqrt(d.value));const node = svg.append("g") .attr("stroke", "#fff") .attr("stroke-width", 1.5) .selectAll(".circles") .data(nodes) .enter() .append("g") .classed('circles', true) .call(drag(simulation))// .attr('transform', d => 'translate('+ d.x +','+ d.y +')');const circle = node.append("circle") .classed('circle', true) .attr("r", 5) .attr("fill", d => color(d.group))node .append("text") .classed('circleText', true) .attr('dy', '0.35em') .attr('dx', 5) .text(d => "Node: "+ d.id);node.append("title").text(d => "Node: "+ 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('transform', d => 'translate('+ d.x +','+ d.y +')')}function forceSimulation(nodes, links) { return d3.forceSimulation(nodes) .force("link", d3.forceLink(links).id(d => d.id)) .force("charge", d3.forceManyBody()) .force("center", d3.forceCenter());}
.circleText { fill: black; stroke: none }
<script src="//d3js.org/d3.v5.js"></script><svg></svg>