<!DOCTYPE html>
<html>
<head>
<title>Bar Chart in D3 v5</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script type='text/javascript' src="./word_wrap.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1>Bar Chart in D3 v5</h1>
<div id="main"></div>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
/*
TODO:
- larger Y-numbers? Auto-Calculated margins?
- beautiful tooltip
- gridlines
- actions on bar click
- actions on body clisk
- colors and legend
DONE:
- multi-line labels. 2019-07
*/
var main = d3.select('#main'); // append charts here
var allSizes = {
big: {
width: 960, height: 500,
margin: {top: 20, right: 20, bottom: 130, left: 45},
padding: 0.05 // padding is like % spaces between bars
}
};
var x, y; // constants used by all charts
// ______ _ _
// | ____| | | (_)
// | |__ _ _ _ __ ___| |_ _ ___ _ __ ___
// | __| | | | '_ \ / __| __| |/ _ \| '_ \/ __|
// | | | |_| | | | | (__| |_| | (_) | | | \__ \
// |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
function conversor(d) {
// The type conversion function can also return null,
// in which case the row will be ignored.
// This is useful for filtering datasets on the client.
// auto-type detect https://observablehq.com/@d3/d3-autotype
return d3.autoType(d);
}
// _____ _ _
// / ____| | | |
// | | | |__ __ _ _ __| |_
// | | | '_ \ / _` | '__| __|
// | |____| | | | (_| | | | |_
// \_____|_| |_|\__,_|_| \__|
// 1. Before chart data is loaded
// chart header
main.append('div').html("<h2>Chart Title</h2>");
// sizes & styles & data
var
sizes = allSizes.big, // change "big" and change "allsizes" to fit
margin = sizes.margin,
padding = sizes.padding;
var
xClass = "axis axis--x",
yClass = "axis axis--y",
barClass = "bar bar_blue",
dataSource = "data1.csv";
var
width = sizes.width - margin.left - margin.right,
height = sizes.height - margin.top - margin.bottom;
// svg-box
// place for the future chart. Includes chart body, legend, and axes
var svg =
main
.append("svg")
.attr("width", sizes.width)
.attr("height", sizes.height)
// scales
// rangeRound: set range and round the resulting value to the nearest integer.
var x = d3.scaleBand().rangeRound([0, width]).padding(padding),
y = d3.scaleLinear().rangeRound([height, 0]);
// chart boby
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// axes-X (object)
var axesX =
g.append("g")
.attr("class", xClass)
.attr("transform", "translate(0," + height + ")");
// axes-Y (object)
var axesY =
g.append("g")
.attr("class", yClass);
// Y-axes text
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("x", -sizes.height/2 + margin.top)
.attr("y", 0)
.attr("dy", "0.71em")
.attr("text-anchor", "middle");
// 3. After chart data is loaded
// load data from csv source
// conversor = function to modify data, runs for each data row.
d3.csv(dataSource, conversor)
.then((data) => {
// scales
x.domain(data.map(function(d) { return d.name; }));
var maxVal = d3.max(data, function(d) { return d.value; });
y.domain([0, maxVal]);
// xAxes, yAxes (axes)
var xAxes = d3.axisBottom(x);
var yAxes = d3.axisLeft(y);
// append data to axes
axesX.call(xAxes)
.selectAll(".tick text")
.call(d3.util.wrap, x.bandwidth());
axesY.call(yAxes);
// bar for each data element
g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", barClass)
.attr("x", function(d) { return x(d.name); })
.attr("y", function(d) { return y(d.value); })
.attr("width", x.bandwidth())
.attr("height", function(d) { return height - y(d.value); });
})
.catch((error) => {
throw error;
});
// 2. Code here exacutes before 3.
body
{
background-color: lightgray;
font-family: Calibri, 'Trebuchet MS', sans-serif
}
#main
{
float: left;
width: 100%;
height: 100%;
}
.bar_blue {
fill: steelblue;
fill-opacity: 1;
}
.bar:hover {
fill-opacity: 0.6;
}
.axis--x path {
display: none;
}
name,value
Locke loremipsu blavlavva daa crakazavrs against megegodzillasss,400000
Reyes thebestof the best labels and even longer,800000
Ford zoommeifucan,1500000
Jarrah akalalalala op woo,1600000
Shephard zinzinzizi fii fooooofiof,2300000
Kwonn opaen bya fuu atension,4200000
// Source:
// https://gist.github.com/guypursey/f47d8cd11a8ff24854305505dbbd8c07
d3.util = d3.util || {};
d3.util.wrap = function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", 0)
.attr("y", y)
.attr("dy", dy + "em")
while (word = words.pop()) {
line.push(word)
tspan.text(line.join(" "))
if (tspan.node().getComputedTextLength() > width) {
line.pop()
tspan.text(line.join(" "))
line = [word]
tspan = text
.append("tspan")
.attr("x", 0)
.attr("y", y)
.attr("dy", `${++lineNumber * lineHeight + dy}em`)
.text(word)
}
}
})
};