R: Making More "Noticeable" Labels in R Leaflet map - r

I made the following map in R (from a data frame with 5 points ordered from "1" to "5"):
library(dplyr)
library(leaflet)
map_data <- data.frame("Lat" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), "Long" = c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ), type = c(1,2,3,4,5))
map_data$type = as.factor(map_data$type)
leaflet(map_data) %>% addTiles() %>% addCircleMarkers(stroke = FALSE, label = ~type,
labelOptions = labelOptions(noHide = TRUE, offset=c(0,-12), fill = TRUE, opacity = 10, weight = 10, textOnly = TRUE))
But the problem is, you can barely see the "labels" for each city:
I would like to make the "labels" a lot more noticeable, something like this:
I tried to play around with the "weight" and "opacity" arguments, but this does not seem to be working.
Can someone please show me how to do this?
Note: I do not want to do this in R SHINY, just using LEAFLET in R.
Reference: Print label on circle markers in leaflet in Rshiny

fillOpacity = before labelOptions:
library(dplyr)
library(leaflet)
map_data <- data.frame("Lat" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), "Long" = c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ), type = c(1,2,3,4,5))
map_data$type = as.factor(map_data$type)
leaflet(map_data) %>%
addTiles() %>%
addCircleMarkers(stroke = FALSE,
label = ~type,
fillOpacity = 0.9,
labelOptions = labelOptions(noHide = TRUE, fill = FALSE, offset = c(5,2), textsize = "18px", textOnly = TRUE))

Related

R: Connecting Dots on a Map

I am working with the R programming language.
Using the "leaflet" library, I made the following map for these 5 cities:
library(dplyr)
library(leaflet)
map_data <- data.frame("Lat" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), "Long" = c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ), type = c(1,2,3,4,5))
map_data$type = as.factor(map_data$type)
leaflet(map_data) %>%
addTiles() %>% addCircleMarkers(stroke = FALSE, label = ~type,fillOpacity = 0.8, labelOptions = labelOptions(direction = "center",style = list('color' = "white"),noHide = TRUE, offset=c(0,0), fill = TRUE, opacity = 1, weight = 10, textOnly = TRUE))
On this above map that I have created, I would now like to "connect" all these "points" (i.e. cities) on the map (in a route) based on their "number" (e.g. connect 1 with 2, 2 with 3, 3 with 4, 4 with 5, 5 with 1), and output the "total distance" of the route. I found a previous post that shows how to do this: How to show path and distance on map with leaflet, shiny apps?
I tried to adapt the code from this post to suit my question:
library(osrm)
route = osrmRoute(c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ), c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), overview = 'full')
route_summary = osrmRoute(c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ), c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), overview = FALSE)
leaflet() %>% addTiles() %>%
addCircleMarkers(c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ), c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), stroke = FALSE, label = ~type,fillOpacity = 0.8,
labelOptions = labelOptions(direction = "center",style = list('color' = "white"),noHide = TRUE, offset=c(0,0), fill = TRUE, opacity = 1, weight = 10, textOnly = TRUE)) %>%
addPolylines(route$lon,route$lat,
label = paste(round(route_summary[1]/60), 'hr - ', round(route_summary[2]), 'km'),
labelOptions = labelOptions(noHide = TRUE))
But this returns the following error:
Error in UseMethod("metaData") :
no applicable method for 'metaData' applied to an object of class "NULL"
Can someone please show me how to fix this problem?
I would like to do this using "leaflet" and not using "rshiny". In the end, I would like the final map to look something like this (this is supposed to represent a "single path" from a Travelling Salesman Problem) :
[![enter image description here][2]][2]
Note: I am starting to think that problem might be that the "osrmRoute()" function might not be able to work for more than 2 points?
https://github.com/riatelab/osrm/issues/41
https://rdrr.io/cran/osrm/man/osrmTrip.html
One way is for you to make API call:
https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md
I'll just outline how can you do it:
data
df <- data.frame(
lon = c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957),
lat = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629)
)
url call
root <- "http://router.project-osrm.org/route/v1/driving/"
options <- c(
continue_straight = "true",
overview = "full",
annotations = "true",
steps = "true"
)
coords <- df %>%
slice(c(seq_len(n()), 1)) %>%
pmap_chr(str_c, sep = ",") %>% str_c(collapse = ";")
options <- options %>%
imap_chr(~str_c(.y, "=", .x)) %>%
str_c(collapse = "&") %>%
str_c("?", .)
res <- rjson::fromJSON(file = str_c(root, coords, options))
Note that I've added first point as 6th row to make circle route.
map
res$routes[[1]]$geometry %>%
googlePolylines::decode() %>%
.[[1]] %>%
leaflet() %>%
addTiles() %>%
addPolylines(lng = ~lon, lat = ~lat) %>%
addCircleMarkers(
data = df,
stroke = FALSE,
label = seq_len(nrow(df)),
fillOpacity = 0.8,
labelOptions = labelOptions(
direction = "center",
style = list('color' = "white"),
noHide = TRUE,
offset=c(0,0),
fill = TRUE,
opacity = 1,
weight = 10,
textOnly = TRUE
)
)
distance
res$routes[[1]]$distance
This is in meters (documentation)
EDIT
There probably is better way of labeling polyline but I don't have time now:
library(sf)
segment_df <- df %>% rbind(df[1,])
d <- segment_df %>%
st_as_sf(coords = c("lon", "lat"), crs = 4326) %>%
{st_distance(.[-6,], .[-1,], by_element = TRUE)} %>%
as.vector() %>%
round()
m <- leaflet() %>% addTiles()
for(i in seq_len(nrow(segment_df) - 1))
m <- m %>% addPolylines(
data = segment_df[i:(i+1),],
lng = ~lon, lat = ~lat, color = "red", label = paste(d[[i]], "m"),
labelOptions(noHide = TRUE, direction = 'top')
)
m <- m %>% addCircleMarkers(
data = df,
stroke = FALSE,
label = seq_len(nrow(df)),
fillOpacity = 0.8,
labelOptions = labelOptions(
direction = "center",
style = list('color' = "white"),
noHide = TRUE,
offset=c(0,0),
fill = TRUE,
opacity = 1,
weight = 10,
textOnly = TRUE
)
)
If you want only to show total distance then that is easier and does not require loop, just replace loop with:
segment_df %>%
leaflet() %>%
addTiles() %>%
addPolylines(
lng = ~lon, lat = ~lat, color = "red",
label = paste(sum(d), "m"),
labelOptions = labelOptions(noHide = TRUE, direction = 'top')
)
I hope you understand (and see from map) that this is not drivable.
Here is an answer I tried based on #det's answer:
library(sf)
library(geosphere)
library(dplyr)
library(leaflet)
library(data.table)
library(VPF)
#add a 6th row that is equal to the 1st row - so that the path loops back
map_data <- data.frame("Lat" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629, 43.6426), "Long" = c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957, -79.3871 ), type = c(1,2,3,4,5,1))
map_data$type = as.factor(map_data$type)
m1 = leaflet(map_data) %>% addTiles() %>% addCircleMarkers(stroke = FALSE, label = ~type,fillOpacity = 0.8,
color = ~ifelse(type==1,"red","blue"), labelOptions = labelOptions(direction = "center",style = list('color' = "white"),
noHide = TRUE, offset=c(0,0), fill = TRUE, opacity = 1, weight = 10, textOnly = TRUE))
m1 %>% addTiles() %>%
addPolylines(data = map_data, lng = ~Long, lat = ~Lat, group = ~type)
Now, I want to calculate the total distance of the trip and have it displayed on the map:
#distances (https://stackoverflow.com/questions/42119438/calculate-distance-between-two-long-lat-coordinates-in-a-dataframe)
result = rbind(
cbind(map_data[1:nrow(map_data)-1,c(1,2)], map_data[-1,c(1,2)]),
cbind(map_data[nrow(map_data), c(1,2)], map_data[1,c(1,2)])
)
colnames(result) <- c("start_lat", "start_long", "end_lat", "end_long")
result$id = as.factor(c(1,2,3,4,5,1))
result = data.frame(result)
for (i in 1:nrow(result)) {
a<-result$start_long[i]
b<-result$start_lat[i]
c<-result$end_long[i]
d<-result$end_lat[i]
result$distance[i]<-distm(c(a,b),c(c,d), fun = distHaversine)
}
#total distance of trip in meters
d = result$distance
total_d = signif(sum(d),3)
m1 %>% addPolylines(
data = map_data,
lng = ~Long, lat = ~Lat, color = "blue", label = paste0(total_d, " meters"),
labelOptions(noHide = TRUE, direction = 'top')
)
I think I finally got it - thanks so much # Det!

Leaflet with Shiny - how to ensure maximum zoom in option for the user

For one of the map use case , need to provide maximum zoom in option for the user in shiny app. Have tried to explore some of the options as per below code. Wanted to understand if this is the maximum limit we can have in shiny app using leaflet or I am missing something , really appreciate some guidance here.
One of the reactjs web application , Zoom In is possible even further - Here we are using bing / google map license though.
field <- raster::shapefile("sampleShapleFile.shp") # shapefile (field) imported
library(leaflet)
library(leaflet.extras)
leaflet(data = field ,
options = leafletOptions(zoomSnap = 0.25, zoomDelta = 0.25)) %>%
addFullscreenControl(position = "topleft", pseudoFullscreen = FALSE) %>%
addBingTiles(
"Aq4GyoG8kzfeKO7Nsav5_BcjVVA_d1ULSTeXeW2zM0aPuANIqhvV5IrFtMjOGX3s",
imagerySet = c("AerialWithLabels"),
group = "AerialWithLabels",
options = tileOptions(minZoom = 0, maxZoom = 18)
) %>%
addPolygons(
fill = FALSE,
stroke = TRUE,
weight = 5,
opacity = 1,
color = "#FFFFFF"
) %>%
addLegend("bottomright", color = "#FFFFFF", labels = "Test") %>%
addMeasure(
position = "bottomleft",
primaryLengthUnit = "meters",
primaryAreaUnit = "sqmeters",
activeColor = "#10bae0",
completedColor = "#241ad9"
) %>%
addDrawToolbar(
targetGroup = 'draw',
polygonOptions = FALSE,
circleOptions = FALSE,
rectangleOptions = FALSE,
markerOptions = FALSE,
circleMarkerOptions = FALSE,
editOptions = editToolbarOptions(selectedPathOptions = selectedPathOptions())
) %>%
addScaleBar(position = "topright",
options = scaleBarOptions(
maxWidth = 1,
metric = TRUE,
imperial = FALSE
))
"maxNativeZoom" with "maxZoom" Option in "addTiles" can be utilized to enhance zoom in level for Google / Bing Map
Useful Reference Links :
https://gis.stackexchange.com/questions/78843/zoom-further-in-than-level-19-with-leaflet-javascript-api
https://github.com/digidem/leaflet-bing-layer/issues/8
## app.R ##
library(shiny)
library(shinydashboard)
library(leaflet)
library(leaflet.extras)
ui <- dashboardPage(dashboardHeader(),
dashboardSidebar(),
dashboardBody(leafletOutput("map")))
server <- function(input, output) {
field <-
raster::shapefile("sample.shp") # shapefile (field) imported
output$map <- renderLeaflet({
leaflet(data = field) %>%
addFullscreenControl(position = "topleft", pseudoFullscreen = FALSE) %>%
# addTiles(
# group = "Satellite",
# urlTemplate = "http://mt0.google.com/vt/lyrs=s&hl=en&x={x}&y={y}&z={z}&s=Ga",
# options = tileOptions(maxZoom = 21 , maxNativeZoom = 18)
# ) %>%
addBingTiles("Aq4GyoG8kzfeKO7Nsav5_BcjVVA_d1ULSTeXeW2zM0aPuANIqhvV5IrFtMjOGX3s",
imagerySet = c("AerialWithLabels"),group = "AerialWithLabels",
maxNativeZoom = 18,maxZoom = 21
) %>%
addPolygons(
fill = FALSE,
stroke = TRUE,
weight = 5,
opacity = 1,
color = "#FFFFFF"
) %>%
addLegend("bottomright", color = "#FFFFFF", labels = "Test") %>%
addMeasure(
position = "bottomleft",
primaryLengthUnit = "meters",
primaryAreaUnit = "sqmeters",
activeColor = "#10bae0",
completedColor = "#241ad9"
) %>%
addDrawToolbar(
targetGroup = 'draw',
polygonOptions = FALSE,
circleOptions = FALSE,
rectangleOptions = FALSE,
markerOptions = FALSE,
circleMarkerOptions = FALSE,
editOptions = editToolbarOptions(selectedPathOptions = selectedPathOptions())
) %>%
addScaleBar(
position = "topright",
options = scaleBarOptions(
maxWidth = 10,
metric = TRUE,
imperial = FALSE
)
)
})
}
shinyApp(ui, server)

Creating Leaflet Geo-Spatial Plots in R

Recently, I have started learning about the R package "leaflet". This package allows you to identify points on a map provided their latitude and longitude. I created some fake data and I was able to successfully make a leaflet plot (with popup options that display properties of each point):
library(dplyr)
library(leaflet)
map_data <- data.frame("Lat" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), "Long" = c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ),
"Job" = c("Economist", "Economist", "Teacher", "Teacher", "Lawyer"),
"First_Name" = c("John","James", "Jack", "Jason", "Jim"),
"Last_Name" = c("Smith","Charles", "Henry", "David", "Robert"),
"vehicle" = c("car", "van", "car", "none", "car"))
map_data %>% leaflet() %>% addTiles() %>% addMarkers(clusterOption=markerClusterOptions(), lng = map_data$Long, lat = map_data$Lat, popup = paste("Job", map_data$Job, "<br>", "First_Name:", map_data$First_Name, "<br>", "Last_Name:", map_data$Last_Name, "<br>", "vehicle:", map_data$vehicle, "<br>" ))
Now, I wanted to take this a few steps further and color code the points based on the "job" of each individual. I found this github tutorial over here that I want to follow: https://poldham.github.io/abs/mapgbif.html
Using the same data I previously created, I tried to re-create a similar plot (slightly modifying it by adding my own popup options). However, when I run my code, I now get an empty map. Can someone please tell me what I am doing wrong? I have attached my code below:
library(dplyr)
library(leaflet)
library(RColorBrewer)
#create map data
map_data <- data.frame("Lati" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), "Longi" = c(-79.3871, -79.3860, -79.3807, -79.3806,-79.3957 ),
"Job" = c("Economist", "Economist", "Teacher", "Teacher", "Lawyer"),
"First_Name" = c("John","James", "Jack", "Jason", "Jim"),
"Last_Name" = c("Smith","Charles", "Henry", "David", "Robert"),
"vehicle" = c("car", "van", "car", "none", "car"))
#create initial map
map <- leaflet::leaflet(map_data) %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addMarkers(~Longi, ~Lati, popup = map_data$Job)
#add markers
map <- leaflet(map_data) %>% addTiles() %>% addCircleMarkers(~Longi,
~Lati, popup = map_data$Job, radius = 1, fillOpacity = 0.5, clusterOptions = markerClusterOptions())
map <- leaflet(map_data) %>% addTiles() %>% addCircleMarkers(~Longi, ~Lati,
popup = map_data$Job, radius = 1, weight = 2, opacity = 0.5, fill = TRUE,
fillOpacity = 0.2)
#create colors (is it possible to make the colors Red, Blue and Green?)
previewColors(colorFactor("Paired", domain = NULL), LETTERS[1:3])
kingdom <- c("Economist", "Lawyer", "Teacher")
my_palette <- brewer.pal(3, "Paired")
previewColors(colorFactor(my_palette, levels = kingdom), kingdom)
factpal <- colorFactor(my_palette, levels = kingdom)
species_circle <- leaflet(map_data) %>% addTiles() %>% addCircleMarkers(~Longi,
~Lati, popup = map_data$Job, radius = 1, weight = 2, opacity = 0.5,
fill = TRUE, fillOpacity = 0.2, color = ~factpal(kingdom))
species_circle
groups = unique(map_data$Job)
#finalize map
map = leaflet(map_data) %>% addTiles(group = "OpenStreetMap")
for (i in groups) {
data = map_data[map_data$kingdom == i, ]
map = map %>% addCircleMarkers(data = data, ~Longi, ~Lati, radius = 1,
weight = 2, opacity = 0.5, fill = TRUE, fillOpacity = 0.2, color = ~factpal(kingdom),
group = i)
}
map %>% addLayersControl(overlayGroups = groups, options = layersControlOptions(collapsed = FALSE)
%>% addTiles() %>% # Add default OpenStreetMap map tiles
addMarkers(lng = map_data$Long, lat = map_data$Lat,
popup = paste("Job", map_data$Job, "<br>",
"First_Name:", map_data$First_Name, "<br>",
"Last_Name:", map_data$Last_Name, "<br>", "vehicle:", map_data$vehicle, "<br>" ))
Thanks!
The main issue with your code is that you filter on variable map_data$kingdom (which is no column of map_data) in the for loop instead of on variablr map_data$Job. Hence data is always an empty df and you don't get any markers.
Besides that:
You don't need the for loop
To get the right assigments for colors map ~factpal(Job) on color instead of ~factpal(kingdom).
You don't need to refer to variables in your data with map_data$. Simply use the name of the variable. Leaflet by default will look for these variables in the dataset you provided with leaflet(map_data)
I reduced all the unnecessary code to focus on the main map code. For illustration purposes I increased the radius of the cirleMarkers to 10 and set the opacity to 1.
library(dplyr)
library(leaflet)
library(RColorBrewer)
# create map data
map_data <- data.frame(
"Lati" = c(43.6426, 43.6424, 43.6544, 43.6452, 43.6629), "Longi" = c(-79.3871, -79.3860, -79.3807, -79.3806, -79.3957),
"Job" = c("Economist", "Economist", "Teacher", "Teacher", "Lawyer"),
"First_Name" = c("John", "James", "Jack", "Jason", "Jim"),
"Last_Name" = c("Smith", "Charles", "Henry", "David", "Robert"),
"vehicle" = c("car", "van", "car", "none", "car")
)
kingdom <- c("Economist", "Lawyer", "Teacher")
my_palette <- brewer.pal(3, "Paired")
factpal <- colorFactor(my_palette, levels = kingdom)
groups <- unique(map_data$Job)
# finalize map
map <- leaflet(map_data) %>%
addTiles(group = "OpenStreetMap") %>%
addCircleMarkers(~Longi, ~Lati, popup = ~Job,
radius = 10, weight = 2, opacity = 1, color = ~factpal(Job),
fill = TRUE, fillOpacity = 1, group = ~Job
)
map %>%
addLayersControl(overlayGroups = groups, options = layersControlOptions(collapsed = FALSE)) %>%
addTiles() %>%
addMarkers(lng = ~Longi,
lat = ~Lati,
popup = ~paste("Job", Job, "<br>",
"First_Name:", First_Name, "<br>",
"Last_Name:", Last_Name, "<br>", "vehicle:", vehicle, "<br>"))
EDIT To achieve the features you mentioned in your comment you could do:
If you want different colors you can simply pass any color vector to colorFactor, e.g.
my_palette <- c("red", "green", "blue")
factpal <- colorFactor(my_palette, levels = kingdom)
To remove the pins drop the line starting with addMarkers. In that case you have to move the code for the popup into addCircleMarkers (but be aware that there is already a popup=~Job in addCircleMarkers, i.e. overwrite this one). Another option would be to add group=~Job to addMarkers. Doing so only the pins for checked jobs will appear on the map.

R Leaflet Label Set direction

Please have a look at the below example code, I would like to use the label direction (MyDirection), which is stored in df to have different label directions within my map.
I can set every label to a specific direction like direction = "top", but somehow its not working if I specify direction = ~MyDirection.
Any Idea/solution would be much appreciated.
Thanks in advance.
library(leaflet)
df <- read.csv(textConnection("
Name,Lat,Long,MyDirection
ANN,51.19,4.46277778,right
BAB,43.26306,-2.94972222,left
BCN,41.29694,2.07833333,top
BCN,41.29694,2.07833333,bottom
"))
#---Create Map----
m <- leaflet(df) %>%
addTiles(group = "OSM (default)") %>%
addCircles(~Long, ~Lat,
label = ~htmlEscape(Name),
labelOptions = labelOptions(noHide = T,
#direction = "top",
#direction = "bottom",
#direction = "left",
#direction = "right",
direction = ~MyDirection))
m
I would like to share my latest approach. I finally managed to set the label direction based on mydf$MyDirection. Instead of adding multiple layers, as i did in my previous example, I used the library "Purrr". This reduces the amount of layers tremendously.
Best Regards
#Libraries----
library(leaflet)
library(htmltools)
library(htmlwidgets)
library(purrr)
#---Data Input----
mydf <- read.csv(textConnection("
Facility,Lat,Long,MyDirection
ANN,51.19,4.46277778,right
BAB,43.26306,-2.94972222,left
BCN,41.29694,2.07833333,top
BCN2,41.29694,2.07833333,bottom
"))
#---Create Vector----
ob_Facility <- mydf %>%
split(., .$Facility)
#---Create Map----
m <- leaflet() %>%
addTiles()
#---Purrr Layers----
names(ob_Facility) %>%
purrr::walk(function(mydf) {
m <<- m %>%
addCircleMarkers(data=ob_Facility[[mydf]],
lng=~Long, lat=~Lat,
group = "Show All",
label = ~Facility,
labelOptions = labelOptions(noHide = T,direction = ~MyDirection))
})
#---Layers control----
m %>%
addLayersControl(
overlayGroups = "Show All",
options = layersControlOptions(collapsed = FALSE)
)%>%
#---Save as HTML File----
saveWidget('Example Go Live Date.html', selfcontained = TRUE)
Hello,
I have figured out a workaround with 4 Layers (top,bottom,left,right) and attached the same group name to each layer.
library(leaflet)
df <- read.csv(textConnection("
Name,Lat,Long,MyDirection
ANN,51.19,4.46277778,right
BAB,43.26306,-2.94972222,left
BCN,41.29694,2.07833333,top
BCN,41.29694,2.07833333,bottom
"))
#---Create 4 additional DFs (1 for each dirction)----
dfLeft = df[df$MyDirection == "left", ]
dfRight = df[df$MyDirection == "right", ]
dfTop = df[df$MyDirection == "top", ]
dfBottom = df[df$MyDirection == "bottom", ]
#---Create Map----
m <- leaflet(df) %>%
addTiles(group = "OSM (default)") %>%
addCircles(~dfLeft$Long, ~dfLeft$Lat, color = '#d40511',
label = ~htmlEscape(dfLeft$Name),
labelOptions = labelOptions(noHide = T,
direction = "left"),
group = "Show All")%>%
addCircles(~dfRight$Long, ~dfRight$Lat, color = '#d40511',
label = ~htmlEscape(dfRight$Name),
labelOptions = labelOptions(noHide = T,
direction = "right"),
group = "Show All")%>%
addCircles(~dfTop$Long, ~dfTop$Lat, color = '#d40511',
label = ~htmlEscape(dfTop$Name),
labelOptions = labelOptions(noHide = T, direction = "top",
offset = c(0, -2)),
group = "Show All")%>%
addCircles(~dfBottom$Long, ~dfBottom$Lat, color = '#d40511',
label = ~htmlEscape(dfBottom$Name),
labelOptions = labelOptions(noHide = T, direction = "bottom",
offset = c(0, 2)),
group = "Show All")
m

R and Leaflet: How to arrange label text across multiple lines

Suppose you have the following data frame:
cities = data.frame( name = c('Madrid','Barcelona','Sevilla'),
country = c('Spain','Spain','Spain'),
region = c('Comunidad de Madrid','Cataluña','Andalucia'),
data = c(100, 200, 300),
lng = c(-3.683333,2.166667,-6.083333),
lat = c(40.433333,41.383333,37.446667))
My idea is to have a map of these cities and labels that could display some relevant information when hovering the corresponding city circles. I'd like to have the label text arranged in several lines. The very first approach below failed:
library( leaflet )
map = leaflet( cities ) %>%
addTiles() %>%
addCircles( lng = ~lng, lat = ~lat, fillColor = 'darkBlue', radius = 10000,
stroke = FALSE, fillOpacity = 0.8, label = paste0( cities$name,'\n', cities$region, '\n', cities$country, '\n', cities$data ) )
as well as other similar attempts. After googling a while, I found a possible solution by involving the htmltools package:
library( htmltools )
map2 = leaflet( cities ) %>%
addTiles() %>%
addCircles( lng = ~lng, lat = ~lat, fillColor = 'darkBlue', radius = 10000,
stroke = FALSE, fillOpacity = 0.8,
label = HTML( paste0( '<p>', cities$name, '<p></p>', cities$region, ', ', cities$country,'</p><p>', cities$data, '</p>' ) ) )
In this case, the information is displayed as I'd like but, within the same label, there is an entry for each city of the dataset. How could I do to have the text of a single city arranged in multiple lines? Any help would be really appreciated
First, create a character vector of html content for each city and then wrap that in a lapply call to set the HTML attribute for correct display when defining the label attribute in adCircles
labs <- lapply(seq(nrow(cities)), function(i) {
paste0( '<p>', cities[i, "name"], '<p></p>',
cities[i, "region"], ', ',
cities[i, "country"],'</p><p>',
cities[i, "data"], '</p>' )
})
map2 = leaflet( cities ) %>%
addTiles() %>%
addCircles(lng = ~lng, lat = ~lat, fillColor = 'darkBlue', radius = 10000,
stroke = FALSE, fillOpacity = 0.8,
label = lapply(labs, htmltools::HTML))
map2
The following also works for two labels:
labels <- sprintf(
"<strong>%s</strong><br/>%g people / mi<sup>2</sup>",
states$name, states$density
) %>% lapply(htmltools::HTML)
m <- m %>% addPolygons(
fillColor = ~pal(density),
label = labels,
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto"))
m
see here for further info.
p.s: I wanted to use it for three labels but couldn't manage to.

Resources