You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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
---
  1. 修改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应用的一部分运行:

  1. 修改example.qmd的YAML配置:
---
title: "Quarto Shiny Module"
format: html
server: shiny
params:
  user_arg: NA
---
  1. 在Shiny中直接调用quarto::quarto_run()加载该文档,或者将Quarto内容拆分为Shiny的UI/Server模块,整合到现有应用中。

问题2:修复iframe中交互式图表失效的问题

iframe用srcdoc加载时,自包含HTML的JS资源路径可能解析异常,可通过以下方式解决:

方法1:用src替代srcdoc加载HTML

将渲染后的HTML放在Shiny的www目录下,直接指定iframe的src路径:

  1. 修改Quarto的output-file配置为www/qmd_output.html
  2. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 16:52:03