In Shiny R, is there a way to run an observeEvent right after an observeEvent with no delay (issue with renderUI)?

◇◆丶佛笑我妖孽 提交于 2020-03-20 21:13:47

问题


Ok my title is a little bit confusing but let me explain.

I am using renderUI to get an audio tag, however, I want to start the audio at a lower volume because it is simply too loud.

The code below works fine, except because I added the delay it starts off at a higher volume and quickly goes to the lower volume but it is still very noticeable. Lowering the delay does not help, I've tried. If I remove the delay, the two observeEvents will run simultaneously and the volume will not be changed. If I move the js$runs tag (which lowers the volume) inside the first observeEvent, it won't work either. I think this is because renderUI does not actually render until the observeEvent has fully completed. Also, I don't think I can remove the renderUI because in my full app, I take a user input to play the audio.

Is there a way to initially start the audio tag at a lower volume? Or is there a way to run the renderUI immediately so that there will be no delay?

All help is appreciated, thanks.

library(shiny)
library(shinyjs)


jsCode <- 'shinyjs.runs = function setHalfVolume() {document.getElementById("myaudio").volume = 0.2;}'

get_audio <- function(){
    tags$audio(id = "myaudio", controls = NA, autoplay = NA, tags$source(src="aud.mpeg"))
}


ui <- fluidPage(
    useShinyjs(),
    extendShinyjs(text = jsCode),

    uiOutput("my_audio"),

    actionButton("guessbutton", "Submit")
)

server <- function(input, output) {
    observeEvent(input$guessbutton, {
        output$my_audio <- renderUI(get_audio())
        #js$runs()
    })

    observeEvent(input$guessbutton, {
        delay(100, js$runs())
    })
}

shinyApp(ui = ui, server = server)

回答1:


As far as I can tell you'll need to drop renderUI for this to work. Otherwise the id of your audio tag won't be existing, when you try to reduce the volume immediately (see your browser's console for according error messages).

I'd suggest you generate the audio tag only once and reduce the volume on app or session start-up, while dynammically changing the src argument of the audio tag.

Please see the following:

library(shiny)
library(shinyjs)

if(!dir.exists("www")){
    dir.create("www")
}

if(!file.exists("./www/Flamenco.ogg")){
    # for license see: https://commons.wikimedia.org/wiki/File:JCZA_-_JCzarnecki-Flamenco.ogg
    download.file("https://upload.wikimedia.org/wikipedia/commons/7/76/JCZA_-_JCzarnecki-Flamenco.ogg", destfile = "./www/Flamenco.ogg", mode = "wb") 
}

ui <- fluidPage(
    useShinyjs(),
    tags$audio(id = "myaudio", controls = NA, autoplay = NA, src = ""),
    p(),
    actionButton("guessbutton", "Submit")
)

server <- function(input, output) {
    runjs("document.getElementById('myaudio').volume = 0.2;") # initially reduce volume
    observeEvent(input$guessbutton, {
        runjs(sprintf("document.getElementById('myaudio').src = '%s';", "Flamenco.ogg")) # dynamically change src, replace "Flamenco.ogg" with your user input
    })
}

shinyApp(ui = ui, server = server)

PS: you can use shinyjs' hidden, hide and show or conditionalPanel if you want to hide the audio tag from your user until that button is pushed.



来源:https://stackoverflow.com/questions/60665381/in-shiny-r-is-there-a-way-to-run-an-observeevent-right-after-an-observeevent-wi

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!