R Shiny嵌入Sankey图时遇NotFound错误,求解决方案
解决Shiny中嵌入Sankey HTML脚本出现NotFound错误的问题
问题核心原因
iframe的src属性要求传入文件路径或URL,而非直接的HTML字符串。你直接将HTML代码传给src=HTML(code),浏览器会把该字符串当作URL解析,自然找不到对应资源,从而触发NotFound错误。
方案1:直接渲染HTML(无需iframe)
你的HTML是静态可视化代码,完全可以直接通过renderUI输出内容,无需嵌套iframe,更简洁高效。
修正后的完整代码:
library(shiny) library(shinyWidgets) library(bslib) code = "<html> <head> <script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script> <script type='text/javascript'> google.charts.load('current', {'packages':['sankey']}); google.charts.setOnLoadCallback(drawChart); function drawChart() { var data = new google.visualization.DataTable(); data.addColumn('string', 'From'); data.addColumn('string', 'To'); data.addColumn('number', 'Weight'); data.addRows([ [ 'A', 'X', 5 ], [ 'A', 'Y', 7 ], [ 'A', 'Z', 6 ], [ 'B', 'X', 2 ], [ 'B', 'Y', 9 ], [ 'B', 'Z', 4 ] ]); // Sets chart options. var options = { width: 600, }; // Instantiates and draws our chart, passing in some options. var chart = new google.visualization.Sankey(document.getElementById('sankey_basic')); chart.draw(data, options); } </script> </head> <body> <div id='sankey_basic' style='width: 900px; height: 300px;'></div> </body> </html> " ui <- fluidPage( navbarPage(id="navid",collapsible = TRUE, position = "static-top", fluid = TRUE, windowTitle = "some title", theme=bslib::bs_theme(version= '3', bootswatch="flatly"), "some title", tabPanel("Intro", fluidPage( titlePanel(h3("Introduction")), fluid = TRUE) ), tabPanel('Input', sidebarLayout( sidebarPanel( actionBttn('sankey', 'Sankey', color='success', style = 'bordered') ), mainPanel( tabPanel('Tab1', uiOutput("map")) ) ))) server <- function(input,output){ output$map <- renderUI({ HTML(code) }) } shinyApp(ui, server)
方案2:临时文件配合iframe(必须用iframe时)
如果因场景限制必须使用iframe,可先将HTML代码写入临时文件,再把文件路径传给iframe的src:
library(shiny) library(shinyWidgets) library(bslib) code = "<html> <head> <script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script> <script type='text/javascript'> google.charts.load('current', {'packages':['sankey']}); google.charts.setOnLoadCallback(drawChart); function drawChart() { var data = new google.visualization.DataTable(); data.addColumn('string', 'From'); data.addColumn('string', 'To'); data.addColumn('number', 'Weight'); data.addRows([ [ 'A', 'X', 5 ], [ 'A', 'Y', 7 ], [ 'A', 'Z', 6 ], [ 'B', 'X', 2 ], [ 'B', 'Y', 9 ], [ 'B', 'Z', 4 ] ]); // Sets chart options. var options = { width: 600, }; // Instantiates and draws our chart, passing in some options. var chart = new google.visualization.Sankey(document.getElementById('sankey_basic')); chart.draw(data, options); } </script> </head> <body> <div id='sankey_basic' style='width: 900px; height: 300px;'></div> </body> </html> " ui <- fluidPage( navbarPage(id="navid",collapsible = TRUE, position = "static-top", fluid = TRUE, windowTitle = "some title", theme=bslib::bs_theme(version= '3', bootswatch="flatly"), "some title", tabPanel("Intro", fluidPage( titlePanel(h3("Introduction")), fluid = TRUE) ), tabPanel('Input', sidebarLayout( sidebarPanel( actionBttn('sankey', 'Sankey', color='success', style = 'bordered') ), mainPanel( tabPanel('Tab1', uiOutput("map")) ) ))) server <- function(input,output){ output$map <- renderUI({ # 创建临时HTML文件 temp_html <- tempfile(fileext = ".html") writeLines(code, temp_html) # 传入文件路径到iframe tags$iframe(seamless="seamless", src= normalizePath(temp_html), width=800, height=800) }) } shinyApp(ui, server)
额外修复点
- 移除了原代码中重复定义的
ui变量 - 修正了拼写错误
tabPabel为tabPanel - 将
htmlOutput替换为更适配UI渲染的uiOutput
内容的提问来源于stack exchange,提问作者Working dollar
相关产品推荐
相关产品推荐

