Last active
December 18, 2015 15:59
-
-
Save bobbydavid/5808079 to your computer and use it in GitHub Desktop.
d3 meta-visualization
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> | |
<meta charset="utf-8"> | |
<!-- author: Robert Martin --> | |
<style> | |
body { | |
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
margin: auto; | |
position: relative; | |
width: 960px; | |
} | |
form { | |
position: absolute; | |
right: 10px; | |
top: 10px; | |
} | |
#breadcrumb { | |
position: absolute; | |
left: 10px; | |
top: 10px; | |
} | |
.node { | |
border: solid 1px white; | |
font: 10px sans-serif; | |
line-height: 12px; | |
overflow: hidden; | |
position: absolute; | |
text-indent: 2px; | |
} | |
</style> | |
<form> | |
<label><input type="radio" name="mode" value="min" checked> d3.v3.min.js</label> | |
<label><input type="radio" name="mode" value="full"> d3.v3.js</label> | |
</form> | |
<div id="breadcrumb"></div> | |
<div id="container"></div> | |
<script src="http://d3js.org/d3.v3.js"></script> | |
<script> | |
var d3Full = d3; | |
</script> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script> | |
var svgMarginTop = 40; | |
var svgWidth = 960, svgHeight = 500 - svgMarginTop; | |
var globalIndex = 0; | |
var getRecursiveSize = function(key, val) { | |
var node = { name: key, index: globalIndex++ }; | |
switch (typeof(val)) { | |
case 'object': | |
var children = []; | |
for (i in val) { | |
children.push(getRecursiveSize(i, val[i])); | |
} | |
if (children.length == 0) { | |
node.size = 2; | |
} else { | |
node.children = children; | |
} | |
break; | |
case 'boolean': | |
case 'number': | |
case 'string': | |
node.size = val.toString().length; | |
break; | |
case 'function': | |
node.name += '()'; | |
node.size = val.toString().length; | |
break; | |
default: | |
console.log('cannot handle type: ' + typeof(val)); | |
throw new Error(); | |
} | |
return node; | |
} | |
var recursiveAdd = function(minNode, fullNode) { | |
if (minNode.children) { | |
minNode.children.forEach(function(child, index) { | |
recursiveAdd(child, fullNode.children[index]); | |
}); | |
} else { | |
minNode.minSize = minNode.size; | |
minNode.fullSize = fullNode.size; | |
delete minNode.size; | |
} | |
}; | |
var root = getRecursiveSize('d3', d3); | |
recursiveAdd(root, getRecursiveSize('d3', d3Full)); | |
// Create d3 elements. | |
var treemap = d3.layout.treemap() | |
.sticky(true) | |
.value(function(d) { return d.minSize; }) | |
.size([svgWidth, svgHeight]); | |
// Create visual elements. | |
var div = d3.select('#container') | |
.style('position', 'relative') | |
.style('width', svgWidth + 'px') | |
.style('height', svgHeight + 'px') | |
.style('top', svgMarginTop + 'px'); | |
var color = d3.scale.category20c(); | |
var node = div.datum(root).selectAll('.node') | |
.data(treemap.nodes) | |
.enter().append('div') | |
.attr('class', 'node') | |
.call(position) | |
.style('background', function(d) { return d.children ? color(d.index) : null; }) | |
.text(function(d) { | |
return d.children ? | |
null : d.name + ' ' + Math.round(d.value / root.value * 1000) / 10 + '%'; | |
}); | |
var breadcrumb = d3.select('#breadcrumb'); | |
// Create interaction. | |
d3.selectAll('input').on('change', function() { | |
var getValue = (this.value == 'min') ? function(d) { return d.minSize; } : | |
function(d) { return d.fullSize; }; | |
treemap.value(getValue); | |
node.data(treemap.nodes) | |
.transition() | |
.duration(1000) | |
.call(position); | |
}); | |
node.on('mouseover', function(node) { | |
var ancestors = [node]; | |
var breadcrumbText = node.name; | |
while (node.parent) { | |
ancestors.push(node.parent); | |
node = node.parent; | |
breadcrumbText = node.name + ' > ' + breadcrumbText; | |
} | |
div.selectAll('.node') | |
.data(ancestors, function(d) { return d.index; }) | |
.style('background', function(d) { return color(d.index); }) | |
.style('opacity', '1.0') | |
.text(function(d) { | |
return d.name + ' ' + Math.round(d.value / root.value * 1000) / 10 + '%' | |
}) | |
.exit() | |
.style('background', null) | |
.style('opacity', '0.0'); | |
breadcrumb.text(breadcrumbText); | |
}); | |
node.on('mouseout', function() { | |
div.selectAll('.node') | |
.style('background', function(d) { return d.children ? color(d.index) : null; }) | |
.style('opacity', '1.0') | |
.text(function(d) { | |
return d.children ? | |
null : d.name + ' ' + Math.round(d.value / root.value * 1000) / 10 + '%'; | |
}); | |
breadcrumb.text(''); | |
}); | |
function position() { | |
this.style('left', function(d) { return d.x + 'px'; }) | |
.style('top', function(d) { return d.y + 'px'; }) | |
.style('width', function(d) { return Math.max(0, d.dx - 1) + 'px'; }) | |
.style('height', function(d) { return Math.max(0, d.dy - 1) + 'px'; }); | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment