3

I want to plot multiple circles on a map, that have multiple overlaps. I would like to fill the circles using the fillOpacity argument. However, i set the fillOpacity to 0.5 and two circles overlap the fillOpacity will differ within the intersection. I would like that the fillOpacity also has "value of 0.5" within the intersection. So that the transparency is homogeneous across the area of both circles.

(A solution within shiny could be also of interest if it would facilitate a solution).

library(leaflet)
m <- leaflet() %>% addTiles()
m <- m %>% setView(-93.65, 42.0285, zoom = 15)
m %>% addCircles(-93.65, 42.0285, radius = 400, stroke = FALSE, fillOpacity = 0.5) %>%
  addCircles(-93.655, 42.0255, radius = 400, stroke = FALSE, fillOpacity = 0.5)

Edit:

Given the comment, i gave it another try. Here is my best attempt (now working): (Inspired from here: Is it possible to include custom css in htmlwidgets for R and/or LeafletR?). i choose the g tag, because the circles seem to be wrapped within that tag. It might be a dirty Workaround since other Elements might be wrapped within that tag as well.

library(leaflet)
library(htmltools)
m <- leaflet() %>% addTiles()
m <- m %>% setView(-93.65, 42.0285, zoom = 15)
m <- m %>% addCircles(-93.65, 42.0285, radius = 400, stroke = FALSE, fillOpacity = 1) %>%
  addCircles(-93.655, 42.0255, radius = 400, stroke = FALSE, fillOpacity = 1)

browsable(
  tagList(list(
    tags$head(
      tags$style('g{opacity:0.3;}')
    ),
    m
  ))
)

enter image description here Shiny attempt (now working):

library(shiny)
library(leaflet)

ui <- fluidPage(
  tags$head(
    tags$style('g{opacity:0.2'),
    tags$script("
      $('div.leaflet-overlay-pane').css('fill-opacity', '0.5');
    ")
  ),
  leafletOutput("mymap")
)

server <- function(input, output, session) {
    output$mymap <- renderLeaflet({
    leaflet() %>%
      addProviderTiles(providers$Stamen.TonerLite,
                       options = providerTileOptions(noWrap = TRUE)
      ) %>%
      addCircles(lng = rnorm(40) * 2 + 13, lat = rnorm(40) + 48, radius = 100000, stroke = FALSE,
                 fillOpacity = 1, group = "ABCD")
  })
}

shinyApp(ui, server)
Tlatwork
  • 1,445
  • 12
  • 35
  • 1
    Doesn't look like it's possible without adding a parent `div` element to the rendered html and changing the css opacity there: https://stackoverflow.com/questions/18334135/leaflet-overlapping-shapes-opacity – JasonAizkalns Feb 27 '19 at 20:41
  • Thanks for the comment. I made an edit with an attempt to solve it. – Tlatwork Feb 27 '19 at 21:10
  • 1
    did the g element work for you? I've been trying things with trying to use jQuery to wrap the elements, but no success yet. Note: to make it easier to only "act" on the circles, you can use something like: `addCircles(..., options = pathOptions(className = "mycircle"))` This will at least add a mycircle class to each of those elements. – JasonAizkalns Feb 27 '19 at 21:31
  • no unfortunately it was just an attempt. I was trying my luck in shiny. See the edit for the attempt. Great id with the pathOptions, i will try to use that. If i understand correctly, you would use it to find the circles and then navigate to the parent? – Tlatwork Feb 27 '19 at 21:40
  • You are correct on the approach as to why add the class, but wasn't able to figure it out. If you try a few things and get it to work, please leave an answer. Unfortunately, there's no such thing (?) yet (?) as a [parent selector in css](https://css-tricks.com/parent-selectors-in-css/). – JasonAizkalns Feb 27 '19 at 21:58
  • just to clarify my previous attempts i all documented in the question (see the edits above) – Tlatwork Feb 27 '19 at 23:07

1 Answers1

1

So setting the g element style opacity (not fill-opacity) to the desired amount and leaving the markers/circles at 1 fill-opacity seems to work:

---
title: "R Notebook"
output:
  html_document:
    df_print: paged
---

<style>
g {
  opacity: 0.5;
}
</style>

```{r leaflet_plot, echo=FALSE, warning=FALSE}
library(leaflet)
m <- leaflet() %>% addTiles()
m <- m %>% setView(-93.65, 42.0285, zoom = 15)
m %>% 
  addCircles(-93.65, 42.0285, radius = 400, stroke = FALSE, fillOpacity = 1) %>%
  addCircles(-93.655, 42.0255, radius = 400, stroke = FALSE, fillOpacity = 1)
```

enter image description here

Granted, the g element is probably too broad/risky, but at least the idea is here now. This is very much in the spirit of having the parent element control opacity like the comment and linked question.

I tried adding various forms of this to the rmarkdown, but was never successful:

```{js}
$('class-of-circles').wrap('div style="opacity: 0.5"></div>);
```

Adding a non-Rmarkdown example:

library(shiny)
library(leaflet)

ui <- fluidPage(
  tags$head(
    tags$style('g { opacity: 0.2 }'),
    tags$script("
      $('div.leaflet-overlay-pane').css('fill-opacity', '0.5');
    ")
  ),
  leafletOutput("mymap")
)

server <- function(input, output, session) {
    output$mymap <- renderLeaflet({
    leaflet() %>%
      addProviderTiles(
          providers$Stamen.TonerLite,
          options = providerTileOptions(noWrap = TRUE)
      ) %>%
      addCircles(
          lng = rnorm(40) * 2 + 13, 
          lat = rnorm(40) + 48, 
          radius = 100000, 
          stroke = FALSE,
          fillOpacity = 1, 
          group = "ABCD"
      )
  })
}

shinyApp(ui, server)
JasonAizkalns
  • 20,243
  • 8
  • 57
  • 116
  • great work, thank you! As i see it, the main difference was to Switch to opacity instead of fill-opacity. I upvoted. To be very precise the question was not about markdown, but it can be used outside of markdown as well, see my Edits in the question (i tried it for base leaflet and shiny leaflet). I think it would be good to mention that shortly for other Readers, before marking the question as accepted. Would that be okay? – Tlatwork Feb 27 '19 at 23:15