1

我发现 timevis 包对于显示时间段非常有用,并且它按预期工作以显示我的数据。

我使用 addCustomTime() 函数添加了一条可拖动的垂直线,这也很好用,但是,我发现我无法获取该线的当前值。

底层 js 小部件公开了与元素交互的函数,但我无法成功访问它们。我试图使用 shinyjs 来捕捉时间线发出的事件,但我也无法让它工作。

我在 R 和闪亮方面相当舒服,但在 js 方面非常新手,所以我怀疑我只是错过了这个技巧。

在我的 ui.R 中,我创建了一个 timevisOutput 对象:

fluidPage(
  timevisOutput("timeline")
)

我正在尝试收听“timechanged”事件:http: //visjs.org/docs/timeline/#Events

当我在 server.R 中添加带有 shinyjs 的侦听器时,我能够看到“mouseenter”事件,但“timechanged”处理程序似乎没有触发:

onevent("mouseenter", "timeline", print("timeline: mouseenter"))
onevent("timechanged", "timeline", print("Saw timechanged!"))

visjs 文档有这个关于“如何监听选择事件”的片段:

timeline.on('select', function (properties) {
  alert('selected items: ' + properties.items);
});

我尝试在 shinyjs::extendShinyjs() 调用中添加它,但这也不起作用。我添加了一个示例来监听有效的 keydown 事件:

$(document).keypress(function(e) { alert('Key pressed: ' + e.which); });

所以这让我觉得我没有正确引用时间线对象。那里的 $(document) 让我觉得我不知道如何正确获取时间线元素。

由于我可以看到时间轴的 mouseenter 事件,但看不到它的 timechanged 事件,我认为我需要 .on() 调用,但是,我认为我没有正确引用时间轴元素/。

在@timelyportfolio 的第一个回复之后:

那是一篇很棒的文章,谢谢!我能够确认事件的外观;我已经能够收听 _selected 事件,但很高兴看到。

我正在尝试获取自定义时间值,它在图表中使用可拖动的线,添加如下:

addCustomTime("mytimevis", Sys.Date(), "CustomTimeId")

底层 javascript 小部件 ( http://visjs.org/docs/timeline ) 的文档显示了一个事件 ("timechanged") 和一个方法 ("getCustomTime()") 以访问其值,但我没有'在跟踪中看不到事件,我也无法弄清楚如何使方法调用起作用。

“timechanged”事件没有出现在跟踪中,这让我觉得我需要从小部件的文档中调用 .on() 才能启用该事件:

timeline.on('select', function (properties) {
  alert('selected items: ' + properties.items);
});

我一直在努力使该方法调用起作用,因为理想情况下我想捕捉它的变化,而且如果我能让它工作,我应该能够让 getCustomTime() 方法也能工作!

4

2 回答 2

4

假设

我会假设您希望将数据放入R. 如果我假设不正确,请告诉我,我会调整。

带有 shiny.trace 的消息

如果您不知道,我经常使用的一个技巧是options(shiny.trace=TRUE),它将用通过 websocket 发送的所有消息填满您的屏幕。这是我在运行以下代码时看到的内容。

library(timevis)

data <- data.frame(
  id      = 1:4,
  content = c("Item one"  , "Item two"  ,"Ranged item", "Item four"),
  start   = c("2016-01-10", "2016-01-11", "2016-01-20", "2016-02-14 15:00:00"),
  end     = c(NA          ,           NA, "2016-02-04", NA)
)

tv <- timevis(data)

# now let's see what messages we get in Shiny
library(shiny)
options(shiny.trace=TRUE)

ui <- timevisOutput("mytimevis")
server <- function(input,output,session) {
  output$mytimevis <- renderTimevis({tv})
}

shinyApp(ui,server)

选择时来自 timevis 的消息屏幕截图

我突出显示了与选择有关的消息。这告诉我们我们可以观察或反应mytimevis_selected

观察选择事件

现在,当我们收到选定的消息时,让我们关闭options(shiny.trace=FALSE)并在控制台中打印。R

options(shiny.trace=FALSE)

ui <- timevisOutput("mytimevis")
server <- function(input,output,session) {
  output$mytimevis <- renderTimevis({tv})

  observeEvent(
    input$mytimevis_selected,
    {
      print(input$mytimevis_selected)
    }
  )
}

shinyApp(ui,server)

添加时变处理程序

根据评论并重新阅读您的问题,我现在了解到您想为timechanged添加一个事件处理程序。我认为这段代码会帮助你度过难关。

library(timevis)
library(shiny)
library(htmltools)
library(htmlwidgets)
library(magrittr)

tv <- timevis() %>%
  addCustomTime(Sys.Date() - 1, "yesterday") %>%
  # add an event handler since this is not one
  #   timevis provides
  htmlwidgets::onRender(
"
function(el,x) {
  // this will be our instance
  var tv = this.timeline;

  tv.on('timechanged', function(id, time) {
    //uncomment debugger if you want to stop here
    //debugger;
    Shiny.onInputChange(el.id + '_timechanged', {id:id, time:time})
  });
}
"
  )


shinyApp(
  ui = fluidPage(
    timevisOutput("timeline"),
    actionButton("btn", "Add time bar 24 hours ago")
  ),
  server = function(input, output) {
    output$timeline <- renderTimevis(
      tv
    )
    observeEvent(input$timeline_timechanged, {
      str(input$timeline_timechanged)
    })
  }
)

跟进

如果我走错了路,或者这些都没有任何意义,请告诉我。我感受到了您的痛苦,并且对这种混合技术进行故障排除可能非常棘手。

于 2016-12-07T05:25:08.363 回答
2

(免责声明:我写的timevis包)

首先:Kenton 的回答非常好,OP 的尝试也很棒。

这更像是一个信息性帖子。

为什么您尝试的方法不起作用

onevent("timechanged", ...)不起作用的原因是该onevent()函数适用于任何标准 javascript 事件,但不适用于不同插件提供的特定事件。

要绑定这样的自定义事件,您需要编写一些简短的自定义 JavaScript 代码。因此,查看 visjs 文档并找到timeline.on('select', ...)代码是正确的路径,但是(正如您所怀疑的)您没有正确引用时间线对象。

出于这个原因,我确保导出实际的底层对象,以便像您这样的人可以以原始格式对其进行操作。要从 timevis 访问时间线对象,请使用$(id)[0].widget.timeline. 由于时间轴的 id 是timeline并且您想调用该on()函数,因此您可以执行类似$("#timeline")[0].widget.timeline.on('select', ...).

为什么这个功能不存在

当我查看 visjs 的文档时,我决定有 4 个事件,当它们发生变化时,小部件会自动导出到闪亮:数据、所选项目、所有项目的 ID 和当前可见的时间窗口。我决定不使用该on('timechanged')事件,因为它的行为与其他所有事件不同:它一次只会返回一个项目。

我的意思是什么?例如,input$timeline_data总是返回此刻的全部数据;input$timeline_select总是告诉你此刻所有选中的项目是什么;input$timeline_timechanged每次拖动不同的垂直条时都会被触发,因此将仅包含最后一个拖动的条,而不是所有条,并且它不会为您提供在一个特定条中询问时间的方法。那有意义吗?

当然,可以编写一些代码来跟踪所有条形图,但是很快就会变得非常混乱(例如,必须确保在添加/删除条形图时得到更新)。所以我选择不去那个兔子洞。

于 2016-12-08T05:40:25.543 回答