Plotting German school holidays with D3.js
Sep 1, 2019
Even though I mainly work with R, I wanted to learn some D3.js and recently had the idea to visualize German school holidays by region for the year 2018-19. Don’t ask me why I chose the school holidays, I don’t know either.
I took the dates from this website: https://www.schulferien.org/deutschland/ferien/2019/
First, here is the result:
Whenever I find the time, I’ll have to do this again in D3.js v4 or v5. Anyway, you probably already know how to extract the HTML and JavaScript code from this website but I’ll make it easier and post it below. Please excuse the vague and potentially incorrect comments, I’m still in the process of learning the D3.js framework.
<html>
<head>
<meta charset='utf-8' />
<title>Schulferien in Deutschland</title>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<style>
body {
font-family: "Arial", sans-serif;
}
.axis {
font-size: 13px;
}
.axis path,
.axis line {
fill: none;
display: none;
}
.label {
font-size: 13px;
}
.grid .tick {
stroke: lightgrey;
opacity: 0.7;
}
.grid path {
stroke-width: 0;
}
div.tooltip {
position: absolute;
text-align: left;
width: auto;
height: auto;
padding: 2px;
font: 13px sans-serif;
background: white;
border: 0px;
border-radius: 4px;
pointer-events: none;
}
</style>
</head>
<body>
<div id="graphic"></div>
<script>
// define data
var data = [
{bundesland: "Baden-Württemberg", ferien: "Winterferien", start: "2018-03-04", end: "2018-03-08"},
{bundesland: "Baden-Württemberg", ferien: "Osterferien", start: "2018-04-15", end: "2018-04-27"},
{bundesland: "Baden-Württemberg", ferien: "Pfingstferien", start: "2018-06-11", end: "2018-06-21"},
{bundesland: "Baden-Württemberg", ferien: "Sommerferien", start: "2018-07-29", end: "2018-09-10"},
{bundesland: "Baden-Württemberg", ferien: "Herbstferien", start: "2018-10-28", end: "2018-10-30"},
{bundesland: "Baden-Württemberg", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-04"},
{bundesland: "Bayern", ferien: "Winterferien", start: "2018-03-04", end: "2018-03-08"},
{bundesland: "Bayern", ferien: "Osterferien", start: "2018-04-15", end: "2018-04-27"},
{bundesland: "Bayern", ferien: "Pfingstferien", start: "2018-06-11", end: "2018-06-21"},
{bundesland: "Bayern", ferien: "Sommerferien", start: "2018-07-29", end: "2018-09-09"},
{bundesland: "Bayern", ferien: "Herbstferien", start: "2018-10-28", end: "2018-10-31"},
{bundesland: "Bayern", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-04"},
{bundesland: "Berlin", ferien: "Winterferien", start: "2018-02-04", end: "2018-02-09"},
{bundesland: "Berlin", ferien: "Osterferien", start: "2018-04-15", end: "2018-04-26"},
{bundesland: "Berlin", ferien: "Pfingstferien", start: "2018-05-31", end: "2018-05-31"},
{bundesland: "Berlin", ferien: "Sommerferien", start: "2018-06-20", end: "2018-08-02"},
{bundesland: "Berlin", ferien: "Herbstferien", start: "2018-10-07", end: "2018-10-19"},
{bundesland: "Berlin", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-04"},
{bundesland: "Brandenburg", ferien: "Winterferien", start: "2018-02-04", end: "2018-02-09"},
{bundesland: "Brandenburg", ferien: "Osterferien", start: "2018-04-15", end: "2018-04-26"},
{bundesland: "Brandenburg", ferien: "Sommerferien", start: "2018-06-20", end: "2018-08-03"},
{bundesland: "Brandenburg", ferien: "Herbstferien", start: "2018-10-04", end: "2018-10-18"},
{bundesland: "Brandenburg", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-03"},
{bundesland: "Bremen", ferien: "Winterferien", start: "2018-01-31", end: "2018-02-01"},
{bundesland: "Bremen", ferien: "Osterferien", start: "2018-04-06", end: "2018-04-23"},
{bundesland: "Bremen", ferien: "Pfingstferien", start: "2018-05-31", end: "2018-05-31"},
{bundesland: "Bremen", ferien: "Sommerferien", start: "2018-07-04", end: "2018-08-14"},
{bundesland: "Bremen", ferien: "Herbstferien", start: "2018-10-04", end: "2018-10-18"},
{bundesland: "Bremen", ferien: "Weihnachtsferien", start: "2018-12-21", end: "2019-01-06"},
{bundesland: "Hamburg", ferien: "Winterferien", start: "2018-02-01", end: "2018-02-01"},
{bundesland: "Hamburg", ferien: "Osterferien", start: "2018-03-04", end: "2018-03-15"},
{bundesland: "Hamburg", ferien: "Pfingstferien", start: "2018-05-13", end: "2018-05-17"},
{bundesland: "Hamburg", ferien: "Sommerferien", start: "2018-06-27", end: "2018-08-07"},
{bundesland: "Hamburg", ferien: "Herbstferien", start: "2018-10-04", end: "2018-10-18"},
{bundesland: "Hamburg", ferien: "Weihnachtsferien", start: "2018-12-20", end: "2019-01-03"},
{bundesland: "Hessen", ferien: "Osterferien", start: "2018-04-15", end: "2018-04-27"},
{bundesland: "Hessen", ferien: "Sommerferien", start: "2018-07-01", end: "2018-08-09"},
{bundesland: "Hessen", ferien: "Herbstferien", start: "2018-09-30", end: "2018-10-12"},
{bundesland: "Hessen", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-11"},
{bundesland: "Mecklenburg-Vorpommern", ferien: "Winterferien", start: "2018-02-04", end: "2018-02-15"},
{bundesland: "Mecklenburg-Vorpommern", ferien: "Osterferien", start: "2018-04-15", end: "2018-04-24"},
{bundesland: "Mecklenburg-Vorpommern", ferien: "Pfingstferien", start: "2018-06-07", end: "2018-06-11"},
{bundesland: "Mecklenburg-Vorpommern", ferien: "Sommerferien", start: "2018-07-01", end: "2018-08-10"},
{bundesland: "Mecklenburg-Vorpommern", ferien: "Herbstferien", start: "2018-10-07", end: "2018-10-12"},
{bundesland: "Mecklenburg-Vorpommern", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-04"},
{bundesland: "Niedersachsen", ferien: "Winterferien", start: "2018-01-31", end: "2018-02-01"},
{bundesland: "Niedersachsen", ferien: "Osterferien", start: "2018-04-08", end: "2018-04-23"},
{bundesland: "Niedersachsen", ferien: "Pfingstferien", start: "2018-05-31", end: "2018-05-31"},
{bundesland: "Niedersachsen", ferien: "Sommerferien", start: "2018-07-04", end: "2018-08-14"},
{bundesland: "Niedersachsen", ferien: "Herbstferien", start: "2018-10-04", end: "2018-10-18"},
{bundesland: "Niedersachsen", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-06"},
{bundesland: "Nordrhein-Westfalen", ferien: "Osterferien", start: "2018-04-15", end: "2018-04-27"},
{bundesland: "Nordrhein-Westfalen", ferien: "Pfingstferien", start: "2018-06-11", end: "2018-06-11"},
{bundesland: "Nordrhein-Westfalen", ferien: "Sommerferien", start: "2018-07-15", end: "2018-08-27"},
{bundesland: "Nordrhein-Westfalen", ferien: "Herbstferien", start: "2018-10-04", end: "2018-10-18"},
{bundesland: "Nordrhein-Westfalen", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-04"},
{bundesland: "Rheinland-Pfalz", ferien: "Winterferien", start: "2018-02-25", end: "2018-03-05"},
{bundesland: "Rheinland-Pfalz", ferien: "Osterferien", start: "2018-04-23", end: "2018-04-30"},
{bundesland: "Rheinland-Pfalz", ferien: "Sommerferien", start: "2018-07-01", end: "2018-08-09"},
{bundesland: "Rheinland-Pfalz", ferien: "Herbstferien", start: "2018-09-30", end: "2018-10-11"},
{bundesland: "Rheinland-Pfalz", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-06"},
{bundesland: "Saarland", ferien: "Winterferien", start: "2018-02-25", end: "2018-03-05"},
{bundesland: "Saarland", ferien: "Osterferien", start: "2018-04-17", end: "2018-04-26"},
{bundesland: "Saarland", ferien: "Sommerferien", start: "2018-07-01", end: "2018-08-09"},
{bundesland: "Saarland", ferien: "Herbstferien", start: "2018-10-07", end: "2018-10-18"},
{bundesland: "Saarland", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-03"},
{bundesland: "Sachsen", ferien: "Winterferien", start: "2018-02-18", end: "2018-03-02"},
{bundesland: "Sachsen", ferien: "Osterferien", start: "2018-04-19", end: "2018-04-26"},
{bundesland: "Sachsen", ferien: "Pfingstferien", start: "2018-05-31", end: "2018-05-31"},
{bundesland: "Sachsen", ferien: "Sommerferien", start: "2018-07-08", end: "2018-08-16"},
{bundesland: "Sachsen", ferien: "Herbstferien", start: "2018-10-14", end: "2018-10-25"},
{bundesland: "Sachsen", ferien: "Weihnachtsferien", start: "2018-12-21", end: "2019-01-03"},
{bundesland: "Sachsen-Anhalt", ferien: "Winterferien", start: "2018-02-11", end: "2018-02-15"},
{bundesland: "Sachsen-Anhalt", ferien: "Osterferien", start: "2018-04-18", end: "2018-04-30"},
{bundesland: "Sachsen-Anhalt", ferien: "Pfingstferien", start: "2018-05-31", end: "2018-06-01"},
{bundesland: "Sachsen-Anhalt", ferien: "Sommerferien", start: "2018-07-04", end: "2018-08-14"},
{bundesland: "Sachsen-Anhalt", ferien: "Herbstferien", start: "2018-10-04", end: "2018-10-11"},
{bundesland: "Sachsen-Anhalt", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-04"},
{bundesland: "Schleswig-Holstein", ferien: "Osterferien", start: "2018-04-04", end: "2018-04-18"},
{bundesland: "Schleswig-Holstein", ferien: "Pfingstferien", start: "2018-05-31", end: "2018-05-31"},
{bundesland: "Schleswig-Holstein", ferien: "Sommerferien", start: "2018-07-01", end: "2018-08-10"},
{bundesland: "Schleswig-Holstein", ferien: "Herbstferien", start: "2018-10-04", end: "2018-10-18"},
{bundesland: "Schleswig-Holstein", ferien: "Weihnachtsferien", start: "2018-12-23", end: "2019-01-06"},
{bundesland: "Thüringen", ferien: "Winterferien", start: "2018-02-11", end: "2018-02-15"},
{bundesland: "Thüringen", ferien: "Osterferien", start: "2018-04-15", end: "2018-04-27"},
{bundesland: "Thüringen", ferien: "Pfingstferien", start: "2018-05-31", end: "2018-05-31"},
{bundesland: "Thüringen", ferien: "Sommerferien", start: "2018-07-08", end: "2018-08-17"},
{bundesland: "Thüringen", ferien: "Herbstferien", start: "2018-10-07", end: "2018-10-19"},
{bundesland: "Thüringen", ferien: "Weihnachtsferien", start: "2018-12-21", end: "2019-01-03"},
]
// assign colors to types of holidays
var color = d3.scale.ordinal()
.domain(["Winterferien","Osterferien","Pfingstferien","Sommerferien","Herbstferien","Weihnachtsferien"])
.range(["#3498db","#1abc9c","#9b59b6","#fed800","#95a5a6","#34495e"]);
// function to read in dates
var parseDate = d3.time.format("%Y-%m-%d").parse;
// function to format dates
var formatDate = d3.time.format("%d.%m.%Y")
// define margins around plotting area
// we need a lot of space on the left for the region names as well as on
// on the bottom for the date
var margin = {
top: 40,
right: 25,
bottom: 100,
left: 170
};
// define height and width of the plotting area
var width = 960 - margin.left - margin.right,
height = 530 - margin.top - margin.bottom;
// create SVG
var svg = d3.select("#graphic")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// create border around plotting area
var borderPath = svg.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("height", height)
.attr("width", width)
.style("stroke", "black")
.style("fill", "none")
.style("stroke-width", 1);
// tooltip element
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// create X axis scale with time scale and manual limits
var x = d3.time.scale()
.domain([parseDate("2018-01-01"), parseDate("2019-02-01")])
.range([0, width])
.nice(d3.time.month);
// create Y axis scale with region names as categories
var y = d3.scale.ordinal()
.rangeRoundBands([0, height], .1)
.domain(data.map( function(d) {
return d.bundesland;
}));
// adjust X axis with 10 ticks
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(8)
.tickFormat(d3.time.format("%m/%Y"));
// adjust Y axis
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
// add title
svg.append("text")
.attr("x", (width / 2))
.attr("y", 0 - (margin.top / 2))
.attr("text-anchor", "middle")
.style("font-size", "20px")
.style("text-decoration", "bold")
.text("Schulferien in Deutschland für 2018/19");
//
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
//
svg.append("g")
.attr("class", "axis")
.call(yAxis);
// draw grid lines
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(
d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(10)
.tickSize(-height, 0, 0)
.tickFormat("")
)
//
svg.append("g")
.selectAll("bar")
.data(data)
.enter()
.append("g")
.append("rect")
.attr("class", "bar")
.attr("y", function(d) { return y(d.bundesland); })
.attr("height", y.rangeBand())
.attr("x", function(d) { return x(parseDate(d.start)); })
.attr("width", function(d) {
return x(parseDate(d.end)) - x(parseDate(d.start))
})
.style("fill", function(d) { return color(d.ferien); })
.style("stroke", "black")
.style("stroke-width", 0.5)
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html(
"<b>Bundesland:</b> " + d.bundesland + "<br/>" +
"<b>Ferien:</b> " + d.ferien + "<br/>" +
"<b>Anfang:</b> " + formatDate(parseDate(d.start)) + "<br/>" +
"<b>Ende:</b> " + formatDate(parseDate(d.end))
)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
</script>
</body>
</html>