This is a scatterplot displaying beer by alcohol by volume (x) and IBU (y). I cannot get the axis labels to display. I checked the DOM, and the text is in the tree, but for some reason, it is not displaying on the screen.
For the y-label, the margins don't seem to be working, and for the x, it is positioned where I want it to be, but I simply cannot see any text.
const dataFiles = ['https://raw.githubusercontent.com/inspectordanno/beer_components/master/scatterplot/data/beers.csv', 'https://raw.githubusercontent.com/inspectordanno/beer_components/master/scatterplot/data/breweries.csv']; //data files to be parsed
const promises = []; //empty array which will contain the promises
dataFiles.forEach(url => {
promises.push(d3.csv(url)); //this parses each csv file and pushes it to the array
});
//dimensions and margins of plot
const margin = {
top: 10,
right: 30,
bottom: 30,
left: 60
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
padding = 30;
const svg = d3.select('body')
.append('svg')
.attr('width', width)
.attr('height', height);
Promise.all(promises).then(data => { //here, I am combining the two arrays in the promise into one big array of beer objects
data[0].forEach(beer => {
const breweryid = beer.brewery_id;
data[1].forEach(brewery => {
if (parseInt(breweryid) == parseInt(brewery.id)) {
beer.brewery_name = brewery.name;
beer.brewery_city = brewery.city;
beer.brewery_state = brewery.state;
}
});
});
let beers = data[0]; //beer data
const xScale = d3.scaleLinear()
.domain([0, d3.max(beers, d => d.abv)])
.range([padding, width - padding *2]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(beers, d => d.ibu)])
.range([height - padding, padding]);
const xAxis = d3.axisBottom()
.scale(xScale)
.ticks(10) //ask steven
.tickFormat(d3.format(',.1%'));
const yAxis = d3.axisLeft()
.scale(yScale)
.ticks(10); //ask steven
// .tickFormat
svg.selectAll('circle')
.data(beers)
.enter()
.append('circle')
.attr('cx', d => {
return xScale(d.abv);
})
.attr('cy', d => {
return yScale(d.ibu);
})
.attr('r', 1)
.attr('fill', 'steelblue')
.on('mouseover', d => console.log(d))
//Create X axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (height - padding) + ")")
.call(xAxis);
//text label for x axis
svg.append("text")
.attr("transform", `translate(${(width/2)}, ${height + margin.top * 4})`)
.style("text-anchor", "middle")
.text("Alcohol by Volume");
// text label for the y axis
svg.append("text")
.attr("transform", "rotate(-90)")
.attr('y', 0 - margin.left * .75)
.attr('x', 0 - (height/2))
.style("text-anchor", "middle")
.text("IBU")
//Create Y axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
}) //end .then of promise
.catch(err => console.log(err)); // catching error in promises
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="main.js" charset="utf-8"></script>
</body>
</html>
The way you're dealing with the margins, dimensions, paddings and translates makes little sense. For instance, you set the properties of the
margin
object, but your SVG has a width and height that simply subtracts those values.I'm not personally neither a user nor a fan of that pattern (that Mike Bostock calls margin convention), but this is how you can do it:
First, set the margins, as you did, and define the
width
andheight
. Then, add the margins for setting the SVG dimensions:Finally, append a
<g>
element, translating it usingmargin.left
andmargin.top
:Here is your code with that change (and changing the translate for the axes as well):