我发现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); });
这让我觉得我没有正确引用时间轴对象。那里的$(文档)让我觉得我不知道如何正确地获取时间轴元素。
由于我可以看到时间轴上的mouseenter事件,但看不到它的时间变化事件,我想我需要.on()调用,但是,我不认为我引用了时间轴元素正确/.
在@afterportfolio的第一个回复之后:
这是一篇很棒的文章,谢谢!我能够确认事件的样子;我已经能够听到_selected事件,但很高兴看到。
我正在尝试获取自定义时间值,该值使用图表中的可拖动线条,它是这样添加的:
addCustomTime("mytimevis", Sys.Date(), "CustomTimeId")
底层javascript小部件(http://visjs.org/docs/timeline)的文档显示了一个事件(" timechanged"),以及一个方法(" getCustomTime()")来获取访问它的价值,但我没有在跟踪中看到事件,也无法弄清楚如何使方法调用工作。
" timechanged"事件没有显示在跟踪中,这使我认为我需要从小部件的doc发出.on()调用才能启用该事件:
timeline.on('select', function (properties) {
alert('selected items: ' + properties.items);
});
我一直在努力让这个方法调用工作,因为理想情况下我想捕获它的变化,而且如果我可以使它工作,我应该能够使getCustomTime()方法工作井!
答案 0 :(得分:4)
我会回答假设您想要获取R
中的数据。如果我认为不正确,请告诉我,我会调整。
如果您不知道,我经常使用的一个技巧是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)
我突出显示了与select相关的消息。这告诉我们,我们可以观察或回应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)
})
}
)
如果我走错了路,或者这一切都没有任何意义,请告诉我。我感觉到你的痛苦,并且排除这种技术混合可能非常棘手。
答案 1 :(得分: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
会被触发,因此只会包含最后拖动的条形图,而不是所有竖条条形图,并且它不会为您提供一种方法来询问时间特定的酒吧。这有意义吗?
当然可以编写一些跟踪所有条形码的代码,但这很快就会非常混乱(例如,它必须确保在条形码时更新添加/移除)。所以我选择不去那个rabbithole。