使用plotlyProxyInvoke

时间:2019-07-10 08:19:45

标签: r animation shiny plotly r-plotly

我正在尝试制作动画图,在其中引入新的轨迹,对轨迹进行动画处理,然后重新缩放轴。我很难让这些东西一起工作。下面是一个代表。除了当我同时具有“ Animate Traces”和“ Rescale Axis”时,它都有效,然后在每次迭代时都会重置轴缩放。

Using Proxy Interface in Plotly/Shiny to dynamically change data

https://community.plot.ly/t/how-to-efficiently-restyle-update-modify-plot-containing-frames/5553

https://plot.ly/javascript/plotlyjs-function-reference/

https://plot.ly/javascript/animations/

很难遵循Plotly文档。我无法获得addFrames,relayout,重新设置样式,做出反应或更新以适合我的工作。我最幸运的是拥有动画。非常感谢您的帮助,我已经为此努力了两个星期。

# plotly_add_anim13.R
library(shiny)
library(plotly)
library(dplyr)
library(purrr)

ui <- fluidPage(
    checkboxInput("add", "Add Trace", TRUE),
    checkboxInput("animate", "Animate Traces", FALSE),
    checkboxInput("rescale", "Rescale Axis", FALSE),
    plotlyOutput("plot")
)

server <- function(input, output, session){

    my <- reactiveValues(
        fnumber = NA, # frame number
        frame = NA, # frame data list
        ntraces = NA, # number of traces
        xrange = NA # xaxis range
        )

    speed = 1000 # redraw interval in milliseconds

    output$plot <- renderPlotly({
        isolate({
            cat("renderPlotly\n")
            my$fnumber <- 1
            my$ntraces <- 2
            f <- as.character(my$fnumber)
            x <- runif(2)
            y <- rep(runif(1), 2)
            t <- c("A", "B")
            ids0 <- paste0(my$ntraces-2, letters[1:2])
            ids1 <- paste0(my$ntraces-1, letters[1:2])
            my$xrange <- c(0,1)
            # https://community.plot.ly/t/how-to-efficiently-restyle-update-modify-plot-containing-frames/5553
            my$frame <- list(
                            name = f,
                            data = list(
                                list(x=x, y=y, frame=f, ids=ids0, type="scatter", mode="lines", showlegend=FALSE),
                                list(x=x, y=y, frame=f, ids=ids1, type="scatter", mode="text", text=t, showlegend=FALSE)
                            ),
                            traces = as.list(as.integer(c(my$ntraces-2, my$ntraces-1))),
                            layout = list(xaxis=list(range=my$xrange, zeroline=FALSE),
                                          yaxis=list(range=c(0,1), tickmode="array", tickvals=seq(0,1,0.2), ticktext=seq(0,1,0.2)))
                        )
            p <- plot_ly()
            p <- do.call(add_trace, prepend(my$frame$data[[1]], list(p)))
            p <- do.call(add_trace, prepend(my$frame$data[[2]], list(p)))
            p <- do.call(layout, prepend(my$frame$layout, list(p)))
            p <- animation_opts(p, frame=speed, transition=speed)
            p
        })
    })

    proxy <- plotlyProxy("plot", session=session)

    # https://shiny.rstudio.com/reference/shiny/0.14/reactiveTimer.html
    autoInvalidate <- reactiveTimer(speed*2)

    observeEvent(autoInvalidate(), {
        # req(NULL)
        # https://stackoverflow.com/questions/50620360/using-proxy-interface-in-plotly-shiny-to-dynamically-change-data
        # https://community.plot.ly/t/how-to-efficiently-restyle-update-modify-plot-containing-frames/5553
        # https://plot.ly/javascript/animations/#frame-groups-and-animation-modes
        # https://plot.ly/javascript/animations/
        if (input$add){
            cat("add trace\n")
            my$fnumber <- my$fnumber + 1
            my$ntraces <- my$ntraces + 2
            f <- as.character(my$fnumber)
            x <- runif(2)
            y <- rep(runif(1), 2)
            t <- c("A", "B")
            ids0 <- paste0(my$ntraces-2, letters[1:2])
            ids1 <- paste0(my$ntraces-1, letters[1:2])
            my$frame$name <- f
            my$frame$data[[my$ntraces-1]] <- list(x=x, y=y, frame=f, ids=ids0, type="scatter", mode="lines", showlegend=FALSE)
            my$frame$data[[my$ntraces-0]] <- list(x=x, y=y, frame=f, ids=ids1, type="scatter", mode="text", text=t, showlegend=FALSE)
            my$frame$traces <- as.list(as.integer(1:my$ntraces - 1))
            plotlyProxyInvoke(proxy, "addTraces",
                              list(
                                my$frame$data[[my$ntraces-1]],
                                my$frame$data[[my$ntraces-0]]
                                ))
            plotlyProxyInvoke(proxy, "animate",
                              # frameOrGroupNameOrFrameList
                              list(
                                name = my$frame$name,
                                data = my$frame$data,
                                traces = my$frame$traces
                              ),
                              # animationAttributes
                              list(
                                frame=list(duration=0),
                                transition=list(duration=0)
                              )
            )# animate

        }
        if (input$animate){
            cat("animate traces\n")
            my$fnumber <- my$fnumber + 1
            f <- as.character(my$fnumber)
            traces <- 1:my$ntraces - 1
            for (i in seq(0, my$ntraces-2, 2)){
                x <- runif(2)
                y <- rep(runif(1), 2)
                t <- c("A", "B")
                ids0 <- paste0(i, letters[1:2])
                ids1 <- paste0(i+1, letters[1:2])
                my$frame$data[[i+1]] <- list(x=x, y=y, frame=f, ids=ids0, type="scatter", mode="lines", showlegend=FALSE)
                my$frame$data[[i+2]] <- list(x=x, y=y, frame=f, ids=ids1, type="scatter", mode="text", text=t, showlegend=FALSE)
            }
            my$frame$name <- f
            plotlyProxyInvoke(proxy, "animate",
                              # frameOrGroupNameOrFrameList
                              list(
                                name = my$frame$name,
                                data = my$frame$data,
                                traces = my$frame$traces
                              ),
                              # animationAttributes
                              list(
                                frame=list(duration=speed),
                                transition=list(duration=speed)
                              )
            )# animate
        }
        if (input$rescale){
            cat("animate layout\n")
            my$fnumber <- my$fnumber + 1
            f <- as.character(my$fnumber)
            my$xrange <- runif(2)*0.1+c(-0.1,1)
            my$frame$name <- f
            my$frame$layout <- list(xaxis=list(range=my$xrange))
            plotlyProxyInvoke(proxy, "animate",
                              # frameOrGroupNameOrFrameList
                              list(
                                name = my$frame$name,
                                data = my$frame$data,
                                traces = my$frame$traces,
                                layout = my$frame$layout
                              ),
                              # animationAttributes
                              list(
                                frame=list(duration=speed),
                                transition=list(duration=speed)
                              )
            ) # animate
        }
    }) # observeEvent

}

shinyApp(ui, server)


0 个答案:

没有答案