Skip to content

Instantly share code, notes, and snippets.

@jlkeiper
Last active August 29, 2015 14:16
Show Gist options
  • Select an option

  • Save jlkeiper/23c4cf255dc98f4042d4 to your computer and use it in GitHub Desktop.

Select an option

Save jlkeiper/23c4cf255dc98f4042d4 to your computer and use it in GitHub Desktop.
complex D3 axes
@font-face {
font-family: 'FontAwesome';
/* src: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/85568/fontawesome-webfont.woff'); */
font-weight: normal;
font-style: normal;
}
html, body {
min-width: 100%;
min-height: 100vh;
padding: 0;
margin: 0;
font-family: 'FontAwesome'; /* "Source Sans Pro"; */
font-weight: 300;
}
body {
// get on the unprefixed train, Safari.
display: -webkit-flex;
-webkit-justify-content: center;
-webkit-align-items: center;
-webkit-flex-direction: column;
// Yay chrome and FF.
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
h1, p {
max-width: 30rem;
font-weight: 300;
}
p {
margin-bottom: 0.5rem;
line-height: 1.5rem;
}
code {
font-family: "Source Code Pro";
background: #f5f5f5;
font-size: 0.9em;
}
svg {
flex-grow: 0;
flex-shrink: 0;
height: 100px;
width: 700px;
margin-top: 1rem;
}
.axis {
// default styling
fill: none;
path, line {
shape-rendering: crispEdges;
stroke: #eee;
stroke-width: 1;
}
// Labels
text {
opacity: 0;
}
&.labeled text {
opacity: 1;
}
&.hours text {
fill: #ccc;
font-size: 1rem;
font-family: "FontAwesome";
}
&.days text {
fill: #999;
font-size: 0.9rem;
text-transform: uppercase;
}
// strokes for the two days axes
&.days {
path, line { stroke: #ccc; }
// don't draw strokes for the labeled axis
&.labeled {
path, line { stroke: none; }
}
}
.nighttime {
fill: darken(#2980b9, 10%);
fill-opacity: 0.25;
}
.daytime {
fill: #f1c40f;
fill-opacity: 0.15;
}
}
<!DOCTYPE html>
<html>
<body>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link href = "axis.css" rel = "stylesheet" type = "text/css"/>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script type="text/javascript" src="http://momentjs.com/downloads/moment.min.js"></script>
<script type="text/javascript" src="http://papaparse.com/resources/js/papaparse.js"></script>
<script type="text/javascript" src="timeline.js"></script>
</body>
</html>
var daysLabelsAxis, daysTickmarksAxis, end, height, hoursAxis, hoursTickSpacing, hoursg, start, svg, timescale, width;
var sun = '\uf185';
var moon = '\uf186';
width = 700;
height = 100;
function prepareAxis() {
start = moment().min(records.time);
start = start.startOf('day');
end = moment(start).add('days', 7);
timescale = d3.time.scale().nice(d3.time.day).domain([start.toDate(), end.toDate()]).range([0, width - 1]);
// hours axis
hoursAxis = d3.svg.axis().scale(timescale).orient('bottom').ticks(d3.time.hour, 3).tickPadding(6).tickSize(8).tickFormat(function (d) {
var hours;
hours = d.getHours();
if (hours === 6) {
return sun;
} else if (hours === 18) {
return moon;
} else {
return null;
}
});
// day axis
daysLabelsAxis = d3.svg.axis().scale(timescale).orient('bottom').ticks(d3.time.hour, 12).tickSize(0).tickPadding(36).tickFormat(function (d) {
var formatter;
if (d.getHours() === 12) {
if (d.getDate() === 1 || moment(d).isSame(start, 'day')) {
formatter = d3.time.format.utc('%a %d %b');
} else {
formatter = d3.time.format.utc('%a %d');
}
return formatter(d);
} else {
return null;
}
});
svg = d3.select('body').append('svg').attr('width', width).attr('height', height);
// hours axis
hoursg = svg.append('g').classed('axis', true).classed('hours', true).classed('labeled', true).attr("transform", "translate(0.5,0.5)").call(hoursAxis);
hoursTickSpacing = timescale(moment(start).add('hours', 3).toDate()) - timescale(start.toDate());
// hours axis
hoursg.selectAll('g.tick').insert('rect', ':first-child').attr('class', function (d, i) {
var hours;
hours = d.getHours();
if (hours < 6 || hours >= 18) {
return 'nighttime';
} else {
return 'daytime';
}
}).attr('x', 0).attr('width', hoursTickSpacing).attr('height', 4);
}
var parseDate = d3.time.format("%d-%m-%Y %H:%M").parse;
function inputData(d) {
d.time = parseDate(d.time);
d.weekhour = parseFloat(d.weekhour);
return d;
}
var x = d3.scale.linear()
.domain([0, 168])
.range([5, width]);
var y = d3.scale.ordinal()
.rangeRoundBands([height, 0], 0.3);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var colorOf = d3.scale.category10();
var records;
var results = Papa.parse("timeseries.csv", {
header : true,
download : true, // is needed even for local files as this interprets the input value as a path instead of simply the data
dynamicTyping : true,
delimiter : ",",
skipEmptyLines : true,
complete : function (results) {
records = results.data;
records.forEach(function (d) {
d.time = parseDate(d.time);
d.time = moment(d.time);
});
y.domain(records.map(function (d) {
return d.type;
}));
x.domain(d3.extent(records, function (d) {
return d.time;
}));
colorOf.domain(records.map(function (d) {
return d.type;
}));
prepareAxis();
visualizeData();
}
});
function visualizeData() {
// day tickmarks axis
daysTickmarksAxis = d3.svg.axis().scale(timescale).orient('bottom').ticks(d3.time.day, 1).tickFormat('').tickSize(5).tickPadding(1);
/* daysTickmarksAxis = d3.svg.axis().scale(timescale).orient('bottom').ticks(d3.time.day, 1).tickFormat('').tickSize(30).tickPadding(6); */
// day tickmarks axis
svg.append('g').classed('axis', true).classed('days', true).attr("transform", "translate(0.5,0.5)").call(daysTickmarksAxis);
svg.append('g').classed('axis', true).classed('days', true).classed('labeled', true).attr("transform", "translate(0.5,0.5)").call(daysLabelsAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.selectAll(".bar")
.data(records)
.enter().append("rect")
.attr("class", "bar")
.attr("y", function (d) {
return y(d.type);
})
.attr("height", y.rangeBand())
.attr("x", function (d) {
return x(d.time);
})
.attr("width", 2)
.style("fill", function (d) {
return colorOf(d.type);
})
}
time type weekday weekhour call_duration
06-01-15 10:12 inc_call 1 46 39
07-01-15 11:12 inc_call 2 71 9
08-01-15 07:12 inc_call 3 91 131
09-01-15 09:12 out_text 4 117 5
10-01-15 17:12 out_call 5 149 22
11-01-15 20:12 inc_text 6 176 5
05-01-15 10:12 inc_text 0 22 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment