在R Shiny中渲染Quarto(.qmd)文件及交互式图表问题求助
问题背景
目标
希望在现有R Shiny应用中渲染多个Quarto文件(.qmd)。
当前方案
目前的做法是将Quarto文件渲染为HTML后,在R Shiny应用中展示,但交互式图表无法正常工作。已知可以在Quarto文档中嵌入Shiny,但需求是将带完整功能的Quarto内容嵌入R Shiny中。
可复现示例代码
app.R
library(shiny) library(quarto) ui <- fluidPage(titlePanel("Reproducable Example"), sidebarLayout( sidebarPanel( textInput(inputId = "user_argument", label = "Argument"), br(), actionButton("render_button", "Render Quarto ") ), mainPanel(uiOutput("quarto_output")) )) server <- function(input, output) { observeEvent(input$render_button, { quarto::quarto_render("example.qmd", execute_params = list(user_arg = input$user_argument)) html <- readLines("qmd_output.html") # Display html in output output$quarto_output <- renderUI({ tags$iframe(srcdoc = html, height = "500px", width = "100%") }) }) } # Run the application shinyApp(ui = ui, server = server)
example.qmd
--- title: "Quarto HTML Basics" format: html: code-tools: true self-contained: true output-file: "qmd_output.html" theme: cosmo execute: warning: false params: user_arg: NA --- ```{r} #| label: fig-temperatures #| fig-cap: "New Haven Temperatures" library(dygraphs) dygraph(nhtemp) %>% dyRangeSelector(dateWindow = c("1920-01-01", "1960-01-01"))
Argument
My name is r params$user_arg.
## 观察结果 - 由Quarto渲染的HTML中交互式图表可正常工作,但在R Shiny中嵌入该HTML后图表失效。 - 使用iframe是因为直接插入HTML会覆盖R Shiny的CSS样式。 ## 求助问题 1. 是否有其他方法可在R Shiny应用中渲染Quarto文件? 2. 若没有,是否有办法在Shiny中从HTML渲染交互式图表? --- # 解决方案 ### 问题1:替代方法嵌入Quarto内容到Shiny 有两种实用思路可以实现完整功能的Quarto内容嵌入: #### 思路1:非自包含HTML配合`includeHTML()`加载 修改Quarto输出配置,关闭自包含模式,让依赖的JS/CSS文件单独生成,再通过Shiny的`includeHTML()`加载渲染后的HTML,同时通过CSS隔离解决样式冲突: 1. 修改`example.qmd`的YAML配置: ```yaml --- title: "Quarto HTML Basics" format: html: code-tools: true self-contained: false # 关闭自包含模式 output-file: "qmd_output.html" theme: cosmo execute: warning: false params: user_arg: NA ---
- 修改Shiny的server逻辑:
server <- function(input, output) { observeEvent(input$render_button, { quarto::quarto_render("example.qmd", execute_params = list(user_arg = input$user_argument)) # 用自定义容器包裹HTML,方便样式隔离 output$quarto_output <- renderUI({ tags$div(class = "quarto-isolated", includeHTML("qmd_output.html")) }) }) }
可以添加自定义CSS文件(比如www/custom.css),给.quarto-isolated类添加样式隔离规则,避免影响Shiny原有样式。
思路2:将Quarto转为Shiny模块
如果不需要Quarto文档独立渲染,可以直接在Quarto中编写Shiny交互元素,将其作为Shiny应用的一部分运行:
- 修改
example.qmd的YAML配置:
--- title: "Quarto Shiny Module" format: html server: shiny params: user_arg: NA ---
- 在Shiny中直接调用
quarto::quarto_run()加载该文档,或者将Quarto内容拆分为Shiny的UI/Server模块,整合到现有应用中。
问题2:修复iframe中交互式图表失效的问题
iframe用srcdoc加载时,自包含HTML的JS资源路径可能解析异常,可通过以下方式解决:
方法1:用src替代srcdoc加载HTML
将渲染后的HTML放在Shiny的www目录下,直接指定iframe的src路径:
- 修改Quarto的
output-file配置为www/qmd_output.html - 修改Shiny的UI渲染逻辑:
output$quarto_output <- renderUI({ tags$iframe(src = "qmd_output.html", height = "500px", width = "100%", frameborder = 0) })
方法2:用样式隔离直接插入HTML
用htmltools::HTML()直接插入HTML内容,同时通过CSS隔离避免样式冲突:
server <- function(input, output) { observeEvent(input$render_button, { quarto::quarto_render("example.qmd", execute_params = list(user_arg = input$user_argument)) html_content <- paste(readLines("qmd_output.html"), collapse = "\n") output$quarto_output <- renderUI({ tags$div( style = "isolation: isolate; width:100%; height:500px; overflow:auto;", HTML(html_content) ) }) }) }
内容的提问来源于stack exchange,提问作者Pawan Rama Mali
相关产品推荐
相关产品推荐

