Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to update polyline/polygon color without re-render #85

Open
courtwarr opened this issue Jul 25, 2023 · 1 comment
Open

How to update polyline/polygon color without re-render #85

courtwarr opened this issue Jul 25, 2023 · 1 comment
Labels
wontfix This will not be worked on

Comments

@courtwarr
Copy link

courtwarr commented Jul 25, 2023

I'm working on a shiny app that render 30-100k polylines and leafgl blows standard leaflet out of the water on render time. However, this map is intended to be interactive, and I'd like to be able to update the colors via leafletProxy without re-rendering the map.

There's no feature of this sort in vanilla leaflet but there is a workaround in a proposed commit covered here (rstudio/leaflet#496) and here (rstudio/leaflet#598) that works well. Rendering all my shapes is very slow the first time, but then simply updating the colors using this method is very fast. I'd love to to be able to update the color of my shapes using leafgl instead. Working reprex below.

library(shiny)
library(sf)
library(leaflet)
library(leafgl)

data <- gadmCHE %>%
  as("SpatialLinesDataFrame") %>%
  st_as_sf() %>%
  st_cast("LINESTRING")

setShapeStyle <- function( map, data = getMapData(map), layerId,
                           stroke = NULL, color = NULL,
                           weight = NULL, opacity = NULL,
                           fill = NULL, fillColor = NULL,
                           fillOpacity = NULL, dashArray = NULL,
                           smoothFactor = NULL, noClip = NULL,
                           options = NULL
){
  options <- c(list(layerId = layerId),
               options,
               filterNULL(list(stroke = stroke, color = color,
                               weight = weight, opacity = opacity,
                               fill = fill, fillColor = fillColor,
                               fillOpacity = fillOpacity, dashArray = dashArray,
                               smoothFactor = smoothFactor, noClip = noClip
               )))
  
  options <- evalFormula(options, data = data)
  
  options <- do.call(data.frame, c(options, list(stringsAsFactors=FALSE)))
  
  layerId <- options[[1]]
  style <- options[-1]
  
  leaflet::invokeMethod(map, data, "setStyle", "shape", layerId, style);
}

ui <- fluidPage(
  tags$head(
    tags$script(HTML(
      '
window.LeafletWidget.methods.setStyle = function(category, layerId, style){
  var map = this;
  if (!layerId){
    return;
  } else if (!(typeof(layerId) === "object" && layerId.length)){ // in case a single layerid is given
    layerId = [layerId];
  }

  //convert columnstore to row store
  style = HTMLWidgets.dataframeToD3(style);
  //console.log(style);

  layerId.forEach(function(d,i){
    var layer = map.layerManager.getLayer(category, d);
    if (layer){ // or should this raise an error?
      layer.setStyle(style[i]);
    }
  });
};
'
    ))
  ),
  fluidRow(
    column(width=6,offset=0,leafletOutput("map")),
    column(width=6,offset=0,leafletOutput("glMap"))
  ),
  radioButtons("color", "Color", choices = c("blue", "red"))
)

server <- function(input, output, session){
  output$map <- renderLeaflet({
    leaflet(data) %>%
      addPolylines(data=data,layerId = as.character(1:nrow(data)))
  })
  
  output$glMap <- renderLeaflet({
    leaflet(data) %>%
      addGlPolylines(data=data,layerId = as.character(1:nrow(data)))
  })
  
  observe({
    leafletProxy("map", data = data) %>%
      setShapeStyle(layerId = as.character(1:nrow(data)), color = input$color)
  })
  
  observe({
    leafletProxy("glMap", data = data) %>%
      setShapeStyle(layerId = as.character(1:nrow(data)), color = input$color)
  })
  
}

shinyApp(ui, server)
@tim-salabim
Copy link
Member

I don't think that's possible. WebGl is not svg and I am not sure if one can update style attributes or if they even exist in webgl... That question would be best asked in the upstream repo, because that's where it needs to be implemented to be available here.

@trafficonese trafficonese added the wontfix This will not be worked on label Jun 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

3 participants