这里写自定义目录标题
- D3.js Tidy tree绘制树形图,单棵树,左右树,平移,拖拽,树形中的天花板实现,源码实现
- D3 简介
- 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]
官网给的样子是下面这个样子的, 但是描述多种关系的时候就尴尬了, 可调整左->右, 右->左,上->下,下->上.但是需要的是中间关联两边如:[左侧关系->中间对象<-右侧关系 ]关联模式,只能自己实现了.
[左侧关系->中间对象<-右侧关系 ] 树形实现
-
效果图,使用测试数据,实际调整数据源即可
-
HTML代码
<div id="chartSvgObjectPanel" style="overflow: hidden; "></div>
- D3代码
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();}
- D3 svg内部节点拖动 平移,d3 tree 中没有提供拖拽功能参考,很多资料文档平移拖拽使用的是:
svg.attr(“transform”, event.transform);
svg.attr(“transform”, transofrm.translate(curTranslate.x, curTranslate.y));
类似这种方式, 其实是错误的或者说异常的, 明显的效果是拖一拖你连图形都不知道哪里去了,简直是忍者,神出鬼没的方式.
// 拖拽平移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 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}]}]};
- 完整实例代码
$(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());
});
-
实际效果图
-
点赞+收藏+关注+好东西持续共享