如何实现Shiny App生成并保存可交互3D HTML图?
解决Shiny中rgl保存3D交互HTML为空的问题
问题根源
原代码使用open3d()会唤起桌面端的rgl可视化窗口,但Shiny服务器端的rglwidget()无法捕获这个桌面窗口的3D场景,导致保存的HTML文件内容为空。此外,直接用字符串拼接路径存在跨系统兼容性风险。
修正后的代码
# Libraries --------------------------------------------------------------- library(shiny) library(shinyDirectoryInput) library(tidyverse) library(rgl) # START: UI --------------------------------------------------------------- ui <- fluidPage( titlePanel(strong("Data Analysis App")), sidebarLayout( sidebarPanel( h3(em("Save Analysis")), directoryInput('directory', label = '选择保存文件夹'), h3(em("Run Analysis")), br(), actionButton("run_button", label = "开始生成") ), mainPanel( h1("操作说明"), br(), p("1) 选择3D图的保存目录"), br(), p("2) 点击「开始生成」按钮") ) ) ) # START: Server ----------------------------------------------------------- server <- function(input, output, session) { # 目录选择逻辑 observeEvent( ignoreNULL = TRUE, eventExpr = input$directory, handlerExpr = { if (input$directory > 0) { selected_directory <- choose.dir(default = readDirectoryInput(session, 'directory')) updateDirectoryInput(session, 'directory', value = selected_directory) } } ) # 点击按钮生成并保存3D图 observeEvent(input$run_button, { # 用file.path保证跨系统路径正确 file_path <- file.path(readDirectoryInput(session, 'directory'), "test.html") # 创建无界面rgl设备,避免弹出桌面窗口,同时让场景可被rglwidget捕获 rgl.open(useNULL = TRUE) # 绘制3D图 plot3d(x = iris$Sepal.Length, y = iris$Sepal.Width, z = iris$Petal.Length) # 保存为交互式HTML htmlwidgets::saveWidget( rglwidget(width = 800, height = 800), file = file_path, libdir = "HTML-dependencies", selfcontained = FALSE ) # 关闭rgl设备释放资源 rgl.close() }) } shinyApp(ui = ui, server = server)
关键修正点
- 替换
open3d()为rgl.open(useNULL = TRUE):创建无界面的rgl渲染设备,让3D场景在Shiny服务器端生成,确保rglwidget()能正确捕获场景内容。 - 使用
file.path()拼接路径:自动适配Windows/macOS/Linux的路径分隔符,避免路径错误。 - 添加
rgl.close():生成完成后关闭rgl设备,释放系统资源。
内容的提问来源于stack exchange,提问作者fneri
相关产品推荐
相关产品推荐

