Reputation: 552
I created a visual data with bar chart but I'm having trouble aligning the text "Gross Domestic Product" and "Units: Billions of Dollars Seasonal Adjustment: Seasonally Adjusted, Annual Rate Notes: A Guide to the National Income and Product Accounts of the United States (NIPA) - (http://www.bea.gov/national/pdf/nipaguid.pdf)"
As of now they are over lapping at the top:
I want to align "Gross Domestic Product" at the top and "Units: Billions of Dollars Seasonal Adjustment: Seasonally Adjusted Annual Rate Notes: A Guide to the National Income and Product Accounts of the United States (NIPA) - (http://www.bea.gov/national/pdf/nipaguid.pdf)" at the bottom like
var url = "https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json";
//Fetch Data By .$getJSON Method
$.getJSON(url, function (d) {
var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
];
var data = d.data;
/*test data by
console.log(data[0][0]);
*/
//create Margin
var margin = { top: 40, right: 20, bottom: 30, left: 50 },
width = 960 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
/*
Define Min & Max Data for Scale
*/
console.log(d.description);
var minDate = new Date(data[0][0]);
var maxDate = new Date(data[d.data.length - 1][0]);
/*
test data by
console.log(minDate);
console.log(maxDate);
*/
/*
define scale then followed by axis
*/
// define x and y scales
// define x and y scales
var xScale = d3.time.scale().
domain([minDate, maxDate]).
range([0, width]);
var yScale = d3.scale.linear().
domain([0, d3.max(data, function (d) {
return d[1];
})]).
range([height, 0]);
// define x axis and y axis
var xAxis = d3.svg.axis().
scale(xScale).
orient("bottom").
ticks(d3.time.years, 5);
var yAxis = d3.svg.axis().
scale(yScale).
orient("left").
ticks(10, "");
var thisDate = new Date(data[0][0]);
/*
Create Tooltip
*/
var toolTip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function (d) {
return ('<strong>$' + d[1].toLocaleString() + ' Billion</strong><p>' + thisDate.getFullYear() + ' - ' + monthNames[thisDate.getMonth()] + '</p>');
});
/*
create svg element then append height and width and g which act as a container
*/
var svg = d3.select(".mainContainer").
attr({
"width": width + margin.right + margin.left,
"height": height + margin.top + margin.bottom
}).
append("g").
attr("transform", "translate(" + margin.left + "," + margin.right + ")");
//call toolTip
svg.call(toolTip);
// Draw xAxis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
//Draw yAxis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Gross Domestic Product, USA");
/*
create bar or bind data
*/
//bind data
svg.selectAll(".bar")
.data(data)
//enter data
.enter().
append("rect")
//update data
.attr("class", "bar")
.attr("x", function (d) { return xScale(new Date(d[0])); })
.attr("width", Math.ceil(width / data.length))
.attr("y", function (d) { return yScale(d[1]); })
.attr("height", function (d) { return height - yScale(d[1]); })
.on('mouseover', toolTip.show)
.on('mouseout', toolTip.hide);
//add description on top and bottom of svg
svg.
attr("class", "title").
append("text").
html("Gross Domestic Product </br>")
svg.
attr("class", "notes").
append("text").
text(d.description);
});
svg {
margin-left: auto;
margin-right: auto;
display: block;
background-color:antiquewhite;
}
body {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: orange;
}
.bar:hover {
fill: orangered ;
}
.d3-tip {
line-height: 1;
font-weight: bold;
padding: 12px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 2px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: 10px;
width: 100%;
line-height: 1;
color: rgba(0, 0, 0, 0.8);
content: "\25BC";
position: absolute;
text-align: center;
}
/* Style northward tooltips differently */
.d3-tip.n:after {
margin: -1px 0 0 0;
top: 100%;
left: 0;
}
.notes {
font-size: 12px;
font-family: sans-serif;
color: steelblue;
padding: 20px;
text-align: center;
vertical-align:bottom;
}
.title {
font-size: 2.5em;
font-family: sans-serif;
color: steelblue;
text-align: center;
padding: 15px 0px 5px 0px;
}
<!DOCTYPE html>
<html>
<head>
<title>D3-Zipline: GDP Bar Graph</title>
<meta charset="utf-8" />
<link href="../Content/bootstrap-theme.min.css" rel="stylesheet" />
<link href="../Content/bootstrap.min.css" rel="stylesheet" />
<script src="../Scripts/d3/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.6.7/d3-tip.min.js"></script>
<link href="demo.css" rel="stylesheet" />
</head>
<body>
<div class="container-fluid text-center">
<br /><br />
<svg class="mainContainer">
</svg>
</div>
<script src="../Scripts/jquery-2.2.1.min.js"></script>
<script src="../Scripts/bootstrap.min.js"></script>
<script src="demo.js"></script>
</body>
</html>
Upvotes: 1
Views: 3943
Reputation: 3112
There are a few things to address here:
Taking them in that order:
X-axis label under the axis, centered
The simplest way to do this is to append your text between the code where you draw the x-axis and the y-axis.
svg.append("text") // text label for the x axis
.attr("class", "notes")
.attr("transform", "translate(" + width/2 + ")")
.attr("y", height + margin.bottom)
.text(d.description)
.call(splitLongLabel); // The next section explains this bit...
Split the long x-axis label over multiple lines
To do this, I've borrowed a little from this answer: https://stackoverflow.com/a/13275930/3442309
It looks like the most sensible place to split the d.description
text is at the "-" character: This is how it's done on the screenshot of how you want the chart to look.
To achieve the split, user tspan
elements
var insertLinebreaks = function (d) {
var el = d; // Get the current element
var words = d.text().split("-"); // Split text at the hyphen
el.text('');
for (var i = 0; i < words.length; i++) { // Then build up the tspans
var tspan = el.append('tspan')
.attr('x', 0)
.text(words[i])
.style("text-anchor", "middle");
if (i > 0)
tspan
.attr('x', 0)
.attr('dy', '15')
.style("text-anchor", "middle");
}
};
To change how and where this label is split, or to make it more generic (eg basing the split on length, rather than a specific character), simply modify how split
is defined
Setting CSS classes for text
In your example, the title was not using the title
CSS class, so not getting the expected style. The reason for this is the following code at the end of your script:
svg.
attr("class", "notes").
append("text").
text(d.description);
What this was doing was setting the notes
style for all text in the svg. More correctly, you should have set the class attribute after appending the text.
Correcting for this, for the title, we now have:
svg.
//attr("class", "title"). <- Removed from here
append("text").
attr("class", "title"). // <- added here
html("Gross Domestic Product </br>")
and I've added some positioning to the javascript for `title, rather than in the CSS:
....
.attr('x', width / 2)
.attr('y', 20)
.style("text-anchor", "middle");
Lastly, I've corrected your CSS, which used color
for applying text color, instead of fill
, which is the correct way
Here's a Fiddle with all the changes described: https://jsfiddle.net/henbox/nuwzxoz8/1/
Upvotes: 2