My application contains a surface plot made with R plotly and the user can use a sliderInput
to specify a level where a contour line (actually a 3D scatterplot) is dynamically drawn. So, when the user clicks on the app's button, the current contour line is deleted and a new one is generated and placed on the plot. My issue; however, is that the use of plotlyProxy
and plotlyProxyInvoke
do not matter - the surface plot is redrawn and the angle of view is reset, which is exactly what I am trying to avoid. Here is my minimal reproducible code:
library(shiny)
library(plotly)
library(isoband)
ui <- fluidPage(
h1("My simple app"),
sliderInput(
inputId = "slider", label = "Select contour level", value = 1, min = 1, max = 40),
actionButton(inputId = "btn", "OK"),
plotlyOutput(outputId = "plot")
)
server <- function(input, output, session){
rv <- reactiveValues()
x <- y <- 0:100
z <- outer(X = x, Y = y, function(x, y) x^0.2 * y^0.6)
observeEvent(input$btn, ignoreInit = TRUE, {
rv$iso <- isolines(x = x, y = y, z = z, levels = isolate({input$slider}))
plotlyProxy("plot", session) %>%
plotlyProxyInvoke(method = "deleteTraces", list(1)) %>%
plotlyProxyInvoke(
method = "addTraces",
list(
type = "scatter3d",
x = rv$iso[[1]]$x,
y = rv$iso[[1]]$y,
z = isolate({input$slider})
)
)
})
output$plot <- renderPlotly({
rv$iso <- isolines(x = x, y = y, z = z, levels = isolate({input$slider}))
plot_ly(
type = "surface",
x = x,
y = y,
z = z
) %>%
add_trace(
type = "scatter3d",
x = rv$iso[[1]]$x,
y = rv$iso[[1]]$y,
z = isolate({input$slider})
)
})