Skip to content

Instantly share code, notes, and snippets.

@emeeks
Last active March 17, 2016 16:18
Show Gist options
  • Save emeeks/38ca13fd2292ce40dcb6 to your computer and use it in GitHub Desktop.
Save emeeks/38ca13fd2292ce40dcb6 to your computer and use it in GitHub Desktop.
Ch. 9, Early Dashboard 2 - D3.js in Action

This is an example from D3.js in Action that continues to develop a data dashboard by including mouseover events on the graphical elements to highlight shared datapoints.

<html>
<head>
<title>D3 in Action Chapter 9 - Example 2</title>
<meta charset="utf-8" />
<script src="https://d3js.org/colorbrewer.v1.min.js" type="text/JavaScript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
</head>
<style>
body,html {
width: 100%;
height: 100%; #a
}
.svgDash {
width: 50%;
height: 50%;
background: #fcfcfc;
}
#leftSVG {
float:left;
}
#spreadsheet {
width: 100%;
height: 50%;
overflow:auto;
background: #fcfcfc;
}
circle.pack {
stroke: black;
stroke-width: 2px;
}
rect.bar {
fill: gray;
stroke: black;
stroke-width: 1px;
}
</style>
<body>
<svg id="leftSVG" class="svgDash"></svg>
<svg id="rightSVG" class="svgDash"></svg>
<div id="spreadsheet"></div>
</body>
<footer>
<script>
window.onresize = function(event) {
redraw();
}
function hover(hoverD) {
var nestArray = hoverD.values || [];
d3.selectAll("circle").filter(function (d) {return d == hoverD}).style("fill", "#94B8FF");
d3.selectAll("rect").filter(function (d) {return d == hoverD || d.values.indexOf(hoverD) > -1})
.style("fill", "#94B8FF");
d3.selectAll("div.datarow")
.filter(function (d) {return d == hoverD || nestArray.indexOf(d) > -1})
.style("background", "#94B8FF");
}
function mouseOut() {
d3.selectAll("circle").style("fill", function(d) {return depthScale(d.depth)});
d3.selectAll("rect").style("fill", "gray").style("stroke-width", 0);
d3.selectAll("div.datarow").style("background", "white");
}
d3.json("tweets.json",function(error,data) {main(data.tweets)});
// d3.selectAll("svg").append("rect").attr("width", 100).attr("height", 100);
function main(incData) {
createSpreadsheet(incData, "#controls");
var nestedTweets = d3.nest()
.key(function (el) {return el.user})
.entries(incData);
packableTweets = {id: "root", values: nestedTweets}
createBar(nestedTweets, "#rightSVG");
createPack(packableTweets, "#leftSVG");
redraw();
}
function canvasSize(targetElement) {
var newHeight = parseFloat(d3.select(targetElement).node().clientHeight);
var newWidth = parseFloat(d3.select(targetElement).node().clientWidth);
return [newWidth,newHeight];
}
function redraw() {
var leftSize = canvasSize("#leftSVG");
packChart.size(leftSize)
d3.select("#leftSVG")
.selectAll("circle")
.attr("class", "pack")
.data(packChart(packableTweets))
.attr("r", function(d) {return d.r - (d.depth * 0)})
.attr("cx", function(d) {return d.x})
.attr("cy", function(d) {return d.y});
var rectNumber = d3.select("#rightSVG").selectAll("rect").size();
var rectData = d3.select("#rightSVG").selectAll("rect").data();
var rectMax = d3.max(rectData, function(d) {return d.values.length});
var rightSize = canvasSize("#rightSVG");
barXScale = d3.scale.ordinal().domain(rectData.map(function(d){return d.key})).rangeBands([0, rightSize[0]]);
console.log(rectMax)
barYScale = d3.scale.linear()
.domain([0, rectMax])
.range([rightSize[1],0])
d3.select("#rightSVG")
.selectAll("rect")
.attr("x", function(d,i) {return barXScale(d.key) + 5})
.attr("width", function() {return barXScale.rangeBand() - 5})
.attr("y", function(d) {return barYScale(d.values.length)})
.style("stroke", "black")
.attr("height", function(d) {return rightSize[1] - barYScale(d.values.length)})
}
function createBar(incData,targetSVG) {
d3.select(targetSVG).selectAll("rect").data(incData)
.enter()
.append("rect")
.attr("class", "bar")
.attr("fill", "darkred")
.on("mouseover", hover)
.on("mouseout", mouseOut);
}
function createPack(incData,targetSVG) {
depthScale = d3.scale.quantize().domain([0,1,2]).range(colorbrewer.Reds[3]);
packChart = d3.layout.pack();
packChart.size([500,500])
.children(function(d) {return d.values})
.value(function(d) {return 1})
d3.select(targetSVG)
.append("g")
.attr("transform", "translate(0,0)")
.selectAll("circle")
.data(packChart(incData))
.enter()
.append("circle")
.style("fill", function(d) {return depthScale(d.depth)})
.on("mouseover", hover)
.on("mouseout", mouseOut);
}
function createSpreadsheet(incData, targetDiv) {
var keyValues = d3.keys(incData[0])
d3.select(targetDiv)
.append("div")
.attr("class", "table")
d3.select("div.table")
.append("div")
.attr("class", "head row")
.selectAll("div.data")
.data(keyValues)
.enter()
.append("div")
.attr("class", "data")
.html(function (d) {return d})
.style("left", function(d,i) {return (i * 100) + "px"});
d3.select("div.table")
.selectAll("div.datarow")
.data(incData, function(d) {return d.content}).enter()
.append("div")
.attr("class", "datarow row")
.style("top", function(d,i) {return (40 + (i * 40)) + "px"})
.on("mouseover", hover)
.on("mouseout", mouseOut);
d3.selectAll("div.datarow")
.selectAll("div.data")
.data(function(d) {return d3.entries(d)})
.enter()
.append("div")
.attr("class", "data")
.html(function (d) {return d.value})
.style("left", function(d,i,j) {return (i * 100) + "px"});
}
</script>
</footer>
</html>
{
"tweets": [
{"user": "Al", "content": "I really love seafood.", "timestamp": " Mon Dec 23 2013 21:30 GMT-0800 (PST)", "retweets": ["Raj","Pris","Roy"], "favorites": ["Sam"]},
{"user": "Al", "content": "I take that back, this doesn't taste so good.", "timestamp": "Mon Dec 23 2013 21:55 GMT-0800 (PST)", "retweets": ["Roy"], "favorites": []},
{"user": "Al", "content": "From now on, I'm only eating cheese sandwiches.", "timestamp": "Mon Dec 23 2013 22:22 GMT-0800 (PST)", "retweets": [], "favorites": ["Roy","Sam"]},
{"user": "Roy", "content": "Great workout!", "timestamp": " Mon Dec 23 2013 7:20 GMT-0800 (PST)", "retweets": [], "favorites": []},
{"user": "Roy", "content": "Spectacular oatmeal!", "timestamp": " Mon Dec 23 2013 7:23 GMT-0800 (PST)", "retweets": [], "favorites": []},
{"user": "Roy", "content": "Amazing traffic!", "timestamp": " Mon Dec 23 2013 7:47 GMT-0800 (PST)", "retweets": [], "favorites": []},
{"user": "Roy", "content": "Just got a ticket for texting and driving!", "timestamp": " Mon Dec 23 2013 8:05 GMT-0800 (PST)", "retweets": [], "favorites": ["Sam", "Sally", "Pris"]},
{"user": "Pris", "content": "Going to have some boiled eggs.", "timestamp": " Mon Dec 23 2013 18:23 GMT-0800 (PST)", "retweets": [], "favorites": ["Sally"]},
{"user": "Pris", "content": "Maybe practice some gymnastics.", "timestamp": " Mon Dec 23 2013 19:47 GMT-0800 (PST)", "retweets": [], "favorites": ["Sally"]},
{"user": "Sam", "content": "@Roy Let's get lunch", "timestamp": " Mon Dec 23 2013 11:05 GMT-0800 (PST)", "retweets": ["Pris"], "favorites": ["Sally", "Pris"]}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment