D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
tlfrd
Full window
Github gist
Opening Hours
Visualing changes in Opening and Closing hours for Felix
<!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <link href="https://fonts.googleapis.com/css?family=Open+Sans:400, 600" rel="stylesheet"> <style> body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } text { font-family: 'Open Sans', sans-serif; } .bar-label { fill: white; } .old-hours { fill: #2c7fb8; stroke: white; } .new-hours { fill: #253494; stroke: white; } .x-axis text { font-size: 14px; } .grid-line { stroke: black; opacity: 0.2; stroke-dasharray: 5,5; } .title { font-size: 20px; } </style> </head> <body> <script> var margin = {top: 100, right: 100, bottom: 100, left: 100}; var width = 960, height = 1000; var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom); var parseTime = d3.timeParse("%H:%M"); var formatTime = d3.timeFormat("%H:%M"); d3.queue() .defer(d3.csv, "opening-hours.csv") .defer(d3.csv, "opening-term-hours.csv") .await(load); function load(error, hours, termHours) { if (error) throw error; var config1 = { width: width - margin.left - margin.right, height: (height / 2) - margin.top - margin.bottom }; var config2 = { width: width - margin.left - margin.right, height: (height / 2.4) - margin.top - margin.bottom } var arr1 = ["Out of Term Hours Old Open","Out of Term Hours Old Close","Out of Term Hours New Open","Out of Term Hours New Close"]; var elem1 = svg.append("g") .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); drawChart(elem1, config1, hours, arr1, "Out Of Term Hours"); var arr2 = ["Opening Term Hours Old","Closing Term Hours Old","Opening Term Hours New","Closing Term Hours New"]; var elem2 = svg.append("g") .attr("transform", "translate(" + [margin.left, margin.top + height / 2] + ")") drawChart(elem2, config2, termHours, arr2, "Term Hours"); } function drawChart(elem, config, data, selectors, label) { var places = d3.scaleBand() .range([0, config.height]) .padding(0.1); places.domain(data.map(d => d["Outlet Name"])); var time = d3.scaleTime() .domain([parseTime("06:00"), parseTime("24:00")]) .range([0, config.width]); data.forEach(function(place) { for (var attribute in place) { if (attribute != "Outlet Name") { place[attribute] = parseTime(place[attribute]); } } }); var title = elem.append("text") .attr("class", "title") .attr("y", -margin.top / 3) .text(label) var xAxis = d3.axisBottom(time) .tickFormat((d, i) => i % 2 == 0 ? formatTime(d) : "") .ticks(24); var xGroup = elem.append("g"); var xAxisElem = xGroup.append("g") .attr("transform", "translate(" + [0, config.height + margin.bottom / 4] + ")") .attr("class", "x-axis") .call(xAxis); var grid = xGroup.append("g").selectAll("line") .data(time.ticks(24)) .enter().append("line") .attr("class", "grid-line") .attr("x1", d => time(d) + 0.5) .attr("x2", d => time(d) + 0.5) .attr("y1", -margin.bottom / 8) .attr("y2", config.height + margin.bottom / 4); var hourBars = elem.append("g") .selectAll("g") .data(data) .enter().append("g") .attr("transform", d => "translate(" + [0, places(d["Outlet Name"])] + ")") .attr("class", "place-hours"); var oldHours = hourBars.append("rect") .attr("class", "old-hours") .attr("x", d => time(d[selectors[0]])) .attr("width", d => time(d[selectors[1]]) - time(d[selectors[0]])) .attr("height", places.bandwidth()); var newHours = hourBars.append("rect") .attr("class", "new-hours") .attr("x", d => time(d[selectors[2]])) .attr("width", d => time(d[selectors[3]]) - time(d[selectors[2]])) .attr("height", places.bandwidth()); var labels = hourBars.append("text") .attr("class", "bar-label") .attr("text-anchor", "middle") .attr("x", d => time(d[selectors[2]])) .attr("dx", d => (time(d[selectors[3]]) - time(d[selectors[2]])) / 2) .attr("y", places.bandwidth() / 2) .attr("dy", places.bandwidth() / 8) .style("font-size", places.bandwidth() / 2) .text(d => d["Outlet Name"]); var legendOffsets = 100; var legend = elem.append("g") .attr("class", "legend") .attr("transform", "translate(" + [config.width - margin.right / 2, -margin.top / 2] +")"); var legendElems = legend.selectAll("g") .data([{class: "old-hours", label: "Old"}, {class: "new-hours", label: "New"}]) .enter().append("g") .attr("transform", (d, i) => "translate(" + [-i * legendOffsets, 0] + ")") legendElems.append("rect") .attr("class", d => d.class) .attr("width", places.bandwidth() / 2) .attr("height", places.bandwidth() / 2) legendElems.append("text") .attr("x", places.bandwidth() / 2) .attr("y", places.bandwidth() / 2) .attr("dx", 10) .attr("dy", -places.bandwidth() / 16) .text(d => d.label); } </script> </body>
https://d3js.org/d3.v4.min.js