Treemap with changing content showing context-sensitive AR paper.
-
-
Save jensgrubert/7929218 to your computer and use it in GitHub Desktop.
Treemap with changing content.
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
{ | |
"name": "Adaptive to what", | |
"children": [ | |
{ | |
"name": "Human Factors", | |
"children": [ | |
{ | |
"name": "Preferences", | |
"children": [ | |
{"name": "Sinclair2001", "size": 1} | |
] | |
}, | |
{ | |
"name": "Capabilities", | |
"children": [ | |
{"name": " Sinclair2001", "size": 1}, | |
{"name": " STricker2012", "size": 1}, | |
{ | |
"name": "Motion", | |
"children": [ | |
{"name": "[STricker2012]", "size": 1} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "State", | |
"children": [ | |
{ | |
"name": "Physiological State", | |
"children": [ | |
{"name": "Xu2012", "size": 1} | |
] | |
}, | |
{ | |
"name": "Attention", | |
"children": [ | |
{"name": " Xu2012", "size": 1} | |
] | |
} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "User Tasks", | |
"children": [ | |
{ | |
"name": "User Goals", | |
"children": [ | |
{"name": "Beadle1997", "size": 1} | |
] | |
}, | |
{ | |
"name": "Information", | |
"children": [ | |
{ | |
"name": "Quantity", | |
"children": [ | |
{"name": "Julier2002", "size": 1} | |
] | |
}, | |
{ | |
"name": "Readabillity", | |
"children": [ | |
{"name": "Gabbard2005", "size": 1} | |
] | |
}, | |
{ | |
"name": "Distance", | |
"children": [ | |
{"name": "Uratani2005", "size": 1} | |
] | |
} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "Activity/Environmental Factors", | |
"children": [ | |
{ | |
"name": "Place", | |
"children": [ | |
{"name": "Bordes2011", "size": 1}, | |
{"name": "Hervas2011", "size": 1} | |
] | |
}, | |
{ | |
"name": "Social Networks", | |
"children": [ | |
{"name": " Hervas2011", "size": 1} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "Technical Factors", | |
"children": [ | |
{ | |
"name": "Interactive System", | |
"children": [ | |
{ | |
"name": "System State", | |
"children": [ | |
{"name": "Bühling2012", "size": 1} | |
] | |
}, | |
{ | |
"name": "Input", | |
"children": [ | |
{ | |
"name": "Environment Sensors", | |
"children": [ | |
{ | |
"name": "Location", | |
"children": [ | |
{ | |
"name": "Spatial Uncertainties", | |
"children": [ | |
{"name": "Drexel20XX", "size": 1}, | |
{"name": "MacIntyre2007", "size": 1} | |
] | |
} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "User Input", | |
"children": [ | |
{"name": "Mendez2007", "size": 1} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "Output", | |
"children": [ | |
{ | |
"name": "Visual Displays ", | |
"children": [ | |
{ | |
"name": "Spatial Arrangement", | |
"children": [ | |
{"name": "Rosten2005", "size": 1}, | |
{"name": "Grasset2012", "size": 1} | |
] | |
}, | |
{ | |
"name": "Composition", | |
"children": [ | |
{"name": "Kalkofen2009", "size": 1}, | |
{"name": "Kalkofen2013", "size": 1} | |
] | |
} | |
] | |
} | |
] | |
} | |
] | |
} | |
] | |
} | |
] | |
} |
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
{ | |
"name": "Adapting What?", | |
"children": [ | |
{ | |
"name": "System Input", | |
"children": [ | |
{ | |
"name": "Interface", | |
"children": [ | |
{"name": "Drexel20XX", "size": 1}, | |
{"name": "STricker2012", "size": 1}, | |
{"name": "Xu2012", "size": 1}, | |
{"name": "Hervas2011", "size": 1} | |
] | |
}, | |
{ | |
"name": "Interaction Modalities", | |
"children": [ | |
{"name": "ArtSense", "size": 1} | |
] | |
} | |
] | |
}, | |
{ | |
"name": "System Output", | |
"children": [ | |
{ | |
"name": "Content", | |
"children": [ | |
{"name": "Beadle1997", "size": 1}, | |
{"name": "Bühling2012", "size": 1} | |
] | |
}, | |
{ | |
"name": "Information Presentation", | |
"children": [ | |
{ | |
"name": "Spatial Arrangement", | |
"children": [ | |
{"name": "Rosten2005", "size": 1}, | |
{"name": "Grasset2012", "size": 1}, | |
{"name": "Bordes2011", "size": 1} | |
] | |
}, | |
{ | |
"name": "Appearance Adaptation", | |
"children": [ | |
{"name": "Kalkofen2013", "size": 1}, | |
{"name": "Sinclair2001", "size": 1}, | |
{"name": "MacIntyre2007", "size": 1}, | |
{"name": " Bordes2011", "size": 1}, | |
{"name": "Uratani2005", "size": 1}, | |
{"name": " Beadle1997", "size": 1}, | |
{"name": " Bühling2012", "size": 1}, | |
{"name": " Drexel20XX", "size": 1}, | |
{"name": "Kalkofen2009", "size": 1} | |
] | |
}, | |
{ | |
"name": "Amount of Data", | |
"children": [ | |
{"name": "Julier2002", "size": 1} | |
] | |
} | |
] | |
} | |
] | |
} | |
] | |
} |
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 http-equiv="Content-Type" content="text/html;charset=utf-8"> | |
<title>Treemap - Neat Zoom Effect</title> | |
<!--<script type="text/javascript" src="./browserdetect/browserdetect.js"></script>--> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="d3.v3.min.js"></script> | |
<style type="text/css"> | |
body { | |
overflow: hidden; | |
margin: 0; | |
font-size: 12px; | |
font-family: "Helvetica Neue", Helvetica; | |
} | |
.footer { | |
z-index: 1; | |
display: block; | |
font-size: 26px; | |
font-weight: 200; | |
text-shadow: 0 1px 0 #fff; | |
} | |
svg { | |
overflow: hidden; | |
} | |
rect { | |
pointer-events: all; | |
cursor: pointer; | |
stroke: #EEEEEE; | |
} | |
.chart { | |
display: block; | |
margin: auto; | |
} | |
.parent .label { | |
color: #FFFFFF; | |
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); | |
-webkit-text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); | |
-moz-text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); | |
} | |
.labelbody { | |
background: transparent; | |
} | |
.label { | |
margin: 2px; | |
white-space: pre; | |
overflow: hidden; | |
text-overflow: ellipsis; | |
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); | |
-webkit-text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); | |
-moz-text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); | |
} | |
.child .label { | |
white-space: pre-wrap; | |
text-align: center; | |
text-overflow: ellipsis; | |
} | |
.cell { | |
font-size: 11px; | |
cursor: pointer | |
} | |
</style> | |
</head> | |
<body> | |
<div id="body"></div> | |
<div class="footer"> | |
<select> | |
<option value="size">Size</option> | |
<option value="count">Count</option> | |
</select> | |
</div> | |
<p> | |
<button onclick="switchData('data-to-what.json')">Show: "Adaptive to What?"</button> | |
<button onclick="switchData('data-what.json')">Show: "Adapting What?"</button> | |
<!--<input name="" id="testData" type="button" value="data"></input> | |
<input name="" id="adaptiveToWhat" type="button" value="Adaptive to what?"></input>--> | |
</p> | |
</body> | |
<script type="text/javascript"> | |
var isIE = false; // BrowserDetect.browser == 'Explorer'; | |
var chartWidth = 550; | |
var chartHeight = 550; | |
var xscale = d3.scale.linear().range([0, chartWidth]); | |
var yscale = d3.scale.linear().range([0, chartHeight]); | |
var color = d3.scale.category10(); | |
var headerHeight = 20; | |
var headerColor = "#555555"; | |
var transitionDuration = 500; | |
var root; | |
var node; | |
var data2; | |
var datFn01 = 'data-cs-ar.json'; | |
var datFn02 = 'data.json'; | |
var treemap = d3.layout.treemap() | |
.round(false) | |
.size([chartWidth, chartHeight]) | |
.sticky(true) | |
.value(function(d) { | |
return d.size; | |
}); | |
var chart = d3.select("#body") | |
.append("svg:svg") | |
.attr("width", chartWidth) | |
.attr("height", chartHeight) | |
.append("svg:g"); | |
function switchData(dataFn) { | |
d3.select("svg").remove(); | |
treemap = d3.layout.treemap() | |
.round(false) | |
.size([chartWidth, chartHeight]) | |
.sticky(true) | |
.value(function(d) { | |
return d.size; | |
}); | |
chart = d3.select("#body") | |
.append("svg:svg") | |
.attr("width", chartWidth) | |
.attr("height", chartHeight) | |
.append("svg:g"); | |
drawTreemap(dataFn); | |
} | |
function drawTreemap(datFn01) { | |
d3.json(datFn01, function(data) { | |
node = root = data; | |
var nodes = treemap.nodes(root); | |
var children = nodes.filter(function(d) { | |
return !d.children; | |
}); | |
var parents = nodes.filter(function(d) { | |
return d.children; | |
}); | |
// create parent cells | |
var parentCells = chart.selectAll("g.cell.parent") | |
.data(parents, function(d) { | |
return "p-" + d.name; | |
}); | |
var parentEnterTransition = parentCells.enter() | |
.append("g") | |
.attr("class", "cell parent") | |
.on("click", function(d) { | |
zoom(d); | |
}); | |
parentEnterTransition.append("rect") | |
.attr("width", function(d) { | |
return Math.max(0.01, d.dx); | |
}) | |
.attr("height", headerHeight) | |
.style("fill", headerColor); | |
parentEnterTransition.append('foreignObject') | |
.attr("class", "foreignObject") | |
.append("xhtml:body") | |
.attr("class", "labelbody") | |
.append("div") | |
.attr("class", "label"); | |
// update transition | |
var parentUpdateTransition = parentCells.transition().duration(transitionDuration); | |
parentUpdateTransition.select(".cell") | |
.attr("transform", function(d) { | |
return "translate(" + d.dx + "," + d.y + ")"; | |
}); | |
parentUpdateTransition.select("rect") | |
.attr("width", function(d) { | |
return Math.max(0.01, d.dx); | |
}) | |
.attr("height", headerHeight) | |
.style("fill", headerColor); | |
parentUpdateTransition.select(".foreignObject") | |
.attr("width", function(d) { | |
return Math.max(0.01, d.dx); | |
}) | |
.attr("height", headerHeight) | |
.select(".labelbody .label") | |
.text(function(d) { | |
return d.name; | |
}); | |
// remove transition | |
parentCells.exit() | |
.remove(); | |
// create children cells | |
var childrenCells = chart.selectAll("g.cell.child") | |
.data(children, function(d) { | |
return "c-" + d.name; | |
}); | |
// enter transition | |
var childEnterTransition = childrenCells.enter() | |
.append("g") | |
.attr("class", "cell child") | |
.on("click", function(d) { | |
zoom(node === d.parent ? root : d.parent); | |
}); | |
childEnterTransition.append("rect") | |
.classed("background", true) | |
.style("fill", function(d) { | |
return color(d.parent.name); | |
}); | |
childEnterTransition.append('foreignObject') | |
.attr("class", "foreignObject") | |
.attr("width", function(d) { | |
return Math.max(0.01, d.dx); | |
}) | |
.attr("height", function(d) { | |
return Math.max(0.01, d.dy); | |
}) | |
.append("xhtml:body") | |
.attr("class", "labelbody") | |
.append("div") | |
.attr("class", "label") | |
.text(function(d) { | |
return d.name; | |
}); | |
if (isIE) { | |
childEnterTransition.selectAll(".foreignObject .labelbody .label") | |
.style("display", "none"); | |
} else { | |
childEnterTransition.selectAll(".foreignObject") | |
.style("display", "none"); | |
} | |
// update transition | |
var childUpdateTransition = childrenCells.transition().duration(transitionDuration); | |
childUpdateTransition.select(".cell") | |
.attr("transform", function(d) { | |
return "translate(" + d.x + "," + d.y + ")"; | |
}); | |
childUpdateTransition.select("rect") | |
.attr("width", function(d) { | |
return Math.max(0.01, d.dx); | |
}) | |
.attr("height", function(d) { | |
return d.dy; | |
}) | |
.style("fill", function(d) { | |
return color(d.parent.name); | |
}); | |
childUpdateTransition.select(".foreignObject") | |
.attr("width", function(d) { | |
return Math.max(0.01, d.dx); | |
}) | |
.attr("height", function(d) { | |
return Math.max(0.01, d.dy); | |
}) | |
.select(".labelbody .label") | |
.text(function(d) { | |
return d.name; | |
}); | |
// exit transition | |
childrenCells.exit() | |
.remove(); | |
// interaction with thml elements | |
d3.select("select").on("change", function() { | |
console.log("select zoom(node)"); | |
treemap.value(this.value == "size" ? size : count) | |
.nodes(root); | |
zoom(node); | |
}); | |
/* | |
d3.select("#testData").on("click", function() { | |
var node = div.datum(data).selectAll(".node") | |
.data(treemap.nodes); | |
node.enter().append("div") | |
.attr("class", "node"); | |
node.transition().duration(1500).call(position) | |
.style("background", function(d) { return d.color ? d.color : "#ffffff"; }) | |
.text(function(d) { return d.children ? "blue" : d.keytable + "(" + d.anzahl + "-" + Math.max(0, d.dx) + "-" + Math.max(0, d.dy) + ")"; }) | |
; | |
}); | |
*/ | |
zoom(node); | |
}); | |
} | |
function size(d) { | |
return d.size; | |
} | |
function count(d) { | |
return 1; | |
} | |
//and another one | |
function textHeight(d) { | |
var ky = chartHeight / d.dy; | |
yscale.domain([d.y, d.y + d.dy]); | |
return (ky * d.dy) / headerHeight; | |
} | |
function getRGBComponents (color) { | |
var r = color.substring(1, 3); | |
var g = color.substring(3, 5); | |
var b = color.substring(5, 7); | |
return { | |
R: parseInt(r, 16), | |
G: parseInt(g, 16), | |
B: parseInt(b, 16) | |
}; | |
} | |
function idealTextColor (bgColor) { | |
var nThreshold = 105; | |
var components = getRGBComponents(bgColor); | |
var bgDelta = (components.R * 0.299) + (components.G * 0.587) + (components.B * 0.114); | |
return ((255 - bgDelta) < nThreshold) ? "#000000" : "#ffffff"; | |
} | |
function zoom(d) { | |
this.treemap | |
.padding([headerHeight/(chartHeight/d.dy), 0, 0, 0]) | |
.nodes(d); | |
// moving the next two lines above treemap layout messes up padding of zoom result | |
var kx = chartWidth / d.dx; | |
var ky = chartHeight / d.dy; | |
var level = d; | |
xscale.domain([d.x, d.x + d.dx]); | |
yscale.domain([d.y, d.y + d.dy]); | |
if (node != level) { | |
if (isIE) { | |
chart.selectAll(".cell.child .foreignObject .labelbody .label") | |
.style("display", "none"); | |
} else { | |
chart.selectAll(".cell.child .foreignObject") | |
.style("display", "none"); | |
} | |
} | |
var zoomTransition = chart.selectAll("g.cell").transition().duration(transitionDuration) | |
.attr("transform", function(d) { | |
return "translate(" + xscale(d.x) + "," + yscale(d.y) + ")"; | |
}) | |
.each("end", function(d, i) { | |
if (!i && (level !== self.root)) { | |
chart.selectAll(".cell.child") | |
.filter(function(d) { | |
return d.parent === self.node; // only get the children for selected group | |
}) | |
.select(".foreignObject .labelbody .label") | |
.style("color", function(d) { | |
return idealTextColor(color(d.parent.name)); | |
}); | |
if (isIE) { | |
chart.selectAll(".cell.child") | |
.filter(function(d) { | |
return d.parent === self.node; // only get the children for selected group | |
}) | |
.select(".foreignObject .labelbody .label") | |
.style("display", "") | |
} else { | |
chart.selectAll(".cell.child") | |
.filter(function(d) { | |
return d.parent === self.node; // only get the children for selected group | |
}) | |
.select(".foreignObject") | |
.style("display", "") | |
} | |
} | |
}); | |
zoomTransition.select(".foreignObject") | |
.attr("width", function(d) { | |
return Math.max(0.01, kx * d.dx); | |
}) | |
.attr("height", function(d) { | |
return d.children ? headerHeight: Math.max(0.01, ky * d.dy); | |
}) | |
.select(".labelbody .label") | |
.text(function(d) { | |
return d.name; | |
}); | |
// update the width/height of the rects | |
zoomTransition.select("rect") | |
.attr("width", function(d) { | |
return Math.max(0.01, kx * d.dx); | |
}) | |
.attr("height", function(d) { | |
return d.children ? headerHeight : Math.max(0.01, ky * d.dy); | |
}) | |
.style("fill", function(d) { | |
return d.children ? headerColor : color(d.parent.name); | |
}); | |
node = d; | |
if (d3.event) { | |
d3.event.stopPropagation(); | |
} | |
} | |
</script> | |
<script type="text/javascript"> | |
drawTreemap('data-to-what.json'); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just checking this out on blocks, how do you trigger a data change?