D3 js - is it possible to draw straight lines between tree nodes?

老子叫甜甜 提交于 2020-01-06 06:30:09

问题


I have created a horizontal tree diagram as shown in below image. I want straight lines between nodes. The curved lines between nodes are default in d3 js. I saw some answers on google for this but did not found any satisfactory result. So is it possible to draw straight lines between nodes in d3 js? If yes then how can I do that?

enter image description here

<!DOCTYPE html>
<html lang="en">

<head>
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
    <script src="https://d3js.org/d3.v3.min.js"></script>
   

    <style>
        .node circle {
            fill: #ff9900;
            stroke: #ff9900;
            stroke-width: 1px;
        }
        
        .node text {
            font: 16px sans-serif;
        }
        
        .link {
            fill: none;
            stroke: #ccc;
            stroke-width: 2px;
        }
    </style>
</head>

<body>

    <script language="javascript">
        var treeData = [{
            "name": "1",
            "parent": "null",
            "children": [{
                "name": "2",
                "parent": "Persons",
                "children": [{
                    "name": "3",
                    "parent": "Country of residence"
                }, {
                    "name": "4",
                    "parent": "Country of residence"
                }, {
                    "name": "5",
                    "parent": "Country of residence"
                }, {
                    "name": "6",
                    "parent": "Country of residence"
                }]
            }]
        }];

        // ************** Generate the tree diagram  *****************
        var margin = {
                top: 20,
                right: 120,
                bottom: 20,
                left: 120
            },
            width = 960 - margin.right - margin.left,
            height = 500 - margin.top - margin.bottom;

        var i = 0;

        var tree = d3.layout.tree().size([height, width]);

        var diagonal = d3.svg.diagonal()
            .projection(function(d) {
                return [d.y, d.x];
            });

        var line = d3.svg.line()
            .x(function(d) {
                return d.lx;
            })
            .y(function(d) {
                return d.ly;
            });

        var svg = d3.select("body").append("svg")
            .attr("width", width + margin.right + margin.left)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");



        root = treeData[0];

        update(root);

        function update(source) {

            // Compute the new tree layout.
            var nodes = tree.nodes(root).reverse(),
                links = tree.links(nodes);

            // Normalize for fixed-depth.
            nodes.forEach(function(d) {
                d.y = d.depth * 180;
            });

            // Declare the nodes…
            var node = svg.selectAll("g.node")
                .data(nodes, function(d) {
                    return d.id || (d.id = ++i);
                });

            // Enter the nodes.
            var nodeEnter = node.enter().append("g")
                .attr("class", "node")
                .attr("transform", function(d) {
                    return "translate(" + d.y + "," + d.x + ")";
                });

            nodeEnter.append("circle")
                .attr("r", 40)
                .style("fill", "#ff9900");



            // append icon inside circle
            nodeEnter.append("image")
                .attr("xlink:href", "http://localhost/d3/user2.jpg")
                .attr("x", "-18px")
                .attr("y", "-18px")
                .attr("width", "35px")
                .attr("height", "35px");


            nodeEnter.append("text")
                .attr("x", function(d) {
                    return d.children || d._children ? -40 : -50;
                })
                .attr("y", function(d) {
                    return d.children || d._children ? 55 : 55;
                })
                .attr("dy", ".35em")
                .attr("text-anchor", function(d) {
                    return d.children || d._children ? "start" : "start";
                })
                .text(function(d) {
                    return d.name;
                })
                .style("fill-opacity", 1);

            // Declare the links…
            var link = svg.selectAll("path.link")
                .data(links, function(d) {
                    return d.target.id;
                });

            // Enter the links.
            link.enter().insert("path", "g")
                .attr("class", "link")
                .attr("d", diagonal);


        }
    </script>
</body>
</body>

</html>

回答1:


Define your line :

        var line = d3.svg.line()
            .x(function(d) {
                return d.y; // because tree is horizontal
            })
            .y(function(d) {
                return d.x; // because tree is horizontal
            });

Change your links function to this because d3.svg.line() takes array of points as argument

Hope this helps

        // Enter the links.
        link.enter().insert("path", "g")
            .attr("class", "link")
            .attr("d", function(d) {
                return line([d.source, d.target]);
            });

<!DOCTYPE html>
<html lang="en">

<head>
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
    <script src="https://d3js.org/d3.v3.min.js"></script>
   

    <style>
        .node circle {
            fill: #ff9900;
            stroke: #ff9900;
            stroke-width: 1px;
        }
        
        .node text {
            font: 16px sans-serif;
        }
        
        .link {
            fill: none;
            stroke: #ccc;
            stroke-width: 2px;
        }
    </style>
</head>

<body>

    <script language="javascript">
        var treeData = [{
            "name": "1",
            "parent": "null",
            "children": [{
                "name": "2",
                "parent": "Persons",
                "children": [{
                    "name": "3",
                    "parent": "Country of residence"
                }, {
                    "name": "4",
                    "parent": "Country of residence"
                }, {
                    "name": "5",
                    "parent": "Country of residence"
                }, {
                    "name": "6",
                    "parent": "Country of residence"
                }]
            }]
        }];

        // ************** Generate the tree diagram  *****************
        var margin = {
                top: 20,
                right: 120,
                bottom: 20,
                left: 120
            },
            width = 960 - margin.right - margin.left,
            height = 500 - margin.top - margin.bottom;

        var i = 0;

        var tree = d3.layout.tree().size([height, width]);

        var diagonal = d3.svg.diagonal()
            .projection(function(d) {
                return [d.y, d.x];
            });

        var line = d3.svg.line()
            .x(function(d) {
                return d.y;
            })
            .y(function(d) {
                return d.x;
            });

        var svg = d3.select("body").append("svg")
            .attr("width", width + margin.right + margin.left)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");



        root = treeData[0];

        update(root);

        function update(source) {

            // Compute the new tree layout.
            var nodes = tree.nodes(root).reverse(),
                links = tree.links(nodes);

            // Normalize for fixed-depth.
            nodes.forEach(function(d) {
                d.y = d.depth * 180;
            });

            // Declare the nodes…
            var node = svg.selectAll("g.node")
                .data(nodes, function(d) {
                    return d.id || (d.id = ++i);
                });

            // Enter the nodes.
            var nodeEnter = node.enter().append("g")
                .attr("class", "node")
                .attr("transform", function(d) {
                    return "translate(" + d.y + "," + d.x + ")";
                });

            nodeEnter.append("circle")
                .attr("r", 40)
                .style("fill", "#ff9900");



            // append icon inside circle
            nodeEnter.append("image")
                .attr("xlink:href", "http://localhost/d3/user2.jpg")
                .attr("x", "-18px")
                .attr("y", "-18px")
                .attr("width", "35px")
                .attr("height", "35px");


            nodeEnter.append("text")
                .attr("x", function(d) {
                    return d.children || d._children ? -40 : -50;
                })
                .attr("y", function(d) {
                    return d.children || d._children ? 55 : 55;
                })
                .attr("dy", ".35em")
                .attr("text-anchor", function(d) {
                    return d.children || d._children ? "start" : "start";
                })
                .text(function(d) {
                    return d.name;
                })
                .style("fill-opacity", 1);

            // Declare the links…
            var link = svg.selectAll("path.link")
                .data(links, function(d) {
                    return d.target.id;
                });

            // Enter the links.
            link.enter().insert("path", "g")
                .attr("class", "link")
                .attr("d", function(d) { return line([d.source, d.target])});


        }
    </script>
</body>
</body>

</html>


来源:https://stackoverflow.com/questions/52551369/d3-js-is-it-possible-to-draw-straight-lines-between-tree-nodes

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!