leaflet
leaflet copied to clipboard
Using BeautifyMarker with Leaflet for R
I am trying to use the BeautifyMarker plugin with Leaflet for R by loading the plugin and utilizing the onRender() function (technique described here https://gist.github.com/jcheng5/c084a59717f18e947a17955007dc5f92. I am unable to load the plugin successfully. I think my assignments in htmlDependency() might be the issue, but I can't seem to figure this out. Thank you!!
library(leaflet)
library(htmltools)
library(htmlwidgets)
library(fontawesome)
beautifyPlugin <- htmlDependency("Leaflet.BeautifyMarker", "1.0.9",
src = c(href = "https://cdn.jsdelivr.net/npm/[email protected]/package.json"),
script = "https://cdn.jsdelivr.net/npm/[email protected]/leaflet-beautify-marker-icon.min.js",
stylesheet = "https://cdn.jsdelivr.net/npm/[email protected]/leaflet-beautify-marker-icon.min.css"
)
registerPlugin <- function(map, plugin) {
map$dependencies <- c(map$dependencies, list(plugin))
map
}
leaflet() %>% setView(-122.23, 37.75, zoom = 10)%>%
addTiles()%>%
registerPlugin(beautifyPlugin) %>%
onRender("function(el, x) {
L.marker([37.77, -122.40] ,
{icon: L.BeautifyIcon.icon()
}).addTo(this).bindPopup('test');
}")
Created on 2020-09-23 by the reprex package (v0.3.0)
Your src
argument points to a package.json
and should instead point to https://cdn.jsdelivr.net/npm/[email protected]/
Then your script
and stylesheet
just need the filenames, without the src
path.
This should work:
beautifyPlugin <- htmlDependency("Leaflet.BeautifyMarker", "1.0.9",
src = c(href="https://cdn.jsdelivr.net/npm/[email protected]/"),
script = "leaflet-beautify-marker-icon.min.js",
stylesheet = "leaflet-beautify-marker-icon.min.css"
)
This worked. Thank you so much!!!
@trafficonese follow up question: This worked to utilize the plugin, but the fontawesome icons don't seem to be accessible. I'm wondering if I need to include the fontawesome stylesheet in my dependencies as well.
library(leaflet)
library(htmltools)
library(htmlwidgets)
library(fontawesome)
beautifyPlugin <- htmlDependency("Leaflet.BeautifyMarker", "1.0.9",
src = c(href="https://cdn.jsdelivr.net/npm/[email protected]/"),
script = "leaflet-beautify-marker-icon.min.js",
stylesheet = list("leaflet-beautify-marker-icon.min.css", c(href = "https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"))
)
Created on 2020-09-23 by the reprex package (v0.3.0)
I think you have to create a new htmlDependency
and register that too:
fontawesomePlugin <- htmlDependency("Leaflet.BeautifyMarkerFA", "1.0.9",
src = c(href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/"),
stylesheet = "font-awesome.min.css"
)
leaflet() %>% setView(-122.23, 37.75, zoom = 10)%>%
addTiles()%>%
registerPlugin(fontawesomePlugin) %>%
registerPlugin(beautifyPlugin) %>%
onRender("function(el, x) {
L.marker([37.77, -122.40] ,
{icon: L.BeautifyIcon.icon()
}).addTo(this).bindPopup('test');
}")
Worked perfectly, thank you!
@trafficonese another related issue:
Utilizing my plugins with leaflet() seems to be working just fine. However, when I try to utilize them with renderLeaflet(), they are not working. Do you know how to solve this or what the issue might be?
Functioning perfectly:
library(leaflet)
library(htmltools)
library(htmlwidgets)
library(fontawesome)
beautifyPlugin <- htmlDependency("Leaflet.BeautifyMarker", "1.0.9",
src = c(href="https://cdn.jsdelivr.net/npm/[email protected]/"),
script = "leaflet-beautify-marker-icon.min.js",
stylesheet = "leaflet-beautify-marker-icon.min.css"
)
fontawesomePlugin <- htmlDependency("Leaflet.BeautifyMarkerFA", "1.0.9",
src = c(href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/"),
stylesheet = "font-awesome.min.css"
)
registerPlugin <- function(map, plugin) {
map$dependencies <- c(map$dependencies, list(plugin))
map
}
leaflet() %>% setView(-74.96, 39.77, zoom = 10) %>% addTiles()%>%
registerPlugin(fontawesomePlugin) %>%
registerPlugin(beautifyPlugin) %>%
onRender(paste0("function(el, x) {
L.marker([39.77, -74.96] ,
{icon: L.BeautifyIcon.icon({ icon:'child', iconShape: 'circle' }) }).addTo(this).bindPopup('test');
}"))
Created on 2020-11-03 by the reprex package (v0.3.0)
Not functioning (from within my server.R file):
output$map <- renderLeaflet({
leaflet()%>%addProviderTiles("Esri.WorldGrayCanvas")%>%
addPolygons(data = shape, color = "black", weight = 1.5, opacity = 1, fill = TRUE, fillOpacity = 0, label = ~NAME, labelOptions = labelOptions(style = list("color" = "black", "font-family" = "serif", "box-shadow" = "3px 3px rgba(0,0,0,0.25)", "font-size" = "15px", "border-color" = "rgba(0,0,0,0.5)")))%>%
addLegend(position = "topright", colors = c("#483D8B", "#00BFFF"), opacity = 1,labels = c("Externally Provided", "Internally Provided"))%>%
registerPlugin(fontawesomePlugin) %>%
registerPlugin(beautifyPlugin) %>%
onRender(paste0("function(el, x) {
L.marker([39.77, -74.96] ,
{icon: L.BeautifyIcon.icon({ icon:'child', iconShape: 'circle' }) }).addTo(this).bindPopup('test');
}"))
})
#> Error in renderLeaflet({: could not find function "renderLeaflet"
Created on 2020-11-03 by the reprex package (v0.3.0)
I don't know how you got this error could not find function "renderLeaflet"
, but you're right, the code snippet doesnt work right away in a shiny app.
Apparently you have to include the HTML-dependencies earlier on, otherwise you will see an error in the browser console, saying that
L.BeautifyIcon is undefined
For Font Awesome, you could include an invisible shiny icon, then you dont have to load the css files. If you have some icons in your shiny-app already, you dont even have to do this.
This should work:
library(shiny)
library(leaflet)
library(htmlwidgets)
ui <- fluidPage(
tags$head(tags$link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/[email protected]/leaflet-beautify-marker-icon.css")),
tags$head(tags$script(src="https://cdn.jsdelivr.net/npm/[email protected]/leaflet-beautify-marker-icon.js")),
div(style="display:none", icon("gear")),
leafletOutput("map")
)
server <- function(input, output, session) {
output$map <- renderLeaflet({
leaflet()%>%
addProviderTiles("Esri.WorldGrayCanvas")%>%
onRender("function(el, x) {
L.marker([39.77, -74.96], {
icon: L.BeautifyIcon.icon({
icon: 'child',
iconShape: 'circle' })
}).addTo(this).bindPopup('test');
}")
})
}
shinyApp(ui, server)
Thank you @trafficonese , this worked for rendering my output map. However, I cannot seem to get it to work with leafletProxy().
My ultimate goal is to utilize the BeautifyMarker plugin reactively. I am trying to place icons on a map given user selection. I had this fully functional using an R plugin (mapkey icons), but it was not a robust enough solution for the level of customizing icons I need. BeautifyMarker is much more appropriate but I just keep running into implementation issues. Do you know how to make this functional with leafletProxy() or what the issue is? Thank you so much!!
library(shiny)
library(shinyWidgets)
#> Warning: package 'shinyWidgets' was built under R version 4.0.3
library(leaflet)
library(data.table)
#> Warning: package 'data.table' was built under R version 4.0.3
library(tigris)
#> To enable
#> caching of data, set `options(tigris_use_cache = TRUE)` in your R script or .Rprofile.
library(fontawesome)
#read in data
prog_dat = fread("Categories.csv")
#> Error in fread("Categories.csv"): File 'Categories.csv' does not exist or is non-readable.
#convert to data table
prog_dat = as.data.table(prog_dat)
#> Error in as.data.table(prog_dat): object 'prog_dat' not found
#Counties Shapefile
shape <- tigris::counties(state = "NJ")
#> | | | 0% | | | 1% | |= | 1% | |= | 2% | |== | 2% | |== | 3% | |== | 4% | |=== | 4% | |=== | 5% | |==== | 5% | |==== | 6% | |===== | 6% | |===== | 7% | |===== | 8% | |====== | 8% | |====== | 9% | |======= | 9% | |======= | 10% | |======= | 11% | |======== | 11% | |======== | 12% | |========= | 12% | |========= | 13% | |========= | 14% | |========== | 14% | |========== | 15% | |=========== | 15% | |=========== | 16% | |============ | 16% | |============ | 17% | |============ | 18% | |============= | 18% | |============= | 19% | |============== | 19% | |============== | 20% | |============== | 21% | |=============== | 21% | |=============== | 22% | |================ | 22% | |================ | 23% | |================ | 24% | |================= | 24% | |================= | 25% | |================== | 25% | |================== | 26% | |=================== | 26% | |=================== | 27% | |=================== | 28% | |==================== | 28% | |==================== | 29% | |===================== | 29% | |===================== | 30% | |===================== | 31% | |====================== | 31% | |====================== | 32% | |======================= | 32% | |======================= | 33% | |======================= | 34% | |======================== | 34% | |======================== | 35% | |========================= | 35% | |========================= | 36% | |========================== | 36% | |========================== | 37% | |========================== | 38% | |=========================== | 38% | |=========================== | 39% | |============================ | 39% | |============================ | 40% | |============================ | 41% | |============================= | 41% | |============================= | 42% | |============================== | 42% | |============================== | 43% | |============================== | 44% | |=============================== | 44% | |=============================== | 45% | |================================ | 45% | |================================ | 46% | |================================= | 46% | |================================= | 47% | |================================= | 48% | |================================== | 48% | |================================== | 49% | |=================================== | 49% | |=================================== | 50% | |=================================== | 51% | |==================================== | 51% | |==================================== | 52% | |===================================== | 52% | |===================================== | 53% | |===================================== | 54% | |====================================== | 54% | |====================================== | 55% | |======================================= | 55% | |======================================= | 56% | |======================================== | 56% | |======================================== | 57% | |======================================== | 58% | |========================================= | 58% | |========================================= | 59% | |========================================== | 59% | |========================================== | 60% | |========================================== | 61% | |=========================================== | 61% | |=========================================== | 62% | |============================================ | 62% | |============================================ | 63% | |============================================ | 64% | |============================================= | 64% | |============================================= | 65% | |============================================== | 65% | |============================================== | 66% | |=============================================== | 66% | |=============================================== | 67% | |=============================================== | 68% | |================================================ | 68% | |================================================ | 69% | |================================================= | 69% | |================================================= | 70% | |================================================= | 71% | |================================================== | 71% | |================================================== | 72% | |=================================================== | 72% | |=================================================== | 73% | |=================================================== | 74% | |==================================================== | 74% | |==================================================== | 75% | |===================================================== | 75% | |===================================================== | 76% | |====================================================== | 76% | |====================================================== | 77% | |====================================================== | 78% | |======================================================= | 78% | |======================================================= | 79% | |======================================================== | 79% | |======================================================== | 80% | |======================================================== | 81% | |========================================================= | 81% | |========================================================= | 82% | |========================================================== | 82% | |========================================================== | 83% | |========================================================== | 84% | |=========================================================== | 84% | |=========================================================== | 85% | |============================================================ | 85% | |============================================================ | 86% | |============================================================= | 86% | |============================================================= | 87% | |============================================================= | 88% | |============================================================== | 88% | |============================================================== | 89% | |=============================================================== | 89% | |=============================================================== | 90% | |=============================================================== | 91% | |================================================================ | 91% | |================================================================ | 92% | |================================================================= | 92% | |================================================================= | 93% | |================================================================= | 94% | |================================================================== | 94% | |================================================================== | 95% | |=================================================================== | 95% | |=================================================================== | 96% | |==================================================================== | 96% | |==================================================================== | 97% | |==================================================================== | 98% | |===================================================================== | 98% | |===================================================================== | 99% | |======================================================================| 99% | |======================================================================| 100%
# Define UI for application
ui <- fluidPage(
tags$head(tags$link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/[email protected]/leaflet-beautify-marker-icon.css")),
tags$head(tags$script(src="https://cdn.jsdelivr.net/npm/[email protected]/leaflet-beautify-marker-icon.js")),
div(style="display:none", icon("gear")),
sidebarLayout(
sidebarPanel(
#user select data types
pickerInput(inputId = "programtype", label = "Program Type(s):", choices = c("AM" = "1",
"BM" = "2",
"CM" = "3",
"CN" = "4",
"DA" = "5",
"DP" = "6",
"EA" = "7",
"EP" = "8",
"FE" = "9",
"GS" = "10",
"HT" = "11",
"IP" = "12",
"MH" = "13",
"M" = "14",
"PP" = "15",
"PE" = "16",
"RE" = "17",
"RP" = "18",
"SB" = "19",
"SO" = "20",
"S" = "21",
"TP" = "22"), selected = NULL, options = pickerOptions(actionsBox = TRUE, liveSearchNormalize = TRUE, liveSearchStyle = "startsWith"), multiple = TRUE),
width = 3
),
mainPanel(
leafletOutput("map", height = 700),
width = 9
),
position = "right"
)
)
# Define server logic
server <- function(input, output) {
#filter data based on user selection
filteredData <- reactive({
prog_dat%>%
dplyr::filter(Proj_Code %in% input$programtype)
})
#Icon Names
iconName <- reactive({
ifelse(filteredData()$Proj_Code== 1, "exclamation-triangle", ifelse(
filteredData()$Proj_Code== 2,"wrench", ifelse(
filteredData()$Proj_Code== 3, "folder-open", ifelse(
filteredData()$Proj_Code== 4, "bell", ifelse(
filteredData()$Proj_Code== 5, "balance-scale", ifelse(
filteredData()$Proj_Code== 6, "plus", ifelse(
filteredData()$Proj_Code== 7, "graduation-cap", ifelse(
filteredData()$Proj_Code== 8, "briefcase", ifelse(
filteredData()$Proj_Code== 9, "users", ifelse(
filteredData()$Proj_Code== 10, "transgender-alt", ifelse(
filteredData()$Proj_Code== 11, "binoculars", ifelse(
filteredData()$Proj_Code== 12, "gift", ifelse(
filteredData()$Proj_Code== 13, "comments", ifelse(
filteredData()$Proj_Code== 14, "compass", ifelse(
filteredData()$Proj_Code== 15, "info-circle", ifelse(
filteredData()$Proj_Code== 16, "child", ifelse(
filteredData()$Proj_Code== 17, "forward", ifelse(
filteredData()$Proj_Code== 18, "home", ifelse(
filteredData()$Proj_Code== 19,"pencil", ifelse(
filteredData()$Proj_Code== 20, "puzzle-piece", ifelse(
filteredData()$Proj_Code== 21, "cog", "car")
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
)
})
#render map
output$map <- renderLeaflet({
leaflet()%>%addProviderTiles("Esri.WorldGrayCanvas")%>%
addPolygons(data = shape, color = "black", weight = 1.5, opacity = 1, fill = TRUE, fillOpacity = 0, label = ~NAME, labelOptions = labelOptions(style = list("color" = "black", "font-family" = "serif", "box-shadow" = "3px 3px rgba(0,0,0,0.25)", "font-size" = "15px", "border-color" = "rgba(0,0,0,0.5)")))
})
#add icons to map based on user selection
observe({
leafletProxy("map", data = filteredData())%>%
onRender(paste0("function(el, x) {
L.marker([",~Latitude,",",~Longitude,"], {
icon: L.BeautifyIcon.icon({
icon:'" ,iconName(), "',
iconShape: 'circle' })
}).addTo(this).bindPopup('test');
}"))
})
}
shinyApp(ui = ui, server = server)
#>
#> Listening on http://127.0.0.1:3697
#> Warning: sf layer has inconsistent datum (+proj=longlat +datum=NAD83 +no_defs).
#> Need '+proj=longlat +datum=WGS84'
#> Warning: Error in eval: object 'prog_dat' not found
Created on 2020-11-08 by the reprex package (v0.3.0)