Skip to content

Instantly share code, notes, and snippets.

@bigarabuza
Last active January 11, 2021 18:25
Show Gist options
  • Save bigarabuza/3fc12643286ee7acda76bd9d96d89635 to your computer and use it in GitHub Desktop.
Save bigarabuza/3fc12643286ee7acda76bd9d96d89635 to your computer and use it in GitHub Desktop.

D3 Introduction Project

This is my first foray into D3. This project was to try out the fundamentals of the library that I have learnt so far.

Activity Type Date Favorite Title Distance Calories Time Avg Run Cadence Max Run Cadence Avg Pace Best Pace Elev Gain Elev Loss Avg Stride Length Avg Vertical Ratio Avg Vertical Oscillation Training Stress Score® Grit Flow Climb Time Bottom Time Min Temp Surface Interval Decompression Best Lap Time Number of Laps Max Temp
Running 2021-01-05 14:55:56 false Philadelphia Running 3.16 416 00:22:18 177 219 7:03 4:14 39 39 1.29 0.0 0.0 0.0 0.0 0.0 22:18 0:00 0.0 0:00 No 01:12.72 4 0.0
Running 2021-01-03 16:44:58 false Philadelphia Running 3.21 410 00:23:11 177 219 7:13 5:09 39 39 1.26 0.0 0.0 0.0 0.0 0.0 23:11 0:00 0.0 0:00 No 01:30.39 4 0.0
Running 2021-01-01 09:19:52 false Philadelphia Running 3.22 407 00:22:57 177 189 7:08 6:15 39 39 1.27 0.0 0.0 0.0 0.0 0.0 22:57 0:00 0.0 0:00 No 01:44.48 4 0.0
Running 2020-12-30 14:09:31 false Philadelphia Running 3.17 398 00:22:45 177 204 7:10 4:46 39 39 1.27 0.0 0.0 0.0 0.0 0.0 22:45 0:00 0.0 0:00 No 01:10.96 4 0.0
Running 2020-12-28 08:26:15 false Philadelphia Running 3.19 402 00:22:39 177 188 7:07 6:00 40 39 1.28 0.0 0.0 0.0 0.0 0.0 22:39 0:00 0.0 0:00 No 01:15.73 4 0.0
Running 2020-12-26 15:43:34 false Randolph Running 2.22 288 00:17:48 171 184 8:01 6:13 334 314 1.18 0.0 0.0 0.0 0.0 0.0 17:48 0:00 0.0 0:00 No 01:54.44 3 0.0
Running 2020-12-23 09:31:19 false Philadelphia Running 3.23 406 00:23:14 176 191 7:12 5:48 37 37 1.27 0.0 0.0 0.0 0.0 0.0 23:14 0:00 0.0 0:00 No 01:32.19 4 0.0
Running 2020-12-21 14:32:10 false Philadelphia Running 5.12 641 00:37:22 176 204 7:17 4:14 56 59 1.26 0.0 0.0 0.0 0.0 0.0 37:22 0:00 0.0 0:00 No 00:58.91 6 0.0
Running 2020-12-14 08:41:27 false Philadelphia Running 3.17 407 00:23:26 177 186 7:24 5:33 39 39 1.23 0.0 0.0 0.0 0.0 0.0 23:26 0:00 0.0 0:00 No 01:17.66 4 0.0
Running 2020-12-12 20:23:13 false Philadelphia Running 6.00 786 00:44:03 177 185 7:21 2:09 93 93 1.24 0.0 0.0 0.0 0.0 0.0 44:03 0:00 0.0 0:00 No 07:04.90 6 0.0
Running 2020-12-10 12:53:41 false Philadelphia Running 3.20 408 00:23:06 177 187 7:13 5:44 39 39 1.26 0.0 0.0 0.0 0.0 0.0 23:06 0:00 0.0 0:00 No 01:26.12 4 0.0
Running 2020-12-08 14:36:13 false Philadelphia Running 3.23 418 00:23:28 175 190 7:16 4:55 39 39 1.26 0.0 0.0 0.0 0.0 0.0 23:28 0:00 0.0 0:00 No 01:32.26 4 0.0
Running 2020-12-06 14:16:50 false Philadelphia Running 6.14 793 00:45:17 176 197 7:23 5:01 76 76 1.24 0.0 0.0 0.0 0.0 0.0 45:17 0:00 0.0 0:00 No 00:55.45 7 0.0
Running 2020-12-04 08:19:20 false Philadelphia Running 3.26 426 00:22:50 176 219 7:01 5:25 39 39 1.30 0.0 0.0 0.0 0.0 0.0 22:50 0:00 0.0 0:00 No 01:47.71 4 0.0
Running 2020-12-01 08:23:48 false Philadelphia Running 3.19 414 00:23:08 175 185 7:15 5:33 43 43 1.27 0.0 0.0 0.0 0.0 0.0 23:08 0:00 0.0 0:00 No 01:18.93 4 0.0
Running 2020-11-29 09:10:41 false Philadelphia Running 3.29 421 00:23:00 176 184 7:00 4:51 38 37 1.31 0.0 0.0 0.0 0.0 0.0 23:00 0:00 0.0 0:00 No 02:00.00 4 0.0
Running 2020-11-28 11:02:31 false Philadelphia Running 3.20 410 00:22:32 176 187 7:03 5:24 39 38 1.30 0.0 0.0 0.0 0.0 0.0 22:32 0:00 0.0 0:00 No 01:20.88 4 0.0
Running 2020-11-25 16:14:51 false Philadelphia Running 3.24 414 00:22:55 175 184 7:04 5:51 38 37 1.30 0.0 0.0 0.0 0.0 0.0 22:55 0:00 0.0 0:00 No 01:44.01 4 0.0
Running 2020-11-23 12:15:44 false Philadelphia Running 3.40 425 00:23:10 177 184 6:49 2:27 40 39 1.34 0.0 0.0 0.0 0.0 0.0 23:10 0:00 0.0 0:00 No 02:50.47 4 0.0
Running 2020-11-22 09:12:00 false Philadelphia Running 3.18 408 00:22:50 177 185 7:10 5:06 39 39 1.27 0.0 0.0 0.0 0.0 0.0 22:50 0:00 0.0 0:00 No 01:19.92 4 0.0
Running 2020-11-20 08:33:36 false Philadelphia Running 3.19 414 00:22:49 177 185 7:09 4:55 42 42 1.27 0.0 0.0 0.0 0.0 0.0 22:49 0:00 0.0 0:00 No 01:22.43 4 0.0
Running 2020-11-16 07:50:14 false Philadelphia Running 3.15 405 00:23:03 175 184 7:19 5:15 38 38 1.26 0.0 0.0 0.0 0.0 0.0 23:03 0:00 0.0 0:00 No 01:04.64 4 0.0
Running 2020-11-15 08:48:35 false Philadelphia Running 4.13 535 00:30:13 175 184 7:19 4:36 56 53 1.25 0.0 0.0 0.0 0.0 0.0 30:13 0:00 0.0 0:00 No 00:52.73 5 0.0
Running 2020-11-11 05:22:16 false Philadelphia Running 3.25 421 00:23:16 176 182 7:09 4:00 42 42 1.28 0.0 0.0 0.0 0.0 0.0 23:16 0:00 0.0 0:00 No 01:45.78 4 0.0
Running 2020-11-08 06:42:24 false Philadelphia Running 3.11 404 00:22:52 175 184 7:21 4:58 43 43 1.25 0.0 0.0 0.0 0.0 0.0 22:52 0:00 0.0 0:00 No 00:47.50 4 0.0
Running 2020-11-05 18:02:59 false Philadelphia Running 3.24 401 00:23:12 172 192 7:10 4:39 39 39 1.30 0.0 0.0 0.0 0.0 0.0 23:12 0:00 0.0 0:00 No 01:43.05 4 0.0
Running 2020-11-04 19:22:32 false Philadelphia Running 3.21 423 00:23:16 175 183 7:15 5:31 35 35 1.27 0.0 0.0 0.0 0.0 0.0 23:16 0:00 0.0 0:00 No 01:30.16 4 0.0
Running 2020-10-31 10:39:49 false Philadelphia Running 4.16 544 00:30:36 179 186 7:21 6:03 19 27 1.22 0.0 0.0 0.0 0.0 0.0 30:36 0:00 0.0 0:00 No 01:10.48 5 0.0
Running 2020-10-24 06:36:49 false Randolph Running 3.29 407 00:27:52 169 224 8:28 6:47 500 474 1.12 0.0 0.0 0.0 0.0 0.0 27:52 0:00 0.0 0:00 No 02:38.74 4 0.0
Running 2020-10-19 05:29:01 false Philadelphia Running 3.15 419 00:23:19 177 186 7:24 6:09 42 38 1.23 0.0 0.0 0.0 0.0 0.0 23:19 0:00 0.0 0:00 No 01:06.94 4 0.0
Running 2020-10-18 07:51:27 false Philadelphia Running 3.22 419 00:23:35 177 183 7:20 6:08 41 41 1.24 0.0 0.0 0.0 0.0 0.0 23:35 0:00 0.0 0:00 No 01:32.29 4 0.0
Running 2020-10-09 08:27:18 false Philadelphia Running 3.16 402 00:22:53 177 189 7:15 6:05 38 38 1.25 0.0 0.0 0.0 0.0 0.0 22:53 0:00 0.0 0:00 No 01:01.55 4 0.0
Running 2020-10-06 05:21:07 false Philadelphia Running 3.15 403 00:22:34 177 184 7:10 4:24 38 39 1.27 0.0 0.0 0.0 0.0 0.0 22:34 0:00 0.0 0:00 No 01:01.15 4 0.0
Running 2020-10-03 13:59:53 false Philadelphia Running 3.15 394 00:22:12 175 185 7:02 4:47 43 43 1.31 0.0 0.0 0.0 0.0 0.0 22:12 0:00 0.0 0:00 No 01:01.88 4 0.0
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link href="style.css" rel="stylesheet" />
<script type="text/javascript" src="https://d3js.org/d3.v5.min.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"
integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ=="
crossorigin="anonymous"
></script>
<script>
moment().format();
</script>
<title>Running Data Viz</title>
</head>
<body>
<script type="text/javascript">
"use strict";
const w = 500,
h = 300,
marginW = 50,
marginH = 30;
let svg = d3
.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
const xScale = d3.scaleTime().range([marginW, w - marginW]);
const yScale = d3.scaleLinear().range([h - marginH, marginH]);
const formatDate = d3.timeFormat("%b %e");
const xAxis = d3
.axisBottom(xScale)
.tickFormat(function (d) {
return formatDate(d);
})
.tickSize(h - marginH * 2 + 10)
.tickPadding(2);
const yAxis = d3
.axisLeft(yScale)
.tickFormat(function (d) {
return moment.utc(d).format("mm:ss");
})
.tickSize(w - marginW * 2 + 10)
.tickPadding(2);
// Data set-up
const data = {};
const parseDate = d3.timeParse("%Y-%m-%d %H:%M:%S");
const regexpTime = /([0-9]+):([0-9]+)/;
let rowConverter = function (d) {
let matchedTimeGrps = d["Avg Pace"].match(regexpTime);
return {
Date: parseDate(d["Date"]),
Pace: moment.duration({
minutes: matchedTimeGrps[1],
seconds: matchedTimeGrps[2],
}),
};
};
d3.csv("garmin_download.csv", rowConverter).then(function (dataset) {
data.runs = dataset;
xScale.domain(d3.extent(dataset, (d) => d.Date));
yScale.domain(d3.extent(dataset, (d) => d.Pace));
drawAxes();
drawPoints();
drawTooltips();
drawTitle();
});
function drawPoints() {
d3.select("svg")
.selectAll("circle")
.data(data.runs)
.enter()
.append("circle")
.attr("cx", (d) => xScale(d.Date))
.attr("cy", (d) => yScale(d.Pace))
.attr("r", 2)
.on("mouseenter", showDetails)
.on("mouseleave", clearDetails);
}
function drawAxes() {
//Axes
const xG = d3
.select("svg")
.append("g")
.attr("class", "x-axis")
.attr("transform", `translate(${[0, marginH]})`)
.call(xAxis);
const yG = d3
.select("svg")
.append("g")
.attr("class", "y-axis")
.attr("transform", `translate(${[w - marginW, 0]})`)
.call(yAxis);
//Labels to axes
d3.select("svg")
.append("text")
.attr("class", "label")
.text("Date")
.attr("transform", `translate(${[w / 2, h - 1]})`);
d3.select("svg")
.append("text")
.attr("class", "label")
.text("Pace (min/mi)")
.attr("transform", `translate(${[1, h / 2]}) rotate(90)`);
}
function drawTooltips() {
const tooltip = d3
.select("svg")
.append("g")
.attr("class", "tooltip")
.attr("opacity", 0);
tooltip
.append("rect")
.attr("width", 80)
.attr("height", 45)
.attr("rx", 3)
.attr("ry", 3)
.attr("x", -3)
.attr("y", -2);
tooltip.append("text").attr("class", "dt").attr("y", 15);
tooltip.append("text").attr("class", "pace").attr("y", 30);
}
function showDetails(d) {
d3.select(this).attr("r", 4);
d3.select(".tooltip")
.attr("opacity", 1)
.attr(
"transform",
`translate(${[10 + xScale(d.Date), yScale(d.Pace) - 20]})`
);
const text1 = d3
.select(".tooltip .dt")
.text("Date: " + formatDate(d.Date));
const text2 = d3
.select(".tooltip .pace")
.text("Pace: " + moment.utc(d.Pace.asMilliseconds()).format("mm:ss"));
const boxWidth =
6 +
d3.max([
text1.node().getComputedTextLength(),
text2.node().getComputedTextLength(),
]);
d3.select(".tooltip rect").attr("width", boxWidth);
}
function clearDetails(d) {
d3.select(this).attr("r", 2);
d3.select(".tooltip").attr("opacity", 0);
}
function drawTitle() {
d3.select("svg")
.append("text")
.attr("transform", `translate(${[w / 2, marginH - 10]})`)
.style("text-anchor", "middle")
.style("font-size", "16px")
.text("Past 3 Month Runs");
}
</script>
</body>
</html>
text {
font-family: "Yanone Kaffeesatz", "Arial Narrow", sans-serif;
font-size: 7pt;
}
.label {
font-size: 9pt;
text-anchor: middle;
}
.domain {
opacity: 0;
}
.y-axis line,
.x-axis line {
stroke-width: 0.25;
stroke: rgba(114, 138, 74, 0.5);
}
.tooltip {
pointer-events: none;
}
.tooltip rect {
fill: #eee;
fill-opacity: 0.8;
stroke: gray;
stroke-opacity: 0.5;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment