Search code examples
rshinyleafletr-leafletesri-leaflet

Connecting R Leaflet to esri vector tile service


I'm building a Shiny leaflet application that I want to use a ESRI vector tile map from my organization for. I can see that leaflet connects to it as the attribution is accurate. However the tiles fail to load. I've tried poking around using different options in the esri.leaflet package and even tried to import javascript plugins with no success.

library(shiny)
library(leaflet)
library(sf)
library(dplyr)
library(here)
library(leaflet.extras)
library(leaflet.esri)
library(bcmaps)
library(rmapshaper)
library(htmltools)
library(htmlwidgets)

ha <- bcmaps::health_ha() %>% 
  ms_simplify(., keep = 0.05, keep_shapes = TRUE) %>% 
  rename_with(tolower, everything()) %>% 
  select(ha_code = hlth_authority_code, 
         ha_name = hlth_authority_name, 
         geometry) %>% 
  st_transform(crs = 4326) %>% 
  mutate(color = c("#3891A7",
                   "#C3860D",
                   "#C42E2E",
                   "#67A63C",
                   "#914FAB"))

ui <- fluidPage(
  leafletOutput("main_map")
)

server <- function(input, output, session) {
  output$main_map <- renderLeaflet({
    leaflet() %>%
    addEsriFeatureLayer(
      url = "https://tiles.arcgis.com/tiles/ubm4tcTYICKBpist/arcgis/rest/services/BC_BASEMAP_20240307/VectorTileServer",
      useServiceSymbology = TRUE
    ) %>% 
      addPolygons(data = ha,
                  stroke = TRUE,
                  weight = 1,
                  color = ~color,
                  opacity = 0.5,
                  fillColor = ~color,
                  fillOpacity = 0.3)
  })
  
  
  
}


shinyApp(ui, server)

Based on comments from G.Cocca I've tried to adapt the code after looking at this question.

library(dplyr)
library(leaflet)
library(htmltools)
library(htmlwidgets)

esriLeafletPlugin <- htmlDependency(
  "esri-leaflet", "3.0.12",
  src = "https://cdn.jsdelivr.net/npm/[email protected]/dist/esri-leaflet.min.js",
  script = "EsriLeaflet.min.js")

esriVectorTilesPlugin <- htmlDependency(
  "esri-leaflet-vector", "4.2.3",
  src = "https://cdn.jsdelivr.net/npm/[email protected]/dist/esri-leaflet-vector-debug.min.js",
  script = "VectorTileLayer.min.js")

registerPlugin <- function(map, plugin) {
  map$dependencies <- c(map$dependencies, list(plugin))
  map}

leaflet() %>%
  registerPlugin(esriLeafletPlugin) %>% 
  registerPlugin(esriVectorTilesPlugin) %>% 
  onRender("function(el, x) {
       L.esri.Vector.vectorTileLayer(
       'https://tiles.arcgis.com/tiles/ubm4tcTYICKBpist/arcgis/rest/services/BC_BASEMAP_20240307/VectorTileServer'
       ).addTo(this);
       }")

However this isn't quite right

Failed to load resource: the server responded with a status of 404 (Not Found)
VM13:3 Uncaught TypeError: Cannot read properties of undefined (reading 'Vector')
    at e.eval (eval at tryEval (htmlwidgets.js:252:16), <anonymous>:3:15)
    at Object.eval (eval at tryEval (htmlwidgets.js:252:16), <anonymous>:6:11)
    at htmlwidgets.js:240:18
    at Array.forEach (<anonymous>)
    at forEach (htmlwidgets.js:55:14)
    at evalAndRun (htmlwidgets.js:230:7)
    at htmlwidgets.js:653:11
    at Array.forEach (<anonymous>)
    at forEach (htmlwidgets.js:55:14)
    at htmlwidgets.js:574:7

Solution

  • The following code imports the vectortile. As I said before you need to register 2 ESRI plugins: Read more at: []https://developers.arcgis.com/esri-leaflet/install-and-setup/

    library(leaflet)
    library(sf)
    library(dplyr)
    library(leaflet.extras)
    library(leaflet.esri)
    library(rmapshaper)
    library(bcmaps)
    library(htmltools)
    library(htmlwidgets)
    
    VectorTilePlugin <- htmlDependency("esri-leaflet-vector", "4.2.3",
                                        src = c(href = "https://unpkg.com/esri-leaflet-vector@4/dist/"),
                                        script = "esri-leaflet-vector.js")
    
    esriPlugin <- htmlDependency("leaflet.esri", "1.0.3",
                                  src = c(href = "https://cdn.jsdelivr.net/leaflet.esri/1.0.3/"),
                                  script = "esri-leaflet.js")
    
    registerPlugin <- function(map, plugin) {
      map$dependencies <- c(map$dependencies, list(plugin))
      map}
    
    ha <- bcmaps::health_ha() %>% 
      ms_simplify(., keep = 0.05, keep_shapes = TRUE) %>% 
      rename_with(tolower, everything()) %>% 
      select(ha_code = hlth_authority_code, 
             ha_name = hlth_authority_name, 
             geometry) %>% 
      st_transform(crs = 4326) %>% 
      mutate(color = c("#3891A7",
                       "#C3860D",
                       "#C42E2E",
                       "#67A63C",
                       "#914FAB"))
    
        leaflet() %>%
          registerPlugin(esriPlugin) %>%
          registerPlugin(VectorTilePlugin)%>%
          onRender("function(el, x){L.esri.Vector.vectorTileLayer('https://tiles.arcgis.com/tiles/ubm4tcTYICKBpist/arcgis/rest/services/BC_BASEMAP_20240307/VectorTileServer').addTo(this);      }") %>%
          addPolygons(data = ha,
                      stroke = TRUE,
                      weight = 1,
                      color = ~color,
                      opacity = 0.5,
                      fillColor = ~color,
                      fillOpacity = 0.3)