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

sliderTextInput与JavaScript动画结合的异常问题求助

sliderTextInput与JavaScript动画结合的异常问题求助

我想通过多张PNG图片制作一个带暂停按钮和输入滑块的动画/GIF,但找了一圈没找到能同时提供暂停按钮和滑块的现成包,所以决定直接在Shiny里用JavaScript来实现动画。

原本用普通数字滑块的时候一切正常,但我想把滑块改成显示完整年份,就换成了sliderTextInput,结果现在出问题了。我对JavaScript不太熟,实在找不到问题出在哪,想请大家帮忙看看!

首先是我生成测试用PNG图片的代码:

# 创建随机图片
num_images <- 23

for (i in 1:num_images) {
  
  # 格式化图片序号为三位数字
  n <- formatC(as.numeric(i), width = 3, format = "d", flag = "0") 
  # 定义文件名
  file_name <- paste0(n, "_random_plot", ".png")
  
  # 打开PNG设备
  png(filename = file_name, width = 800, height = 600)
  
  # 生成随机散点图,标题显示对应年份
  plot(runif(100), runif(100), main = paste("Year:", 2000 + i - 1))
  dev.off()
}

然后是我的Shiny应用代码,核心是用JS控制动画和滑块交互:

library(shiny)
library(shinyWidgets)

ui <- fluidPage(
  actionButton("pause", "暂停/播放"),
  sliderTextInput(
    inputId = "year_slider",
    label = "选择年份:",
    choices = 2000:2022,
    selected = 2000
  ),
  uiOutput("image_container")
)

server <- function(input, output, session) {
  output$image_container <- renderUI({
    tags$div(
      id = "animation_img",
      tags$img(src = "001_random_plot.png", width = "800px")
    )
  })
  
  # 控制动画的JavaScript代码
  observe({
    tags$script(HTML('
      let intervalId;
      let currentIndex = 1;
      const totalImages = 23;
      
      // 绑定暂停/播放按钮事件
      document.getElementById("pause").addEventListener("click", function() {
        if (intervalId) {
          clearInterval(intervalId);
          intervalId = null;
        } else {
          intervalId = setInterval(updateImage, 1000);
        }
      });
      
      // 更新显示的图片
      function updateImage() {
        currentIndex = currentIndex % totalImages + 1;
        const imgNumber = currentIndex.toString().padStart(3, "0");
        document.getElementById("animation_img").innerHTML = `<img src="${imgNumber}_random_plot.png" width="800px">`;
        // 同步更新滑块值
        Shiny.setInputValue("year_slider", 2000 + currentIndex - 1);
      }
      
      // 监听滑块手动调整事件
      document.getElementById("year_slider").addEventListener("input", function(e) {
        const selectedYear = parseInt(e.target.value);
        currentIndex = selectedYear - 2000 + 1;
        const imgNumber = currentIndex.toString().padStart(3, "0");
        document.getElementById("animation_img").innerHTML = `<img src="${imgNumber}_random_plot.png" width="800px">`;
        // 手动调整滑块时暂停动画
        if (intervalId) {
          clearInterval(intervalId);
          intervalId = null;
        }
      });
      
      // 页面加载后自动启动动画
      intervalId = setInterval(updateImage, 1000);
    '))
  })
}

shinyApp(ui, server)

换成sliderTextInput之后,动画和滑块的同步出现了问题:有时候拖动滑块后图片不更新,有时候自动播放时滑块不会跟着变化,我怀疑是JS里获取滑块元素或者值的方式不对,但自己实在查不出来问题所在,有没有大佬能帮我看看呀?

备注:内容来源于stack exchange,提问作者Marie Veit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.16 10:33:00