Merge branch 'master' of https://github.com/mbostock/d3
Conflicts: d3.min.js
This commit is contained in:
Коммит
2548d4fa32
1
Makefile
1
Makefile
|
@ -105,6 +105,7 @@ d3.layout.js: \
|
|||
src/layout/pie.js \
|
||||
src/layout/stack.js \
|
||||
src/layout/hierarchy.js \
|
||||
src/layout/tree.js \
|
||||
src/layout/treemap.js \
|
||||
src/end.js
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
(function(){d3 = {version: "1.9.1"}; // semver
|
||||
(function(){d3 = {version: "1.10.1"}; // semver
|
||||
if (!Date.now) Date.now = function() {
|
||||
return +new Date();
|
||||
};
|
||||
|
@ -2573,7 +2573,7 @@ function d3_svg_lineStepAfter(points) {
|
|||
function d3_svg_lineCardinalClosed(points, tension) {
|
||||
return points.length < 3
|
||||
? d3_svg_lineLinear(points)
|
||||
: points[0] + d3_svg_lineHermite(points,
|
||||
: points[0] + d3_svg_lineHermite((points.push(points[0]), points),
|
||||
d3_svg_lineCardinalTangents([points[points.length - 2]]
|
||||
.concat(points, [points[1]]), tension));
|
||||
}
|
||||
|
@ -2637,18 +2637,17 @@ function d3_svg_lineHermite(points, tangents) {
|
|||
function d3_svg_lineCardinalTangents(points, tension) {
|
||||
var tangents = [],
|
||||
a = (1 - tension) / 2,
|
||||
p0 = points[0],
|
||||
p1 = points[1],
|
||||
p2 = points[2],
|
||||
i = 2,
|
||||
p0,
|
||||
p1 = points[0],
|
||||
p2 = points[1],
|
||||
i = 1,
|
||||
n = points.length;
|
||||
while (++i < n) {
|
||||
tangents.push([a * (p2[0] - p0[0]), a * (p2[1] - p0[1])]);
|
||||
p0 = p1;
|
||||
p1 = p2;
|
||||
p2 = points[i];
|
||||
tangents.push([a * (p2[0] - p0[0]), a * (p2[1] - p0[1])]);
|
||||
}
|
||||
tangents.push([a * (p2[0] - p0[0]), a * (p2[1] - p0[1])]);
|
||||
return tangents;
|
||||
}
|
||||
|
||||
|
|
238
d3.layout.js
238
d3.layout.js
|
@ -739,6 +739,244 @@ function d3_layout_hierarchyValue(d) {
|
|||
function d3_layout_hierarchySort(a, b) {
|
||||
return b.value - a.value;
|
||||
}
|
||||
// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
|
||||
d3.layout.tree = function() {
|
||||
var hierarchy = d3.layout.hierarchy(),
|
||||
separation = d3_layout_treeSeparation,
|
||||
size = [1, 1]; // width, height
|
||||
|
||||
function tree(d, i) {
|
||||
var nodes = hierarchy.call(this, d, i),
|
||||
root = nodes[0];
|
||||
|
||||
function firstWalk(node, previousSibling) {
|
||||
var children = node.children,
|
||||
layout = node._tree;
|
||||
if (children) {
|
||||
var n = children.length,
|
||||
firstChild = children[0],
|
||||
previousChild,
|
||||
ancestor = firstChild,
|
||||
child,
|
||||
i = -1;
|
||||
while (++i < n) {
|
||||
child = children[i];
|
||||
firstWalk(child, previousChild);
|
||||
ancestor = apportion(child, previousChild, ancestor);
|
||||
previousChild = child;
|
||||
}
|
||||
d3_layout_treeShift(node);
|
||||
var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
|
||||
if (previousSibling) {
|
||||
layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
|
||||
layout.mod = layout.prelim - midpoint;
|
||||
} else {
|
||||
layout.prelim = midpoint;
|
||||
}
|
||||
} else {
|
||||
if (previousSibling) {
|
||||
layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function secondWalk(node, x) {
|
||||
node.x = node._tree.prelim + x;
|
||||
var children = node.children;
|
||||
if (children) {
|
||||
var i = -1,
|
||||
n = children.length;
|
||||
x += node._tree.mod;
|
||||
while (++i < n) {
|
||||
secondWalk(children[i], x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function apportion(node, previousSibling, ancestor) {
|
||||
if (previousSibling) {
|
||||
var vip = node,
|
||||
vop = node,
|
||||
vim = previousSibling,
|
||||
vom = node.parent.children[0],
|
||||
sip = vip._tree.mod,
|
||||
sop = vop._tree.mod,
|
||||
sim = vim._tree.mod,
|
||||
som = vom._tree.mod,
|
||||
shift;
|
||||
while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
|
||||
vom = d3_layout_treeLeft(vom);
|
||||
vop = d3_layout_treeRight(vop);
|
||||
vop._tree.ancestor = node;
|
||||
shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
|
||||
if (shift > 0) {
|
||||
d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
|
||||
sip += shift;
|
||||
sop += shift;
|
||||
}
|
||||
sim += vim._tree.mod;
|
||||
sip += vip._tree.mod;
|
||||
som += vom._tree.mod;
|
||||
sop += vop._tree.mod;
|
||||
}
|
||||
if (vim && !d3_layout_treeRight(vop)) {
|
||||
vop._tree.thread = vim;
|
||||
vop._tree.mod += sim - sop;
|
||||
}
|
||||
if (vip && !d3_layout_treeLeft(vom)) {
|
||||
vom._tree.thread = vip;
|
||||
vom._tree.mod += sip - som;
|
||||
ancestor = node;
|
||||
}
|
||||
}
|
||||
return ancestor;
|
||||
}
|
||||
|
||||
// Initialize temporary layout variables.
|
||||
d3_layout_treeVisitAfter(root, function(node, previousSibling) {
|
||||
node._tree = {
|
||||
ancestor: node,
|
||||
prelim: 0,
|
||||
mod: 0,
|
||||
change: 0,
|
||||
shift: 0,
|
||||
number: previousSibling ? previousSibling._tree.number + 1 : 0
|
||||
};
|
||||
});
|
||||
|
||||
// Compute the layout using Buchheim et al.'s algorithm.
|
||||
firstWalk(root);
|
||||
secondWalk(root, -root._tree.prelim);
|
||||
|
||||
// Compute the left-most, right-most, and depth-most nodes for extents.
|
||||
var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost),
|
||||
right = d3_layout_treeSearch(root, d3_layout_treeRightmost),
|
||||
deep = d3_layout_treeSearch(root, d3_layout_treeDeepest),
|
||||
x0 = left.x - separation(left, right) / 2,
|
||||
x1 = right.x + separation(right, left) / 2,
|
||||
y1 = deep.depth;
|
||||
|
||||
// Clear temporary layout variables; transform x and y.
|
||||
d3_layout_treeVisitAfter(root, function(node) {
|
||||
node.x = (node.x - x0) / (x1 - x0) * size[0];
|
||||
node.y = node.depth / y1 * size[1];
|
||||
delete node._tree;
|
||||
});
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
tree.sort = d3.rebind(tree, hierarchy.sort);
|
||||
tree.children = d3.rebind(tree, hierarchy.children);
|
||||
tree.value = d3.rebind(tree, hierarchy.value);
|
||||
|
||||
tree.separation = function(x) {
|
||||
if (!arguments.length) return separation;
|
||||
separation = x;
|
||||
return tree;
|
||||
};
|
||||
|
||||
tree.size = function(x) {
|
||||
if (!arguments.length) return size;
|
||||
size = x;
|
||||
return tree;
|
||||
};
|
||||
|
||||
return tree;
|
||||
};
|
||||
|
||||
function d3_layout_treeSeparation(a, b) {
|
||||
return a.parent == b.parent ? 1 : 2;
|
||||
}
|
||||
|
||||
// function d3_layout_treeSeparationRadial(a, b) {
|
||||
// return (a.parent == b.parent ? 1 : 2) / a.depth;
|
||||
// }
|
||||
|
||||
function d3_layout_treeLeft(node) {
|
||||
return node.children ? node.children[0] : node._tree.thread;
|
||||
}
|
||||
|
||||
function d3_layout_treeRight(node) {
|
||||
return node.children ? node.children[node.children.length - 1] : node._tree.thread;
|
||||
}
|
||||
|
||||
function d3_layout_treeSearch(node, compare) {
|
||||
var children = node.children;
|
||||
if (children) {
|
||||
var child,
|
||||
n = children.length,
|
||||
i = -1;
|
||||
while (++i < n) {
|
||||
if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
|
||||
node = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function d3_layout_treeRightmost(a, b) {
|
||||
return a.x - b.x;
|
||||
}
|
||||
|
||||
function d3_layout_treeLeftmost(a, b) {
|
||||
return b.x - a.x;
|
||||
}
|
||||
|
||||
function d3_layout_treeDeepest(a, b) {
|
||||
return a.depth - b.depth;
|
||||
}
|
||||
|
||||
function d3_layout_treeVisitAfter(node, callback) {
|
||||
function visit(node, previousSibling) {
|
||||
var children = node.children;
|
||||
if (children) {
|
||||
var child,
|
||||
previousChild = null,
|
||||
i = -1,
|
||||
n = children.length;
|
||||
while (++i < n) {
|
||||
child = children[i];
|
||||
visit(child, previousChild);
|
||||
previousChild = child;
|
||||
}
|
||||
}
|
||||
callback(node, previousSibling);
|
||||
}
|
||||
visit(node, null);
|
||||
}
|
||||
|
||||
function d3_layout_treeShift(node) {
|
||||
var shift = 0,
|
||||
change = 0,
|
||||
children = node.children,
|
||||
i = children.length,
|
||||
child;
|
||||
while (--i >= 0) {
|
||||
child = children[i]._tree;
|
||||
child.prelim += shift;
|
||||
child.mod += shift;
|
||||
shift += child.shift + (change += child.change);
|
||||
}
|
||||
}
|
||||
|
||||
function d3_layout_treeMove(ancestor, node, shift) {
|
||||
ancestor = ancestor._tree;
|
||||
node = node._tree;
|
||||
var change = shift / (node.number - ancestor.number);
|
||||
ancestor.change += change;
|
||||
node.change -= change;
|
||||
node.shift += shift;
|
||||
node.prelim += shift;
|
||||
node.mod += shift;
|
||||
}
|
||||
|
||||
function d3_layout_treeAncestor(vim, node, ancestor) {
|
||||
return vim._tree.ancestor.parent == node.parent
|
||||
? vim._tree.ancestor
|
||||
: ancestor;
|
||||
}
|
||||
// Squarified Treemaps by Mark Bruls, Kees Huizing, and Jarke J. van Wijk
|
||||
d3.layout.treemap = function() {
|
||||
var hierarchy = d3.layout.hierarchy(),
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -19,11 +19,12 @@ circle.node {
|
|||
}
|
||||
path.hull {
|
||||
fill: lightsteelblue;
|
||||
opacity: 0.3;
|
||||
fill-opacity: 0.3;
|
||||
}
|
||||
line.link {
|
||||
stroke: #333;
|
||||
opacity: 0.5;
|
||||
stroke-opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
@ -144,9 +145,7 @@ function convexHulls(nodes, index, offset) {
|
|||
// create convex hulls
|
||||
var hulls = [];
|
||||
for (i in h) {
|
||||
var p = d3.geom.hull(h[i]);
|
||||
p.push(p[0]); // close the loop
|
||||
hulls.push({group: i, path: p});
|
||||
hulls.push({group: i, path: d3.geom.hull(h[i])});
|
||||
}
|
||||
|
||||
return hulls;
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
<li><a href="stream/stream.html">stream</a></li>
|
||||
<li><a href="stream/stack.html">stack</a></li>
|
||||
<li><a href="symbol-map/symbol-map.html">symbol-map</a></li>
|
||||
<li><a href="tree/tree.html">tree</a></li>
|
||||
<li><a href="tree/tree-radial.html">tree-radial</a></li>
|
||||
<li><a href="treemap/treemap.html">treemap</a></li>
|
||||
<li><a href="voronoi/voronoi.html">voronoi</a></li>
|
||||
<li><a href="zoom/zoom.html">zoom</a></li>
|
||||
|
|
|
@ -0,0 +1,286 @@
|
|||
{
|
||||
"flare": {
|
||||
"analytics": {
|
||||
"cluster": {
|
||||
"AgglomerativeCluster": 3938,
|
||||
"CommunityStructure": 3812,
|
||||
"HierarchicalCluster": 6714,
|
||||
"MergeEdge": 743
|
||||
},
|
||||
"graph": {
|
||||
"BetweennessCentrality": 3534,
|
||||
"LinkDistance": 5731,
|
||||
"MaxFlowMinCut": 7840,
|
||||
"ShortestPaths": 5914,
|
||||
"SpanningTree": 3416
|
||||
},
|
||||
"optimization": {
|
||||
"AspectRatioBanker": 7074
|
||||
}
|
||||
},
|
||||
"animate": {
|
||||
"Easing": 17010,
|
||||
"FunctionSequence": 5842,
|
||||
"interpolate": {
|
||||
"ArrayInterpolator": 1983,
|
||||
"ColorInterpolator": 2047,
|
||||
"DateInterpolator": 1375,
|
||||
"Interpolator": 8746,
|
||||
"MatrixInterpolator": 2202,
|
||||
"NumberInterpolator": 1382,
|
||||
"ObjectInterpolator": 1629,
|
||||
"PointInterpolator": 1675,
|
||||
"RectangleInterpolator": 2042
|
||||
},
|
||||
"ISchedulable": 1041,
|
||||
"Parallel": 5176,
|
||||
"Pause": 449,
|
||||
"Scheduler": 5593,
|
||||
"Sequence": 5534,
|
||||
"Transition": 9201,
|
||||
"Transitioner": 19975,
|
||||
"TransitionEvent": 1116,
|
||||
"Tween": 6006
|
||||
},
|
||||
"data": {
|
||||
"converters": {
|
||||
"Converters": 721,
|
||||
"DelimitedTextConverter": 4294,
|
||||
"GraphMLConverter": 9800,
|
||||
"IDataConverter": 1314,
|
||||
"JSONConverter": 2220
|
||||
},
|
||||
"DataField": 1759,
|
||||
"DataSchema": 2165,
|
||||
"DataSet": 586,
|
||||
"DataSource": 3331,
|
||||
"DataTable": 772,
|
||||
"DataUtil": 3322
|
||||
},
|
||||
"display": {
|
||||
"DirtySprite": 8833,
|
||||
"LineSprite": 1732,
|
||||
"RectSprite": 3623,
|
||||
"TextSprite": 10066
|
||||
},
|
||||
"flex": {
|
||||
"FlareVis": 4116
|
||||
},
|
||||
"physics": {
|
||||
"DragForce": 1082,
|
||||
"GravityForce": 1336,
|
||||
"IForce": 319,
|
||||
"NBodyForce": 10498,
|
||||
"Particle": 2822,
|
||||
"Simulation": 9983,
|
||||
"Spring": 2213,
|
||||
"SpringForce": 1681
|
||||
},
|
||||
"query": {
|
||||
"AggregateExpression": 1616,
|
||||
"And": 1027,
|
||||
"Arithmetic": 3891,
|
||||
"Average": 891,
|
||||
"BinaryExpression": 2893,
|
||||
"Comparison": 5103,
|
||||
"CompositeExpression": 3677,
|
||||
"Count": 781,
|
||||
"DateUtil": 4141,
|
||||
"Distinct": 933,
|
||||
"Expression": 5130,
|
||||
"ExpressionIterator": 3617,
|
||||
"Fn": 3240,
|
||||
"If": 2732,
|
||||
"IsA": 2039,
|
||||
"Literal": 1214,
|
||||
"Match": 3748,
|
||||
"Maximum": 843,
|
||||
"methods": {
|
||||
"add": 593,
|
||||
"and": 330,
|
||||
"average": 287,
|
||||
"count": 277,
|
||||
"distinct": 292,
|
||||
"div": 595,
|
||||
"eq": 594,
|
||||
"fn": 460,
|
||||
"gt": 603,
|
||||
"gte": 625,
|
||||
"iff": 748,
|
||||
"isa": 461,
|
||||
"lt": 597,
|
||||
"lte": 619,
|
||||
"max": 283,
|
||||
"min": 283,
|
||||
"mod": 591,
|
||||
"mul": 603,
|
||||
"neq": 599,
|
||||
"not": 386,
|
||||
"or": 323,
|
||||
"orderby": 307,
|
||||
"range": 772,
|
||||
"select": 296,
|
||||
"stddev": 363,
|
||||
"sub": 600,
|
||||
"sum": 280,
|
||||
"update": 307,
|
||||
"variance": 335,
|
||||
"where": 299,
|
||||
"xor": 354,
|
||||
"_": 264
|
||||
},
|
||||
"Minimum": 843,
|
||||
"Not": 1554,
|
||||
"Or": 970,
|
||||
"Query": 13896,
|
||||
"Range": 1594,
|
||||
"StringUtil": 4130,
|
||||
"Sum": 791,
|
||||
"Variable": 1124,
|
||||
"Variance": 1876,
|
||||
"Xor": 1101
|
||||
},
|
||||
"scale": {
|
||||
"IScaleMap": 2105,
|
||||
"LinearScale": 1316,
|
||||
"LogScale": 3151,
|
||||
"OrdinalScale": 3770,
|
||||
"QuantileScale": 2435,
|
||||
"QuantitativeScale": 4839,
|
||||
"RootScale": 1756,
|
||||
"Scale": 4268,
|
||||
"ScaleType": 1821,
|
||||
"TimeScale": 5833
|
||||
},
|
||||
"util": {
|
||||
"Arrays": 8258,
|
||||
"Colors": 10001,
|
||||
"Dates": 8217,
|
||||
"Displays": 12555,
|
||||
"Filter": 2324,
|
||||
"Geometry": 10993,
|
||||
"heap": {
|
||||
"FibonacciHeap": 9354,
|
||||
"HeapNode": 1233
|
||||
},
|
||||
"IEvaluable": 335,
|
||||
"IPredicate": 383,
|
||||
"IValueProxy": 874,
|
||||
"math": {
|
||||
"DenseMatrix": 3165,
|
||||
"IMatrix": 2815,
|
||||
"SparseMatrix": 3366
|
||||
},
|
||||
"Maths": 17705,
|
||||
"Orientation": 1486,
|
||||
"palette": {
|
||||
"ColorPalette": 6367,
|
||||
"Palette": 1229,
|
||||
"ShapePalette": 2059,
|
||||
"SizePalette": 2291
|
||||
},
|
||||
"Property": 5559,
|
||||
"Shapes": 19118,
|
||||
"Sort": 6887,
|
||||
"Stats": 6557,
|
||||
"Strings": 22026
|
||||
},
|
||||
"vis": {
|
||||
"axis": {
|
||||
"Axes": 1302,
|
||||
"Axis": 24593,
|
||||
"AxisGridLine": 652,
|
||||
"AxisLabel": 636,
|
||||
"CartesianAxes": 6703
|
||||
},
|
||||
"controls": {
|
||||
"AnchorControl": 2138,
|
||||
"ClickControl": 3824,
|
||||
"Control": 1353,
|
||||
"ControlList": 4665,
|
||||
"DragControl": 2649,
|
||||
"ExpandControl": 2832,
|
||||
"HoverControl": 4896,
|
||||
"IControl": 763,
|
||||
"PanZoomControl": 5222,
|
||||
"SelectionControl": 7862,
|
||||
"TooltipControl": 8435
|
||||
},
|
||||
"data": {
|
||||
"Data": 20544,
|
||||
"DataList": 19788,
|
||||
"DataSprite": 10349,
|
||||
"EdgeSprite": 3301,
|
||||
"NodeSprite": 19382,
|
||||
"render": {
|
||||
"ArrowType": 698,
|
||||
"EdgeRenderer": 5569,
|
||||
"IRenderer": 353,
|
||||
"ShapeRenderer": 2247
|
||||
},
|
||||
"ScaleBinding": 11275,
|
||||
"Tree": 7147,
|
||||
"TreeBuilder": 9930
|
||||
},
|
||||
"events": {
|
||||
"DataEvent": 2313,
|
||||
"SelectionEvent": 1880,
|
||||
"TooltipEvent": 1701,
|
||||
"VisualizationEvent": 1117
|
||||
},
|
||||
"legend": {
|
||||
"Legend": 20859,
|
||||
"LegendItem": 4614,
|
||||
"LegendRange": 10530
|
||||
},
|
||||
"operator": {
|
||||
"distortion": {
|
||||
"BifocalDistortion": 4461,
|
||||
"Distortion": 6314,
|
||||
"FisheyeDistortion": 3444
|
||||
},
|
||||
"encoder": {
|
||||
"ColorEncoder": 3179,
|
||||
"Encoder": 4060,
|
||||
"PropertyEncoder": 4138,
|
||||
"ShapeEncoder": 1690,
|
||||
"SizeEncoder": 1830
|
||||
},
|
||||
"filter": {
|
||||
"FisheyeTreeFilter": 5219,
|
||||
"GraphDistanceFilter": 3165,
|
||||
"VisibilityFilter": 3509
|
||||
},
|
||||
"IOperator": 1286,
|
||||
"label": {
|
||||
"Labeler": 9956,
|
||||
"RadialLabeler": 3899,
|
||||
"StackedAreaLabeler": 3202
|
||||
},
|
||||
"layout": {
|
||||
"AxisLayout": 6725,
|
||||
"BundledEdgeRouter": 3727,
|
||||
"CircleLayout": 9317,
|
||||
"CirclePackingLayout": 12003,
|
||||
"DendrogramLayout": 4853,
|
||||
"ForceDirectedLayout": 8411,
|
||||
"IcicleTreeLayout": 4864,
|
||||
"IndentedTreeLayout": 3174,
|
||||
"Layout": 7881,
|
||||
"NodeLinkTreeLayout": 12870,
|
||||
"PieLayout": 2728,
|
||||
"RadialTreeLayout": 12348,
|
||||
"RandomLayout": 870,
|
||||
"StackedAreaLayout": 9121,
|
||||
"TreeMapLayout": 9191
|
||||
},
|
||||
"Operator": 2490,
|
||||
"OperatorList": 5248,
|
||||
"OperatorSequence": 4190,
|
||||
"OperatorSwitch": 2581,
|
||||
"SortOperator": 2023
|
||||
},
|
||||
"Visualization": 16540
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
||||
<title>Node-Link Tree (Radial)</title>
|
||||
<script type="text/javascript" src="../../d3.js"></script>
|
||||
<script type="text/javascript" src="../../d3.layout.js"></script>
|
||||
<link type="text/css" rel="stylesheet" href="tree.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="chart"></div>
|
||||
<script type="text/javascript" src="tree-radial.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,60 @@
|
|||
var r = 960 / 2;
|
||||
|
||||
var tree = d3.layout.tree()
|
||||
.size([360, r - 120])
|
||||
.sort(null)
|
||||
.children(function(d) { return isNaN(d.value) ? d3.entries(d.value) : null; })
|
||||
.separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
|
||||
|
||||
var vis = d3.select("#chart").append("svg:svg")
|
||||
.attr("width", r * 2)
|
||||
.attr("height", r * 2 - 150)
|
||||
.append("svg:g")
|
||||
.attr("transform", "translate(" + r + "," + r + ")");
|
||||
|
||||
d3.json("flare.json", function(json) {
|
||||
var nodes = tree(d3.entries(json)[0]);
|
||||
|
||||
var link = vis.selectAll("g.link")
|
||||
.data(nodes)
|
||||
.enter().append("svg:g")
|
||||
.attr("class", "link");
|
||||
|
||||
link.selectAll("line")
|
||||
.data(children)
|
||||
.enter().append("svg:line")
|
||||
.attr("x1", function(d) { return x(d.parent); })
|
||||
.attr("y1", function(d) { return y(d.parent); })
|
||||
.attr("x2", function(d) { return x(d.child); })
|
||||
.attr("y2", function(d) { return y(d.child); });
|
||||
|
||||
var node = vis.selectAll("g.node")
|
||||
.data(nodes)
|
||||
.enter().append("svg:g")
|
||||
.attr("class", "node")
|
||||
.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
|
||||
|
||||
node.append("svg:circle")
|
||||
.attr("r", 5);
|
||||
|
||||
node.append("svg:text")
|
||||
.attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
|
||||
.attr("dy", ".31em")
|
||||
.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
|
||||
.attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
|
||||
.text(function(d) { return d.data.key; });
|
||||
|
||||
// Returns parent+child objects for any children of `d`.
|
||||
function children(d) {
|
||||
return (d.children || []).map(function(v) {
|
||||
return {
|
||||
parent: d,
|
||||
child: v
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// Radial scales for x and y.
|
||||
function x(d) { return d.y * Math.cos((d.x - 90) / 180 * Math.PI); }
|
||||
function y(d) { return d.y * Math.sin((d.x - 90) / 180 * Math.PI); }
|
||||
});
|
|
@ -0,0 +1,14 @@
|
|||
.node circle {
|
||||
fill: #fff;
|
||||
stroke: steelblue;
|
||||
stroke-width: 1.5px;
|
||||
}
|
||||
|
||||
.node {
|
||||
font: 10px sans-serif;
|
||||
}
|
||||
|
||||
.link {
|
||||
stroke: #ccc;
|
||||
stroke-width: 1.5px;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
||||
<title>Node-Link Tree</title>
|
||||
<script type="text/javascript" src="../../d3.js"></script>
|
||||
<script type="text/javascript" src="../../d3.layout.js"></script>
|
||||
<link type="text/css" rel="stylesheet" href="tree.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="chart"></div>
|
||||
<script type="text/javascript" src="tree.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,55 @@
|
|||
var w = 960,
|
||||
h = 2000;
|
||||
|
||||
var tree = d3.layout.tree()
|
||||
.size([h, w - 160])
|
||||
.sort(null)
|
||||
.children(function(d) { return isNaN(d.value) ? d3.entries(d.value) : null; });
|
||||
|
||||
var vis = d3.select("#chart").append("svg:svg")
|
||||
.attr("width", w)
|
||||
.attr("height", h)
|
||||
.append("svg:g")
|
||||
.attr("transform", "translate(40, 0)");
|
||||
|
||||
d3.json("flare.json", function(json) {
|
||||
var nodes = tree(d3.entries(json)[0]);
|
||||
|
||||
var link = vis.selectAll("g.link")
|
||||
.data(nodes)
|
||||
.enter().append("svg:g")
|
||||
.attr("class", "link");
|
||||
|
||||
link.selectAll("line")
|
||||
.data(children)
|
||||
.enter().append("svg:line")
|
||||
.attr("x1", function(d) { return d.parent.y; })
|
||||
.attr("y1", function(d) { return d.parent.x; })
|
||||
.attr("x2", function(d) { return d.child.y; })
|
||||
.attr("y2", function(d) { return d.child.x; });
|
||||
|
||||
var node = vis.selectAll("g.node")
|
||||
.data(nodes)
|
||||
.enter().append("svg:g")
|
||||
.attr("class", "node")
|
||||
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
|
||||
|
||||
node.append("svg:circle")
|
||||
.attr("r", 5);
|
||||
|
||||
node.append("svg:text")
|
||||
.attr("dx", function(d) { return d.children ? -8 : 8; })
|
||||
.attr("dy", 3)
|
||||
.attr("text-anchor", function(d) { return d.children ? "end" : "start"; })
|
||||
.text(function(d) { return d.data.key; });
|
||||
|
||||
// Returns parent+child objects for any children of `d`.
|
||||
function children(d) {
|
||||
return (d.children || []).map(function(v) {
|
||||
return {
|
||||
parent: d,
|
||||
child: v
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
|
@ -1 +1 @@
|
|||
d3 = {version: "1.9.1"}; // semver
|
||||
d3 = {version: "1.10.1"}; // semver
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
|
||||
d3.layout.tree = function() {
|
||||
var hierarchy = d3.layout.hierarchy(),
|
||||
separation = d3_layout_treeSeparation,
|
||||
size = [1, 1]; // width, height
|
||||
|
||||
function tree(d, i) {
|
||||
var nodes = hierarchy.call(this, d, i),
|
||||
root = nodes[0];
|
||||
|
||||
function firstWalk(node, previousSibling) {
|
||||
var children = node.children,
|
||||
layout = node._tree;
|
||||
if (children) {
|
||||
var n = children.length,
|
||||
firstChild = children[0],
|
||||
previousChild,
|
||||
ancestor = firstChild,
|
||||
child,
|
||||
i = -1;
|
||||
while (++i < n) {
|
||||
child = children[i];
|
||||
firstWalk(child, previousChild);
|
||||
ancestor = apportion(child, previousChild, ancestor);
|
||||
previousChild = child;
|
||||
}
|
||||
d3_layout_treeShift(node);
|
||||
var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
|
||||
if (previousSibling) {
|
||||
layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
|
||||
layout.mod = layout.prelim - midpoint;
|
||||
} else {
|
||||
layout.prelim = midpoint;
|
||||
}
|
||||
} else {
|
||||
if (previousSibling) {
|
||||
layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function secondWalk(node, x) {
|
||||
node.x = node._tree.prelim + x;
|
||||
var children = node.children;
|
||||
if (children) {
|
||||
var i = -1,
|
||||
n = children.length;
|
||||
x += node._tree.mod;
|
||||
while (++i < n) {
|
||||
secondWalk(children[i], x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function apportion(node, previousSibling, ancestor) {
|
||||
if (previousSibling) {
|
||||
var vip = node,
|
||||
vop = node,
|
||||
vim = previousSibling,
|
||||
vom = node.parent.children[0],
|
||||
sip = vip._tree.mod,
|
||||
sop = vop._tree.mod,
|
||||
sim = vim._tree.mod,
|
||||
som = vom._tree.mod,
|
||||
shift;
|
||||
while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
|
||||
vom = d3_layout_treeLeft(vom);
|
||||
vop = d3_layout_treeRight(vop);
|
||||
vop._tree.ancestor = node;
|
||||
shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
|
||||
if (shift > 0) {
|
||||
d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
|
||||
sip += shift;
|
||||
sop += shift;
|
||||
}
|
||||
sim += vim._tree.mod;
|
||||
sip += vip._tree.mod;
|
||||
som += vom._tree.mod;
|
||||
sop += vop._tree.mod;
|
||||
}
|
||||
if (vim && !d3_layout_treeRight(vop)) {
|
||||
vop._tree.thread = vim;
|
||||
vop._tree.mod += sim - sop;
|
||||
}
|
||||
if (vip && !d3_layout_treeLeft(vom)) {
|
||||
vom._tree.thread = vip;
|
||||
vom._tree.mod += sip - som;
|
||||
ancestor = node;
|
||||
}
|
||||
}
|
||||
return ancestor;
|
||||
}
|
||||
|
||||
// Initialize temporary layout variables.
|
||||
d3_layout_treeVisitAfter(root, function(node, previousSibling) {
|
||||
node._tree = {
|
||||
ancestor: node,
|
||||
prelim: 0,
|
||||
mod: 0,
|
||||
change: 0,
|
||||
shift: 0,
|
||||
number: previousSibling ? previousSibling._tree.number + 1 : 0
|
||||
};
|
||||
});
|
||||
|
||||
// Compute the layout using Buchheim et al.'s algorithm.
|
||||
firstWalk(root);
|
||||
secondWalk(root, -root._tree.prelim);
|
||||
|
||||
// Compute the left-most, right-most, and depth-most nodes for extents.
|
||||
var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost),
|
||||
right = d3_layout_treeSearch(root, d3_layout_treeRightmost),
|
||||
deep = d3_layout_treeSearch(root, d3_layout_treeDeepest),
|
||||
x0 = left.x - separation(left, right) / 2,
|
||||
x1 = right.x + separation(right, left) / 2,
|
||||
y1 = deep.depth;
|
||||
|
||||
// Clear temporary layout variables; transform x and y.
|
||||
d3_layout_treeVisitAfter(root, function(node) {
|
||||
node.x = (node.x - x0) / (x1 - x0) * size[0];
|
||||
node.y = node.depth / y1 * size[1];
|
||||
delete node._tree;
|
||||
});
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
tree.sort = d3.rebind(tree, hierarchy.sort);
|
||||
tree.children = d3.rebind(tree, hierarchy.children);
|
||||
tree.value = d3.rebind(tree, hierarchy.value);
|
||||
|
||||
tree.separation = function(x) {
|
||||
if (!arguments.length) return separation;
|
||||
separation = x;
|
||||
return tree;
|
||||
};
|
||||
|
||||
tree.size = function(x) {
|
||||
if (!arguments.length) return size;
|
||||
size = x;
|
||||
return tree;
|
||||
};
|
||||
|
||||
return tree;
|
||||
};
|
||||
|
||||
function d3_layout_treeSeparation(a, b) {
|
||||
return a.parent == b.parent ? 1 : 2;
|
||||
}
|
||||
|
||||
// function d3_layout_treeSeparationRadial(a, b) {
|
||||
// return (a.parent == b.parent ? 1 : 2) / a.depth;
|
||||
// }
|
||||
|
||||
function d3_layout_treeLeft(node) {
|
||||
return node.children ? node.children[0] : node._tree.thread;
|
||||
}
|
||||
|
||||
function d3_layout_treeRight(node) {
|
||||
return node.children ? node.children[node.children.length - 1] : node._tree.thread;
|
||||
}
|
||||
|
||||
function d3_layout_treeSearch(node, compare) {
|
||||
var children = node.children;
|
||||
if (children) {
|
||||
var child,
|
||||
n = children.length,
|
||||
i = -1;
|
||||
while (++i < n) {
|
||||
if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
|
||||
node = child;
|
||||
}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function d3_layout_treeRightmost(a, b) {
|
||||
return a.x - b.x;
|
||||
}
|
||||
|
||||
function d3_layout_treeLeftmost(a, b) {
|
||||
return b.x - a.x;
|
||||
}
|
||||
|
||||
function d3_layout_treeDeepest(a, b) {
|
||||
return a.depth - b.depth;
|
||||
}
|
||||
|
||||
function d3_layout_treeVisitAfter(node, callback) {
|
||||
function visit(node, previousSibling) {
|
||||
var children = node.children;
|
||||
if (children) {
|
||||
var child,
|
||||
previousChild = null,
|
||||
i = -1,
|
||||
n = children.length;
|
||||
while (++i < n) {
|
||||
child = children[i];
|
||||
visit(child, previousChild);
|
||||
previousChild = child;
|
||||
}
|
||||
}
|
||||
callback(node, previousSibling);
|
||||
}
|
||||
visit(node, null);
|
||||
}
|
||||
|
||||
function d3_layout_treeShift(node) {
|
||||
var shift = 0,
|
||||
change = 0,
|
||||
children = node.children,
|
||||
i = children.length,
|
||||
child;
|
||||
while (--i >= 0) {
|
||||
child = children[i]._tree;
|
||||
child.prelim += shift;
|
||||
child.mod += shift;
|
||||
shift += child.shift + (change += child.change);
|
||||
}
|
||||
}
|
||||
|
||||
function d3_layout_treeMove(ancestor, node, shift) {
|
||||
ancestor = ancestor._tree;
|
||||
node = node._tree;
|
||||
var change = shift / (node.number - ancestor.number);
|
||||
ancestor.change += change;
|
||||
node.change -= change;
|
||||
node.shift += shift;
|
||||
node.prelim += shift;
|
||||
node.mod += shift;
|
||||
}
|
||||
|
||||
function d3_layout_treeAncestor(vim, node, ancestor) {
|
||||
return vim._tree.ancestor.parent == node.parent
|
||||
? vim._tree.ancestor
|
||||
: ancestor;
|
||||
}
|
|
@ -121,7 +121,7 @@ function d3_svg_lineStepAfter(points) {
|
|||
function d3_svg_lineCardinalClosed(points, tension) {
|
||||
return points.length < 3
|
||||
? d3_svg_lineLinear(points)
|
||||
: points[0] + d3_svg_lineHermite(points,
|
||||
: points[0] + d3_svg_lineHermite((points.push(points[0]), points),
|
||||
d3_svg_lineCardinalTangents([points[points.length - 2]]
|
||||
.concat(points, [points[1]]), tension));
|
||||
}
|
||||
|
@ -185,18 +185,17 @@ function d3_svg_lineHermite(points, tangents) {
|
|||
function d3_svg_lineCardinalTangents(points, tension) {
|
||||
var tangents = [],
|
||||
a = (1 - tension) / 2,
|
||||
p0 = points[0],
|
||||
p1 = points[1],
|
||||
p2 = points[2],
|
||||
i = 2,
|
||||
p0,
|
||||
p1 = points[0],
|
||||
p2 = points[1],
|
||||
i = 1,
|
||||
n = points.length;
|
||||
while (++i < n) {
|
||||
tangents.push([a * (p2[0] - p0[0]), a * (p2[1] - p0[1])]);
|
||||
p0 = p1;
|
||||
p1 = p2;
|
||||
p2 = points[i];
|
||||
tangents.push([a * (p2[0] - p0[0]), a * (p2[1] - p0[1])]);
|
||||
}
|
||||
tangents.push([a * (p2[0] - p0[0]), a * (p2[1] - p0[1])]);
|
||||
return tangents;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,5 +46,5 @@ interpolate(cardinal):
|
|||
interpolate(cardinal-closed):
|
||||
[[0, 0]]: M0,0L0,0Z
|
||||
[[0, 0], [5, 5]]: M0,0L5,5L5,0L0,0Z
|
||||
[[0, 0], [5, 5], [10, 0]]: M0,0C0,0,3.5,5,5,5S10,0,10,0L10,0C10,0,6.5,0,5,0S0,0,0,0Z
|
||||
[[0, 0], [5, 5], [10, 0]]: M0,0C-0.7500000000000001,0.7500000000000001,3.5,5,5,5S10.75,0.7500000000000001,10,0S0.7500000000000001,-0.7500000000000001,0,0L10,0C10.75,0,6.5,0,5,0S-0.7500000000000001,0,0,0S9.25,0,10,0Z
|
||||
|
||||
|
|
|
@ -41,5 +41,5 @@ interpolate(cardinal):
|
|||
interpolate(cardinal-closed):
|
||||
[[0, 0]]: M0,0
|
||||
[[0, 0], [5, 5]]: M0,0L5,5
|
||||
[[0, 0], [5, 5], [10, 0]]: M0,0C0,0,3.5,5,5,5S10,0,10,0
|
||||
[[0, 0], [5, 5], [10, 0]]: M0,0C-0.7500000000000001,0.7500000000000001,3.5,5,5,5S10.75,0.7500000000000001,10,0S0.7500000000000001,-0.7500000000000001,0,0
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче