28

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

LuPi
  • 295
  • 1
  • 3
  • 6

3 Answers3

53

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
SymbolixAU
  • 25,502
  • 4
  • 67
  • 139
TimSalabim
  • 5,604
  • 1
  • 25
  • 36
  • 1
    This is exactly what I was searching for and looks so simple and obvious that it should have come to my mind by myself. Just a minor adjustment to your code the last ')' is not required. Thanks. – LuPi Apr 03 '17 at 09:59
  • Thanks for the hint with the bracket... Copy&paste error – TimSalabim Apr 03 '17 at 17:34
  • 7
    in 2019, if `labs` is already a column in `cities`, you can continue to use the `~` pattern `addCircles(label = ~HTML(labs), ...)`, also `paste(sep =
    , ...)` is an alternative label building pattern for multiliners (https://rstudio.github.io/leaflet)/popups.html)
    – Nate Feb 23 '19 at 17:18
  • 1
    @Nate, your link is broken - can you fix? Tks! – Nova Oct 21 '19 at 20:29
  • 4
    Non-broken link to the [documentation website for popup](https://rstudio.github.io/leaflet/popups.html). Thanks @Nova! (sorry can't edit previous comment due to age) – Nate Oct 22 '19 at 12:39
  • 3
    @Nate's comment really helped me. I didn't want spaces between separate lines in my label, and `
    ` was the answer (instead of `

    ` and `

    `).
    – Nova Oct 25 '19 at 15:31
4

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.

goodyonsen
  • 71
  • 4
1

@goodyonsen More labels can be added, for example you wanted 3 labels, in this case add an extra break and adequate specifier (e.g. %g). In your code, to turn it into 3 labels (adding another character string -name- for the sake of example), you can do :

labels <- sprintf(
  "<strong>%s</strong><br/>%g people / mi<sup>2</sup><br/>%s",
  states$name, states$density, states$name
) %>% lapply(htmltools::HTML)

Jojo
  • 11
  • 3