Built with blockbuilder.org
xxxxxxxxxx
<meta charset="utf-8">
<style>
.barPos {
fill: green;
}
.barNeg {
fill: red;
}
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
g.tick text {
font-size: 16px;
}
text.valueLabel {
font-weight: bold;
font-family: monospace, sans-serif;
/*default red value label, if it's positive we override with green */
fill: red;
}
text.positiveVal {
fill: green;
}
text.domainLabel {
font-weight: bold;
font-family: monospace, sans-serif;
}
</style>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, left: 200, bottom: 40, right: 0},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width]);
var y = d3.scale.ordinal()
.rangeRoundBands([0, height], 0.1);
var yLabel = d3.scale.ordinal()
.rangeRoundBands([0, height], 0.1);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.outerTickSize(0);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickSize(0)
.tickPadding(6);
var labelAxis = d3.svg.axis()
.scale(yLabel)
.orient('right')
.tickSize(0)
.tickPadding(6);
var svg = d3.select("body").append("svg")
.attr("width", "100%")
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
d3.json("datatest.json", function(data) {
//Get the max of our values, we'll use that to determine the range of xaxis ticks
var valArray = data.map(function(d) {return d.value});
var tickRange = (Math.max(...valArray)+20);
//next three lines responsible for printing data to the x-axis ticks, the domain labels, and the values next to the bar rectangles(
//tickRange + 1 so that the last tick prints onto the page
x.domain([0, (tickRange + 1)]);
y.domain(data.map(function(d) { return d.name; }));
yLabel.domain(data.map(function(d) {return d.value; }));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + x(0) + ",0)")
.call(yAxis);
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", function(d) { return "bar bar" + (d.value < 100 ? "Neg" : "Pos"); })
.attr("y", function(d) { return y(d.name); })
.attr("stroke-width", 1)
.attr("stroke", "black")
.attr("width", function(d) { return Math.abs(x(d.value) - x(100)); })
.attr("height", y.rangeBand())
//Loop over each rectangle and determine how to place it on the 100 axis
//based on the class of barPos or barNeg, or, is the value over or under 100
.each(function(d) {
var rec = d3.select(this);
//get what width of bar should be; this is used to translate the negative bar over the y axis
var barWidth = Math.abs(x(d.value) - x(100));
if(this.classList.contains("barPos")) {
rec.attr("x", function(d) { return x(100) })
d3.select("valLabel").append("text").text(d.value);
} else {
rec.attr("x", function(d) { return ((x(100)) - barWidth) })
}
});
////Get the location of the 100 tick on the viz
var hundredCoord = null;
svg.selectAll(".tick").each(function(data) {
var tick = d3.select(this);
// pull the transform data out of the tick
var transform = d3.transform(tick.attr("transform")).translate;
//when we reach the tick at 100; pull out its location on the svg from the transform var
if (data === 100) {
hundredCoord = transform[0];
}
});
//Add the bar values to the chart at the 100 tick reference line
svg.append("g")
.attr("class", "label")
.attr("transform", "translate(" + hundredCoord + ",0)")
.call(labelAxis);
//look at each value label and give it a class, and if the value is greater than 100, translate it across the 100 tick reference line
svg.selectAll("g.label g text").each(function(){
this.classList.add("valueLabel");
if(this.textContent > 100){
this.setAttribute("dx", "-2.5em");
this.classList.add("positiveVal");
this.setAttribute("fill", "green");
}
});
//add a class to the domain label text element
svg.selectAll("g.y g.tick text").each(function() {
this.classList.add("domainLabel");
});
//Draw a vertical reference line at the 100 tick
svg.append("line")
.style("stroke", "black")
.attr("stroke-width", 3)
.attr("x1", hundredCoord)
.attr("y1", 0)
.attr("x2", hundredCoord)
.attr("y2", height)
});
function type(d) {
d.value = +d.value;
return d;
}
</script>
Updated missing url //d3js.org/d3.v3.min.js to https://d3js.org/d3.v3.min.js
https://d3js.org/d3.v3.min.js