英文:
Using shiny and plotly, how can I animate a vertical line on a time series that scrolls with the current frame of an embedded movie?
问题
我理解了。以下是您要求的中文翻译:
我正在使用R、shiny和plotly制作一个仪表板。我想展示一个视频,并在其下方显示与视频中的每一刻相关的时间序列图。当用户播放视频时,我想在图中显示一个垂直线,该线对应于视频中的当前播放时间。换句话说,这是一种类似于滚动播放头的功能。
这里的代码和示例数据实现了我想要的,但效果不佳,存在两个问题。
1. 这条线只会每秒更新一次。理想情况下,我希望它能更平滑地移动,类似于每秒30帧,以匹配视频。
2. 据我了解plotly和shiny(即了解不太深刻),每次移动垂直线时,我都在重新绘制整个图表。在这里的示例数据中,这可能不是问题。但最终我将使用非常大的数据集并进行一些平滑处理,因此我只想绘制时间序列一次,并单独更新垂直线的位置。关于使用plotlyProxyInvoke的说明可以在[这里](https://plotly-r.com/linking-views-with-shiny.html#proxies)找到,但我无法在我的情况下实现这些想法。
我在R和ggplot方面相当熟练,但这是我第一次同时使用shiny和plotly,如果我漏掉了一些基本的东西,还请谅解。非常感谢任何建议!
英文:
I am making a dashboard using R, shiny and plotly. I would like to show a video, and beneath it a plot of a time series that relates to each moment in the video. When the user plays the video, I want to show a vertical line on the plot that corresponds to current playing time on the video. In other words, it's a sort of scrolling playhead.
The code and toy data here achieves what I want, but poorly. There are two problems.
-
The line only updates about once a second. Ideally, I'd like it to move more smoothly, something like 30 frames per second to match the video.
-
As I understand plotly and shiny (ie not very well), then each time I am moving the vertical line, I am re-drawing the whole plot. With the toy data here, that may not be problem. But eventually I will be using very large data sets and doing some smoothing, so I only want to draw the time series once, and update the vertical line position by itself. There are instructions about using plotlyProxyInvoke herebut I can't implement those ideas in my case.
I'm fairly competent in R and ggplot, but this is my first time with both shiny and plotly, so apologies if I'd missing something basic. Any suggestions very much appreciated!
library(shiny)
library(video)
data <- data.frame(t=1:45,y=sample(x=50,size = 45))
ui <- fluidPage(
mainPanel(
video(
"https://vjs.zencdn.net/v/oceans.mp4",
elementId = "video"),
tags$p( "Duration:",
textOutput("video_seek", container = tags$strong, inline = TRUE), "/",
textOutput("video_duration", container = tags$strong, inline = TRUE) ),
plotlyOutput(outputId = "sparkline")
) )
server <- function(input, output,session) {
output$sparkline <- renderPlotly({
p <- ggplotly( ggplot(data,aes(x=t,y=y))+geom_line() )
add_segments(p,x=input$video_seek,xend=input$video_seek,y=0,yend=50,inherit = F) })
output$video_duration <- renderText({input$video_duration })
output$video_seek <- renderText({ input$video_seek })
}
shinyApp(ui,server)
答案1
得分: 0
你可以使用 plotlyProxy
与 plotlyProxyInvoke
。
想法是在 renderPlotly
函数中创建基本的图表,并使用 plotlyProxyInvoke
更新对应于小型图表的迹线。
library(shiny)
library(video)
library(plotly)
data <- data.frame(t = 1:45,
y = sample(50, size = 45))
server <- function(input, output,session) {
output$sparkline <- renderPlotly({
plot_ly(
data,
x = ~t,
y = ~y,
type = "scatter",
mode = "lines"
) %>%
add_segments(x = 0, xend = 0, y = 0, yend = 50) %>%
layout(xaxis = list(range = c(0, ceiling(req(input$video_duration)))))
})
output$video_duration <- renderText(input$video_duration)
output$video_seek <- renderText(input$video_seek)
observeEvent(input$video_seek, {
plotlyProxy("sparkline") %>%
plotlyProxyInvoke("restyle",
list(x = list(rep(input$video_seek, 2))),
1)
})
}
英文:
You can use plotlyProxy
together with plotlyProxyInvoke
.
Idea is that you make the basic plot in the renderPlotly
function and use plotlyProxyInvoke
to update the trace corresponding to the sparkline.
library(shiny)
library(video)
library(plotly)
data <- data.frame(t = 1:45,
y = sample(50, size = 45))
server <- function(input, output,session) {
output$sparkline <- renderPlotly({
plot_ly(
data,
x = ~t,
y = ~y,
type = "scatter",
mode = "lines"
) %>%
add_segments(x = 0, xend = 0, y = 0, yend = 50) %>%
layout(xaxis = list(range = c(0, ceiling(req(input$video_duration)))))
})
output$video_duration <- renderText(input$video_duration)
output$video_seek <- renderText(input$video_seek)
observeEvent(input$video_seek, {
plotlyProxy("sparkline") %>%
plotlyProxyInvoke("restyle",
list(x = list(rep(input$video_seek, 2))),
1)
})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论