【D3.js Tidy tree绘制树形图,单棵树,左右树,平移,拖拽,树形中的天花板实现,源码实现】

这里写自定义目录标题

  • [D3.js Tidy tree绘制树形图,单棵树,左右树,平移,拖拽,树形中的天花板实现,源码实现](#D3.js Tidy tree绘制树形图,单棵树,左右树,平移,拖拽,树形中的天花板实现,源码实现)
    • [D3 简介](#D3 简介)
    • [D3 官网有很多例子,这里说的是Tidy tree[树形图表svg]](#D3 官网有很多例子,这里说的是Tidy tree[树形图表svg])
    • [[左侧关系->中间对象<-右侧关系 ] 树形实现](#[左侧关系->中间对象<-右侧关系 ] 树形实现)

D3.js Tidy tree绘制树形图,单棵树,左右树,平移,拖拽,树形中的天花板实现,源码实现

D3 简介

D3 的全称是(Data-Driven Documents),顾名思义可以知道是一个被数据驱动的文档。听名字有点抽象,说简单一点,其实就是一个 JavaScript 的函数库,使用它主要是用来做数据可视化的。可以帮助你使用 HTML, CSS, SVG 以及 Canvas 来展示数据。D3 遵循现有的 Web 标准,可以不需要其他任何框架独立运行在现代浏览器中,它结合强大的可视化组件来驱动 DOM 操作。

JavaScript 文件的后缀名通常为 .js,故 D3 也常使用 D3.js 称呼。D3 提供了各种简单易用的函数,大大简化了 JavaScript 操作数据的难度。由于它本质上是 JavaScript ,所以用 JavaScript 也是可以实现所有功能的,但它能大大减小你的工作量,尤其是在数据可视化方面,D3 已经将生成可视化的复杂步骤精简到了几个简单的函数,你只需要输入几个简单的数据,就能够转换为各种绚丽的图形。有过 JavaScript 基础的朋友一定很容易理解它。

D3 官网有很多例子,这里说的是Tidy tree[树形图表svg]

官网给的样子是下面这个样子的, 但是描述多种关系的时候就尴尬了, 可调整左->右, 右->左,上->下,下->上.但是需要的是中间关联两边如:[左侧关系->中间对象<-右侧关系 ]关联模式,只能自己实现了.

[左侧关系->中间对象<-右侧关系 ] 树形实现

  1. 效果图,使用测试数据,实际调整数据源即可

  2. HTML代码

html 复制代码
  <div id="chartSvgObjectPanel" style="overflow: hidden; "></div>
  1. D3代码
js 复制代码
			var tidyTreeChart = function () {
                // Compute the tree height; this approach will allow the height of the
                // SVG to scale according to the breadth (width) of the tree layout.
                const root = d3.hierarchy(data);
                const dx = 10;
                const dy = width / (root.height + 1);
                const moveX = width - (dy / 3); // 向右侧偏移

                // Create a tree layout.
                const tree = d3.tree().nodeSize([dx, dy]);

                // Sort the tree and apply the layout.
                root.sort((a, b) => d3.ascending(a.data.name, b.data.name));
                tree(root);

                // Compute the extent of the tree. Note that x and y are swapped here
                // because in the tree layout, x is the breadth, but when displayed, the
                // tree extends right rather than down.
                let x0 = Infinity;
                let x1 = -x0;
                root.each(d => {
                    if (d.x > x1) x1 = d.x;
                    if (d.x < x0) x0 = d.x;
                });

                // Compute the adjusted height of the tree.
                const height = x1 - x0 + dx * 2;
                var w = width + moveX;

                // 拖拽及扩大缩放
                const svg = d3.create("svg")
                    .attr("width", w)
                    .attr("height", height)
                    .attr("viewBox", [-dy / 3, x0 - dx, w, height])
                    .attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;");

                // --------------------------------------------------------
                // -- 左侧绘制
                // --------------------------------------------------------

                //创建一个贝塞尔生成曲线生成器
                var left_curve_generator = d3.linkHorizontal()
                    .x(function (d) {
                        return d.y;
                    })
                    .y(function (d) {
                        return d.x;
                    });


                // 添加箭头
                svg.append("defs")
                    .selectAll("marker")
                    .data(root.links())
                    .join("marker")
                    .attr("id", (d, i) => `line-left-${i}`)
                    .attr("viewBox", "0 -5 10 10")
                    // 箭头偏移
                    .attr("refX", 8)
                    .attr("refY", 0)
                    .attr("markerWidth", 6)
                    .attr("markerHeight", 6)
                    .attr("orient", "auto")
                    .append("path")
                    .attr("fill", "rgba(182,181,181,0.98)")
                    // .attr("d", "M0,-5L10,0L0,5");
                    .attr("d", "M 0 3 L 0 3 C 1 1 1 -1 0 -3 C 3 -1 3 -1 5 0 C 3 1 3 1 0 3");

                const linkLeft = svg.append("g")
                    .attr("fill", "none")
                    .attr("stroke", "#555")
                    .attr("stroke-opacity", 0.4)
                    .attr("stroke-width", 1.5)
                    .selectAll()
                    .data(root.links())
                    .join("path")
                    .attr("d", function (d) {
                        var start = {x: d.source.x, y: moveX - d.source.y};// *****使用treeWidth减去当前y,实现反转
                        var end = {x: d.target.x, y: moveX - d.target.y};  // *****使用treeWidth减去当前y,实现反转
                        return left_curve_generator({source: start, target: end});
                    })
                    .attr("marker-end", (d, i) => `url(#line-left-${i})`)
                ;

                const nodeLeft = svg.append("g")
                    .attr("stroke-linejoin", "round")
                    .attr("stroke-width", 3)
                    .selectAll()
                    .data(root.descendants())
                    .join("g")
                    .attr("transform", d => `translate(${moveX - d.y},${d.x})`);

                nodeLeft.append("circle")
                    .attr("fill", d => d.children ? "#8e36ad" : "#999")
                    .attr("stroke", "#fdbc17")
                    .attr("stroke-width", 1)
                    .attr("r", 2.5);

                nodeLeft.append("text")
                    .attr("dy", "0.31em")
                    .attr("x", function (d, i) {
                        return d.children ? 8 : -8;
                    })
                    .attr("text-anchor", d => d.children ? "start" : "end")
                    .text(function (d, i) {
                        // console.info(d, i);
                        // 左侧第一层不添加名称, 右侧添加,只要添加一次就好
                        if (d.depth > 0) {
                            return d.data.name;
                        } else {
                            return "";
                        }
                    })
                    // .attr("stroke", "white")
                    .attr("paint-order", "stroke");

                // --------------------------------------------------------
                // -- 右侧绘制
                // --------------------------------------------------------
                // 添加箭头
                svg.append("defs")
                    .selectAll("marker")
                    .data(root.links())
                    .join("marker")
                    .attr("id", (d, i) => `line-right-${i}`)
                    .attr("viewBox", "0 -5 10 10")
                    // 箭头偏移
                    .attr("refX", 8)
                    .attr("refY", 0)
                    .attr("markerWidth", 6)
                    .attr("markerHeight", 6)
                    .attr("orient", "auto")
                    .append("path")
                    .attr("fill", "rgba(182,181,181,0.98)")
                    // .attr("d", "M0,-5L10,0L0,5");
                    .attr("d", "M 0 3 L 0 3 C 1 1 1 -1 0 -3 C 3 -1 3 -1 5 0 C 3 1 3 1 0 3");

                const link = svg.append("g")
                    .attr("fill", "none")
                    .attr("stroke", "#555")
                    .attr("stroke-opacity", 0.4)
                    .attr("stroke-width", 1.5)
                    .selectAll()
                    .data(root.links())
                    .join("path")
                    .attr("d", d3.linkHorizontal()
                        .x(d => d.y + moveX)
                        .y(d => d.x))
                    .attr("marker-end", (d, i) => `url(#line-right-${i})`)
                ;

                const node = svg.append("g")
                    .attr("stroke-linejoin", "round")
                    .attr("stroke-width", 3)
                    .selectAll()
                    .data(root.descendants())
                    .join("g")
                    .attr("transform", d => `translate(${d.y + moveX},${d.x})`);

                node.append("circle")
                    .attr("fill", d => d.children ? "#8e36ad" : "#999")
                    .attr("stroke", "#28936c")
                    .attr("stroke-width", 1)
                    .attr("r", 2.5);

                node.append("text")
                    .attr("dy", "0.31em")
                    .attr("x", d => d.children ? -8 : 8)
                    .attr("text-anchor", d => d.children ? "end" : "start")
                    .text(d => d.data.name)
                    // .attr("stroke", "white")
                    .attr("paint-order", "stroke");

                return svg.node();
            }
  1. D3 svg内部节点拖动 平移,d3 tree 中没有提供拖拽功能参考,很多资料文档平移拖拽使用的是:
    svg.attr("transform", event.transform);
    svg.attr("transform", transofrm.translate(curTranslate.x, curTranslate.y));
    类似这种方式, 其实是错误的或者说异常的, 明显的效果是拖一拖你连图形都不知道哪里去了,简直是忍者,神出鬼没的方式.
javascript 复制代码
// 拖拽平移
                svg.call(d3.zoom()
                    // 限制缩放比例
                    .scaleExtent([0.1, 15])
                    .on("zoom",
                        t => {

                            // ----------------------------------------
                            // -- 左侧
                            // ----------------------------------------

                            linkLeft.attr('transform', d3.zoomTransform(svg.node()));
                            nodeLeft.attr('transform', d3.zoomTransform(svg.node()));
                            // 文字移动
                            nodeLeft.selectAll('text')
                                .attr("x", (d) => {
                                    return moveX - d.y + (d.children ? 8 : -8);
                                })
                                .attr("y", (d) => {
                                    return d.x;
                                });
                            nodeLeft.selectAll('circle')
                                .attr("cx", (d) => {
                                    return moveX - d.y;
                                })
                                .attr("cy", (d) => {
                                    return d.x;
                                });

                            // ----------------------------------------
                            // -- 右侧
                            // ----------------------------------------

                            link.attr('transform', d3.zoomTransform(svg.node()));
                            node.attr('transform', d3.zoomTransform(svg.node()));
                            // 文字移动
                            node.selectAll('text')
                                .attr("x", (d) => {
                                    return d.y + moveX + (d.children ? -8 : 8);
                                })
                                .attr("y", (d) => {
                                    return d.x;
                                });
                            node.selectAll('circle')
                                .attr("cx", (d) => {
                                    return d.y + moveX;
                                })
                                .attr("cy", (d) => {
                                    return d.x;
                                });

                            // 缩放比例
                            // console.info("缩放比例:" + t.transform.k);
                            d3.select("#svg-scale").text((t.transform.k * 100.00).toFixed(2));
                        })
                );
  1. 测试数据源
javascript 复制代码
var data = {
                    "name": "flare",
                    "children": [
                        {
                            "name": "analytics",
                            "children": [
                                {
                                    "name": "cluster",
                                    "children": [
                                        {"name": "AgglomerativeCluster", "size": 3938},
                                        {"name": "CommunityStructure", "size": 3812},
                                        {"name": "HierarchicalCluster", "size": 6714},
                                        {"name": "MergeEdge", "size": 743}
                                    ]
                                },
                                {
                                    "name": "graph",
                                    "children": [
                                        {"name": "BetweennessCentrality", "size": 3534},
                                        {"name": "LinkDistance", "size": 5731},
                                        {"name": "MaxFlowMinCut", "size": 7840},
                                        {"name": "ShortestPaths", "size": 5914},
                                        {"name": "SpanningTree", "size": 3416}
                                    ]
                                },
                                {
                                    "name": "optimization",
                                    "children": [
                                        {"name": "AspectRatioBanker", "size": 7074}
                                    ]
                                }
                            ]
                        },
                        {
                            "name": "animate",
                            "children": [
                                {"name": "Easing", "size": 17010},
                                {"name": "FunctionSequence", "size": 5842},
                                {
                                    "name": "interpolate",
                                    "children": [
                                        {"name": "ArrayInterpolator", "size": 1983},
                                        {"name": "ColorInterpolator", "size": 2047},
                                        {"name": "DateInterpolator", "size": 1375},
                                        {"name": "Interpolator", "size": 8746},
                                        {"name": "MatrixInterpolator", "size": 2202},
                                        {"name": "NumberInterpolator", "size": 1382},
                                        {"name": "ObjectInterpolator", "size": 1629},
                                        {"name": "PointInterpolator", "size": 1675},
                                        {"name": "RectangleInterpolator", "size": 2042}
                                    ]
                                },
                                {"name": "ISchedulable", "size": 1041},
                                {"name": "Parallel", "size": 5176},
                                {"name": "Pause", "size": 449},
                                {"name": "Scheduler", "size": 5593},
                                {"name": "Sequence", "size": 5534},
                                {"name": "Transition", "size": 9201},
                                {"name": "Transitioner", "size": 19975},
                                {"name": "TransitionEvent", "size": 1116},
                                {"name": "Tween", "size": 6006}
                            ]
                        },
                        {
                            "name": "data",
                            "children": [
                                {
                                    "name": "converters",
                                    "children": [
                                        {"name": "Converters", "size": 721},
                                        {"name": "DelimitedTextConverter", "size": 4294},
                                        {"name": "GraphMLConverter", "size": 9800},
                                        {"name": "IDataConverter", "size": 1314},
                                        {"name": "JSONConverter", "size": 2220}
                                    ]
                                },
                                {"name": "DataField", "size": 1759},
                                {"name": "DataSchema", "size": 2165},
                                {"name": "DataSet", "size": 586},
                                {"name": "DataSource", "size": 3331},
                                {"name": "DataTable", "size": 772},
                                {"name": "DataUtil", "size": 3322}
                            ]
                        },
                        {
                            "name": "display",
                            "children": [
                                {"name": "DirtySprite", "size": 8833},
                                {"name": "LineSprite", "size": 1732},
                                {"name": "RectSprite", "size": 3623},
                                {"name": "TextSprite", "size": 10066}
                            ]
                        },
                        {
                            "name": "flex",
                            "children": [
                                {"name": "FlareVis", "size": 4116}
                            ]
                        },
                        {
                            "name": "physics",
                            "children": [
                                {"name": "DragForce", "size": 1082},
                                {"name": "GravityForce", "size": 1336},
                                {"name": "IForce", "size": 319},
                                {"name": "NBodyForce", "size": 10498},
                                {"name": "Particle", "size": 2822},
                                {"name": "Simulation", "size": 9983},
                                {"name": "Spring", "size": 2213},
                                {"name": "SpringForce", "size": 1681}
                            ]
                        },
                        {
                            "name": "query",
                            "children": [
                                {"name": "AggregateExpression", "size": 1616},
                                {"name": "And", "size": 1027},
                                {"name": "Arithmetic", "size": 3891},
                                {"name": "Average", "size": 891},
                                {"name": "BinaryExpression", "size": 2893},
                                {"name": "Comparison", "size": 5103},
                                {"name": "CompositeExpression", "size": 3677},
                                {"name": "Count", "size": 781},
                                {"name": "DateUtil", "size": 4141},
                                {"name": "Distinct", "size": 933},
                                {"name": "Expression", "size": 5130},
                                {"name": "ExpressionIterator", "size": 3617},
                                {"name": "Fn", "size": 3240},
                                {"name": "If", "size": 2732},
                                {"name": "IsA", "size": 2039},
                                {"name": "Literal", "size": 1214},
                                {"name": "Match", "size": 3748},
                                {"name": "Maximum", "size": 843},
                                {
                                    "name": "methods",
                                    "children": [
                                        {"name": "add", "size": 593},
                                        {"name": "and", "size": 330},
                                        {"name": "average", "size": 287},
                                        {"name": "count", "size": 277},
                                        {"name": "distinct", "size": 292},
                                        {"name": "div", "size": 595},
                                        {"name": "eq", "size": 594},
                                        {"name": "fn", "size": 460},
                                        {"name": "gt", "size": 603},
                                        {"name": "gte", "size": 625},
                                        {"name": "iff", "size": 748},
                                        {"name": "isa", "size": 461},
                                        {"name": "lt", "size": 597},
                                        {"name": "lte", "size": 619},
                                        {"name": "max", "size": 283},
                                        {"name": "min", "size": 283},
                                        {"name": "mod", "size": 591},
                                        {"name": "mul", "size": 603},
                                        {"name": "neq", "size": 599},
                                        {"name": "not", "size": 386},
                                        {"name": "or", "size": 323},
                                        {"name": "orderby", "size": 307},
                                        {"name": "range", "size": 772},
                                        {"name": "select", "size": 296},
                                        {"name": "stddev", "size": 363},
                                        {"name": "sub", "size": 600},
                                        {"name": "sum", "size": 280},
                                        {"name": "update", "size": 307},
                                        {"name": "variance", "size": 335},
                                        {"name": "where", "size": 299},
                                        {"name": "xor", "size": 354},
                                        {"name": "_", "size": 264}
                                    ]
                                },
                                {"name": "Minimum", "size": 843},
                                {"name": "Not", "size": 1554},
                                {"name": "Or", "size": 970},
                                {"name": "Query", "size": 13896},
                                {"name": "Range", "size": 1594},
                                {"name": "StringUtil", "size": 4130},
                                {"name": "Sum", "size": 791},
                                {"name": "Variable", "size": 1124},
                                {"name": "Variance", "size": 1876},
                                {"name": "Xor", "size": 1101}
                            ]
                        },
                        {
                            "name": "scale",
                            "children": [
                                {"name": "IScaleMap", "size": 2105},
                                {"name": "LinearScale", "size": 1316},
                                {"name": "LogScale", "size": 3151},
                                {"name": "OrdinalScale", "size": 3770},
                                {"name": "QuantileScale", "size": 2435},
                                {"name": "QuantitativeScale", "size": 4839},
                                {"name": "RootScale", "size": 1756},
                                {"name": "Scale", "size": 4268},
                                {"name": "ScaleType", "size": 1821},
                                {"name": "TimeScale", "size": 5833}
                            ]
                        },
                        {
                            "name": "util",
                            "children": [
                                {"name": "Arrays", "size": 8258},
                                {"name": "Colors", "size": 10001},
                                {"name": "Dates", "size": 8217},
                                {"name": "Displays", "size": 12555},
                                {"name": "Filter", "size": 2324},
                                {"name": "Geometry", "size": 10993},
                                {
                                    "name": "heap",
                                    "children": [
                                        {"name": "FibonacciHeap", "size": 9354},
                                        {"name": "HeapNode", "size": 1233}
                                    ]
                                },
                                {"name": "IEvaluable", "size": 335},
                                {"name": "IPredicate", "size": 383},
                                {"name": "IValueProxy", "size": 874},
                                {
                                    "name": "math",
                                    "children": [
                                        {"name": "DenseMatrix", "size": 3165},
                                        {"name": "IMatrix", "size": 2815},
                                        {"name": "SparseMatrix", "size": 3366}
                                    ]
                                },
                                {"name": "Maths", "size": 17705},
                                {"name": "Orientation", "size": 1486},
                                {
                                    "name": "palette",
                                    "children": [
                                        {"name": "ColorPalette", "size": 6367},
                                        {"name": "Palette", "size": 1229},
                                        {"name": "ShapePalette", "size": 2059},
                                        {"name": "SizePalette", "size": 2291}
                                    ]
                                },
                                {"name": "Property", "size": 5559},
                                {"name": "Shapes", "size": 19118},
                                {"name": "Sort", "size": 6887},
                                {"name": "Stats", "size": 6557},
                                {"name": "Strings", "size": 22026}
                            ]
                        },
                        {
                            "name": "vis",
                            "children": [
                                {
                                    "name": "axis",
                                    "children": [
                                        {"name": "Axes", "size": 1302},
                                        {"name": "Axis", "size": 24593},
                                        {"name": "AxisGridLine", "size": 652},
                                        {"name": "AxisLabel", "size": 636},
                                        {"name": "CartesianAxes", "size": 6703}
                                    ]
                                },
                                {
                                    "name": "controls",
                                    "children": [
                                        {"name": "AnchorControl", "size": 2138},
                                        {"name": "ClickControl", "size": 3824},
                                        {"name": "Control", "size": 1353},
                                        {"name": "ControlList", "size": 4665},
                                        {"name": "DragControl", "size": 2649},
                                        {"name": "ExpandControl", "size": 2832},
                                        {"name": "HoverControl", "size": 4896},
                                        {"name": "IControl", "size": 763},
                                        {"name": "PanZoomControl", "size": 5222},
                                        {"name": "SelectionControl", "size": 7862},
                                        {"name": "TooltipControl", "size": 8435}
                                    ]
                                },
                                {
                                    "name": "data",
                                    "children": [
                                        {"name": "Data", "size": 20544},
                                        {"name": "DataList", "size": 19788},
                                        {"name": "DataSprite", "size": 10349},
                                        {"name": "EdgeSprite", "size": 3301},
                                        {"name": "NodeSprite", "size": 19382},
                                        {
                                            "name": "render",
                                            "children": [
                                                {"name": "ArrowType", "size": 698},
                                                {"name": "EdgeRenderer", "size": 5569},
                                                {"name": "IRenderer", "size": 353},
                                                {"name": "ShapeRenderer", "size": 2247}
                                            ]
                                        },
                                        {"name": "ScaleBinding", "size": 11275},
                                        {"name": "Tree", "size": 7147},
                                        {"name": "TreeBuilder", "size": 9930}
                                    ]
                                },
                                {
                                    "name": "events",
                                    "children": [
                                        {"name": "DataEvent", "size": 2313},
                                        {"name": "SelectionEvent", "size": 1880},
                                        {"name": "TooltipEvent", "size": 1701},
                                        {"name": "VisualizationEvent", "size": 1117}
                                    ]
                                },
                                {
                                    "name": "legend",
                                    "children": [
                                        {"name": "Legend", "size": 20859},
                                        {"name": "LegendItem", "size": 4614},
                                        {"name": "LegendRange", "size": 10530}
                                    ]
                                },
                                {
                                    "name": "operator",
                                    "children": [
                                        {
                                            "name": "distortion",
                                            "children": [
                                                {"name": "BifocalDistortion", "size": 4461},
                                                {"name": "Distortion", "size": 6314},
                                                {"name": "FisheyeDistortion", "size": 3444}
                                            ]
                                        },
                                        {
                                            "name": "encoder",
                                            "children": [
                                                {"name": "ColorEncoder", "size": 3179},
                                                {"name": "Encoder", "size": 4060},
                                                {"name": "PropertyEncoder", "size": 4138},
                                                {"name": "ShapeEncoder", "size": 1690},
                                                {"name": "SizeEncoder", "size": 1830}
                                            ]
                                        },
                                        {
                                            "name": "filter",
                                            "children": [
                                                {"name": "FisheyeTreeFilter", "size": 5219},
                                                {"name": "GraphDistanceFilter", "size": 3165},
                                                {"name": "VisibilityFilter", "size": 3509}
                                            ]
                                        },
                                        {"name": "IOperator", "size": 1286},
                                        {
                                            "name": "label",
                                            "children": [
                                                {"name": "Labeler", "size": 9956},
                                                {"name": "RadialLabeler", "size": 3899},
                                                {"name": "StackedAreaLabeler", "size": 3202}
                                            ]
                                        },
                                        {
                                            "name": "layout",
                                            "children": [
                                                {"name": "AxisLayout", "size": 6725},
                                                {"name": "BundledEdgeRouter", "size": 3727},
                                                {"name": "CircleLayout", "size": 9317},
                                                {"name": "CirclePackingLayout", "size": 12003},
                                                {"name": "DendrogramLayout", "size": 4853},
                                                {"name": "ForceDirectedLayout", "size": 8411},
                                                {"name": "IcicleTreeLayout", "size": 4864},
                                                {"name": "IndentedTreeLayout", "size": 3174},
                                                {"name": "Layout", "size": 7881},
                                                {"name": "NodeLinkTreeLayout", "size": 12870},
                                                {"name": "PieLayout", "size": 2728},
                                                {"name": "RadialTreeLayout", "size": 12348},
                                                {"name": "RandomLayout", "size": 870},
                                                {"name": "StackedAreaLayout", "size": 9121},
                                                {"name": "TreeMapLayout", "size": 9191}
                                            ]
                                        },
                                        {"name": "Operator", "size": 2490},
                                        {"name": "OperatorList", "size": 5248},
                                        {"name": "OperatorSequence", "size": 4190},
                                        {"name": "OperatorSwitch", "size": 2581},
                                        {"name": "SortOperator", "size": 2023}
                                    ]
                                },
                                {"name": "Visualization", "size": 16540}
                            ]
                        }
                    ]
                };
  1. 完整实例代码
javascript 复制代码
  $(document).ready(function () {
            var data = {
                    "name": "flare",
                    "children": [
                        {
                            "name": "analytics",
                            "children": [
                                {
                                    "name": "cluster",
                                    "children": [
                                        {"name": "AgglomerativeCluster", "size": 3938},
                                        {"name": "CommunityStructure", "size": 3812},
                                        {"name": "HierarchicalCluster", "size": 6714},
                                        {"name": "MergeEdge", "size": 743}
                                    ]
                                },
                                {
                                    "name": "graph",
                                    "children": [
                                        {"name": "BetweennessCentrality", "size": 3534},
                                        {"name": "LinkDistance", "size": 5731},
                                        {"name": "MaxFlowMinCut", "size": 7840},
                                        {"name": "ShortestPaths", "size": 5914},
                                        {"name": "SpanningTree", "size": 3416}
                                    ]
                                },
                                {
                                    "name": "optimization",
                                    "children": [
                                        {"name": "AspectRatioBanker", "size": 7074}
                                    ]
                                }
                            ]
                        },
                        {
                            "name": "animate",
                            "children": [
                                {"name": "Easing", "size": 17010},
                                {"name": "FunctionSequence", "size": 5842},
                                {
                                    "name": "interpolate",
                                    "children": [
                                        {"name": "ArrayInterpolator", "size": 1983},
                                        {"name": "ColorInterpolator", "size": 2047},
                                        {"name": "DateInterpolator", "size": 1375},
                                        {"name": "Interpolator", "size": 8746},
                                        {"name": "MatrixInterpolator", "size": 2202},
                                        {"name": "NumberInterpolator", "size": 1382},
                                        {"name": "ObjectInterpolator", "size": 1629},
                                        {"name": "PointInterpolator", "size": 1675},
                                        {"name": "RectangleInterpolator", "size": 2042}
                                    ]
                                },
                                {"name": "ISchedulable", "size": 1041},
                                {"name": "Parallel", "size": 5176},
                                {"name": "Pause", "size": 449},
                                {"name": "Scheduler", "size": 5593},
                                {"name": "Sequence", "size": 5534},
                                {"name": "Transition", "size": 9201},
                                {"name": "Transitioner", "size": 19975},
                                {"name": "TransitionEvent", "size": 1116},
                                {"name": "Tween", "size": 6006}
                            ]
                        },
                        {
                            "name": "data",
                            "children": [
                                {
                                    "name": "converters",
                                    "children": [
                                        {"name": "Converters", "size": 721},
                                        {"name": "DelimitedTextConverter", "size": 4294},
                                        {"name": "GraphMLConverter", "size": 9800},
                                        {"name": "IDataConverter", "size": 1314},
                                        {"name": "JSONConverter", "size": 2220}
                                    ]
                                },
                                {"name": "DataField", "size": 1759},
                                {"name": "DataSchema", "size": 2165},
                                {"name": "DataSet", "size": 586},
                                {"name": "DataSource", "size": 3331},
                                {"name": "DataTable", "size": 772},
                                {"name": "DataUtil", "size": 3322}
                            ]
                        },
                        {
                            "name": "display",
                            "children": [
                                {"name": "DirtySprite", "size": 8833},
                                {"name": "LineSprite", "size": 1732},
                                {"name": "RectSprite", "size": 3623},
                                {"name": "TextSprite", "size": 10066}
                            ]
                        },
                        {
                            "name": "flex",
                            "children": [
                                {"name": "FlareVis", "size": 4116}
                            ]
                        },
                        {
                            "name": "physics",
                            "children": [
                                {"name": "DragForce", "size": 1082},
                                {"name": "GravityForce", "size": 1336},
                                {"name": "IForce", "size": 319},
                                {"name": "NBodyForce", "size": 10498},
                                {"name": "Particle", "size": 2822},
                                {"name": "Simulation", "size": 9983},
                                {"name": "Spring", "size": 2213},
                                {"name": "SpringForce", "size": 1681}
                            ]
                        },
                        {
                            "name": "query",
                            "children": [
                                {"name": "AggregateExpression", "size": 1616},
                                {"name": "And", "size": 1027},
                                {"name": "Arithmetic", "size": 3891},
                                {"name": "Average", "size": 891},
                                {"name": "BinaryExpression", "size": 2893},
                                {"name": "Comparison", "size": 5103},
                                {"name": "CompositeExpression", "size": 3677},
                                {"name": "Count", "size": 781},
                                {"name": "DateUtil", "size": 4141},
                                {"name": "Distinct", "size": 933},
                                {"name": "Expression", "size": 5130},
                                {"name": "ExpressionIterator", "size": 3617},
                                {"name": "Fn", "size": 3240},
                                {"name": "If", "size": 2732},
                                {"name": "IsA", "size": 2039},
                                {"name": "Literal", "size": 1214},
                                {"name": "Match", "size": 3748},
                                {"name": "Maximum", "size": 843},
                                {
                                    "name": "methods",
                                    "children": [
                                        {"name": "add", "size": 593},
                                        {"name": "and", "size": 330},
                                        {"name": "average", "size": 287},
                                        {"name": "count", "size": 277},
                                        {"name": "distinct", "size": 292},
                                        {"name": "div", "size": 595},
                                        {"name": "eq", "size": 594},
                                        {"name": "fn", "size": 460},
                                        {"name": "gt", "size": 603},
                                        {"name": "gte", "size": 625},
                                        {"name": "iff", "size": 748},
                                        {"name": "isa", "size": 461},
                                        {"name": "lt", "size": 597},
                                        {"name": "lte", "size": 619},
                                        {"name": "max", "size": 283},
                                        {"name": "min", "size": 283},
                                        {"name": "mod", "size": 591},
                                        {"name": "mul", "size": 603},
                                        {"name": "neq", "size": 599},
                                        {"name": "not", "size": 386},
                                        {"name": "or", "size": 323},
                                        {"name": "orderby", "size": 307},
                                        {"name": "range", "size": 772},
                                        {"name": "select", "size": 296},
                                        {"name": "stddev", "size": 363},
                                        {"name": "sub", "size": 600},
                                        {"name": "sum", "size": 280},
                                        {"name": "update", "size": 307},
                                        {"name": "variance", "size": 335},
                                        {"name": "where", "size": 299},
                                        {"name": "xor", "size": 354},
                                        {"name": "_", "size": 264}
                                    ]
                                },
                                {"name": "Minimum", "size": 843},
                                {"name": "Not", "size": 1554},
                                {"name": "Or", "size": 970},
                                {"name": "Query", "size": 13896},
                                {"name": "Range", "size": 1594},
                                {"name": "StringUtil", "size": 4130},
                                {"name": "Sum", "size": 791},
                                {"name": "Variable", "size": 1124},
                                {"name": "Variance", "size": 1876},
                                {"name": "Xor", "size": 1101}
                            ]
                        },
                        {
                            "name": "scale",
                            "children": [
                                {"name": "IScaleMap", "size": 2105},
                                {"name": "LinearScale", "size": 1316},
                                {"name": "LogScale", "size": 3151},
                                {"name": "OrdinalScale", "size": 3770},
                                {"name": "QuantileScale", "size": 2435},
                                {"name": "QuantitativeScale", "size": 4839},
                                {"name": "RootScale", "size": 1756},
                                {"name": "Scale", "size": 4268},
                                {"name": "ScaleType", "size": 1821},
                                {"name": "TimeScale", "size": 5833}
                            ]
                        },
                        {
                            "name": "util",
                            "children": [
                                {"name": "Arrays", "size": 8258},
                                {"name": "Colors", "size": 10001},
                                {"name": "Dates", "size": 8217},
                                {"name": "Displays", "size": 12555},
                                {"name": "Filter", "size": 2324},
                                {"name": "Geometry", "size": 10993},
                                {
                                    "name": "heap",
                                    "children": [
                                        {"name": "FibonacciHeap", "size": 9354},
                                        {"name": "HeapNode", "size": 1233}
                                    ]
                                },
                                {"name": "IEvaluable", "size": 335},
                                {"name": "IPredicate", "size": 383},
                                {"name": "IValueProxy", "size": 874},
                                {
                                    "name": "math",
                                    "children": [
                                        {"name": "DenseMatrix", "size": 3165},
                                        {"name": "IMatrix", "size": 2815},
                                        {"name": "SparseMatrix", "size": 3366}
                                    ]
                                },
                                {"name": "Maths", "size": 17705},
                                {"name": "Orientation", "size": 1486},
                                {
                                    "name": "palette",
                                    "children": [
                                        {"name": "ColorPalette", "size": 6367},
                                        {"name": "Palette", "size": 1229},
                                        {"name": "ShapePalette", "size": 2059},
                                        {"name": "SizePalette", "size": 2291}
                                    ]
                                },
                                {"name": "Property", "size": 5559},
                                {"name": "Shapes", "size": 19118},
                                {"name": "Sort", "size": 6887},
                                {"name": "Stats", "size": 6557},
                                {"name": "Strings", "size": 22026}
                            ]
                        },
                        {
                            "name": "vis",
                            "children": [
                                {
                                    "name": "axis",
                                    "children": [
                                        {"name": "Axes", "size": 1302},
                                        {"name": "Axis", "size": 24593},
                                        {"name": "AxisGridLine", "size": 652},
                                        {"name": "AxisLabel", "size": 636},
                                        {"name": "CartesianAxes", "size": 6703}
                                    ]
                                },
                                {
                                    "name": "controls",
                                    "children": [
                                        {"name": "AnchorControl", "size": 2138},
                                        {"name": "ClickControl", "size": 3824},
                                        {"name": "Control", "size": 1353},
                                        {"name": "ControlList", "size": 4665},
                                        {"name": "DragControl", "size": 2649},
                                        {"name": "ExpandControl", "size": 2832},
                                        {"name": "HoverControl", "size": 4896},
                                        {"name": "IControl", "size": 763},
                                        {"name": "PanZoomControl", "size": 5222},
                                        {"name": "SelectionControl", "size": 7862},
                                        {"name": "TooltipControl", "size": 8435}
                                    ]
                                },
                                {
                                    "name": "data",
                                    "children": [
                                        {"name": "Data", "size": 20544},
                                        {"name": "DataList", "size": 19788},
                                        {"name": "DataSprite", "size": 10349},
                                        {"name": "EdgeSprite", "size": 3301},
                                        {"name": "NodeSprite", "size": 19382},
                                        {
                                            "name": "render",
                                            "children": [
                                                {"name": "ArrowType", "size": 698},
                                                {"name": "EdgeRenderer", "size": 5569},
                                                {"name": "IRenderer", "size": 353},
                                                {"name": "ShapeRenderer", "size": 2247}
                                            ]
                                        },
                                        {"name": "ScaleBinding", "size": 11275},
                                        {"name": "Tree", "size": 7147},
                                        {"name": "TreeBuilder", "size": 9930}
                                    ]
                                },
                                {
                                    "name": "events",
                                    "children": [
                                        {"name": "DataEvent", "size": 2313},
                                        {"name": "SelectionEvent", "size": 1880},
                                        {"name": "TooltipEvent", "size": 1701},
                                        {"name": "VisualizationEvent", "size": 1117}
                                    ]
                                },
                                {
                                    "name": "legend",
                                    "children": [
                                        {"name": "Legend", "size": 20859},
                                        {"name": "LegendItem", "size": 4614},
                                        {"name": "LegendRange", "size": 10530}
                                    ]
                                },
                                {
                                    "name": "operator",
                                    "children": [
                                        {
                                            "name": "distortion",
                                            "children": [
                                                {"name": "BifocalDistortion", "size": 4461},
                                                {"name": "Distortion", "size": 6314},
                                                {"name": "FisheyeDistortion", "size": 3444}
                                            ]
                                        },
                                        {
                                            "name": "encoder",
                                            "children": [
                                                {"name": "ColorEncoder", "size": 3179},
                                                {"name": "Encoder", "size": 4060},
                                                {"name": "PropertyEncoder", "size": 4138},
                                                {"name": "ShapeEncoder", "size": 1690},
                                                {"name": "SizeEncoder", "size": 1830}
                                            ]
                                        },
                                        {
                                            "name": "filter",
                                            "children": [
                                                {"name": "FisheyeTreeFilter", "size": 5219},
                                                {"name": "GraphDistanceFilter", "size": 3165},
                                                {"name": "VisibilityFilter", "size": 3509}
                                            ]
                                        },
                                        {"name": "IOperator", "size": 1286},
                                        {
                                            "name": "label",
                                            "children": [
                                                {"name": "Labeler", "size": 9956},
                                                {"name": "RadialLabeler", "size": 3899},
                                                {"name": "StackedAreaLabeler", "size": 3202}
                                            ]
                                        },
                                        {
                                            "name": "layout",
                                            "children": [
                                                {"name": "AxisLayout", "size": 6725},
                                                {"name": "BundledEdgeRouter", "size": 3727},
                                                {"name": "CircleLayout", "size": 9317},
                                                {"name": "CirclePackingLayout", "size": 12003},
                                                {"name": "DendrogramLayout", "size": 4853},
                                                {"name": "ForceDirectedLayout", "size": 8411},
                                                {"name": "IcicleTreeLayout", "size": 4864},
                                                {"name": "IndentedTreeLayout", "size": 3174},
                                                {"name": "Layout", "size": 7881},
                                                {"name": "NodeLinkTreeLayout", "size": 12870},
                                                {"name": "PieLayout", "size": 2728},
                                                {"name": "RadialTreeLayout", "size": 12348},
                                                {"name": "RandomLayout", "size": 870},
                                                {"name": "StackedAreaLayout", "size": 9121},
                                                {"name": "TreeMapLayout", "size": 9191}
                                            ]
                                        },
                                        {"name": "Operator", "size": 2490},
                                        {"name": "OperatorList", "size": 5248},
                                        {"name": "OperatorSequence", "size": 4190},
                                        {"name": "OperatorSwitch", "size": 2581},
                                        {"name": "SortOperator", "size": 2023}
                                    ]
                                },
                                {"name": "Visualization", "size": 16540}
                            ]
                        }
                    ]
                };
                
            // 指定图表的尺寸。
            const width = 1000;
            const height = 600;

			/**
             * 树形向图
             */
            var tidyTreeChart = function () {
                // Compute the tree height; this approach will allow the height of the
                // SVG to scale according to the breadth (width) of the tree layout.
                const root = d3.hierarchy(data);
                const dx = 10;
                const dy = width / (root.height + 1);
                const moveX = width - (dy / 3); // 向右侧偏移

                // Create a tree layout.
                const tree = d3.tree().nodeSize([dx, dy]);

                // Sort the tree and apply the layout.
                root.sort((a, b) => d3.ascending(a.data.name, b.data.name));
                tree(root);

                // Compute the extent of the tree. Note that x and y are swapped here
                // because in the tree layout, x is the breadth, but when displayed, the
                // tree extends right rather than down.
                let x0 = Infinity;
                let x1 = -x0;
                root.each(d => {
                    if (d.x > x1) x1 = d.x;
                    if (d.x < x0) x0 = d.x;
                });

                // Compute the adjusted height of the tree.
                const height = x1 - x0 + dx * 2;
                var w = width + moveX;

                // 拖拽及扩大缩放
                const svg = d3.create("svg")
                    .attr("width", w)
                    .attr("height", height)
                    .attr("viewBox", [-dy / 3, x0 - dx, w, height])
                    .attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;");

                // 拖拽平移
                svg.call(d3.zoom()
                    // 限制缩放比例
                    .scaleExtent([0.1, 15])
                    .on("zoom",
                        t => {

                            // ----------------------------------------
                            // -- 左侧
                            // ----------------------------------------

                            linkLeft.attr('transform', d3.zoomTransform(svg.node()));
                            nodeLeft.attr('transform', d3.zoomTransform(svg.node()));
                            // 文字移动
                            nodeLeft.selectAll('text')
                                .attr("x", (d) => {
                                    return moveX - d.y + (d.children ? 8 : -8);
                                })
                                .attr("y", (d) => {
                                    return d.x;
                                });
                            nodeLeft.selectAll('circle')
                                .attr("cx", (d) => {
                                    return moveX - d.y;
                                })
                                .attr("cy", (d) => {
                                    return d.x;
                                });

                            // ----------------------------------------
                            // -- 右侧
                            // ----------------------------------------

                            link.attr('transform', d3.zoomTransform(svg.node()));
                            node.attr('transform', d3.zoomTransform(svg.node()));
                            // 文字移动
                            node.selectAll('text')
                                .attr("x", (d) => {
                                    return d.y + moveX + (d.children ? -8 : 8);
                                })
                                .attr("y", (d) => {
                                    return d.x;
                                });
                            node.selectAll('circle')
                                .attr("cx", (d) => {
                                    return d.y + moveX;
                                })
                                .attr("cy", (d) => {
                                    return d.x;
                                });

                            // 缩放比例
                            // console.info("缩放比例:" + t.transform.k);
                            d3.select("#svg-scale").text((t.transform.k * 100.00).toFixed(2));
                        })
                );

                // --------------------------------------------------------
                // -- 左侧绘制
                // --------------------------------------------------------

                //创建一个贝塞尔生成曲线生成器
                var left_curve_generator = d3.linkHorizontal()
                    .x(function (d) {
                        return d.y;
                    })
                    .y(function (d) {
                        return d.x;
                    });


                // 添加箭头
                svg.append("defs")
                    .selectAll("marker")
                    .data(root.links())
                    .join("marker")
                    .attr("id", (d, i) => `line-left-${i}`)
                    .attr("viewBox", "0 -5 10 10")
                    // 箭头偏移
                    .attr("refX", 8)
                    .attr("refY", 0)
                    .attr("markerWidth", 6)
                    .attr("markerHeight", 6)
                    .attr("orient", "auto")
                    .append("path")
                    .attr("fill", "rgba(182,181,181,0.98)")
                    // .attr("d", "M0,-5L10,0L0,5");
                    .attr("d", "M 0 3 L 0 3 C 1 1 1 -1 0 -3 C 3 -1 3 -1 5 0 C 3 1 3 1 0 3");

                const linkLeft = svg.append("g")
                    .attr("fill", "none")
                    .attr("stroke", "#555")
                    .attr("stroke-opacity", 0.4)
                    .attr("stroke-width", 1.5)
                    .selectAll()
                    .data(root.links())
                    .join("path")
                    .attr("d", function (d) {
                        var start = {x: d.source.x, y: moveX - d.source.y};// *****使用treeWidth减去当前y,实现反转
                        var end = {x: d.target.x, y: moveX - d.target.y};  // *****使用treeWidth减去当前y,实现反转
                        return left_curve_generator({source: start, target: end});
                    })
                    .attr("marker-end", (d, i) => `url(#line-left-${i})`)
                ;

                const nodeLeft = svg.append("g")
                    .attr("stroke-linejoin", "round")
                    .attr("stroke-width", 3)
                    .selectAll()
                    .data(root.descendants())
                    .join("g")
                    .attr("transform", d => `translate(${moveX - d.y},${d.x})`);

                nodeLeft.append("circle")
                    .attr("fill", d => d.children ? "#8e36ad" : "#999")
                    .attr("stroke", "#fdbc17")
                    .attr("stroke-width", 1)
                    .attr("r", 2.5);

                nodeLeft.append("text")
                    .attr("dy", "0.31em")
                    .attr("x", function (d, i) {
                        return d.children ? 8 : -8;
                    })
                    .attr("text-anchor", d => d.children ? "start" : "end")
                    .text(function (d, i) {
                        // console.info(d, i);
                        // 左侧第一层不添加名称, 右侧添加,只要添加一次就好
                        if (d.depth > 0) {
                            return d.data.name;
                        } else {
                            return "";
                        }
                    })
                    // .attr("stroke", "white")
                    .attr("paint-order", "stroke");

                // --------------------------------------------------------
                // -- 右侧绘制
                // --------------------------------------------------------
                // 添加箭头
                svg.append("defs")
                    .selectAll("marker")
                    .data(root.links())
                    .join("marker")
                    .attr("id", (d, i) => `line-right-${i}`)
                    .attr("viewBox", "0 -5 10 10")
                    // 箭头偏移
                    .attr("refX", 8)
                    .attr("refY", 0)
                    .attr("markerWidth", 6)
                    .attr("markerHeight", 6)
                    .attr("orient", "auto")
                    .append("path")
                    .attr("fill", "rgba(182,181,181,0.98)")
                    // .attr("d", "M0,-5L10,0L0,5");
                    .attr("d", "M 0 3 L 0 3 C 1 1 1 -1 0 -3 C 3 -1 3 -1 5 0 C 3 1 3 1 0 3");

                const link = svg.append("g")
                    .attr("fill", "none")
                    .attr("stroke", "#555")
                    .attr("stroke-opacity", 0.4)
                    .attr("stroke-width", 1.5)
                    .selectAll()
                    .data(root.links())
                    .join("path")
                    .attr("d", d3.linkHorizontal()
                        .x(d => d.y + moveX)
                        .y(d => d.x))
                    .attr("marker-end", (d, i) => `url(#line-right-${i})`)
                ;

                const node = svg.append("g")
                    .attr("stroke-linejoin", "round")
                    .attr("stroke-width", 3)
                    .selectAll()
                    .data(root.descendants())
                    .join("g")
                    .attr("transform", d => `translate(${d.y + moveX},${d.x})`);

                node.append("circle")
                    .attr("fill", d => d.children ? "#8e36ad" : "#999")
                    .attr("stroke", "#28936c")
                    .attr("stroke-width", 1)
                    .attr("r", 2.5);

                node.append("text")
                    .attr("dy", "0.31em")
                    .attr("x", d => d.children ? -8 : 8)
                    .attr("text-anchor", d => d.children ? "end" : "start")
                    .text(d => d.data.name)
                    // .attr("stroke", "white")
                    .attr("paint-order", "stroke");

                return svg.node();
            }

  			// 把创建的svg 添加到div容器中 默认方式
            $('#chartSvgObjectPanel').html( 
                tidyTreeChart()
            );
});
  1. 实际效果图





  2. 点赞+收藏+关注+好东西持续共享

相关推荐
安冬的码畜日常12 天前
【D3.js in Action 3 精译_044】5.1 饼图和环形图的创建(四):数据标签的添加
前端·javascript·信息可视化·数据可视化·d3.js·d3环形图·d3饼图
安冬的码畜日常1 个月前
【D3.js in Action 3 精译_040】4.4 D3 弧形图的绘制方法
javascript·信息可视化·d3.js·d3弧形图·d3环形图
安冬的码畜日常2 个月前
【D3.js in Action 3 精译_039】4.3 D3 面积图的绘制方法及其边界标签的添加
前端·javascript·数据可视化·d3.js·d3面积图
Prosper Lee2 个月前
D3.js(五):实现组织架构图
开发语言·javascript·d3.js·组织架构图
安冬的码畜日常2 个月前
【D3.js in Action 3 精译_032】第四章 D3 直线、曲线与弧线的绘制 + 4.1 坐标轴的创建(上)
前端·javascript·信息可视化·数据可视化·d3.js·d3条形图
安冬的码畜日常3 个月前
【D3.js in Action 3 精译_030】3.5 给 D3 条形图加注图表标签(下):Krisztina Szűcs 人物专访 + 3.6 本章小结
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
安冬的码畜日常3 个月前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
安冬的码畜日常3 个月前
【D3.js in Action 3 精译_027】3.4 让 D3 数据适应屏幕(下)—— D3 分段比例尺的用法
前端·javascript·信息可视化·数据可视化·d3.js·d3比例尺·分段比例尺
安冬的码畜日常3 个月前
【D3.js in Action 3 精译_028】3.4 小节 DIY 实战:使用 Observable 在线绘制 D3 条形图
前端·javascript·信息可视化·数据可视化·d3.js·observable
安冬的码畜日常3 个月前
【D3.js in Action 3 精译_025】3.4 让 D3 数据适应屏幕(中)—— 线性比例尺的用法
前端·javascript·信息可视化·数据可视化·d3.js·d3比例尺·javascript可视化