Skip to content

Instantly share code, notes, and snippets.

@scameron
Created March 2, 2012 06:44
Show Gist options
  • Save scameron/1956297 to your computer and use it in GitHub Desktop.
Save scameron/1956297 to your computer and use it in GitHub Desktop.
Sparkline in table.
<!DOCTYPE html>
<html>
<head>
<title>Animated Sparkline</title>
<script src="http://bost.ocks.org/mike/d3.v2.min.js"></script>
<style type="text/css">
svg {
display: block;
position: relative;
}
path {
stroke: steelblue;
stroke-width: 1;
fill: none;
}
circle {
fill: red;
stroke: white;
stroke-width: .75;
}
#settings {
border: 1px solid;
margin: 30px 0px 0px 30px;
padding: 10px;
width: 270px;
float:left
}
#refreshbutton {
margin: 30px 0px 20px;
width: 50%;
height: 188px;
float:left;
}
#main {
margin: 10px 30px;
float: left;
}
input {
margin: 3px 10px;
width: 60px;
}
label {
width: 180px;
display: inline-block;
}
button {
margin: 10px 0px 5px 0px;
}
button#refresh {
margin: 0px 0px 0px 30px;
}
hr {
width: 75%;
height: 1px;
border-width: 0;
background-color: gray;
margin-left: 30px;
}
table {
border: 1px solid #BBB;
border-collapse: collapse;
}
#vizCol {
width: 500px;
}
table th {
padding: 5px;
border: 1px solid #BBB;
background: #EEE;
}
table td {
padding: 5px;
border: 1px solid #BBB;
height: 50px;
}
</style>
<script type="text/javascript">
var duration = 5000;
var ballRadius = 2;
var rowCount = 10, values = 60;
var data = new Array();
var graphs; // Holds the sparklines themselves
var line;
function generateData() {
data.length = 0;
for (var i = 0; i < rowCount; i++ ) {
data.push(new Array());
for (var j = 0; j < values; j++) {
data[i].push(Math.round(Math.random() * 10));
}
}
}
function refreshLines() {
d3.select("table tbody").selectAll("tr")
.data(data)
.selectAll("path")
.data(function(d) { return [d]; })
.transition()
.duration(duration / 2)
.ease("linear")
.attr("d", line);
}
function refresh() {
generateData();
refreshLines();
}
function draw() {
generateData();
var rows = d3.select("table tbody").selectAll("tr")
.data(data)
.enter().append("tr");
rows.selectAll("td.column1")
.data(function(d, i) { return [i]; })
.enter().append("td")
.attr("class", "column1")
.text(function(d) { return d+1; });
var cellHeight = 0, cellWidth = 0;
graphs = rows.selectAll("td.column2")
.data(function(d) { return [d]; })
.enter().append("td")
.attr("class", "column2")
.each(function() {
cellHeight = this.clientHeight;
cellWidth = this.clientWidth;
})
.append("svg")
.attr("height", cellHeight)
.attr("width", cellWidth);
var x = d3.scale.linear().domain([0, 1]).range([0, cellWidth / (data[0].length-1)]);
// take ball radius into account so it doesn't dip below or above the visible area
var y = d3.scale.linear().domain([0, 10]).range([ballRadius, cellHeight - ballRadius]);
line = d3.svg.line()
.interpolate("linear")
.x(function(d,i) { return x(i); })
.y(function(d) { return cellHeight - y(d); });
graphs.append("clipPath")
.attr("id", function(d, i, j) { return "clippy" + j; })
.append("rect");
var path = graphs.append("g")
.attr("clip-path", function(d, i, j) { return "url(#clippy" + j + ")"; })
.selectAll("path")
.data(function(d) { return [d]; })
.enter().append("path")
.attr("class", "path")
.attr("d", line);
var y_start = y(data[0][0]);
var circle = graphs.append("circle")
.attr("class", "circle")
.attr("cy", y_start)
.attr("r", ballRadius);
graphs.selectAll("rect").attr("height", cellHeight);
var currentX = new Array(rows);
var transition = d3.transition()
.duration(duration)
.ease("linear");
transition.selectAll("rect")
.attrTween("width", function(d, i) {
return function(t) {
return currentX[i];
};
});
transition.selectAll("circle")
.attrTween("transform", function(d, i) {
return function(t) {
return followPath(path[i][0], t, i);
};
})
.each("end", function() { this.style.visibility = "hidden"; });
function followPath(pathElement, t, i) {
var l = pathElement.getTotalLength();
var p = pathElement.getPointAtLength(t * l);
currentX[i] = p.x;
return "translate(" + p.x + ", " + (p.y - y_start) + ")";
}
}
function redraw() {
rowCount = inputRowCount.value;
values = inputNumValues.value;
duration = inputDuration.value * 1000;
updateStyles(inputWidth.value, inputHeight.value);
d3.select("table tbody").selectAll("tr").remove();
draw();
}
function redrawOnEnter(e) {
// look for window.event in case event isn't passed in
if (typeof e == 'undefined' && window.event) { e = window.event; }
if (e.keyCode == 13)
{
document.getElementById("redraw").click();
}
}
function updateStyles(w, h) {
var theRules = new Array();
if (document.styleSheets[0].cssRules) {
theRules = document.styleSheets[0].cssRules
}
else if (document.styleSheets[0].rules) { // IE uses rules not cssRules
theRules = document.styleSheets[0].rules
}
for (var i = 0; i < theRules.length; i++) {
if ( theRules[i].selectorText.toLowerCase()=="#vizcol" ) {
theRules[i].style.width = w + "px";
}
else if ( theRules[i].selectorText.toLowerCase()=="table td" ) {
theRules[i].style.height = h + "px";
}
}
}
</script>
</head>
<body>
<div id="settings">
<label for="inputRowCount">Number of Rows: </label><input id="inputRowCount" type="text" value="10" onkeypress="redrawOnEnter(event)"></br>
<label for="inputNumValues">Number of Values: </label><input id="inputNumValues" type="text" value="60" onkeypress="redrawOnEnter(event)"></br>
<label for="inputWidth">Cell Width (px): </label><input id="inputWidth" type="text" value="500" onkeypress="redrawOnEnter(event)"></br>
<label for="inputHeight">Cell Height (px): </label><input id="inputHeight" type="text" value="50" onkeypress="redrawOnEnter(event)"></br>
<label for="inputDuration">Time to Draw (sec): </label><input id="inputDuration" type="text" value="5" onkeypress="redrawOnEnter(event)"></br>
<button id="redraw" onclick="redraw();">Redraw Table</button><br/>
</div>
<div id="refreshbutton">
<button id="refresh" onclick="refresh();">Refresh Data</button>
</div>
<hr>
<div id="main">
<table>
<colgroup>
<col/>
<col id="vizCol"/>
</colgroup>
<thead>
<tr>
<th>Description</th>
<th>Visualization</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<script>
draw();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment