D3.js绘制竖向组织架构图

d3新手上路,记个笔记(*^_^*)

先上效果图:

主要参考:https://bl.ocks.org/mbostock/3184089 

https://github.com/justincy/d3-pedigree-examples

d3版本为3.x

主要代码如下:

const width = 1200;
        const height = 500;
        const boxWidth = 120,
            boxHeight = 40;
        // Setup zoom and pan
        let zoom = d3.behavior.zoom()
            .scaleExtent([.1,1])
            .on('zoom', function(){
                svg.attr("transform", "translate(" + d3.event.translate + ") scale(" + d3.event.scale + ")");
            });

        let svg = d3.select('#pedigreehoriz')
            .append('svg')
            .attr('width', width)
            .attr('height', height)
            .call(zoom)
            .append('g')
            .attr('transform', 'translate(0)');

        // Compute the layout.
        let tree = d3.layout.tree()
            .size([width - 500, height - 220])
            .separation(function () {
                return .5;
            })
            .children(function (person) {
                if (person.collapsed) {
                    return;
                } else {
                    return person._parents;
                }
            }),
            nodes = tree.nodes(data),
            links = tree.links(nodes);

        // Update nodes    
        var node = svg.selectAll("g.person")
            // The function we are passing provides d3 with an id
            // so that it can track when data is being added and removed.
            // This is not necessary if the tree will only be drawn once
            // as in the basic example.
            .data(nodes, function (person) {
                return person.id;
            });

        // Add any new nodes
        var nodeEnter = node.enter().append("g")
            .attr("class", "person");
        // .on('click', togglePerson);

        // Draw the rectangle person boxes
        nodeEnter.append("rect")
            .attr('y', 0)
            .attr('x', function (d) {
                return d.depth !==2 ? -(boxWidth/2) : -(boxHeight/2)
            })
            .attr('width', function (d) {
                return d.depth !== 2 ? boxWidth : boxHeight;
            })
            .attr('height', function (d) {
                return d.depth !== 2 ? boxHeight : boxWidth;
            })
            .on('click', function (evt) {
                console.log(evt);
            });

        // Draw the person's name and position it inside the box
        nodeEnter.append("text")
            .attr('y', function (d) {
                return d.depth !==2 ? boxHeight/2 + 5 : 0;
            })
            .attr('rotate', function (d) {//显示竖直显示中文时rotate为0,英文-90
                return 0;
            })
            .attr('style', function (d) {
                return d.depth !== 2 ? '' : "writing-mode: tb;letter-spacing:0px";
            })
            .attr("text-anchor", function (d) {
                return d.depth !==2 ? 'middle' : "start";
            })
            .text(function (d) {
                return d.name;
            });

        // Update the position of both old and new nodes
        node.attr("transform", function (d) {
            return "translate(" + d.x + "," + d.y + ")";
        });

        // Remove nodes we aren't showing anymore
        node.exit().remove();

        // Update links
        var link = svg.selectAll("path.link")

            // The function we are passing provides d3 with an id
            // so that it can track when data is being added and removed.
            // This is not necessary if the tree will only be drawn once
            // as in the basic example.
            .data(links, function (d) {
                return d.target.id;
            });

        // Add new links    
        link.enter().append("path")
            .attr("class", "link");

        // Remove any links we don't need anymore
        // if part of the tree was collapsed
        link.exit().remove();

        // Update the links positions (old and new)
        link.attr("d", elbow);

        function elbow(d) {
            let sourceX = d.source.x,
                sourceY = d.source.y + boxHeight,
                targetX = d.target.x,
                targetY = d.target.y;

            return "M" + sourceX + "," + sourceY +
                "V" + ((targetY - sourceY )/2 + sourceY) +
                "H" + targetX +
                "V" + targetY;

        }

数据:

{
    "name": "中国",
    "id": "06ada7cd-3078-54bc-bb87-72e9d6f38abf",
    "_parents": [
      {
        "name": "北京",
        "id": "a39bfa73-6617-5e8e-9470-d26b68787e52",
        "_parents": [
          {
            "name": "一环",
            "id": "fc956046-a5c3-502f-b853-d669804d428f",
          },
          {
            "name": "二环",
            "id": "fa5b0c07-9000-5475-a90e-b76af7693a57"
          },
          {
            "name": "三环",
            "id": "667d2bb6-c26e-5881-9bdc-7ac9805f96c2"
          },
          {
            "name": "四环",
            "id": "104039bb-d353-54a9-a4f2-09fda08b58bb"
          },
          {
            "name": "五环",
            "id": "06c7b0cb-cd21-53be-81bd-9b088af96904",
          }
        ]
      },
      {
        "name": "上海",
        "id": "522266d2-f01a-5ec0-9977-622e4cb054c0",
        "_parents": [
          {
            "name": "内环(内)",
            "id": "da430aa2-f438-51ed-ae47-2d9f76f8d831",
          },
          {
            "name": "中环",
            "id": "d384197e-2e1e-5fb2-987b-d90a5cdc3c15"
          },
          {
            "name": "外环",
            "id": "ea01728f-e542-53a6-acd0-6f43805c31a3"
          },
          {
            "name": "外一环",
            "id": "4f910be4-b827-50be-b783-6ba3249f6ebc"
          },
          {
            "name": "外二环",
            "id": "bfd1612c-b90d-5975-824c-49ecf62b3d5f",
          }
        ]
      }
    ]
  }

主要遇到的问题:

树的横向纵向:

这里的x、y和官方例子的树是反的,找到这个不同。。都是泪

树节点的连接线:http://www.w3school.com.cn/svg/svg_path.asp

还有就是字母大小写也有绝对和相对定位的区别,这也踩坑了。。

还有一小部分样式:

.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 1.5px;
}

.person rect {
  fill: #fff;
  stroke: steelblue;
  stroke-width: 1px;
}

.person {
  font: 14px sans-serif;
  cursor: pointer;
}

猜你喜欢

转载自blog.csdn.net/u014324940/article/details/81206364