r-spatial / leafem

leaflet extensions for mapview
https://r-spatial.github.io/leafem/
Other
107 stars 28 forks source link

addFgb uses wrong label and layerId #80

Open trafficonese opened 3 months ago

trafficonese commented 3 months ago

Wrong Label

When a vector is used for label they are mixed up, as flatgeobuf apparently doesnt handle the Geojson in a sequential way, but still always in the same order (not sure which order yet). So the following is not working with the cntr index. https://github.com/r-spatial/leafem/blob/830d010f6087ba85bb71d7391d78db60dc8fef53/inst/htmlwidgets/lib/FlatGeoBuf/fgb.js#L122-L126

Different layerId behaviour

The layerId in leaflet works differently and also a vector can be passed to identify single elements. Using a vector with the current versions throws this error:

Warning: Error in validateScalarName: Invalid argument 'name' (must be a non-empty character string and contain no '/' or '\')

Currently the FBG-File is loaded as attachment using the layerId as name. Could we switch this to group instead or use a combination of group, file, url? Those values should be of length = 1 or?

Then we could also return the layerId in the mouse-events here: https://github.com/r-spatial/leafem/blob/830d010f6087ba85bb71d7391d78db60dc8fef53/inst/htmlwidgets/lib/FlatGeoBuf/fgb.js#L15

using something like this id: e.layer.feature.properties[layerId].toString()

The behaviour would still be different to leaflet, as we would have to pass a string indicating the column to be used as layerId (e.g. layerId = "id"), but at least we could identify which element was clicked exactly.

And another problem I encountered with this method. If the layerId column is a numeric, the tooltip will not be displayed and ths error comes up. The function .toString() or + "" didnt help.

Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'. at e._updateContent (leaflet.js:5:89421) at e.update (leaflet.js:5:88713) at e.onAdd (leaflet.js:5:88115) at e.onAdd (leaflet.js:5:94883) at e._layerAdd (leaflet.js:5:64708) at e.whenReady (leaflet.js:5:44748) at e.addLayer (leaflet.js:5:65087) at e.openTooltip (leaflet.js:5:96860) at e.openTooltip (leaflet.js:5:98033) at e._openTooltip (leaflet.js:5:98858)

Here is an example Shiny App to play around:

Click me ``` library(leafem) library(leaflet) library(shiny) library(terra) library(sf) ## Transform Data to FGB ############ linesdf <- st_as_sf(leaflet::atlStorms2005) linesdf$id <- paste0("id_",1:nrow(linesdf)) shp <- vect(linesdf) shp_ext <- unname(as.vector(ext(shp))) fgb_path <- tempfile(fileext = ".fgb") writeVector(shp, fgb_path, filetype = "FlatGeobuf") ## UI ################## ui <- fluidPage(leafletOutput("map", height = 500), splitLayout(cellWidths = c("49%","49%"), div( h3("FGB"), verbatimTextOutput("print_fgb") ), div( h3("Leaflet"), verbatimTextOutput("print_leaflet") ))) ## SERVER ################## server <- function(input, output){ output$map <- renderLeaflet({ leaflet("map") %>% fitBounds(shp_ext[1], shp_ext[3], shp_ext[2], shp_ext[4]) %>% addTiles() %>% addFgb(fgb_path, fill = FALSE, group = "Lines_FGB", layerId = "id", popup = TRUE, label = .subset2(linesdf, "id") # label = "id" ) %>% # leafgl::addGlPolylines(data = linesdf, # layerId = .subset2(linesdf, "id"), # color = "#337ab7", # opacity = 0.9, # popup = NULL, # group = "Strassengraph_Glify", # preserveDrawingBuffer = TRUE, # sensitivity = 0.001, # sensitivityHover = 0.03) %>% leaflet::addPolylines(data = linesdf, layerId = .subset2(linesdf, "id"), label = .subset2(linesdf, "id"), color = "#337ab7", opacity = 0.9, popup = NULL, group = "Lines") %>% addLayersControl( position = "topright", overlayGroups = c("Lines_FGB", "Lines" ), options = layersControlOptions(collapsed = F, autoZIndex = TRUE) ) }) ## Ouputs ############### output$print_fgb <- renderPrint({ click <- req(input$map_shape_click) req(click$group == "Lines_FGB") df <- linesdf[.subset2(linesdf, "id") == click[["id"]],] if (nrow(df) == 0) { showNotification("not found") } else { leafletProxy("map") %>% clearGroup("sel") %>% addPolylines(data = df, label = df$id, group="sel", color = "red", options = pathOptions(interactive = FALSE)) } print(click) }) output$print_leaflet <- renderPrint({ click <- req(input$map_shape_click) req(click$group == "Lines") df <- linesdf[.subset2(linesdf, "id") == click[["id"]],] if (nrow(df) == 0) { showNotification("not found") } else { leafletProxy("map") %>% clearGroup("sel") %>% addPolylines(data = df, label = df$id, group="sel", color = "red", options = pathOptions(interactive = FALSE)) } print(click) }) } shinyApp(ui = ui, server = server) ```
trafficonese commented 3 months ago

I just saw that this is expected, when writing the FGB. It should work with SPATIAL_INDEX=NO" as described here https://github.com/r-spatial/leafem/issues/53#issuecomment-1059087041

fl = tempfile(fileext = ".fgb")
sf::st_write(
  obj = franconia
  , dsn = fl
  , driver = "FlatGeobuf"
  , layer_options = c("SPATIAL_INDEX=NO")
)