css r -如何在shinyapp中自动滚动到div的底部?

9o685dep  于 2023-05-02  发布在  其他
关注(0)|答案(2)|浏览(128)

我想保持滚动条在底部每当新的内容被添加。

printText <- function() {
  for(i in 1:20){
    Sys.sleep(0.1)
    shinyjs::html("text", paste("My text", i, "<br>"), add = TRUE)
    y = i + 1
  }
  return(y)
}
library(shiny)
library(shinyjs)
runApp(list(
  ui = shinyUI(fluidPage(
    shinyjs::useShinyjs(),
    titlePanel("Print consol output"),
    sidebarLayout(
      sidebarPanel(actionButton("go", "Go")),
      mainPanel(
        style = "overflow-y:scroll; max-height: 100px; position:relative;",
        div(id = "text")
      )
    )
  )),
  server = shinyServer(function(input, output, session){
    observeEvent(input$go, {
      shinyjs::html("text", "")
      y <- printText()
    })
  })
))

我已经找到了调用javascript的相关解决方案,但它在我的情况下不起作用。
下面是js代码:

function scrollToBottom(){
  var elem = document.getElementById('text');
  elem.scrollTop = elem.scrollHeight;
};

我尝试在div之前添加includeScript来调用函数,例如,includeScript(“myJSfile.js”),但它没有工作。
我做错了什么?
非常感谢。

vyswwuz2

vyswwuz21#

这对我很有效:

library(shiny)

ui <- fluidPage(
  tags$head(
    # Some css to style the div to make it more easily visible
    tags$style(
      '#outDiv{
        height:150px;
        overflow-y:scroll;
        border: 1px solid black;
        border-radius:15px;
        padding:15px;
      }
      '
    ),
    # Custom shiny to javascript binding
    # scrolls "outDiv" to bottom once called
    tags$script(
      '
      Shiny.addCustomMessageHandler("scrollCallback",
        function(color) {
          var objDiv = document.getElementById("outDiv");
          objDiv.scrollTop = objDiv.scrollHeight;
        }
      );'
    )
  ),
  sidebarLayout(
    sidebarPanel(
      actionButton('go','Start Printing')
    ),
    mainPanel(
      div(id='outDiv',
        htmlOutput('out')
      )
      # Text output

    )
  )
)

server <- function(input, output, session) {
  autoInvalidate <- reactiveTimer(250, session) # Timer function

  ptm      <- proc.time() # Start time
  startTxt <- ''          # Start string to show on screen

  # Function to print new line when reactiveTimer invalidates
  startPrint <- function(){
    output$out <- renderText({ 
      ctm <- proc.time() - ptm
      autoInvalidate() # Start invalidating function every n miliseconds

      # Format string to print
      curr.font <- sample(colours(distinct=T), 1) 
      curr.txt  <- sprintf('<font color="%s"> %4.2f</font> seconds from start <br>', curr.font, ctm[[3]]) 
      startTxt  <<- paste(startTxt, curr.txt, collapse = '')

      # Call custom javascript to scroll window
      session$sendCustomMessage(type = "scrollCallback", 1)

      return(startTxt)
    })
  }

  observeEvent(input$go,{
    startPrint()
  })
}

runApp(shinyApp(ui,server))

这里的技巧是,每次更新文本输出时,我都调用Javascript函数来滚动div。让我知道这个答案是否令人费解。

yvfmudvl

yvfmudvl2#

下面是一个可接受答案的最小可重复示例,以更好地突出实现该方法绝对必要的内容。

library(shiny)

ui = fluidPage(
  tags$head(
    tags$script(
      '
      Shiny.addCustomMessageHandler("scrollCallback",
        function(foo) {
          var objDiv = document.getElementById("outDiv");
          objDiv.scrollTop = objDiv.scrollHeight;
        }
      );'
    )
  ),
  fluidPage(
    mainPanel(
      div(id='outDiv',style='height:150px;overflow-y:scroll;',
          uiOutput('out')
      )
    )
  )
)

server = function(input, output, session) {
  
  new_text = ''
  autoInvalidate <- reactiveTimer(250, session)
  
  observeEvent(autoInvalidate(),{
    new_text <<- paste(new_text,'<br>',sample(letters,1))
    output$out = renderUI({HTML(new_text)})
    session$sendCustomMessage(type='scrollCallback', 'foo')
  })

}

runApp(shinyApp(ui,server))

相关问题