Reputation: 69
Created a d3.js bar chart based on some examples I've seen online and I've come across a problem. I'd like to align the starting datapoint based on the x-axis with the y-intercept. However, I can't seem to do so correctly even after various changes (changing scale.ordinal to scale.linear, adding transform to y-axis, etc.).
Likewise, I'd like the ending point in the x-axis to be aligned with the last data point. There's like an invisible padding before and after the range of starting and beginning of the datapoints in the chart.
I've consulted this question here as it seems similar to my problem but came up short with my expected results: D3Js Bar Chart Bars Starting Way After beginning of X-Axis
Here's the current code that I have:
var dataUrl = 'https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json';
// set the dimensions of the canvas
var margin = {
top: 20,
right: 20,
bottom: 70,
left: 40
},
width = 1500 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// set the ranges
var x = d3.scale.ordinal().rangeRoundBands([0, width], 0.01, 1);
var y = d3.scale.linear().range([height, 0]);
// define the axis
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
// Added for the vertical lines (need to remove later)
.innerTickSize(-height)
.outerTickSize(0)
.tickPadding(10);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
var svg = d3.select(".chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// load the data
d3.json(dataUrl, function(error, data) {
data.data.forEach(function(d) {
d.GDP = d[0];
d.Year = +d[1];
});
// scale the range of the data
x.domain(data.data.map(function(d) {
return d.GDP;
}));
y.domain([0, d3.max(data.data, function(d) {
return d.Year;
})]);
// add axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)");
svg.append("g")
.attr("class", "y axis")
// .attr("transform", "translate(" + margin.left + ", 0)")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 5)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Gross Domestic Product, USA");
// Add bar chart with tooltip
svg.selectAll("bar")
.data(data.data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.GDP);
})
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.Year);
})
.attr("height", function(d) {
return height - y(d.Year);
})
.on("mouseover", function(d) {
var monthNameFormat = d3.time.format("%b-%Y")
var gdp_date = monthNameFormat(new Date(d[0]))
var formatDecimalComma = d3.format(",.2f")
var curr = formatDecimalComma(d[1])
div.transition()
.duration(200)
.style("opacity", .9);
div.html(gdp_date + "<br/> $" + curr + " Billion")
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
});
.chart rect {
fill: steelblue;
}
.chart text {
fill: black;
font: 10px sans-serif;
text-anchor: middle;
}
bar {
fill: steelblue;
}
.bar:hover {
fill: red;
}
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
div.tooltip {
position: absolute;
text-align: center;
width: 130px;
height: 30px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!-- Source: https://bost.ocks.org/mike/bar/3/ -->
<div id="chart" align="center">
<svg class="chart"></svg>
</div>
Upvotes: 1
Views: 2366
Reputation: 102198
Change rangeRoundBands
to rangeBands
and remove all the paddings:
var x = d3.scale.ordinal().rangeBands([0, width]);
Here is your code with that change:
var dataUrl = 'https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json';
// set the dimensions of the canvas
var margin = {
top: 20,
right: 20,
bottom: 70,
left: 40
},
width = 1500 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// set the ranges
var x = d3.scale.ordinal().rangeBands([0, width]);
var y = d3.scale.linear().range([height, 0]);
// define the axis
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
// Added for the vertical lines (need to remove later)
.innerTickSize(-height)
.outerTickSize(0)
.tickPadding(10);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(10);
var svg = d3.select(".chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// load the data
d3.json(dataUrl, function(error, data) {
data.data.forEach(function(d) {
d.GDP = d[0];
d.Year = +d[1];
});
// scale the range of the data
x.domain(data.data.map(function(d) {
return d.GDP;
}));
y.domain([0, d3.max(data.data, function(d) {
return d.Year;
})]);
// add axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)");
svg.append("g")
.attr("class", "y axis")
// .attr("transform", "translate(" + margin.left + ", 0)")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 5)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Gross Domestic Product, USA");
// Add bar chart with tooltip
svg.selectAll("bar")
.data(data.data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.GDP);
})
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.Year);
})
.attr("height", function(d) {
return height - y(d.Year);
})
.on("mouseover", function(d) {
var monthNameFormat = d3.time.format("%b-%Y")
var gdp_date = monthNameFormat(new Date(d[0]))
var formatDecimalComma = d3.format(",.2f")
var curr = formatDecimalComma(d[1])
div.transition()
.duration(200)
.style("opacity", .9);
div.html(gdp_date + "<br/> $" + curr + " Billion")
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
});
.chart rect {
fill: steelblue;
}
.chart text {
fill: black;
font: 10px sans-serif;
text-anchor: middle;
}
bar {
fill: steelblue;
}
.bar:hover {
fill: red;
}
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
div.tooltip {
position: absolute;
text-align: center;
width: 130px;
height: 30px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!-- Source: https://bost.ocks.org/mike/bar/3/ -->
<div id="chart" align="center">
<svg class="chart"></svg>
</div>
Upvotes: 1