Create a bar chart with positive and negative values along the horizontal axis with D3.js.
forked from HarryStevens's block: Positive-Negative Bar Chart
license: gpl-3.0 |
Create a bar chart with positive and negative values along the horizontal axis with D3.js.
forked from HarryStevens's block: Positive-Negative Bar Chart
name | value | |
---|---|---|
A | 1.31 | |
B | -3.63 | |
C | -2.96 | |
D | 1.41 | |
E | -2.03 | |
F | -3.82 | |
G | 1.41 | |
H | 0.45 | |
I | -3.26 | |
J | 2.13 | |
K | 0.84 | |
L | -0.05 | |
M | -1.43 | |
N | -1.81 | |
O | -0.71 | |
P | 1.94 | |
Q | 14.68 | |
R | 0.33 | |
S | -1.86 | |
T | 0.69 | |
U | -2.41 | |
V | 0.04 | |
W | -3.12 | |
X | 0.8 | |
Y | 0.77 | |
Z | -4.42 |
<html> | |
<head> | |
<style> | |
body { | |
font-family: "Helvetica Neue", sans-serif; | |
margin: 0 auto; | |
display: table; | |
} | |
.name, .value { | |
font-size: .7em; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="chart"></div> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script> | |
var margin = {top: 10, right: 0, bottom: 0, left: 0}, | |
width = 400 - margin.left - margin.right, | |
height = 500 - margin.top - margin.bottom; | |
var svg = d3.select(".chart").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 + ")"); | |
var x = d3.scaleLinear() | |
.range([0,width]); | |
var y = d3.scaleBand() | |
.rangeRound([height,0]) | |
.padding(0.2); | |
d3.csv("data.csv",types,function(error,data){ | |
if (error) throw error; | |
data.sort(function(a,b){ | |
return b.value - a.value; | |
}); | |
x.domain(d3.extent(data, function(d){ return d.value; })); | |
y.domain(data.map(function(d) { return d.name; })); | |
svg.selectAll(".bar") | |
.data(data) | |
.enter().append("rect") | |
.attr("class", "bar") | |
.attr("x", function(d){ return d.value < 0 ? x(d.value) : x(0); }) | |
.attr("width", function(d){ return d.value < 0 ? x(d.value * -1) - x(0) : x(d.value) - x(0); }) | |
.attr("y", function(d){ return y(d.name); }) | |
.attr("height", y.bandwidth()) | |
.attr("fill", function(d){ return d.value < 0 ? "#d7191c": "#1a9641"; }); | |
svg.selectAll(".value") | |
.data(data) | |
.enter().append("text") | |
.attr("class", "value") | |
.attr("x", function(d){ | |
if (d.value < 0){ | |
return (x(d.value * -1) - x(0)) > 20 ? x(d.value) + 2 : x(d.value) - 1; | |
} else { | |
return (x(d.value) - x(0)) > 20 ? x(d.value) - 2 : x(d.value) + 1; | |
} | |
}) | |
.attr("y", function(d){ return y(d.name); }) | |
.attr("dy", y.bandwidth() - 2.55) | |
.attr("text-anchor", function(d){ | |
if (d.value < 0){ | |
return (x(d.value * -1) - x(0)) > 20 ? "start" : "end"; | |
} else { | |
return (x(d.value) - x(0)) > 20 ? "end" : "start"; | |
} | |
}) | |
.style("fill", function(d){ | |
if (d.value < 0){ | |
return (x(d.value * -1) - x(0)) > 20 ? "#fff" : "#3a403d"; | |
} else { | |
return (x(d.value) - x(0)) > 20 ? "#fff" : "#3a403d"; | |
} | |
}) | |
.text(function(d){ return d.value; }); | |
svg.selectAll(".name") | |
.data(data) | |
.enter().append("text") | |
.attr("class", "name") | |
.attr("x", function(d){ return d.value < 0 ? x(0) + 2.55 : x(0) - 2.55 }) | |
.attr("y", function(d){ return y(d.name); }) | |
.attr("dy", y.bandwidth() - 2.55) | |
.attr("text-anchor", function(d){ return d.value < 0 ? "start" : "end"; }) | |
.text(function(d){ return d.name; }); | |
svg.append("line") | |
.attr("x1", x(0)) | |
.attr("x2", x(0)) | |
.attr("y1", 0 + margin.top) | |
.attr("y2", height - margin.top) | |
.attr("stroke", "#3a403d") | |
.attr("stroke-width", "1px"); | |
}); | |
function types(d){ | |
d.value = +d.value; | |
return d; | |
} | |
</script> | |
</body> | |
</html> |