addFgb uses wrong label and layerId
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)
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")
)