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

如何在Shiny应用中为JS导出功能添加加载器

给Shiny应用的JS导出PDF功能添加加载器

以下是针对需求修改后的完整代码,通过纯前端JS实现加载器的显示与隐藏,适配原有导出逻辑:

library(shiny)
library(shinyWidgets)

js <- "
    function Export(){
      // 显示加载器并禁用按钮
      $('#loader').show();
      $('#export').prop('disabled', true);
      
      var $img = $('#img');
      var width = $img.width();
      var height = $img.height();
      
      domtoimage.toPng($('html')[0])
        .then(function (blob) {
          var pdf = new jsPDF('p', 'mm', 'a4');
          var imgProps = pdf.getImageProperties(blob);
          var pdfWidth = pdf.internal.pageSize.width;
          var pdfHeight = pdf.internal.pageSize.height;
          var widthRatio = pdfWidth / width;
          var heightRatio = pdfHeight / height;
          var ratio = Math.min(widthRatio, heightRatio);
          var w = imgProps.width * ratio;
          var h = imgProps.height * ratio;
          pdf.addImage(blob, 'PNG', 0, 0, w, h);
          pdf.save('allPage.pdf');
        })
        .catch(function(error) {
          console.error('导出失败:', error);
        })
        .finally(function() {
          // 无论成功失败,隐藏加载器并启用按钮
          $('#loader').hide();
          $('#export').prop('disabled', false);
        });
    }
    "

ui <- fluidPage(
  tags$head(
    tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"),
    tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/dom-to-image/2.6.0/dom-to-image.min.js"),
    tags$script(HTML(js)),
    tags$style(HTML("
      #loader {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, 0.5);
        display: flex;
        justify-content: center;
        align-items: center;
        z-index: 9999;
      }
      .loader-content {
        color: white;
        font-size: 18px;
        text-align: center;
      }
      .loader-spinner {
        border: 4px solid rgba(255, 255, 255, 0.3);
        border-top: 4px solid white;
        border-radius: 50%;
        width: 40px;
        height: 40px;
        animation: spin 1s linear infinite;
        margin: 0 auto 10px;
      }
      @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
      }
    "))
  ),
  
  # 加载器元素,默认隐藏
  div(id = "loader", style = "display: none;",
      div(class = "loader-content",
          div(class = "loader-spinner"),
          "正在导出PDF,请稍候..."
      )
  ),
  
  # 背景图片
  tags$img(id = "img",
           src = "http://upload.wikimedia.org/wikipedia/commons/5/5d/AaronEckhart10TIFF.jpg",
           style = 'position: absolute; width: 1250px; height: 880px;'),
  
  div(
    id = "container1",
    style = "position: absolute; left: 30px; top: 170px; display: inline-block; vertical-align: middle; width: 300px;",
    
    actionButton("export", "Export to PDF",
                 onclick = "Export();")
  )
  
)

server <- function(input, output, session) {
  
}

shinyApp(ui, server)

关键修改说明

  • 加载器UI与样式:新增全屏半透明加载层,包含旋转动画和提示文本,通过CSS设置层级置顶,确保覆盖所有页面内容,清晰提示用户当前处于加载状态。
  • JS逻辑优化:
    • 导出开始时立即显示加载器,并禁用导出按钮,防止重复触发操作
    • 使用finally回调统一处理加载器隐藏和按钮启用,无论导出成功或失败,都能恢复页面正常状态
    • 添加catch回调捕获导出过程中的错误,便于调试排查问题
  • 无额外依赖:纯前端实现,无需修改服务器端逻辑,完美适配原有JS导出流程

内容的提问来源于stack exchange,提问作者TarJae

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 20:05:13