D3.js Zoom on area graph, weird behaivor if y domain takes negative value

You forgot to use newY(0) instead of y(0) so now when you zoom, the zero line is where it should be, not where it was when you started

// set the dimensions and margins of the graph
let margin = {
    top: 0,
    right: 0,
    bottom: 30,
    left: 30
  },
  width = 440 - margin.left - margin.right,
  height = 240 - margin.top - margin.bottom;

// append the svg object to the body of the page
let svg = d3.select("#my_dataviz")
  .append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform",
    "translate(" + margin.left + "," + margin.top + ")");

//Read the data
d3.csv("https://raw.githubusercontent.com/dimitriiBirsan/RandomNumbersYear1970-2031/main/testing%20negative%20numbers.csv",

  // When reading the csv, I must format variables:
  function(d) {
    return {
      date: d3.timeParse("%m/%d/%Y")(d.date),
      value: d.value
    }
  },

  // Now I can use this dataset:
  function(data) {
    // Add X axis --> it is a date format
    let x = d3.scaleTime()
      .domain(d3.extent(data, function(d) {
        return +d.date;
      }))
      .range([0, width]);
    let xAxis = svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x).ticks(4));

    // Add Y axis
    let y = d3.scaleLinear()
      .domain(d3.extent(data, function(d) {
        return +d.value;
      }))
      .range([height, 0]);
    let yAxis = svg.append("g")
      .call(d3.axisLeft(y));

    function make_x_gridlines(x) {
      return d3.axisBottom(x)
    }

    function make_y_gridlines(y) {
      return d3.axisLeft(y)
    }

    // Add a clipPath : everything out of this area won't be drawn
    let clip = svg.append("defs").append("svg:clipPath")
      .attr("id", "clip")
      .append("svg:rect")
      .attr("width", width)
      .attr("height", height)
      .attr("x", 0)
      .attr("y", 0);

    // Add the area
    let line = svg.append('g')
      .attr("clip-path", "url(#clip)")
    line.append("path")
      .datum(data)
      .attr("class", "polyArea")
      .attr("fill", "blue")
      .attr("opacity", 0.7)
      .attr("stroke", "none")
      .attr("stroke-width", 1.5)
      .attr("d", d3.area()
        .x(function(d) {
          return x(d.date)
        })
        .y0(y(0))
        .y1(function(d) {
          return y(d.value)
        })
        .curve(d3.curveStepAfter)
        .defined((d, i) => (i != null))
      );

    let zoom = d3.zoom()
      .scaleExtent([1, 50]) // This control how much you can unzoom (x0.5) and zoom (x20)
      .translateExtent([
        [0, 0],
        [width, height]
      ])
      .extent([
        [0, 0],
        [width, height]
      ])
      .on("zoom", updateChart);

    // This adds an invisible rect on top of the chart area. This rect can recover pointer events: necessary to understand when the user zoom
    svg.append("rect")
      .attr("width", width)
      .attr("height", height)
      .style("fill", "none")
      .style("pointer-events", "all")
      .attr('transform', 'translate(' + margin.top + ')')
      .call(zoom);

    function updateChart() {
      // recover the new scale
      let newX = d3.event.transform.rescaleX(x);
      let newY = d3.event.transform.rescaleY(y);

      // update axes with these new boundaries
      xAxis.call(d3.axisBottom(newX).ticks(5))
      yAxis.call(d3.axisLeft(newY))
      // update location
      svg
        .select('.polyArea')
        .attr("d", d3.area()
          .x(function(d) {
            return newX(d.date)
          })
          .y0(newY(0))
          .y1(function(d) {
            return newY(d.value)
          })
          .curve(d3.curveStepAfter)
          .defined((d, i) => (i != null)))
    }
  })
.grid line {
  stroke: grey;
  stroke-opacity: 0.7;
  shape-rendering: crispEdges;
}

.grid path {
  stroke-width 0;
}
<main>
  <div id="my_dataviz">
  </div>
</main>
<script src="https://d3js.org/d3.v4.js"></script>

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top