Skip to content

Instantly share code, notes, and snippets.

@waharnum
Last active August 29, 2015 14:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save waharnum/e9e8d710bcc55304a380 to your computer and use it in GitHub Desktop.
Save waharnum/e9e8d710bcc55304a380 to your computer and use it in GitHub Desktop.
Pie chart + table example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Pie layout</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<style type="text/css">
svg text {
font-family: sans-serif;
font-size: 12px;
fill: white;
}
svg g:focus,
svg g:hover
{
outline:none;
}
svg g:hover path,
svg g:focus path,
svg g.matched path
{
fill: black;
}
table tr:hover td,
table tr:focus td,
table tr.matched td {
background-color:black;
color: white;
}
</style>
</head>
<body>
<p id="add">
Click to add.
</p>
<p id="subtract">
Click to subtract.
</p>
<script type="text/javascript">
var randomInteger = function(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
//Width and height
var w = 500;
var h = 500;
var dataset = [
{label: "iPhone", value: 400},
{label: "Android", value: 370},
{label: "Windows Phone", value: 25},
{label: "Blackberry", value:87}
];
// Label-based key function
var key = function(d) {
return d.label;
};
var findMatchingSliceByLabel = function(matchLabel, selector) {
de = d3.selectAll(selector).filter(function (d) {
if(matchLabel == d.data.label) return true;
});
return de;
}
var findMatchingRowByLabel = function(matchLabel, selector) {
de = d3.selectAll(selector).filter(function (d) {
if(matchLabel == d.label) return true;
});
return de;
}
var outerRadius = w / 2;
var innerRadius = 0;
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var pie = d3.layout.pie()
.value(function(d) { return d.value });
//Easy colors accessible via a 20-step ordinal scale
var color = d3.scale.category20();
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create table element
var table = d3.select("body")
.append("table")
.append("tbody");
//Set up groups
var arcs = svg.selectAll("g.arc")
.data(pie(dataset, key))
.enter()
.append("g")
.on("mouseover", function(d,i) {
elem = findMatchingRowByLabel(d3.select(this).data()[0].data.label, "table tbody tr")
.classed("matched",true);
})
.on("mouseout", function(d,i) {
elem = findMatchingRowByLabel(d3.select(this).data()[0].data.label, "table tbody tr")
.classed("matched",false);
})
.attr("tabindex", function(d,i) {
return i;
})
.attr("class", "arc")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");
//Set up table
var rows = table.selectAll("tbody tr")
.data(dataset, key)
.enter()
.append("tr")
.on("mouseover", function(d,i) {
findMatchingSliceByLabel(d3.select(this).data()[0].label, "svg g.arc")
.classed("matched", true);
})
.on("mouseout", function(d,i) {
findMatchingSliceByLabel(d3.select(this).data()[0].label, "svg g.arc")
.classed("matched", false);
})
.html(function(d, i) {
return "<td>"+d.label+"</td>"+
"<td>"+d.value+"</td>"+
"<td style='background-color:"+color(i)+";'>&nbsp;&nbsp;&nbsp;&nbsp;</td>";
});
//Draw arc paths
arcs.append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
//Labels
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d) {
// return d.data.label;
return d.value;
});
d3.selectAll("p")
.on("click", function() {
paragraphId = this.id;
if(paragraphId == "add") {
newValue = {label: "Random Phone Brand #"+randomInteger(1000,50000), value: randomInteger(50,600)};
// newValue = randomInteger(0,30);
dataset.push(newValue);
} else if(paragraphId == "subtract") {
dataset.pop();
}
var arcs = svg.selectAll("g.arc")
.data(pie(dataset, key));
arcs.select("path")
.attr("d", arc);
arcs.select("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
var newArcs = arcs.enter()
.append("g")
.attr("tabindex", function(d,i) {
return i;
})
.on("mouseover", function(d,i) {
elem = findMatchingRowByLabel(d3.select(this).data()[0].data.label, "table tbody tr")
.classed("matched",true);
})
.on("mouseout", function(d,i) {
elem = findMatchingRowByLabel(d3.select(this).data()[0].data.label, "table tbody tr")
.classed("matched",false);
})
.attr("class", "arc")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");
newArcs.append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc)
newArcs.append("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d) {
// return d.data.label;
return d.value;
});
var removedArcs = arcs.exit()
.remove("g");
var rows = table.selectAll("tbody tr")
.data(dataset,key);
var newRows = rows.enter()
.append("tr")
.on("mouseover", function(d,i) {
findMatchingSliceByLabel(d3.select(this).data()[0].label, "svg g.arc")
.classed("matched", true);
})
.on("mouseout", function(d,i) {
findMatchingSliceByLabel(d3.select(this).data()[0].label, "svg g.arc")
.classed("matched", false);
})
.html(function(d, i) {
return "<td>"+d.label+"</td>"+
"<td>"+d.value+"</td>"+
"<td style='background-color:"+color(i)+";'>&nbsp;&nbsp;&nbsp;&nbsp;</td>";
});
var removedRows = rows.exit()
.remove("tr");
});
// Returns an attrTween for translating along the specified path element.
function translateAlong(path) {
var l = path.getTotalLength();
return function(d, i, a) {
return function(t) {
var p = path.getPointAtLength(t * l);
return "translate(" + (p.y+outerRadius) + "," + (p.x+outerRadius) + ")";
};
};
}
// Draw circular path around pie chart, for player-positioning purposes
var radians = 2 * Math.PI;
var points = 50;
var angle = d3.scale.linear()
.domain([0, points-1])
.range([0, radians]);
var line = d3.svg.line.radial()
.interpolate("cardinal-closed")
.tension(1)
.radius(outerRadius)
.angle(function(d, i) { return angle(i); });
var path = svg.append("path").datum(d3.range(points))
.attr("class", "line")
.attr("d", line)
.attr("stroke", "black")
.attr("stroke-width", 5)
.attr("fill-opacity", 0)
.attr("transform", "translate(" + (outerRadius) + ", " + (outerRadius) + ")")
;
var circle = svg.append("circle")
.attr("r", 13)
.attr("fill", "red")
.attr("transform", "translate(0,250)");
function transition() {
circle.transition()
.delay(500)
.duration(15000)
.attrTween("transform", translateAlong(path.node()))
.each("end", transition);
}
transition();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment