I changed the attributes of the X axis to plot its values over the bars of the chart. But anywhere I put the code, the values are always plotted before ("behind") the bars and therefore we cannot see it.
//This part of the code is OUTSIDE of the update function (line 44 of the fiddle)
//append group to plot X axis
const xAxisGroup = g.append("g")
.attr("class", "x axis")
.attr("transform", `translate(0, ${HEIGHT})`)
//This part of the code is INSIDE the update function (line 92)
const xAxisCall = d3.axisBottom(x)
xAxisGroup.call(xAxisCall)
.selectAll("text")
.attr("x", "-5") // <<<--- I change this to 50
.attr("y", "10")
.attr("text-anchor", "end")
.attr("transform", "rotate(-45)") // <<<--- I changed this to -90
How would be possible to plot this values over the bars instead?
This is the fiddle of the original chart and this is the modified one. The month values may be behind the bars... :-/
CodePudding user response:
In an SVG, whatever is painted later stays on top. So, just append your x axis <g>
element after painting the rectangles. Alternatively, raise it:
xAxisGroup.raise()
Here's your code with that change:
//set general margin, width and height values
const MARGIN = {
LEFT: 128,
RIGHT: 8,
TOP: 32,
BOTTOM: 128
}
const WIDTH = 400 - MARGIN.LEFT - MARGIN.RIGHT
const HEIGHT = 300 - MARGIN.TOP - MARGIN.BOTTOM
//append svg plot area into div chart area
const svg = d3.select("#chart-area").append("svg")
.attr("width", WIDTH MARGIN.LEFT MARGIN.RIGHT)
.attr("height", HEIGHT MARGIN.TOP MARGIN.BOTTOM)
//append group into svg
const g = svg.append("g")
.attr("transform", `translate(${MARGIN.LEFT}, ${MARGIN.TOP})`)
//X label
g.append("text")
.attr("class", "x axis-label")
.attr("x", WIDTH / 2)
.attr("y", HEIGHT 60)
.attr("font-size", "20px")
.attr("text-anchor", "middle")
.text("Month")
//Y label
g.append("text")
.attr("class", "y axis-label")
.attr("x", -(HEIGHT / 2))
.attr("y", -60)
.attr("font-size", "20px")
.attr("text-anchor", "middle")
.attr("transform", "rotate(-90)")
.text("Value")
//set scale for X axis
const x = d3.scaleBand()
.range([0, WIDTH])
.paddingInner(0.3)
.paddingOuter(0.2)
//set scale for Y axis
const y = d3.scaleLinear()
.range([HEIGHT, 0])
//append group to plot X axis
const xAxisGroup = g.append("g")
.attr("class", "x axis")
.attr("transform", `translate(0, ${HEIGHT})`)
//append group to plot Y axis
const yAxisGroup = g.append("g")
.attr("class", "y axis")
//import data
d3.csv("https://raw.githubusercontent.com/dbahiense/sotabook/main/revenues.csv").then(data => {
//parse values
data.forEach(d => {
d.revenue = Number(d.revenue)
d.profit = Number(d.profit)
})
//listen drop-down lists and trigger update function on change
//state
d3.select("#state")
.on("change", function(event, d) {
update(data)
})
//round
d3.select("#round")
.on("change", function(event, d) {
update(data)
})
//plot chart on page first load
update(data)
})
// update chart function
function update(data) {
//drop-down list listened values
let state = d3.select("#state").property("value")
let round = d3.select("#round").property("value")
//filter data by drop-down list values
let filteredData = data.filter(function(d) {
return d.state == state & d.round == round
})
//set domains for X and Y axes
x.domain(filteredData.map(d => d.month))
y.domain([0, d3.max(filteredData, d => d.revenue)])
const xAxisCall = d3.axisBottom(x)
const yAxisCall = d3.axisLeft(y)
//.tickFormat(d => d "m")
yAxisGroup.call(yAxisCall)
// JOIN new data with old elements.
const rects = g.selectAll("rect")
.data(filteredData)
// EXIT old elements not present in new data.
rects.exit().remove()
// UPDATE old elements present in new data.
rects
.attr("y", d => y(d.revenue))
.attr("x", (d) => x(d.month))
.attr("width", x.bandwidth)
.attr("height", d => HEIGHT - y(d.revenue))
// ENTER new elements present in new data.
rects.enter().append("rect")
.attr("y", d => y(d.revenue))
.attr("x", (d) => x(d.month))
.attr("width", x.bandwidth)
.attr("height", d => HEIGHT - y(d.revenue))
.attr("fill", "steelblue")
xAxisGroup.raise()
.call(xAxisCall)
.selectAll("text")
.attr("x", "50")
.attr("y", "10")
.attr("text-anchor", "end")
.attr("transform", "rotate(-90)")
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="">
<title>5.4</title>
<!-- Bootstrap -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3 Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- Custom styling -->
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<!-- Bootstrap grid setup -->
<div >
<div >
<select id="state">
<option value="US">US</option>
<option value="EU">EU</option>
<option value="AS">AS</option>
</select>
<select id="round">
<option value="1">1</option>
<option value="2">2</option>
</select>
</div>
<div >
<div id="chart-area"></div>
</div>
</div>
<!-- External JS libraries -->
<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2 poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft 2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<!-- Custom JS below-->
</body>
</html>