如何从 timevis 中的可拖动垂直条中获取日期?
How can I get the date from the draggable vertical bar in timevis?
我发现 timevis 包对于显示时间段非常有用,它可以按预期显示我的数据。
我已经使用 addCustomTime() 函数添加了一条可拖动的垂直线,这也很好用,但是,我发现我无法获取该线的当前值。
底层的js小部件公开了与元素交互的函数,但我一直无法成功访问它们。我曾尝试使用 shinyjs 来捕捉时间线发出的事件,但我也无法让它发挥作用。
我对 R 和 shiny 相当满意,但在 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 文档在 "how to listen for a select event":
上有这个片段
timeline.on('select', function (properties) {
alert('selected items: ' + properties.items);
});
我尝试在 shinyjs::extendShinyjs() 调用中添加它,但这也不起作用。我添加了一个示例来监听有效的按键事件:
$(document).keypress(function(e) { alert('Key pressed: ' + e.which); });
这让我觉得我没有正确引用时间轴对象。那里的 $(document) 让我觉得我不知道如何正确获取时间轴元素。
因为我可以看到时间轴的 mouseenter 事件,但看不到它的时间更改事件,我想我需要 .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() 方法作为好吧!
假设
我会假设您想要获取 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)
我突出显示了与 select 有关的消息。这告诉我们可以观察或对 mytimevis_selected
.
做出反应
观察select事件
现在,让我们关闭 options(shiny.trace=FALSE)
并在收到 selected 消息时在 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)
})
}
)
跟进
如果我走错了路或者 none 这是否有意义,请告诉我。我感受到你的痛苦,对这种混合技术进行故障排除可能非常棘手。
(免责声明:我写了 timevis
包)
首先:Kenton 的回答非常好,OP 的尝试也很棒。
这更像是一个信息 post。
为什么您尝试的方法不起作用
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 个事件,只要它们发生变化,小部件就会自动导出到 shiny:数据、所选项目、所有项目的 ID 和当前可见时间 window。我决定不使用 on('timechanged')
事件,因为它的行为与其他事件不同:它一次只会 return 一项。
这是什么意思?比如input$timeline_data
总是returns整个数据在这一刻; input$timeline_select
总是告诉你此时所有选中的项目是什么; input$timeline_timechanged
每次拖动不同的垂直条时都会被触发,因此只会包含最后拖动的条,而不是所有条,并且它不会让您在一个特定的条中询问时间.这有意义吗?
当然可以编写一些代码来跟踪所有柱状图,但这很快就会变得非常混乱(例如,必须确保在柱状图 added/removed).所以我选择不去那个兔子洞。
我发现 timevis 包对于显示时间段非常有用,它可以按预期显示我的数据。
我已经使用 addCustomTime() 函数添加了一条可拖动的垂直线,这也很好用,但是,我发现我无法获取该线的当前值。
底层的js小部件公开了与元素交互的函数,但我一直无法成功访问它们。我曾尝试使用 shinyjs 来捕捉时间线发出的事件,但我也无法让它发挥作用。
我对 R 和 shiny 相当满意,但在 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 文档在 "how to listen for a select event":
上有这个片段timeline.on('select', function (properties) {
alert('selected items: ' + properties.items);
});
我尝试在 shinyjs::extendShinyjs() 调用中添加它,但这也不起作用。我添加了一个示例来监听有效的按键事件:
$(document).keypress(function(e) { alert('Key pressed: ' + e.which); });
这让我觉得我没有正确引用时间轴对象。那里的 $(document) 让我觉得我不知道如何正确获取时间轴元素。
因为我可以看到时间轴的 mouseenter 事件,但看不到它的时间更改事件,我想我需要 .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() 方法作为好吧!
假设
我会假设您想要获取 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)
我突出显示了与 select 有关的消息。这告诉我们可以观察或对 mytimevis_selected
.
观察select事件
现在,让我们关闭 options(shiny.trace=FALSE)
并在收到 selected 消息时在 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)
})
}
)
跟进
如果我走错了路或者 none 这是否有意义,请告诉我。我感受到你的痛苦,对这种混合技术进行故障排除可能非常棘手。
(免责声明:我写了 timevis
包)
首先:Kenton 的回答非常好,OP 的尝试也很棒。
这更像是一个信息 post。
为什么您尝试的方法不起作用
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 个事件,只要它们发生变化,小部件就会自动导出到 shiny:数据、所选项目、所有项目的 ID 和当前可见时间 window。我决定不使用 on('timechanged')
事件,因为它的行为与其他事件不同:它一次只会 return 一项。
这是什么意思?比如input$timeline_data
总是returns整个数据在这一刻; input$timeline_select
总是告诉你此时所有选中的项目是什么; input$timeline_timechanged
每次拖动不同的垂直条时都会被触发,因此只会包含最后拖动的条,而不是所有条,并且它不会让您在一个特定的条中询问时间.这有意义吗?
当然可以编写一些代码来跟踪所有柱状图,但这很快就会变得非常混乱(例如,必须确保在柱状图 added/removed).所以我选择不去那个兔子洞。