Home > database >  D3.js: Cannot make Y axis scrollable and X axis fixed
D3.js: Cannot make Y axis scrollable and X axis fixed

Time:11-20

I am trying to recreate enter image description here

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?

Live deploy here

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>

  • Related