What is the fastest option for toggling visibility of deckgl layers in Shiny environment?

120 views Asked by At

I am working on a Shiny app that uses deckgl to visualize scatterpoint and polygon data for multiple data sources. I am wondering if there is a faster way to toggle layer visibility. At present, I am using the recommended deckgl_proxy() + update_deckgl() method from the documentation (https://cran.r-project.org/web/packages/deckgl/readme/README.html). It seems as if the bottleneck here is fetching the data on the call to add_polygon_layer(). Being able to update a layer property in a reactive environment like below would be ideal, but if anyone has advice on how to accomplish this, that would be awesome.

observeEvent(input$AddPoly, {
deckgl_proxy('mymap') %>%
 set_layer_visibility(id = "Neighborhood Layer", visible = ifelse(input$AddPoly = "ON", TRUE, FALSE)) %>%
update_deckgl(it="works")})

The neighborhood var is arbitrary (and ugly)

library(shiny)
library(deckgl)
#> deckgl 0.3.0 wrapping deck.gl.js 8.1.9
#>   Documentation: https://crazycapivara.github.io/deckgl/
#>   Issues, notes and bleeding edge: https://github.com/crazycapivara/deckgl
#> 
#> If you want to add a basemap from mapbox, it is recommended that you store your API token in an environment variable called MAPBOX_API_TOKEN.
library(graphics)
library(data.table)

n_points = 2000
testdf <- sf_bike_parking[1:n_points,]
testdf$ID <- 1:n_points-1
testdf$neighborhood <- ((testdf$ID - (testdf$ID %% 5))/ 5) + 1 # Groups of 5 from adjacent rows

polys = list()
for(i in 1:(n_points/5)){
  tmp = list(x=testdf[testdf$neighborhood == i,]$lng,
             y=testdf[testdf$neighborhood == i,]$lat) 
  polys[[i]] = data.table::transpose(tmp)[chull(tmp)]
  
}

polydf = data.frame(neighborhood = 1:(n_points/5))

polydf$geo = polys


ui <- fluidPage(
  radioButtons(
    "AddPoly",
    "Show Polygons",
    choices = c("ON", "OFF"),
    selected = "ON"),
  deckglOutput("mymap"))


server <- function(input, output, session) {
  # Initial Call
  output$mymap <- renderDeckgl({
    m <- deckgl(
      latitude = mean(testdf$lat),
      longitude = mean(testdf$lng),
      zoom=4
      ) %>%
      add_scatterplot_layer(
        id="Station Layer",
        data = testdf,
        getPosition = ~lng + lat,
        getColor=c(255,0,0,255),
        stroked=TRUE,
        radiusMinPixels = 5,
        radiusScale = 10,
      ) %>% 
      add_polygon_layer( 
        id= "Neighborhood layer",
        data= polydf,
        getPolygon = ~geo,
        getFillColor = c(0,0,255,255),
        getLineColor = c(255,255,255,255),
        filled=TRUE,
        stroked=TRUE,
        wireframe=TRUE,
        lineWidthMinPixels = 4,
      ) %>% 
      add_basemap()

  m
  })
  
  observeEvent(input$AddPoly, {
    deckgl_proxy('mymap') %>% 
      add_scatterplot_layer(
        id="StationLayer",
        data = testdf,
        getPosition = ~lng + lat,
        getColor=c(255,0,0,255),
        radiusMinPixels = 5,
        radiusScale = 10,
      ) %>% 
      {if (input$AddPoly == "ON")
        add_polygon_layer(., # POLYGONS FOR PSUs
                          id= "Neighborhood layer",
                          data= polydf,
                          getPolygon = ~geo,
                          getFillColor = c(0,0,255,255),
                          getLineColor = c(255,255,255,255),
                          lineWidthMinPixels = 4,
        ) else . } %>%
      add_basemap() %>%
      update_deckgl(it="works")
  })
}
shinyApp(ui, server)

I have something that works but it struggles with larger data/more layers.  Would prefer something snappier
0

There are 0 answers