DT::datatable中plotly图表初始宽度不一致问题求助
问题:Shiny中DT表格内Plotly图表初始宽度不一致

表格内的Plotly图表初始渲染时宽度不一致,仅第一行图表占满列宽。调整窗口大小后所有图表会自动适配为正常宽度,且该问题在不同浏览器中均存在。期望所有图表从初始渲染时就保持一致的最大宽度。
复现代码
library(shiny) library(plotly) ui <- fluidPage( htmltools::findDependencies(plotlyOutput("pl")), DT::DTOutput("dt") ) server <- function(input, output, session) { output$dt <- DT::renderDT({ df <- data.frame( x=paste0("plot",1:4), z=sapply(1:4, function(ii) { as.character(plotlyOutput(paste0("plotly", ii), height = 100)) }) ) DT::datatable(df, escape = FALSE, options = list( preDrawCallback = V8::JS('function() { Shiny.unbindAll(this.api().table().node()); }'), drawCallback = V8::JS('function() { Shiny.bindAll(this.api().table().node()); } ') )) }) output$plotly1 <- renderPlotly(plot_ly(iris, x=~Sepal.Width, y=~Sepal.Length, color=~Species, type = "scatter") |> plotly::layout(title = list(text= "plotly1"))) output$plotly2 <- renderPlotly(plot_ly(iris, x=~Sepal.Width, y=~Sepal.Length, color=~Species, type = "scatter") |> plotly::layout(title = list(text= "plotly2"))) output$plotly3 <- renderPlotly(plot_ly(iris, x=~Sepal.Width, y=~Sepal.Length, color=~Species, type = "scatter") |> plotly::layout(title = list(text= "plotly3"))) output$plotly4 <- renderPlotly(plot_ly(iris, x=~Sepal.Width, y=~Sepal.Length, color=~Species, type = "scatter") |> plotly::layout(title = list(text= "plotly4"))) } shinyApp(ui, server)
解决方案
方法1:强制设置Plotly容器与图表宽度
在创建plotlyOutput时显式指定宽度为100%,同时在图表的layout中也配置宽度为100%,确保容器和图表都占满所在列的宽度:
修改生成plotlyOutput的代码:
z=sapply(1:4, function(ii) { as.character(plotlyOutput(paste0("plotly", ii), height = 100, width = "100%")) })
同时更新每个renderPlotly中的layout配置:
# 以plotly1为例,其余三个同理 output$plotly1 <- renderPlotly( plot_ly(iris, x=~Sepal.Width, y=~Sepal.Length, color=~Species, type = "scatter") |> plotly::layout(title = list(text= "plotly1"), width = "100%") )
方法2:在DT绘制完成后触发Plotly重绘
利用DT的drawCallback,在表格渲染完成后遍历所有Plotly图表,调用relayout方法强制重计算宽度:
修改DT的options中的drawCallback:
options = list( preDrawCallback = V8::JS('function() { Shiny.unbindAll(this.api().table().node()); }'), drawCallback = V8::JS('function() { Shiny.bindAll(this.api().table().node()); // 遍历所有Plotly容器,触发宽度适配 document.querySelectorAll(".plotly").forEach(function(el) { if(Plotly) Plotly.relayout(el, {width: el.offsetWidth}); }); } ') )
方法3:用CSS强制约束容器宽度
在UI中添加自定义CSS样式,强制所有Plotly输出容器的宽度为100%,优先级设为最高:
ui <- fluidPage( tags$style(HTML(" .plotly { width: 100% !important; } ")), htmltools::findDependencies(plotlyOutput("pl")), DT::DTOutput("dt") )
内容的提问来源于stack exchange,提问作者Noskario
相关产品推荐
相关产品推荐

