Resizing browser window breaks D3 Plot

Running a ShinyApp and issue occurs when resizing the browser window the d3 plot breaks:

# app.R

library(shiny)
library(r2d3)

test <- d3Output("test")

server <- function(input, output) {
  dat <- data.frame(
    date =
      seq.Date(as.Date("2020-01-01"), as.Date("2020-01-03"), by = "days"),
    n = 1:3
  )
  output$test <- renderD3({
    r2d3(
      data = dat,
      script = "www/assets/example.js"
    )
  })
}

shinyApp(
  ui =
    htmlTemplate(
      "www/index.html",
      test = test
    ),
  server
)

Here's the d3.js script

r2d3.onRender(function (data, svg, width, height, options) {

    let parseTime = d3.timeParse("%Y-%m-%d");
    data.map(function (d) {
        d.date = parseTime(d.date),
            d.n = +d.n
    });

    let margin = ({ top: 10, right: 10, bottom: 60, left: 40 })

    let xScale = d3.scaleBand()
        .domain(data.map(d => d.date))
        .range([margin.left, width - margin.left])
        .padding(0.2);

    let yScale = d3.scaleLinear()
        .domain(d3.extent(data, d => d.n))
        .range([height - margin.bottom, 0]);

    let xAxis = d3.axisBottom()
        .tickFormat(d3.timeFormat("%Y-%m-%d"))
        .scale(xScale)
        .tickSizeOuter(0)

    let yAxis = d3.axisLeft()
        .scale(yScale)

    svg.selectAll('rect')
        .data(data)
        .enter().append("rect")
        .attr("width", xScale.bandwidth())
        .attr("x", d => xScale(d.date))
        .attr("y", d => yScale(d.n))
        .attr("height", d => height - margin.bottom - yScale(d.n))

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


    svg.append("g")
        .attr("class", "axis")
        .attr("transform", `translate(${margin.left}, 0)`)
        .call(yAxis)
});

And the index.html

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  {{ headContent() }}
</head>

<body>
  <div style="margin: 30px">
    {{ test }}
  </div>
</body>

</html>

Any help would be appreciated.

Thanks

I found a workaround for anyone encountering a similar issue, although, I don't think this is an ideal solution. The issue I think comes from how r2d3 handles resizing. If you make the resize function do nothing, and prevent the default callback, you can then set the <svg> ViewBox preserveAspectRatio attributes to handle the resizing of the container. Here's the updated js script:

r2d3.onRender(function (data, svg, width, height, options) {

    svg.attr("viewBox", `0 0 ${width} ${height}`)
       .attr("preserveAspectRatio", "xMinYMin meet")

    let parseTime = d3.timeParse("%Y-%m-%d");

    data.map(function (d) {
        d.date = parseTime(d.date),
            d.n = +d.n
    });

    let margin = ({ top: 10, right: 10, bottom: 60, left: 40 })

    let xScale = d3.scaleBand()
        .domain(data.map(d => d.date))
        .range([margin.left, width - margin.left])
        .padding(0.2);

    let yScale = d3.scaleLinear()
        .domain(d3.extent(data, d => d.n))
        .range([height - margin.bottom, 0]);

    let xAxis = d3.axisBottom()
        .tickFormat(d3.timeFormat("%Y-%m-%d"))
        .scale(xScale)
        .tickSizeOuter(0)

    let yAxis = d3.axisLeft()
        .scale(yScale)

    svg.selectAll('rect')
        .data(data)
        .enter().append("rect")
        .attr("width", xScale.bandwidth())
        .attr("x", d => xScale(d.date))
        .attr("y", d => yScale(d.n))
        .attr("height", d => height - margin.bottom - yScale(d.n))

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


    svg.append("g")
        .attr("class", "axis")
        .attr("transform", `translate(${margin.left}, 0)`)
        .call(yAxis)
});

r2d3.onResize(function (width, height) {

});

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.