/**
* I started with Scott Murray's tutorial, here: http://alignedleft.com/tutorials/d3/making-a-bar-chart
* Then I introduced es6, pulled out some common functions, added scales and color scales.
* To get good contrasting colors for the labels, used some methods from tinycolor.
* I walk through the changes on my blog: http://billkidwell.com/post/2016-07-04-some-fun-with-d3-scales/
*/
// The canvas represents the entire SVG
var canvas = { w: 700, h: 250 };
// Chart area is where the primary chart graphic appears
var chart = { w: 500, h: 100, x: 100, y: 100 };
var barPadding = 5;
var dataset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,
11, 12, 15, 20, 25, 17, 16, 18, 23, 25 ];
var x = d3.scale.ordinal()
.rangeBands([0, chart.w], .1);
var y = d3.scale.linear()
.range([chart.h, 0]);
var blueScale = d3.scale.linear()
.domain([d3.min(dataset), d3.max(dataset)])
.range(["lightblue", "darkblue"]);
var inverseBlue = d3.scale.linear()
.domain([d3.max(dataset), d3.min(dataset)])
.range(["lightblue", "darkblue"]);
function contrastingColor(d) {
var barColor = d3.rgb(blueScale(d));
var color = d3.rgb(inverseBlue(d)); // start with the color from the inverse scale
if (isDark(barColor)) return color.brighter(2);
else return color.darker(2);
}
x.domain(dataset.map( (d) => d ));
y.domain([0, d3.max(dataset)]);
console.log(d3.max(dataset));
var labelFont = {
family: 'sans-serif',
size: '11px'
}
function font(selection, fontInfo) {
selection.attr('font-family', fontInfo.family)
.attr('font-size', fontInfo.size)
return selection;
}
function fill(selection, fillColor) {
selection.attr("fill", fillColor);
return selection;
}
// Thanks to tinycolor
function getBrightness(color) {
//http://www.w3.org/TR/AERT#color-contrast
var rgb = d3.rgb(color)
return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
}
// Thanks to tinycolor
function isDark(color) {
return getBrightness(color) < 128;
}
// Thanks to tinycolor
function isLight(color) {
return !isDark(color);
}
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", canvas.w)
.attr("height", canvas.h);
var group = svg.append("g")
.attr("transform", "translate(" + chart.x + "," + chart.y + ")");
group.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d) => x(d))
.attr("y", (d) => y(d))
.attr("width", x.rangeBand())
.attr("height", (d) => chart.h - y(d) )
.call(fill, (d) => blueScale(d));
group.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d )
.attr("x", (d, i) => x(d) + 0.5*x.rangeBand() ) // center of range
.attr("text-anchor", "middle") // bottom middle is anchor
.attr("y", (d) => y(d) + 15 )
.call(font, labelFont)
.call(fill, (d)=> contrastingColor(d));
View Compiled
This Pen doesn't use any external CSS resources.