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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 22:47:48