Shiny无法渲染js文件 视频循环播放addEventListener报错求助
报错原因
你遇到的 Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') 报错,核心原因是你的JS脚本在Shiny页面初始化时就立即执行了,但id为myvideo的视频元素是通过renderUI动态生成的,脚本执行时该元素还未被渲染到DOM树中,document.getElementById('myvideo')返回null,自然无法调用addEventListener方法。
解决方案
两种常用修复方案,任选其一即可:
方案1:将JS逻辑与视频元素绑定输出
直接把JS代码写在renderUI的返回值内,确保视频元素生成后JS才执行,无需额外引入hope.js文件:
ui <- navbarPage("", tabPanel("exp", id = 'exp', fluidPage( fluidRow("i", uiOutput("vid")) ) ) ) server <- function(input, output, session) { output$vid <- renderUI({ tagList( tags$video(id = 'myvideo', type = 'video/mp4', src = "http://www.w3schools.com/html/mov_bbb.mp4", controls = "controls", controlsList = "nodownload", autoplay = "autoplay", muted = "muted" ), tags$script(HTML(" var myvid = document.getElementById('myvideo'); var myvids = [ 'http://www.w3schools.com/html/mov_bbb.mp4', 'http://www.w3schools.com/html/movie.mp4' ]; var activeVideo = 0; myvid.addEventListener('ended', function(e) { activeVideo = (++activeVideo) % myvids.length; myvid.src = myvids[activeVideo]; myvid.play(); }); ")) ) }) } shinyApp(ui, server)
注意:你原代码中加了
loop = "loop"属性,如果要实现多视频轮播效果,需要去掉该属性,否则单视频会自动循环,不会触发ended事件执行轮播逻辑。
方案2:修改hope.js添加加载监听
如果要保留独立的JS文件,可修改hope.js内容,监听Shiny动态输出完成事件后再执行逻辑:
$(document).on('shiny:value', function(event) { // 仅当vid输出完成时执行逻辑 if (event.name === 'vid') { var myvid = document.getElementById('myvideo'); var myvids = [ "http://www.w3schools.com/html/mov_bbb.mp4", "http://www.w3schools.com/html/movie.mp4" ]; var activeVideo = 0; myvid.addEventListener('ended', function(e) { activeVideo = (++activeVideo) % myvids.length; myvid.src = myvids[activeVideo]; myvid.play(); }); } });
该方案下你原有的Shiny代码不需要做其他修改,脚本会等uiOutput("vid")的内容完全渲染到页面后再执行,不会出现找不到元素的问题。
内容的提问来源于stack exchange,提问作者Srikanth Viswanathan
相关产品推荐
相关产品推荐

