As you can see, the y axis is being cut off while the x axis is not fixed or properly visible. Based on the example linked above, the only thing I can see controlling the scrolling is overflow-y
, which I've added to my svg here:
let chart = d3.select("#chart2")
.append("svg")
.attr("width", width margin.left margin.right)
.attr("height", height margin.top margin.bottom)
.append("g")
.style("overflow-y", "scroll")
.attr("transform", "translate(" margin.left "," margin.top ")");
This does not work. What am I doing wrong and how can I replicate the fixed x axis and scrollable y axis example with my code?
CodePudding user response:
When you look closely at the example you posted, you'll see that they used two (!) SVGs. One for the chart and one for the axis. Starting with that already solves a big part of the problem.
The next thing is that SVGs are not scrollable. Again, looking at the example shows you that the overflow: scroll
is actually on the div
, not on the SVG.
const margin = {
top: 20,
right: 20,
bottom: 30,
left: 150
};
const width = 960 - margin.left - margin.right;
const height = 500 - margin.top - margin.bottom;
let chart = d3.select("#chart2")
.append("div")
.classed("chart", true)
.append("svg")
.attr("width", width margin.left margin.right)
.attr("height", height margin.top margin.bottom)
.append("g")
.style("overflow-y", "scroll")
.attr("transform", "translate(" margin.left "," margin.top ")");
// Make sure to create a separate SVG for the XAxis
let axis = d3.select("#chart2")
.append("svg")
.attr("width", width margin.left margin.right)
.attr("height", 40)
.append("g")
.attr("transform", "translate(" margin.left ", 0)");
// Load the data
d3.csv("https://raw.githubusercontent.com/thedivtagguy/daily-data/master/dd_cropYieldsD3/cropYieldsD3/data/land_use.csv").then(function(data) {
// console.log(data);
const years = Array.from(new Set(data.map(d => d.year)));
const countries = Array.from(new Set(data.map(d => d.entity)));
// Sort countries based on change in land use in descending order
const sortedCountries = countries.sort((a, b) => {
const aChange = data.filter(d => d.entity === a).map(d => d.change).reduce((a, b) => a b);
const bChange = data.filter(d => d.entity === b).map(d => d.change).reduce((a, b) => a b);
return aChange - bChange;
});
const x = d3.scaleBand()
.range([0, width])
.domain(years)
.padding(0.1);
const y = d3.scaleBand()
.range([height * 6, 0])
.domain(sortedCountries)
.padding(0.1);
// Only 10 years
axis.call(d3
.axisBottom(x)
.tickValues(years.filter((d, i) => !(i % 10))))
.selectAll("text")
.style("color", "black")
.style("position", "fixed")
.attr("transform", "translate(-10,10)rotate(-45)")
.style("text-anchor", "end");
chart.append("g")
.call(d3.axisLeft(y))
.selectAll("text")
.style("color", "black")
.attr("transform", "translate(-10,0)")
.style("text-anchor", "end");
const colorScale = d3.scaleSequential()
.domain([0, d3.max(data, d => d.change)])
.interpolator(d3.interpolateInferno);
// add the squares
chart.selectAll()
.data(data, function(d) {
return d.year ':' d.entity;
})
.join("rect")
.attr("x", function(d) {
return x(d.year)
})
.attr("y", function(d) {
return y(d.entity)
})
.attr("rx", 4)
.attr("ry", 4)
.attr("width", x.bandwidth())
.attr("height", y.bandwidth())
.style("fill", function(d) {
return colorScale(d.change)
console.log(d.change);
})
.style("stroke-width", 4)
.style("stroke", "none")
.style("opacity", 0.8)
});
#chart2 .chart {
width: 960px;
max-height: 470px;
overflow-y: scroll;
overflow-x: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<div id="chart2"></div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>