Skip to content

Instantly share code, notes, and snippets.

@robu3
Created August 2, 2013 17:07
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save robu3/6141560 to your computer and use it in GitHub Desktop.
Save robu3/6141560 to your computer and use it in GitHub Desktop.
Jawbone Up Spiral Visualization
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>
body {
font-family: sans-serif;
}
h1 {
font-size: 24px;
margin-left: 350px;
}
p {
margin-left: 300px;
font-size: 12px;
width: 400px;
}
.line {
fill: none;
stroke: #000000;
}
.point {
fill: blue;
stroke: #000;
}
.reference-point {
stroke: #000;
fill: #FFF;
fill-opacity: 0;
}
.tooltip {
visibility: hidden;
color: #000;
stroke: #000;
fill: #FFF;
stroke-width: 4px;
fill-opacity: .9;
}
.tooltip-text {
stroke: none;
fill: #000;
text-anchor: start;
font-family: sans-serif;
font-size: 14px;
}
.tooltip-title {
font-weight: bold;
font-size: 16px;
}
</style>
</head>
<body>
<h1>Jawbone Up Visualization</h1>
<p>My (in)activity over the past 30 days. Each day is a point on the spiral, with the points closest to the center being the most recent. Color indicates activity and size indicates the number of hours slept on that day.</p>
<div id="canvas"></div>
<script src="up.js"></script>
</body>
</html>
date m_active_time m_calories m_distance m_inactive_time m_lcat m_lcit m_steps m_workout_count m_workout_time s_asleep_time s_awake s_awake_time s_awakenings s_bedtime s_deep s_duration s_light s_quality
20130617 5536 736.072444384 6566 27240 1701 11640 8107 2 3962 95 4141 448 1 78 14580 20649 6069 76
20130618 1655 113.300000288 2170 29520 162 10020 2886 0 0 1438 2345 356 0 1401 14280 21481 7201 83
20130619 1721 126.421999279 2407 29220 188 3780 3114 0 0 119 1582 448 0 103 12780 19740 6960 72
20130620 1218 89.2879992612 1657 30000 205 9120 2184 0 0 110 3299 484 1 94 12384 20260 7876 70
20130621 5701 626.405809723 6388 27060 1602 8460 7948 2 4078 1416 7429 515 2 1400 15840 25920 10080 95
20130622 2621 187.760000497 3501 27720 382 6120 4635 0 0 182 1750 430 0 160 10680 15000 4320 56
20130623 2018 169.07199949 3046 30600 466 14520 3814 0 0 1429 2153 473 0 1418 15181 29160 13979 99
20130624 1503 107.459000323 2086 30720 338 6300 2715 0 0 9 3036 453 1 1433 13303 24703 11400 85
20130625 1814 126.360999916 2488 30300 276 8220 3258 0 0 68 4013 532 1 57 16230 24690 8460 89
20130626 5105 562.23639028 6155 27240 1924 13980 7576 2 3742 31 692 430 0 20 15540 24120 8580 89
20130627 1497 107.551999599 1978 29040 368 7920 2630 0 0 159 5254 543 1 138 13272 19272 6000 71
20130628 4662 605.813001946 9231 24300 2093 4680 9778 1 1927 190 3913 514 0 169 11881 19440 7559 68
20130629 5891 239.570999503 4501 24660 363 2340 5860 1 2917 91 755 495 0 80 13980 24180 10200 83
20130630 2643 194.369999349 3645 25560 329 3660 4766 0 0 125 6666 629 1 104 11760 25320 13560 80
20130701 1320 96.6280005462 1791 30480 143 5700 2352 0 0 255 2491 462 1 247 7450 10511 3061 37
20130702 1419 100.484999884 1926 30720 171 4800 2538 0 0 50 5752 554 1 39 17760 25859 8099 96
20130703 1795 125.791000623 2369 28860 234 7860 3143 0 0 64 5500 548 2 53 16221 24343 8122 88
20130704 3390 247.416999221 4610 26580 1137 4620 6054 0 0 179 5530 678 1 168 16860 25500 8640 89
20130705 5079 425.573692427 5912 29100 1661 24060 7335 2 3738 90 3232 561 1 86 10159 25459 15300 76
20130706 5281 343.028000057 6531 23700 1715 4320 8919 0 0 150 7174 573 3 133 14687 19307 4620 71
20130707 4786 654.656000763 9738 23040 2228 3240 10232 1 1938 1419 1263 513 1 1408 20639 31550 10911 100
20130708 1502 109.121000692 2053 31080 272 8400 2685 0 0 164 4069 473 2 153 12074 15291 3217 58
20130709 23402 105.160999753 1967 29880 179 8880 2611 1 22158 71 3787 567 1 67 16075 26275 10200 91
20130710 1266 91.520999182 1723 30120 203 9840 2274 0 0 91 1264 490 0 75 15240 24000 8760 87
20130711 2100 135.838000312 2567 29400 244 4620 3518 0 0 151 4170 534 1 134 14238 19986 5748 74
20130712 5308 298.472001024 5382 27900 1422 8640 6754 2 3625
20130713 1946 137.576999631 2621 26940 166 4260 3461 0 0 105 5154 596 2 101 15362 24813 9451 86
20130714 27 2.1660000384 41 18300 20 18300 52 0 0
20130715 928 66.6670001931 1227 31440 224 17160 1627 0 0
20130716 6292 180.592999429 3423 27360 384 7080 4515 1 3886 13 6485 522 2 2 15180 24935 9755 87
20130717 3289 239.090999722 4423 27360 610 4800 5842 0 0 1431 1918 425 1 1415 15481 25821 10340 93
20130718 1496 106.443999439 2022 30540 194 10500 2667 0 0 101 4197 500 2 90 11899 20520 8621 71
20130719 5526 360.946000315 6540 26040 1720 4680 8201 2 3633 3 5182 543 1 1418 15961 28981 13020 100
20130720 78 6.4430000372 111 26640 37 20460 144 0 0 236 4665 794 2 224 21060 29700 8640 100
20130721 1846 133.220000178 2487 26940 210 7260 3277 0 0
20130722 3762 298.082999837 5498 21900 786 2580 6984 0 0
20130723 1731 126.228999734 2339 29700 155 4920 3080 0 0 1426 916 445 0 1415 16983 27540 10557 100
20130724 1045 75.4680002183 1419 31380 174 22680 1868 0 0 4 830 443 0 1433 13980 26460 12480 91
20130725 3179 204.916999795 3649 28140 1627 8640 4549 1 2014 95 5494 544 1 84 14289 22149 7860 81
20130726 1706 131.128999341 2419 30000 441 10020 3133 0 0
20130727 3826 268.222999323 4971 23700 1168 2760 6644 0 0 211 4676 610 1 205 12510 19748 7238 66
20130728 4786 637.933998216 9537 22620 2054 2700 10080 1 1900 74 2757 501 1 51 13920 24434 10514 83
/*global d3*/
// global app variable
var up = {
width: 960,
height: 700
};
// ## loadData(rows)
// Loads the data into the chart
function loadData(rows) {
rows = rows.reverse();
console.log(rows);
var maxSteps,
maxSleep,
goalSteps = 10000, // 一日万歩
goalSleep = 28800,
minRadius = 2,
radius = 25,
svg = d3.select("svg"),
colorScale;
// find upper bounds of steps and sleep
maxSteps = d3.max(rows, function (r) {
return parseInt(r.m_steps);
});
maxSleep = d3.max(rows, function (r) {
return parseInt(r.s_duration);
});
var s = goalSteps / 5;
colorScale = d3.scale.linear()
.domain([s, s * 2, s * 3, s * 4, goalSteps])
.range(["#3333FF", "#9933FF", "#FF33FF", "#FF3399", "#FF3333"]);
// draw reference circles / points
svg.selectAll("circle.reference-point")
.attr("r", radius);
// color and size data points
var rSleep = (radius - minRadius) / goalSleep;
svg.selectAll("circle.datapoint")
.data(rows)
.attr("class", "point")
.attr("r", function (d) { return minRadius + d.s_duration * rSleep; })
.attr("style", function (d) {
return "fill: " + colorScale(d.m_steps);
});
}
// ## generateSpiral
// Archimedean spiral
// in polar coords: r = a + b * (theta)
function generateSpiral(width, points, step) {
var a = 0,
i,
x,
y,
r,
theta,
buffer = [];
// initialize
points = points || 10;
step = step || Math.PI * 0.25;
for (i = 0; i < points; i++) {
theta = step * i;
r = a + width * theta;
x = r * Math.cos(theta);
y = r * Math.sin(theta);
buffer.push({ x: x, y: y });
}
return buffer;
}
// ## drawSpiral()
// Draws the spiral and data points that make up the graph
function drawSpiral() {
var step = Math.PI * .05,
points = generateSpiral(22, 100, step),
i,
x = up.width / 2,
y = up.height / 2,
svg = d3.select("#canvas")
.append("svg")
.attr("width", up.width)
.attr("height", up.height),
line = d3.svg.line()
.x(function (d) { return x + d.x; })
.y(function (d) { return y + d.y; })
.interpolate("cardinal"),
// connect dots
spiral = svg.append("path")
.datum(points)
.attr("class", "line")
.attr("d", line),
// simple tooltip
tooltip = svg
.append("g")
.attr("class", "tooltip");
// add rectangle
tooltip.append("rect")
.attr("width", 125)
.attr("height", 70)
.attr("rx", 5)
.attr("ry", 5);
// add text elements for tooltip
var tooltipTextTop = tooltip
.append("text")
.attr("x", 5)
.attr("y", 40)
.attr("class", "tooltip-text"),
tooltipTextBottom = tooltip
.append("text")
.attr("x", 5)
.attr("y", 60)
.attr("class", "tooltip-text"),
tooltipTextTitle = tooltip
.append("text")
.attr("x", 5)
.attr("y", 20)
.attr("class", "tooltip-text tooltip-title");
// draw points
for (i = 0; i < points.length; i++) {
// skip points because they are bunched together at the beginning of the spiral
// the first entire revolution is skipped
if (i * step < Math.PI * 2) {
continue;
}
// use every other spiral vertex as a data point position
if (i % 2 > 0) {
continue;
}
// add data point circle
svg.insert("circle", ".tooltip")
.attr("class", "datapoint")
.attr("r", 0)
.attr("cx", x + points[i].x)
.attr("cy", y + points[i].y)
.on("mouseover", function (d) {
var me = d3.select(this),
x = parseFloat(me.attr("cx")) + parseFloat(me.attr("r")) + 10,
y = parseFloat(me.attr("cy")) - parseFloat(tooltip.select("rect").attr("height")) / 2;
// set tooltip text
tooltipTextTitle
.text(d.date.substring(4, 6) + "/" + d.date.substring(6, 8) + "/" + d.date.substring(0, 4))
.style("fill", me.style("fill"));
tooltipTextTop.text("Steps: " + parseInt(d.m_steps).toLocaleString());
tooltipTextBottom.text("Sleep: " + parseFloat(d.s_duration / 3600).toFixed(2) + " hours");
return tooltip
.style("visibility", "visible")
.attr("transform", "translate(" + x + "," + y + ")")
.select("rect")
.style("stroke", me.style("fill"));
})
.on("mouseout", function (d) {
return tooltip.style("visibility", "hidden");
});
}
}
function bootstrap() {
// draw the spiral
drawSpiral();
d3.csv("up-data.csv", function (rows) {
loadData(rows);
});
}
bootstrap();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment