问题
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