An experiment on treemap coloring, using color encoding for depth. Instead of regions, boundaries are colored. A categorical color scale is used to help find nodes at the same level in other parts of the map, while some padding between lines is used together with decreasing thickness to convey a sense of nesting.
Last active
December 26, 2015 18:45
-
-
Save nitaku/7dc03ae7fd1c5c337c5a to your computer and use it in GitHub Desktop.
Treemaps: boundary coloring
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
svg = d3.select('svg') | |
width = svg.node().getBoundingClientRect().width | |
height = svg.node().getBoundingClientRect().height | |
size = Math.round(Math.min(width, height) * 0.8) | |
boundary_thickness = d3.scale.sqrt() | |
.range([3,0.5]) | |
boundary_color = (i) -> d3.hcl(50+100*i,50,50) | |
treemap = d3.layout.treemap() | |
.size([size, size]) | |
.value((node) -> node.size) | |
# translate the viewBox to have (0,0) at the center of the vis | |
svg | |
.attr | |
viewBox: "#{-width/2} #{-height/2} #{width} #{height}" | |
# append a group for zoomable content | |
zoomable_layer = svg.append('g') | |
# define a zoom behavior | |
zoom = d3.behavior.zoom() | |
.scaleExtent([1,10]) # min-max zoom | |
.on 'zoom', () -> | |
# GEOMETRIC ZOOM | |
zoomable_layer | |
.attr | |
transform: "translate(#{zoom.translate()})scale(#{zoom.scale()})" | |
# bind the zoom behavior to the main SVG | |
svg.call(zoom) | |
# group the visualization | |
vis = zoomable_layer.append('g') | |
.attr | |
transform: "translate(#{-size/2},#{-size/2})" | |
d3.json 'http://wafi.iit.cnr.it/webvis/tmp/flare.json', (tree) -> | |
data = treemap.nodes(tree) | |
boundary_thickness | |
.domain([d3.min(data, (d) -> d.depth), d3.max(data, (d) -> d.depth)]) | |
levels_data = d3.nest() | |
.key (d) -> d.depth | |
.entries data | |
levels_data.forEach (d) -> d.key = +d.key | |
# drawing order: deep to shallow | |
levels_data.sort (a,b) -> d3.descending(a.key,b.key) | |
levels = vis.selectAll '.level' | |
.data levels_data | |
levels.enter().append 'g' | |
.attr | |
class: 'level' | |
strips = levels.selectAll '.boundary_strip' | |
.data (d) -> d.values | |
enter_strips = strips.enter().append 'rect' | |
.attr | |
class: 'boundary_strip' | |
x: (node) -> node.x | |
y: (node) -> node.y | |
width: (node) -> node.dx | |
height: (node) -> node.dy | |
'stroke-width': (node) -> 12 | |
lines = levels.selectAll '.boundary_line' | |
.data (d) -> d.values | |
enter_lines = lines.enter().append 'rect' | |
.attr | |
class: 'boundary_line' | |
x: (node) -> node.x | |
y: (node) -> node.y | |
width: (node) -> node.dx | |
height: (node) -> node.dy | |
stroke: (node) -> boundary_color(node.depth) | |
'stroke-width': (node) -> boundary_thickness(node.depth) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
html, body { | |
padding: 0; | |
margin: 0; | |
width: 100%; | |
height: 100%; | |
overflow: hidden; | |
} | |
svg { | |
width: 100%; | |
height: 100%; | |
background: white; | |
} | |
.boundary_line { | |
vector-effect: non-scaling-stroke; | |
fill: none; | |
} | |
.boundary_strip { | |
stroke: white; | |
vector-effect: non-scaling-stroke; | |
fill: none; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Treemaps: boundary coloring</title> | |
<link type="text/css" href="index.css" rel="stylesheet"/> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
</head> | |
<body> | |
<svg></svg> | |
<script src="index.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Generated by CoffeeScript 1.10.0 | |
(function() { | |
var boundary_color, boundary_thickness, height, size, svg, treemap, vis, width, zoom, zoomable_layer; | |
svg = d3.select('svg'); | |
width = svg.node().getBoundingClientRect().width; | |
height = svg.node().getBoundingClientRect().height; | |
size = Math.round(Math.min(width, height) * 0.8); | |
boundary_thickness = d3.scale.sqrt().range([3, 0.5]); | |
boundary_color = function(i) { | |
return d3.hcl(50 + 100 * i, 50, 50); | |
}; | |
treemap = d3.layout.treemap().size([size, size]).value(function(node) { | |
return node.size; | |
}); | |
svg.attr({ | |
viewBox: (-width / 2) + " " + (-height / 2) + " " + width + " " + height | |
}); | |
zoomable_layer = svg.append('g'); | |
zoom = d3.behavior.zoom().scaleExtent([1, 10]).on('zoom', function() { | |
return zoomable_layer.attr({ | |
transform: "translate(" + (zoom.translate()) + ")scale(" + (zoom.scale()) + ")" | |
}); | |
}); | |
svg.call(zoom); | |
vis = zoomable_layer.append('g').attr({ | |
transform: "translate(" + (-size / 2) + "," + (-size / 2) + ")" | |
}); | |
d3.json('http://wafi.iit.cnr.it/webvis/tmp/flare.json', function(tree) { | |
var data, enter_lines, enter_strips, levels, levels_data, lines, strips; | |
data = treemap.nodes(tree); | |
boundary_thickness.domain([ | |
d3.min(data, function(d) { | |
return d.depth; | |
}), d3.max(data, function(d) { | |
return d.depth; | |
}) | |
]); | |
levels_data = d3.nest().key(function(d) { | |
return d.depth; | |
}).entries(data); | |
levels_data.forEach(function(d) { | |
return d.key = +d.key; | |
}); | |
levels_data.sort(function(a, b) { | |
return d3.descending(a.key, b.key); | |
}); | |
levels = vis.selectAll('.level').data(levels_data); | |
levels.enter().append('g').attr({ | |
"class": 'level' | |
}); | |
strips = levels.selectAll('.boundary_strip').data(function(d) { | |
return d.values; | |
}); | |
enter_strips = strips.enter().append('rect').attr({ | |
"class": 'boundary_strip', | |
x: function(node) { | |
return node.x; | |
}, | |
y: function(node) { | |
return node.y; | |
}, | |
width: function(node) { | |
return node.dx; | |
}, | |
height: function(node) { | |
return node.dy; | |
}, | |
'stroke-width': function(node) { | |
return 12; | |
} | |
}); | |
lines = levels.selectAll('.boundary_line').data(function(d) { | |
return d.values; | |
}); | |
return enter_lines = lines.enter().append('rect').attr({ | |
"class": 'boundary_line', | |
x: function(node) { | |
return node.x; | |
}, | |
y: function(node) { | |
return node.y; | |
}, | |
width: function(node) { | |
return node.dx; | |
}, | |
height: function(node) { | |
return node.dy; | |
}, | |
stroke: function(node) { | |
return boundary_color(node.depth); | |
}, | |
'stroke-width': function(node) { | |
return boundary_thickness(node.depth); | |
} | |
}); | |
}); | |
}).call(this); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment