how to use D3js force-directed diagram to look like tree diagram

42 views Asked by At

I have created a force-directed diagram that is like this

enter image description here

but I want it to be like this

enter image description here

and also add node text to it

this is my current code

            // Specify the dimensions of the chart.
            const width = 928;
            const height = 600;

            // Specify the color scale.
            const color = d3.scaleOrdinal(d3.schemeCategory10);
           const data1 = {
                "nodes": [
                    { "id": "A", "group": 1 },
                    { "id": "B", "group": 1 },
                    { "id": "C", "group": 1 },
                    { "id": "D", "group": 1 },
                    { "id": "E", "group": 1 },
                    { "id": "F", "group": 1 },
                    { "id": "G", "group": 1 },
                     ],
                "links": [
                    { "source": "A", "target": "B", "value": 1 },
                    { "source": "A", "target": "C", "value": 1 },
                    { "source": "B", "target": "D", "value": 1 },
                    { "source": "B", "target": "E", "value": 1 },
                    { "source": "C", "target": "F", "value": 1 },
                    { "source": "C", "target": "G", "value": 1 },
                    
                ]
            }

            // The force simulation mutates links and nodes, so create a copy
            // so that re-evaluating this cell produces the same result.
            const links = data1.links.map(d => ({ ...d }));
            const nodes = data1.nodes.map(d => ({ ...d }));

            // Create a simulation with several forces.
            const simulation = d3.forceSimulation(nodes)
                .force("link", d3.forceLink(links).id(d => d.id))
                .force("charge", d3.forceManyBody())
                .force("center", d3.forceCenter(width / 2, height / 2))
                .on("tick", ticked);

            // Create the SVG container.
            const svg = d3.select("svg")
                .attr("width", width)
                .attr("height", height)
                .attr("viewBox", [0, 0, width, height])
                .attr("style", "max-width: 100%; height: auto;");

            // Add a line for each link, and a circle for each node.
            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("circle")
                .attr("r", 5)
                .attr("fill", d => color(d.group));

            node.append("title")
                .text(d => d.id);

            // Set the position attributes of links and nodes each time the simulation ticks.
            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);
            }

            // Reheat the simulation when drag starts, and fix the subject position.
            function dragstarted(event) {
                if (!event.active) simulation.alphaTarget(0.3).restart();
                event.subject.fx = event.subject.x;
                event.subject.fy = event.subject.y;
            }

            // Update the subject (dragged node) position during drag.
            function dragged(event) {
                event.subject.fx = event.x;
                event.subject.fy = event.y;
            }

            // Restore the target alpha so the simulation cools after dragging ends.
            // Unfix the subject position now that it’s no longer being dragged.
            function dragended(event) {
                if (!event.active) simulation.alphaTarget(0);
                event.subject.fx = null;
                event.subject.fy = null;
            }

How can I do it ?

0

There are 0 answers