R Shiny键输入绑定

时间:2014-07-26 17:17:34

标签: r shiny

在Shiny应用程序中,是否可以使用绑定来侦听用户按下的键?

我对JavaScript不太熟悉,但我正在寻找类似的东西:

window.onkeydown = function (e) {
    var code = e.keyCode ? e.keyCode : e.which;
    alert(code);
};

然后在server.R中使用键输入,例如:

shinyServer(function(input, output) {

  output$text <- renderText({
    paste('You have pressed the following key:', input$key)
  })

  # ...

})

4 个答案:

答案 0 :(得分:21)

您可以为按键添加侦听器。 Shiny.onInputChange可用于将按下的键绑定到闪亮变量:

library(shiny)
runApp( list(ui = bootstrapPage(
  verbatimTextOutput("results"),
  tags$script('
    $(document).on("keypress", function (e) {
       Shiny.onInputChange("mydata", e.which);
    });
  ') 
)
, server = function(input, output, session) {

  output$results = renderPrint({
    input$mydata
  })
}
))

您可以替换keydown个事件:

  tags$script('
    $(document).on("keydown", function (e) {
       Shiny.onInputChange("mydata", e.which);
    });
  ') 

答案 1 :(得分:1)

我一直在研究R软件包{keys},以解决此问题。基本上,它是Mousetrap javascript库的包装。这样,观察按键就很容易了:

library(shiny)
library(keys)

hotkeys <- c(
  "1", 
  "command+shift+k", 
  "up up down down left right left right b a enter"
)

ui <- fluidPage(
  useKeys(),
  keysInput("keys", hotkeys)
)

server <- function(input, output, session) {
  observeEvent(input$keys, {
    print(input$keys)
  })
}

shinyApp(ui, server)

此处提供更多信息:https://github.com/r4fun/keys

答案 2 :(得分:0)

如果您希望这可以用于多次按下,您可以创建一个额外的按键计数器,在按键上更新,将该值绑定到另一个变量,并观察计数器而不是键码。这是一些示例UI代码:

  tags$script('
    pressedKeyCount = 0;
    $(document).on("keydown", function (e) {
       Shiny.onInputChange("pressedKey", pressedKeyCount++);
       Shiny.onInputChange("pressedKeyId", e.which);
    });'
  )

以及相关的服务器代码:

  observeEvent(input$pressedKey, {
    if(input$pressedKeyId >= 49 && input$pressedKeyId <= 57){ # numbers
      values$numClick <- (input$pressedKeyId - 48);
      flipNumber();
    }
    if(input$pressedKeyId >= 37 && input$pressedKeyId <= 40){ # arrow keys
      arrowCode <- input$pressedKeyId - 37;
      xInc <- ((arrowCode+1) %% 2) * (arrowCode - 1);
      yInc <- ((arrowCode) %% 2) * (arrowCode - 2) * -1;
      if(!any(values$click == c(-1,-1))){
        values$click <- (((values$click - 1) + c(xInc, yInc) + 9) %% 9) + 1;
      }
    }
  });

答案 3 :(得分:0)

在@jdharrison和@gringer的基础上,我想要一个监听器,该监听器不仅可以跟踪是否已按下某个键,而且还可以跟踪当前按下/按下的键。

这给了我以下内容:

library(shiny)

ui = bootstrapPage(
  verbatimTextOutput("results"),
  ## keydown
  tags$script('
    downKeyCount = 0;
    $(document).on("keydown", function (e) {
       Shiny.onInputChange("downKey", downKeyCount++);
       Shiny.onInputChange("downKeyId", e.code);
    });'
  ),
  ## keyup
  tags$script('
    upKeyCount = 0;
    $(document).on("keyup", function (e) {
       Shiny.onInputChange("upKey", upKeyCount++);
       Shiny.onInputChange("upKeyId", e.code);
    });'
  )
)

server = function(input, output, session){
  keyRecords = reactiveValues()

  output$results = renderPrint({ 
    keys = reactiveValuesToList(keyRecords);
    names(keys[unlist(keys)]);
  })
  observeEvent(input$downKey, { keyRecords[[input$downKeyId]] = TRUE });
  observeEvent(input$upKey, { keyRecords[[input$upKeyId]] = FALSE });
}

shinyApp(ui = ui, server = server)

上方的关键详细信息/更改:

  • 我们使用e.code代替e.which,因为这为我们提供了有关按下哪些键的更有用的描述。例如。 "KeyA",而不是65。但是,这意味着我们无法区分大小写。
  • 我们使用keydownkeyup而不是keypress,因为keypress似乎超时。因此,如果您按住某个键,keypress将处于活动状态(返回TRUE)1-2秒钟,然后变为无效状态(返回FALSE)。
  • 我们最初使用@jdharrison的简单侦听器。但是,我们在上面的代码中使用@gringer的key-pressed-count方法,因为否则连续两次按下或释放同一键都不会响应。但是,如果要强制用户交替按键,则建议使用简单的侦听器。

Shiny v1.4,R v3.6.2