Home > Software engineering >  D3 chart zooms the plot but not the axis - callback.apply is not a function
D3 chart zooms the plot but not the axis - callback.apply is not a function

Time:10-31

I've got a chart based on this tutorial

It's working very all apart from that when I zoom, the plot works but not the x-axis. The problem lies on my zoom function

const zoomed = (event) => {
      xScale.range(
        [margin.left, width - margin.right].map((d) =>
          event.transform.applyX(d)
        )
      );

      svg
        .selectAll(".bars rect")
        .attr("x", (d) => xScale(d.name))
        .attr("width", xScale.bandwidth());

      svg.selectAll(".x-axis").call(xAxis);
    };

The last line svg.selectAll(".x-axis").call(xAxis); throws the error: callback.apply is not a function.

if I log svg.selectAll(".x-axis") to the console I get the corresponding nodes with the call method attached so I don't know why's not working. I'm using d3 7.6.1 so this method might not work in the same way but after researching, I couldn't find an answer.

Here's a sandbox

CodePudding user response:

When you zoom, you want to recreate the x scale inside the g.x-axis element. To do that you need to call an axis generator on that element like that:

axisGenerator(d3.selectAll(".x-axis"))

which is equivalent to execute:

d3.selectAll(".x-axis").call(axisGenerator)

In your code the parameter to call() is not an axis generator. The xAxis variable is a d3 selection. So you first need to create an axis generator:

const xAxis = d3.axisBottom(xScale).tickSizeOuter(0);

And then initialize the x axis by creating a group element and call the axis generator on it:

svg.append("g")
   .attr("transform", `translate(0, ${height - margin.bottom})`)
   .attr("class", "x-axis")
   .call(xAxis)

In your zoomed function, you can then update the x axis like that:

svg.selectAll(".x-axis").call(xAxis);
  • Related