随机选择视频时shinyjs函数失效,单选按钮不显示求助
Shiny双视频随机选择+播放完成显示按钮修复方案
问题根源
你的双视频版本有两个关键问题导致按钮无法显示:
- YouTube iframe未启用JavaScript API:所有视频的
src都缺少&enablejsapi=1参数,没有这个参数,YouTube Player API无法监听播放状态变化,自然触发不了显示按钮的逻辑。 - 冗余代码引发的潜在冲突:两个分支重复加载YouTube API脚本,虽不会直接报错,但易引发不必要的资源加载问题,且冗余代码增加了维护成本。
修复后的完整代码
library(shiny) library(shinyjs) ui <- fluidPage( useShinyjs(), uiOutput("video"), hidden( radioButtons( "instructions", "Have you finished watching the instructions?", choices = list( "Yes" = 'finished_instructions' ), width = '100%', selected = character(0) ) ) ) server <- function(input, output) { # 定义两个视频URL,已添加enablejsapi参数 video_urls <- c( "https://www.youtube.com/embed/-CrOeCzMFSQ?si=3pKfFn_AnvVXKASX&enablejsapi=1", "https://www.youtube.com/embed/HlYFfFUdPcw?si=v3V_FzhmndmYXJSS&enablejsapi=1" ) # 随机选择一个视频URL selected_video <- sample(video_urls, 1) output$video <- renderUI({ HTML( sprintf(' <div> <iframe id="my-iframe" width="560" height="315" src="%s" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ></iframe> <script type="text/javascript"> // 仅在API未加载时插入脚本,避免重复加载 if (typeof YT === "undefined") { var tag = document.createElement("script"); tag.src = "https://www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName("script")[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); } var player; function onYouTubeIframeAPIReady() { player = new YT.Player("my-iframe"); player.addEventListener("onStateChange", function(state){ // 状态0表示视频播放完成 if (state.data === 0) { document.getElementById("instructions").classList.remove("shinyjs-hide"); } }); } </script> </div>', selected_video) ) }) } shinyApp(ui, server)
关键修改说明
- 启用YouTube JS API:在每个视频URL末尾添加
&enablejsapi=1,这是监听播放状态的核心前提。 - 代码重构:用数组存储视频地址,通过
sample随机选择,避免重复编写两段几乎完全一致的HTML/JS代码,提升可维护性。 - API脚本加载优化:添加
typeof YT === "undefined"判断,确保仅在API未加载时插入脚本,避免重复加载资源。 - 简化DOM结构:移除不必要的
<html>和<body>标签,Shiny已提供完整页面结构,嵌套会导致DOM层级异常。
内容的提问来源于stack exchange,提问作者dot_codes
相关产品推荐
相关产品推荐

