Adding padding to sides of zoomed in chart elements, including the x-axis

Hi all,

I’ve got kind of a tricky problem here. I’m building a zoomable/pannable weather chart (designed for mobile). I plan on having a static line in the middle of the screen which reads the value of the point it is currently over. Here’s an example.
Screenshot 2023-05-08 at 7.25.40 AM

To allow for this I’ve adding some padding (of half the screen width) to the right and left sides of the elements of the chart, so that I can pan the first and last values of the plot under the line. Specifically, I’ve added the padding to the range of the xScale.

  const xScalePath = d3
    .scaleTime()
    .domain(d3.extent(waves, (d) => new Date(d.date)))
    .range([
      dimensions.margin.left + padding,
      dimensions.width - dimensions.margin.right - padding
    ]);

This seems to work, except I’m having problems figuring out how to add this padding to either side of the x-axis, so that it also pans.

I want the domain of the xScale to extend to the entire, zoomed out, plot, but I can’t seem to adjust the range to account for the extra padding I want on either side. In this notebook I’ve also adding the padding to the range of the x-axis xScale and then transform on zoom. This has the tick marks lining up correctly with the chart, but as you can see it’s adding the padding to the current zoomed in view of the scale rather than the ends of the entire scale. I hope that makes sense.
Basically this is what I would like to see as I pan to either side
Screenshot 2023-05-08 at 7.21.36 AM

Here is the example in a notebook

Okay, figured out a solution in the second cell, but will it adds padding to each end, how do I specify the amount of padding to be 50% of the svg, so that the last data point is in the middle of the chart?

With translateExtent I randomly subtracting and 100 from x0 and x1, but does not add a padding of 100 pixels to each end. If my width of the inner chart area was 500px, how would I add 250pixels of padding to each end?


  const zoom = d3
    .zoom()
    .scaleExtent([zoomLevel, zoomLevel]) 
    .extent([
      [dimensions.margin.left, 0],
      [dimensions.width - dimensions.margin.right, dimensions.height]
    ])
    .translateExtent([
      [dimensions.margin.left - 100, -Infinity],
      [dimensions.width - dimensions.margin.right + 100, Infinity]
    ])

Okay, actually solved! I forgot I needed to account for the zoom scale factor applied.

    const zoom = d3
      .zoom()
      .scaleExtent([zoomLevel, zoomLevel])
      .translateExtent([
        [
          dimensions.margin.left -
            (dimensions.width + dimensions.margin.left - dimensions.margin.right) /
              2 /
              zoomLevel,
          -Infinity,
        ],
        [dimensions.width - dimensions.margin.right, Infinity],
      ])
      .on('zoom', zoomed)