我想使用一个闪亮的应用程序和 dygraphs 来浏览一个时间序列(有很多点,这里是 2E6)。 下面的脚本是一个最小的例子,除了数字输入
start
的变化导致显示冻结 5 秒外,它工作得很好。相比之下,使用范围选择器移动几乎没有延迟。所以我想这应该是可行的,但我没有运气解决这个问题。
有什么办法可以改善吗?
library(shiny)
library(dygraphs)
ui <- fluidPage(
# Sidebar
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
numericInput("start", label = "Start (iteration)",
value = 1, step = 5E4),
numericInput("duration", label = "Duration (iterations)",
value = 5E4)
),
# Main
mainPanel(
dygraphOutput("plot")
)
)
)
server <- function(input, output) {
z<-rnorm(2E6,1,10) # data
time<-1:length(z)
df<-data.frame(time,z)
output$plot <- renderDygraph({
dygraph(df) %>% dyRangeSelector(dateWindow = c(input$start,input$start+input$duration) )
})
}
shinyApp(ui = ui, server = server)
此行为的原因是每当您更改
input$start
(input$duration
) whole plot 重新渲染。当您简单地更改选择器手柄时,dygraph
确保显示相关数据,无需 重新渲染整个图形(这实际上是 dygraph 的功能之一)。
您可以借助一些 JavaScript 来实现这种行为。思路如下:
在您的
renderDygraph
函数中,您不依赖于input$start
(input$duration
)。这避免了当其中一个值发生变化时重新渲染整个图形。
你包含一个
observer
,它调用 dygraph JavaScript 函数 updateOptions
,它反过来更新 x 轴上的可见范围(因此基本上与手动更改范围手柄相同)。
为此,您需要:
htmlwidgtes::onRender
来表示),这样我们就可以稍后调用 updateOptions
。shinyjs
为您封装它)。代码千言万语,下面是一个有效的例子:
library(shiny)
library(dygraphs)
library(htmlwidgets)
ch <- JS("
var plots = [];
Shiny.addCustomMessageHandler('adjust-x-axis', function(limits) {
const dg = plots['plot'];
if (dg) {
dg.updateOptions({dateWindow: [limits.xmin, limits.xmax]});
}
});")
ui <- fluidPage(
# Sidebar
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
numericInput("start", label = "Start (iteration)",
value = 1, step = 5E4),
numericInput("duration", label = "Duration (iterations)",
value = 5E4)
),
# Main
mainPanel(
tags$head(
tags$script(
ch,
type = "text/javascript"
)
),
dygraphOutput("plot")
)
)
)
server <- function(input, output, session) {
z <- rnorm(2E6, 1, 10) # data
time <- 1:length(z)
df <- data.frame(time, z)
output$plot <- renderDygraph({
dygraph(df) %>%
dyRangeSelector(dateWindow = c(1, 1 + 5E4)) %>%
onRender("function(el, x) {
plots['plot'] = this.dygraph;
}")
})
observe({
start <- req(input$start)
duration <- req(input$duration)
session$sendCustomMessage(
"adjust-x-axis",
list(xmin = start, xmax = start + duration)
)
})
}
shinyApp(ui = ui, server = server)