Enclosure diagrams use containment to represent the hierarchy. Although circle packing is not as space-efficient as a treemap, it better reveals the hierarchy. Implementation based on work by Jeff Heer. Data shows the Flare class hierarchy, also courtesy Jeff Heer.
A fork and port of mike’s js version (gist/block), programmed in clojurescript atop the maturing strokes library.
This is running atop the first version of strokes that is able to repair a persistent data structure that has been mutated by javascript as the d3 layouts do - effectively trying to add new fields to the clojure maps. In this example the mrhyde function repersist
reconstructs a persistent view of each node.
(Merge request? Use the repo version.)
<!DOCTYPE html>
<meta charset="utf-8">
<title>Circle-pack</title>
<style>
circle {
fill: rgb(31, 119, 180);
fill-opacity: .25;
stroke: rgb(31, 119, 180);
stroke-width: 1px;
}
.leaf circle {
fill: #ff7f0e;
fill-opacity: 1;
}
text {
font: 10px sans-serif;
}
</style>
<body>
<script type="text/javascript" src="//d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="strokes-circle-pack.js"></script>
(ns strokes.examples.circle-pack
(:require [clojure.string :refer [join]]
[mrhyde.typepatcher :refer [repersist]]
[strokes :refer [d3]]))
(strokes/bootstrap)
(def diameter 960)
(def formatfn (d3/format ",d"))
(def pack (.. d3 -layout pack
(size [(- diameter 4), (- diameter 4)])
(value :size)))
(def svg (.. d3 (select "body") (append "svg")
(attr "width" diameter)
(attr "height" diameter)
(append "g")
(attr "transform" "translate(2,2)")))
; (-> d3 (.json "flare-full.json" (fn [error, jsroot]
; (let [root (js->clj jsroot :keywordize-keys true)
; node (-> svg (.datum root) (.selectAll ".node")
(strokes/fetch-edn "flare.edn" (fn [error, root]
(let [node (.. svg (datum root) (selectAll ".node")
(data (repersist (.-nodes pack) :skip [:children :parent]))
(enter) (append "g")
(attr "class" #(if (contains? % :children) "node" "leaf node"))
(attr "transform" #(str "translate(" (:x %) "," (:y %) ")")))]
(.. node (append "title")
(text #(str (:name %) (if (contains? % :children) "" (formatfn (:size %))))))
(.. node (append "circle")
(attr "r" :r))
(.. node (filter #(not (:children %))) (append "text")
(attr "dy" ".3em")
(style "text-anchor" "middle")
(text #(subs (:name %) 0 (/ (:r %) 3)))) )))
(.. d3 (select (.-frameElement js/self)) (style "height" (str diameter "px")))
{: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}]}]}