Code Monkey home page Code Monkey logo

leafgl's Introduction

leafgl - performant WebGL rendering for leaflet

R-CMD-check Codecov test coverage

monthly total CRAN status

An R package for fast web gl rendering of features on leaflet maps. It’s an R port of https://github.com/robertleeplummerjr/Leaflet.glify where more detailed information/documentation can be found. Also, if you like what you get here, make sure to star the original repo!


Installation

Stable version from CRAN
install.packages("leafgl")
Development version from Github
devtools::install_github("r-spatial/leafgl")

What does it do?

It allows rendering of a large amount of features on a leaflet map. What exactly a “large amount” is, depends

  1. on the types of features and
  2. on the hardware/software of the rendering machine.

Regarding 1. millions of points should be no problem, but millions of polygons might, depending on their complexity - i.e. the number of vertices.

With regard to 2., obviously the amount of RAM will matter most but there are other, more suptle, problems that can occur.

Given it’s name, leafgl is intended to fully integrate with the leaflet package, though it is very likely that it won’t be a 1:1 replacement for the respective leaflet::add* functions. For example, given the intention to render/visualise as many features as possible we need to make a compromise on what additional information we allow to be part of the rendering. So far, we allow coloring of features and popups based on one column of the feature attributes, hence you cannot provide your own popup content. This may seem drastic, but all this information is costly both in terms of performance/speed and memory. In the end, who wants to wait for a map that the browser isn’t able to render anyway…

What doesn’t it do?

For starters, it doesn’t guarantee to be working tomorrow. At this stage leafgl is pre-alpha and under heavy development so things are likely to change frequently. For example, we are thinking about shorter funtion names (e.g. addGlPolygons instead of the current addGlifyPolygons). Additionally, we are still figuring out which pathway is best to use in order to pass data from R to the browser. As a result, rendering environments other than the browser (or RStudio viewer) may not work properly or at all until we approach a more stable implementation.

NOTE

Depending on your operating system and browser, you may see some weird colors that do not correspond to the ones that you specified. The only known work-around at this stage is to set opacity = 1. For more details the inclined reader is referred to this issue

What can I do to help?

A lot! First and foremost you can use it as often as possible and report issues/bugreports and/or feature request (see end of page for details). If you have ideas on how to enhance functionality without impacting performance too much and feel confident enough to provide pull request, please don’t hesitate. Finally, if you have proficient knowledge of JavaScript and want/know how to improve the package in any way, we would very much love to hear from you!

Example usage

1 Mio. points on a map

This will render 1 Mio. points on a standard leaflet map.

library(leaflet)
library(leafgl)
library(sf)

n = 1e6

df1 = data.frame(id = 1:n,
                 x = rnorm(n, 10, 3),
                 y = rnorm(n, 49, 1.8))

pts = st_as_sf(df1, coords = c("x", "y"), crs = 4326)

options(viewer = NULL) # view in browser

leaflet() %>%
  addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
  addGlPoints(data = pts, group = "pts") %>%
  setView(lng = 10.5, lat = 49.5, zoom = 6)



Colouring points by value mapping

For this we use library(colourvalues) because it can create color voctors in the blink of an eye!

library(leaflet)
library(leafgl)
library(sf)
library(colourvalues)

n = 1e6

df1 = data.frame(id = 1:n,
                 x = rnorm(n, 10, 3),
                 y = rnorm(n, 49, 1.8))

pts = st_as_sf(df1, coords = c("x", "y"), crs = 4326)

cols = colour_values_rgb(pts$id, include_alpha = FALSE) / 255

leaflet() %>%
  addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
  addGlPoints(data = pts, fillColor = cols, group = "pts") %>%
  setView(lng = 10.5, lat = 49.5, zoom = 6)



100k polygons on a map

In reality, it only 97112 polygons… But who wants to be pedantic here?

This data was downloaded from https://download.geofabrik.de/europe/switzerland.html

library(leaflet)
library(leafgl)
library(sf)
library(colourvalues)

ch_lu = st_read("/media/timpanse/d8346522-ef28-4d63-9bf3-19fec6e13aab/bu_lenovo/software/testing/mapview/switzerland/landuse.shp")

ch_lu = ch_lu[, c(1, 3, 4)] # don't handle NAs so far

options(viewer = NULL)

cols = colour_values_rgb(ch_lu$type, include_alpha = FALSE) / 255

leaflet() %>%
  addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
  addGlPolygons(data = ch_lu, 
                color = cols, 
                popup = "type",
                group = "pols") %>%
  setView(lng = 8.3, lat = 46.85, zoom = 9) %>% 
  addLayersControl(overlayGroups = "pols")



Shiny

Thanks to [@ColinFay](https://github.com/ColinFay) leafgl has dedicated shiny functions. Given that what leafgl produces is a leaflet map, we only need to use leafglOutput in our ui call. In the server call we can simply use renderLeaflet. Here an example:

library(leaflet)
library(leafgl)
library(sf)
library(shiny)

n = 1e6

df1 = data.frame(id = 1:n,
                 x = rnorm(n, 10, 3),
                 y = rnorm(n, 49, 1.8))

pts = st_as_sf(df1, coords = c("x", "y"), crs = 4326)

options(viewer = NULL) # view in browser

m = leaflet() %>%
  addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
  addGlPoints(data = pts, group = "pts") %>%
  setView(lng = 10.5, lat = 49.5, zoom = 4) %>% 
  addLayersControl(overlayGroups = "pts")

ui <- fluidPage(
  leafglOutput("mymap")
)

server <- function(input, output, session) {
  output$mymap <- renderLeaflet(m)
}

shinyApp(ui, server)


Contact

Please file Pull requests, bug reports and feature requests at https://github.com/r-spatial/leafgl/issues

leafgl's People

Contributors

colinfay avatar tim-salabim avatar trafficonese avatar uribo avatar z3tt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

leafgl's Issues

renderLeafgl not working - object 'expr' not found

When trying to use renderLeafgl in a shiny app, the following error message appears:

Warning: Error in func: object 'expr' not found
[No stack trace available]

Not exactly sure why expr gets lost. However, since the function is not really necessary as renderLeaflet works just fine and is also used everywhere in the examples / Readme, we could possibly omit the function at all and explain this in leafglOutput.

If we want to keep the function, we can either just reassign it (renderLeafgl <- renderLeaflet) or copy the code from renderLeaflet. In these 2 cases we would have to add htmlwidgets to the Suggests.

Or we set the default quoted = TRUE, which also fixes the problem and doesnt add any packages.

Can the opacity depend on a variable?

For example, in addPolygon you could specify fillOpacity to depend on the variable most_common_gender_percentage, like this:

addPolygons(
fillColor = ~ mypal_bin(mydata$most_common_gender), # color shows most common gender
fillOpacity = ~ most_common_gender_percentage, ## opacity proportionnal to the common gender percentage)

addGlPolygons not rendering polygons but the outer edge of all the shape

Hello I have a shapefile of blocks geography of cook county and trying to plot them on leaflet map. When I cast multipolygons to to polygons using this command

leaflet() %>% 
  addProviderTiles(providers[[113]]) %>% 
  addGlPolygons(data = st_transform(st_cast(blocks_sf_f, "POLYGON"),
                                        crs = '+proj=longlat +datum=WGS84'),weight = 0.1,
                popup = "GEOID10")

I get the below map

image

when I select random rows then individual polygons are being loaded

leaflet() %>% 
  addProviderTiles(providers[[113]]) %>% 
  addGlPolygons(data = st_transform(st_cast(blocks_sf_f[c(1:10000),], "POLYGON"),
                                        crs = '+proj=longlat +datum=WGS84'),
                weight = "10px",
                color = "green",
                popup = "GEOID10", fillColor = "yellow")```

then the shapes are being loaded, though sequential but one can not see the border. Let me know if there is a workaround for it or not ? to show just the stroke using weight. I tried that option too but for reason the weight also does not do anything. ALso is therer any option for for fillcolor to be not anything, like addPolygons has fill = FALSE argument

image

Possibility of using leaflet.extra::addSearchFeature to addGlPolygons

Sorry to bother you again, I have another question/feature request.

For the map I'm building, I need to add search field the user to quickly pin point the feature (postal code) it's looking for. The package leaflet.extra has this functionality which works really well:

library(sf)  
library(leaflet)
library(leafgl)
library(colourvalues)
library(leaflet.extras)

nc <- st_read(system.file("gpkg/nc.gpkg", package="sf"), quiet = TRUE) %>% 
  st_transform(st_crs(4326)) %>% 
  st_cast('POLYGON')

cols = colour_values_rgb(nc$AREA, palette = "inferno", include_alpha = FALSE) / 255
colpal <- colorNumeric(palette = "inferno", domain=nc$AREA, n=10)


leaflet(data=nc) %>% 
addProviderTiles(provider = providers$OpenStreetMap) %>%
addPolygons(color  = ~colpal(AREA),
            popup = ~NAME,
            label = ~NAME,
            group = "name") %>% 
addSearchFeatures(targetGroups  = 'name',
                  options = searchFeaturesOptions(zoom=10, openPopup=TRUE))

This creates a map which I can search:

image

I want to reproduce this but by using addGlPolygons instead of addPolygons. The problem is that addSearchFeatures requires addPolygons's label parameter using a ~ or called with nc$NAME which isn't available in addGlPolygon:

leaflet() %>%
   addProviderTiles(provider = providers$OpenStreetMap) %>%
   addGlPolygons(nc, 
                 color = cols,
                 popup = "NAME",
                 label = ~NAME,
                 group = "name") %>% 
   fitBounds(lng1 = unname(st_bbox(nc)$xmin), lng2 = unname(st_bbox(nc)$xmax), lat1 = unname(st_bbox(nc)$ymin), lat2 = unname(st_bbox(nc)$ymax)) %>% 
   addSearchFeatures(targetGroups  = 'name',
                     options = searchFeaturesOptions(zoom=10, openPopup=TRUE))
Error in geojsonsf::sf_geojson(data, ...) : 
  unused argument (label = ~NAME) 

My actual problem requires me to plot around 50,000 polygons, so I have to use leafgl instead of basic leaflet. However, the search feature is really needed to sort through all the 50,000 polygons. I tried to go around the problem by using leafgl to plot the polygons and adding an invisible leaflet::addMarkers to allow the search. I was expecting leaflet to be able to handle 50,000 points which should be simpler than 50,000 polygons but it wasn't the case, it failed. The code I used:

suppressWarnings(nc_marker <- st_centroid(nc))
  
leaflet() %>%
  addProviderTiles(provider = providers$OpenStreetMap) %>%
  addMarkers(data = nc_marker,
                   popup = ~NAME,
                   label = ~NAME,
                   group = "name",
                   options = markerOptions(opacity = 0)) %>% 
  addSearchFeatures(targetGroups  = 'name',
                    options = searchFeaturesOptions(zoom=10, openPopup=TRUE)) %>%
  addGlPolygons(data = nc, 
                color = cols, 
                popup = "NAME") %>%
  fitBounds(lng1 = unname(st_bbox(nc)$xmin), lng2 = unname(st_bbox(nc)$xmax),
            lat1 = unname(st_bbox(nc)$ymin), lat2 = unname(st_bbox(nc)$ymax)) 

Which produce:

image

Do you think there a way to add the label argument in your addGl* functions so they are compatible with leaflet.extra?

Support for layer ordering

Hi,

Wondering if this package can support AddMapPane and options = pathOptions(pane = "somename")) for layering lines on top of polygons?

Thanks!

Does Shiny input$map_shape_click work with glPolygons?

Hello,
Firstly...awesome package, this has huge potential for me displaying my model mesh results, so keep up the excellent work!

However, I am having an issue inside of Shiny context, how do you capture the click event for individual polygons?

I have an observer that adds a polygon layer like this:

observe({
  req(grid_poly())  
leafletProxy('map') %>%
      clearShapes() %>%

 
  addGlPolygons(data = grid_poly(), 
              opacity = 1,
              color = cols,
              group = "Grid") 
})

Then I have another one that fires when a polygon is clicked and highlights it:

click_element <- eventReactive(input$map_shape_click, {

  input$map_shape_click$id
})

# highlight the clicked element
observe({

  req(click_element()) # do this if click_element() is not null

  # Add the clicked element to the map in aqua, and remove when a new one is clicked
  map <- leafletProxy('map') %>%
      removeShape('element') %>%
      addPolygons(data = grid_poly()[grid_poly()$id == click_element(), ],
                  fill = TRUE,
                  color = '#00ffff', opacity = 1, layerId = 'element')
})

But this doesn't seem to work. But this did work using the generic AddPolygons() for leaflet. Is this something inherently different about GLpoly's?

Thanks!

popup not working if Polylines are added twice

I want to overlay an already visible Polyline with another one, with a different popup. Interestingly that does not work if the data is part of the already visible layer. I tried the CRAN and current github versions without success.
The click event stops here

if (map.hasLayer(lineslayer.glLayer)) {

Interestingly, if the 2nd Polyline uses data = data[11:nrow(data),] instead, the example will work.

Here is an example to illustrate the problem.

library(leaflet)
library(leafgl)

data <- sf::st_as_sf(leaflet::atlStorms2005)

leaflet() %>% 
  addTiles() %>% 
  addGlPolylines(
    data = data[1:10,],
    group = "base", 
    color = "red", 
    popup = TRUE) %>% 
  addGlPolylines(
    data = data[1:10,],
    # data = data[11:nrow(data),],
    color = "blue",
    group = "base2",
    popup = ~sprintf("I am a special Popup<br><b>Name :</b> %s<br><b>MaxWind :</b> %s",
                     Name , MaxWind)) %>% 
  hideGroup("base") %>% 
  addLayersControl(overlayGroups = "base")

Animation?

Hello,

Not an issue as such, more me thinking out loud, This (excellent) project could be used for animations?

For example I've got a few datasets of around 50,000 points at 1 minute resolution over a day. I'm struggling to create an animation/visualisation of them. Perhaps using the mapshot function in leaflet and this library I could quickly plot 24 x 60 PNG files and then stitch them together.

Cheers.

PR propsal: UpdateMapPane

Thanks so much for developing the leaflet R package! I was wondering if you had thought about adding the functionality to programmatically update the z-index for a map pane? This functionality would be useful for a Shiny App so that users can re-order the layers (via panes) as needed (via leafletProxy) without needing to add/remove layers. I would be happy to develop/write up a PR to add this functionality (e.g. using an updateMapPane function) if that would be helpful? I completely understand if you (the maintainers/developers) are swamped with other tasks, so please let me know if you will not have time to reivew/merge a PR and I will not waste your time with a low priority PR?

[Feature request] Having a removeGl*() function

{leaflet} allows to leaflet::removeMarker() (and other remove*) so that in a Shiny App you can trigger removal of elements from the server side.

Would be nice to have a removeGlPoints() (and friends) to do the same thing on a map rendered with {leafgl}.

I can dig into that if you think that's a good idea.

test-leafgl-colors.R fails if {colourvalues} not installed

Running test-leafgl-colors.R without the colourvalues package installed gives this error:

-- Error (test-leafgl-colors.R:153:3): Formula as color ------------------------
Error: invalid color name 'rainbow'
Backtrace:
 1. `%>%`(...) test-leafgl-colors.R:153:2
 2. leafgl::addGlPoints(...)
 4. leafgl::makeColorMatrix.formula(fillColor, data, palette = palette) C:/Research/leafgl/R/utils-color.R:52:2
 6. leafgl::makeColorMatrix.integer(x, data, palette, ...) C:/Research/leafgl/R/utils-color.R:52:2
 8. grDevices::col2rgb(pal(x), alpha = FALSE)

The problem seems to be that leaflet::colorNumeric doesn't recognize "rainbow" as a valid palette here:

pal <- leaflet::colorNumeric(palette, x, alpha = FALSE, ...)
)

Changing the call to palette="viridis" makes the test pass.

leafgl not rendering data

Thanks for making this wonderful package!

However, I can not get it working on my machine. The base leaflet maps will render but when using any type of addGlPolylines/gons/points function this data does not render. I am wondering if there is some sort of R/package version combination that is required or if you have any other suggestions on why data is not rendering? I have tried a few different R versions. Below is session info...and the code I try to run from the leafgl README

sessionInfo()
R version 3.6.2 (2019-12-12)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252
[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C
[5] LC_TIME=English_United States.1252

attached base packages:
[1] stats graphics grDevices utils datasets methods base

other attached packages:
[1] sp_1.3-1 shiny_1.5.0 ggthemes_4.2.0 magrittr_1.5 viridis_0.5.1
[6] viridisLite_0.3.0 forcats_0.5.0 stringr_1.4.0 dplyr_1.0.2 purrr_0.3.4
[11] readr_1.3.1 tidyr_1.0.0 tibble_3.0.4 ggplot2_3.3.2 tidyverse_1.3.0
[16] leaflet_2.0.3 sf_0.9-6 leafgl_0.1.1

loaded via a namespace (and not attached):
[1] fs_1.5.0 usethis_1.6.3 lubridate_1.7.4 devtools_2.3.2
[5] httr_1.4.2 rprojroot_2.0.2 tools_3.6.2 backports_1.1.4
[9] R6_2.5.0 KernSmooth_2.23-16 DBI_1.1.0 colorspace_1.4-1
[13] withr_2.3.0 tidyselect_1.1.0 gridExtra_2.3 prettyunits_1.1.1
[17] processx_3.4.4 curl_4.3 compiler_3.6.2 cli_2.1.0
[21] rvest_0.3.6 geojsonsf_2.0.1 xml2_1.3.2 desc_1.2.0
[25] scales_1.0.0 classInt_0.4-3 callr_3.5.1 digest_0.6.20
[29] pkgconfig_2.0.3 htmltools_0.5.0 sessioninfo_1.1.1 dbplyr_2.0.0
[33] fastmap_1.0.1 htmlwidgets_1.5.2 rlang_0.4.8 readxl_1.3.1
[37] rstudioapi_0.13 generics_0.1.0 jsonlite_1.6 crosstalk_1.1.0.1
[41] Rcpp_1.0.2 munsell_0.5.0 fansi_0.4.0 lifecycle_0.2.0
[45] stringi_1.4.3 yaml_2.2.0 pkgbuild_1.1.0 grid_3.6.2
[49] promises_1.1.1 crayon_1.3.4 lattice_0.20-38 haven_2.3.1
[53] jsonify_1.2.1 hms_0.5.3 ps_1.4.0 pillar_1.4.6
[57] pkgload_1.1.0 reprex_0.3.0 glue_1.4.2 leaflet.providers_1.9.0
[61] remotes_2.2.0 modelr_0.1.8 vctrs_0.3.5 httpuv_1.5.4
[65] testthat_3.0.0 cellranger_1.1.0 gtable_0.3.0 assertthat_0.2.1
[69] mime_0.7 xtable_1.8-4 broom_0.7.2 e1071_1.7-2
[73] later_1.1.0.1 class_7.3-15 memoise_1.1.0 units_0.6-3
[77] ellipsis_0.3.1

`
library(leafgl)
library(sf)
library(leaflet)
library(tidyverse)

storms = st_as_sf(atlStorms2005)

leaflet() %>%
addProviderTiles(provider = providers$CartoDB.Positron) %>%
addGlPolylines(data = storms, popup = TRUE, opacity = 1)

`

JavaScript errors in Shiny app

When starting a Shiny app using leafgl, many errors are reported in the JavaScript console.

This minimal app

library(leaflet)
library(leafgl)
library(shiny)

m = leaflet() %>%
  addTiles()

ui <- fluidPage(
  leafglOutput("mymap")
)

server <- function(input, output, session) {
  output$mymap <- renderLeaflet(m)
}

shinyApp(ui, server)

generates these errors in the JavaScript console:

aquare.glsl:1 Failed to load resource: the server responded with a status of 404 (Not Found)
canvasoverlay.js:142 Uncaught ReferenceError: module is not defined
    at canvasoverlay.js:142
index.js:1 Uncaught ReferenceError: require is not defined
    at index.js:1
map-matrix.js:1 Uncaught ReferenceError: module is not defined
    at map-matrix.js:1
points.js:1 Uncaught ReferenceError: require is not defined
    at points.js:1
shapes.js:2 Uncaught ReferenceError: require is not defined
    at shapes.js:2
lines.js:2 Uncaught ReferenceError: require is not defined
    at lines.js:2
utils.js:75 Uncaught ReferenceError: module is not defined
    at utils.js:75
dot.glsl:1 Uncaught SyntaxError: Unexpected identifier
point.glsl:1 Uncaught SyntaxError: Unexpected identifier
polygon.glsl:1 Uncaught SyntaxError: Unexpected identifier
puck.glsl:1 Uncaught SyntaxError: Unexpected identifier
simple-circle.glsl:1 Uncaught SyntaxError: Unexpected identifier
aquare.glsl:1 Failed to load resource: the server responded with a status of 404 (Not Found)
default.glsl:1 Uncaught SyntaxError: Unexpected identifier

The cause is lines 13-27 in https://github.com/r-spatial/leafgl/blob/master/R/glify-helpers.R. These lines include files which have already been included in glify.js by the Leaflet.glify build process. Removing those lines removes the errors without any impact on functionalty.

Presumably the same lines should be removed from glifyDependenciesSrc and glifyDependenciesFl; I don't understand the purpose of those two functions well enough to be sure.

Pandoc does not recognize mime type of glsl files

When using {leafgl} in a self-contained rmarkdown doc the following error occurs. This does not happen when the file is not self-contained.

Could not determine mime type for `~/R/R-3.6/x86_64-pc-linux-gnu/leafgl/htmlwidgets/Leaflet.glify/src/shader/fragment/dot.glsl'
Error: pandoc document conversion failed with error 63

This is an issue with Pandoc not being able to recognize the MIME type for glsl files
jgm/pandoc#6000

How to use addLegend with leafgl

Hi all. This is probably a stupid question, but do you have any example of how to use leafgl package with addLegend function of leaflet ?

I need to create a map with a lot of LINESTRING objects colored according to a value and I have to add a legend at the bottom of the map explaining the meaning of the colors. I can easily create the map and color the lines but I don't know how to add a legend since the addLegend function requires pal and values parameters while addGlPolylines requires just a rgb matrix.

Weird behavior where polygons will change colour when they haven't been clicked in r shiny

I am trying to make a shiny app where the user uses a slider input to create n leaflet maps. Then on these maps clickable polygons are displayed, when the user clicks on the polygon the polygon changes colour.

I had this working with leaflet and addPolygons but because I need 19000+ polygons on (up to) 99 maps, I've been trying to use leafgl and addGlPolygons.

At first the maps seem to work ok, but then they start to display weird behavior where polygons will change colour when they haven't been clicked.

When they are initially plotted they are blue, but when the app errors they are removed.

Then I also get this weird sad face with cross eyes in the top-left corner of the leaflet.
kBG7K

library(shiny)
library(leaflet)
library(sp)
library(leafgl)
library(dplyr)

## create five square polygons
Sr1 <- Polygon(cbind(c(1, 2, 2, 1, 1), c(1, 1, 2, 2, 1)))
Sr2 <- Polygon(cbind(c(2, 3, 3, 2, 2), c(1, 1, 2, 2, 1)))
Sr3 <- Polygon(cbind(c(3, 4, 4, 3, 3), c(1, 1, 2, 2, 1)))
Sr4 <- Polygon(cbind(c(4, 5, 5, 4, 4), c(1, 1, 2, 2, 1)))
Sr5 <- Polygon(cbind(c(5, 6, 6, 5, 5), c(1, 1, 2, 2, 1)))

Srs1 <- Polygons(list(Sr1), "s1")
Srs2 <- Polygons(list(Sr2), "s2")
Srs3 <- Polygons(list(Sr3), "s3")
Srs4 <- Polygons(list(Sr4), "s4")
Srs5 <- Polygons(list(Sr5), "s5")

SpP <- SpatialPolygons(list(Srs1, Srs2, Srs3, Srs4, Srs5), 1:5)

ui <- fluidPage(
  sliderInput("nomaps", "Number of maps:",
              min = 1, max = 5, value = 1
  ),
  uiOutput("plots")
)

change_color <- function(map, id_to_remove, data, colour, new_group){
  leafletProxy(map) %>%
    removeGlPolygons(id_to_remove) %>% # remove previous occurrence
    addGlPolygons(
      data = data,
      label = data$display,
      layerId = data$ID,
      group = new_group, # change group
      color = colour)
}

server <- function(input,output,session){
  
  ## Polygon data
  rv <- reactiveValues(
    df = SpatialPolygonsDataFrame(SpP, data = data.frame(
      ID = c("1", "2", "3", "4", "5"),
      display = c("1", "1","1", "1","1")
    ), match.ID = FALSE)
  )
  
  # initialization
  output$map <- renderLeaflet({
    leaflet(options = leafletOptions( zoomControl = FALSE, minZoom = 6.2, maxZoom = 6.2, dragging = FALSE)) 
  })
  
  observe({
    
    data <- rv$df
    
      lapply(1:input$nomaps, function(i) {
      
        output[[paste("plot", i, sep = "_")]] <- renderLeaflet({
          leaflet(options = leafletOptions(zoomControl = FALSE, minZoom = 6.2, maxZoom = 6.2, dragging = FALSE))%>%
            addGlPolygons(
              data = data,
              label = data$display,
              layerId = data$ID,
              group = "unclicked_poly",
              color = cbind(0, 0.2, 1),
              fillOpacity = 1)
          
        })
      })
  })
  
  # Create plot tag list
  output$plots <- renderUI({
    
      plot_output_list <- lapply(1:input$nomaps, function(i) {
        plotname <- paste("plot", i, sep = "_")
        leafglOutput(plotname)
      })
      
      do.call(tagList, plot_output_list)
    
  })
  
  observe ({
    lapply(1:input$nomaps, function(i) {
    
      observeEvent(input[[paste0("plot_", i,"_glify_click",sep="")]], {
        
        selected.id <- input[[paste0("plot_", i,"_glify_click",sep="")]]
        data <- rv$df[rv$df$ID==selected.id$id,]
        
        change_color(map = paste0("plot_", i, sep=""),
                     id_to_remove =  selected.id$id,
                     data = data,
                     colour = "yellow",
                     new_group = "clicked1_poly") 
      })
    })
    })

  }

shinyApp(ui, server)

License

Hi Tim,

This is very good work.

Is there an explicit license?

Issue with color rendering addGLPolygons

Hi Tim,

I can't reproduce your example and change polygons color when usin addGlPolygons/points. I thought it might come from RStudio viewer, but the issue persists when displayed in a browser.
More importantly, I'd like to set my own color palette, but the colors aren't the right one when displayed (when they are).
Thx for any hint.

library(mapview)
library(leaflet)
library(leafgl)
library(sf)
library(colourvalues)

n = 1e3

df1 = data.frame(id = 1:n,
                 x = rnorm(n, 10, 3),
                 y = rnorm(n, 49, 1.8),
                 col=rep(c(0,1),each=500))

pts = st_as_sf(df1, coords = c("x", "y"), crs = 4326)

cols = colour_values_rgb(pts$id, palette="plasma",include_alpha = FALSE) / 255
head(cols)
leaflet() %>%
    addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
    addGlPoints(data = pts, color = cols, group = "pts") %>%
    setView(lng = 10.5, lat = 49.5, zoom = 6) %>% 
    addLayersControl(overlayGroups = "pts")

return this

Then trying to set a user-definded color palette:

my_col <- cols
COL <- col2rgb(c("lightgrey","orange"))/255
my_col[which(df1$col==0),] <- rep(COL[,1],each=length(which(df1$col==0)))
my_col[which(df1$col!=0),] <- rep(COL[,2],each=length(which(df1$col==0)))

m <- leaflet() %>%
  addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
  addGlPoints(data = pts, color = my_col, group = "pts") %>%
  setView(lng = 10.5, lat = 49.5, zoom = 6) %>% 
  addLayersControl(overlayGroups = "pts")

mapshot(m,url="test_addGL_color.html")

Adding stroke and weight option to addGlPolygons

Hello,

I need to make a map with leafgl where the polygons have a color inside and a thin border. I'm able to do it with leaflet but not leafgl. Is there an option that I missed or could it be implemented?

RE:

data preparation:

library(sf)  
library(leaflet)
library(leafgl)
library(colourvalues)

nc <- st_read(system.file("gpkg/nc.gpkg", package="sf"), quiet = TRUE) %>% 
  st_transform(st_crs(4326)) %>% 
  st_cast('POLYGON')

cols = colour_values_rgb(nc$AREA, palette = "inferno", include_alpha = FALSE) / 255
colpal <- colorNumeric(palette = "inferno", domain=nc$AREA, n=10)

using leaflet:

leaflet(data=nc) %>% 
  addProviderTiles(provider = providers$OpenStreetMap) %>%
  addPolygons(color  = ~colpal(AREA),
              stroke = T,
              weight = 0.8) 

gives:

mori

Which has nice borders.

with leafgl

leaflet() %>%
   addProviderTiles(provider = providers$OpenStreetMap) %>%
   addGlPolygons(nc, color = cols,stroke = T,
                 weight = 0.8) %>% 
   fitBounds(lng1 = unname(st_bbox(nc)$xmin), lng2 = unname(st_bbox(nc)$xmax), lat1 = unname(st_bbox(nc)$ymin), lat2 = unname(st_bbox(nc)$ymax))
Error in geojsonsf::sf_geojson(data, ...) : 
  unused arguments (stroke = T, weight = 0.8)

gives an error and if I remove the bad arguments (stroke = T and weight = 0.8), I get:
mgl

Which has no borders. Is there an equivalent of the stroke = T and weight = 0.8 arguments in leafgl?

Thanks

addGlPolygons fillColor does not work

Hello - I've been trying to use leafgl::addGlPolygons to render a large dataset of polygons, but the fill does not seem to be working. Here is example adapted from ?addGlPolygons:

gadm = st_as_sf(gadmCHE)
gadm = st_cast(gadm, "POLYGON")
cols = grey.colors(nrow(gadm))
cols_fill = topo.colors(nrow(gadm))
leaflet() %>%
addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
addGlPolygons(data = gadm, color = cols, fillColor =cols, popup = TRUE)

leafgl vs deckgl vs mapdeck

it seems leaflet GL solution is not popular than deckgl or mapdeck which base on uber deck.gl framework, and I am a new bee with large-scale point viz.

Do anyone know why we need these frameworks which looks like an overlay with each other, what is the difference between them?

Color problem when using different tiles providers?

I've noticed the the color used to with addGlifyPolygons doesn't work for all tile providers.

See RE:

# loading the libraries
library(sf)  
library(leaflet)
library(leaflet.glify)
library(colourvalues)

# preparing the shapefile
nc <- st_read(system.file("gpkg/nc.gpkg", package="sf"), quiet = TRUE) %>% 
  st_transform(st_crs(4326)) %>% 
  st_cast('POLYGON')

# setting the colors
cols = colour_values_rgb(nc$AREA, palette = "inferno", include_alpha = FALSE) / 255

# making the first map like in your example:
leaflet() %>%
  addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
  leaflet.glify:::addGlifyPolygons(nc, color = cols) %>% 
  fitBounds(lng1 = unname(st_bbox(nc)$xmin), lng2 = unname(st_bbox(nc)$xmax), lat1 = unname(st_bbox(nc)$ymin), lat2 = unname(st_bbox(nc)$ymax))

image

# making the second map with a different tile provider:
leaflet() %>%
  addProviderTiles(provider = providers$OpenStreetMap.Mapnik) %>%
  leaflet.glify:::addGlifyPolygons(nc, color = cols) %>% 
  fitBounds(lng1 = unname(st_bbox(nc)$xmin), lng2 = unname(st_bbox(nc)$xmax), lat1 = unname(st_bbox(nc)$ymin), lat2 = unname(st_bbox(nc)$ymax))

image

Do you know what the problem is?

Cursor don't change to pointer when hovering GlPoint features

After adding to the map a large number of GlPoint features (360000+), I found that the cursor does not automatically change to the pointing hand when hovering a feature. If I click on it, the popup is displayed normally; when the popup is visible, the cursor changes normally to pointer.

screenshooting a map with leafgl layer doesnt work

I dont think this is really a leafgl error and more a bug of the underlying JS-libraries (webshot, html2canvas, FileSaver?) but taking a screenshot of a map with leafgl data doesnt display the layer in the resulting image.

I tried several approaches to take a screenshot; mapview::mapshot, shinyscreenshot::screenshot and leaflet.extras2::addEasyprint.

Here's a shiny app which tries all those methods:

library(shiny)  
library(sf)
library(leaflet)
library(leafgl)
library(leaflet.extras2)
library(shinyscreenshot)
library(mapview)

storms = st_as_sf(atlStorms2005)
cols = heat.colors(nrow(storms))

ui <- fluidPage(
  actionButton("go", "Take a screenshot with `shinyscreenshot`"),
  actionButton("mapshot", "Take a screenshot with `mapview`"),
  leafletOutput("map"))

m <- leaflet()  %>% 
  addTiles() %>%
  addEasyprint(options = easyprintOptions(exportOnly = TRUE)) %>%
  addGlPolylines(data = storms, color = cols, popup = TRUE, opacity = 1)

server <- function(input, output, session) {
  output$map <- renderLeaflet({
    m
  })
  observeEvent(input$go, {
    screenshot()
  })
  observeEvent(input$mapshot, {
    mapshot(m, file = paste0(getwd(), "/map.png"))
  })
}
shinyApp(ui, server)

popup parameter not working in `addGlPolygons`

Hi and thanks you for this useful package.
Since the transfer from {leaflet.glify} to {leafgl}, the popup parameter does not work any more in addGlPolygons.

You can try with the example of the documentation. If I click on the polygons no popup appears. Same code with previous addGlifyPolygons is good:

library(mapview)
library(leaflet)
library(leafgl)
library(sf)
library(colourvalues)

fran = st_cast(franconia, "POLYGON")

cols = colour_values_rgb(fran$NUTS_ID, include_alpha = FALSE) / 255

options(viewer = NULL)

leaflet() %>%
  addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
  addGlPolygons(data = fran, color = cols, popup = "NAME_ASCI") %>%
  # leaflet.glify::addGlifyPolygons(data = fran, color = cols, popup = "NAME_ASCI") %>% 
  addMouseCoordinates() %>%
  setView(lng = 10.5, lat = 49.5, zoom = 8)

Warnings in test-leafgl-colors.R

Running under R 4.0.3, test-leafgl-colors.R gives several warnings such as this:

-- Warning (test-leafgl-colors.R:456:3): List as color -------------------------
Length of color vector does not match number of data rows.
  The vector is repeated to match the number of rows.
Backtrace:
 1. `%>%`(...) test-leafgl-colors.R:456:2
 2. leafgl::addGlPoints(...)
 4. leafgl::makeColorMatrix.list(fillColor, data, palette = palette) C:/Research/leafgl/R/utils-color.R:52:2
 6. leafgl::makeColorMatrix.numeric(x, data, palette, ...) C:/Research/leafgl/R/utils-color.R:52:2
 7. leafgl::checkDim(x, data) C:/Research/leafgl/R/utils-color.R:67:6

Although this is reported as a warning, it seems to be a bug as it results in the wrong colors being used.

The problem is in makeColorMatrix.list:

} else if (all(classes == "matrix")) {

In R 4.0 the class of a matrix is c("matrix" "array") so the above test fails.

JS canvasoverlay.js "module" and "require" not defined

Hello and thanks for a great add-on to leaflet R. Using it on the first example in your page, points load fine, but adding a popup fails (no popups) with several JS errors that I list below. File aquare.glsl is aalso not found. Am I doing something wrong or is it an issue regaaarding versions?

canvasoverlay.js:142 Uncaught ReferenceError: module is not defined at canvasoverlay.js:142
index.js:1 Uncaught ReferenceError: require is not defined at index.js:1
map-matrix.js:1 Uncaught ReferenceError: module is not defined at map-matrix.js:1
points.js:1 Uncaught ReferenceError: require is not defined at points.js:1
shapes.js:2 Uncaught ReferenceError: require is not defined at shapes.js:2
lines.js:2 Uncaught ReferenceError: require is not defined at lines.js:2
utils.js:75 Uncaught ReferenceError: module is not defined at utils.js:75
dot.glsl:1 Uncaught SyntaxError: Unexpected identifier (module.exports function not working)
point.glsl:1 Uncaught SyntaxError: Unexpected identifier (module.exports function not working)
polygon.glsl:1 Uncaught SyntaxError: Unexpected identifier (module.exports function not working)
puck.glsl:1 Uncaught SyntaxError: Unexpected identifier (module.exports function not working)
simple-circle.glsl:1 Uncaught SyntaxError: Unexpected identifier (module.exports function not working)
aquare.glsl:1 Failed to load resource: the server responded with a status of 404 (Not Found)
default.glsl:1 Uncaught SyntaxError: Unexpected identifier

Pass LayerId

Hi, there's a way to pass a layer ID to each point?

I want to build some individual graphics per point. The only information I'm getting now is the event 'click'. I can do some workaround to get the closest point to the Lat Long returned from the event 'click', but that is not ideal.

Thx for the awesome package.

Support icons for points

This might hurt performance, but would be good to have. This will allows the points to be as useful as markers.

Support simpleCircle rendering

I would like to use leafgl to render points without borders. The simpleCircle fragment shader in leaflet.glify does this. Can this be exposed as a user option?

Using the simpleCircle shader requires adding

    fragmentShaderSource: () => {
        return L.glify.shader.fragment.simpleCircle;
      }

to the call to L.glify.points in addGlifyPoints.js. What is the best way to do that optionally, so the existing functionality is preserved?

Thanks!

how to make clusterOptions for addGlPoints

is it possible to add clusters to addGlPoints?

For example this is what can be done in leaflet:

leaflet(quakes) %>% addTiles() %>% addMarkers(
clusterOptions = markerClusterOptions()
)

can we do something similar like the following?

leaflet(quakes) %>% addTiles() %>% addGlPoints(
clusterOptions = markerClusterOptions()
)

How to use addLegend with leafgl (continuous variable)

It was first reported here (#24). The author of the post did figure out by himself how to add a legend for a character or factor variable. But it does not work well with a continuous variable. I could use cut() to create a categorical value out of my continuous variable. But I was hoping there was a better (and nicer) way to do it.

Using this example, how would one add a legend?

library(mapview)
library(leaflet)
library(leafgl)
library(sf)
library(colourvalues)

n = 1e6

df1 = data.frame(id = 1:n,
x = rnorm(n, 10, 3),
y = rnorm(n, 49, 1.8))

pts = st_as_sf(df1, coords = c("x", "y"), crs = 4326)

cols = colour_values_rgb(pts$id, include_alpha = FALSE) / 255

options(viewer = NULL)

system.time({
m = leaflet() %>%
addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
addGlPoints(data = pts, color = cols, group = "pts") %>%
addMouseCoordinates() %>%
setView(lng = 10.5, lat = 49.5, zoom = 6) %>%
addLayersControl(overlayGroups = "pts")
})

m

Support for CRS.Simple

Would it be possible to support maps which are not in the standard projection? Specifically I would like to use addGlPoints with a map created using L.CRS.Simple. My base map is a microscope image of a tissue section; I would like to draw points representing hundreds of thousands of cells as a layer on top. It works (slowly) to use leaflet::addCircles with coordinates in the range 0-255; this fails with leafgl::addGlPoints because it tries to convert the points to EPSG:4326.

Example with no base map:

library(leaflet)
library(leafgl)
library(magrittr)

n=1000
pts = data.frame(id = 1:n,
                 x = rnorm(n, 128, 30),
                 y = rnorm(n, -128, 18))

crs <- leafletCRS(crsClass = "L.CRS.Simple")
map = leaflet(options = leafletOptions(crs = crs)) %>% 
  setView(128, -128, 1) 

# Works
map %>% addCircles(data=pts, lat=~y, lng=~x)

# Doesn't work
map %>% addGlPoints(st_as_sf(pts, coords=c('x', 'y')))

#Error in st_transform.sfc(st_geometry(x), crs, ...) : 
#  sfc object should have crs set
#Calls: %>% ... st_transform.sf -> st_transform -> st_transform.sfc

Support for MULTIPOLYGON

This is not a bug, but a feature request, and unfortunately I offer nothing in the way of a solution, just the ask.

leaflet::addPolygons() supports MULTIPOLYGONs so it would be nice if leafgl::addGlPolygons() did too. It's my goal to completely replace {leaflet} functions with {leafgl} functions.

AddGlPolylines not working with side-by-side pane option of leaflet.extras2 package

Hello,

I am trying to put two large shapefiles using addGlPolylines() on the left and the right pane using addSidebyside function but for some reason the functionality does not appear to work.

When using addPolylines the feature works well (side-by-side) but as soon as I use addGlPolylines() the shapefile appears on both the panes, as if it does not recognize the two layers.

Any help on this would be greatly appreciated

library(leaflet)
library(leafgl)
library(leaflet.extras2)
leaflet() %>%
  addMapPane("left", zIndex = 0) %>%
  addMapPane("right", zIndex = 0) %>%
  addProviderTiles(providers$CartoDB,  group = "base", layerId = "baseid",
           options = pathOptions(pane = "right")) %>%
  addProviderTiles(providers$CartoDB.DarkMatter, group="carto", layerId = "cartoid",
                   options = pathOptions(pane = "left")) %>%
  addGlPolylines(data = avg9_sf, color = "green", group = "green",
                   options = pathOptions(pane = "left")) %>%
  addPolylines(data = avg6_sf, color = "red", group = "red",
                   options = pathOptions(pane = "right")) %>%
  addLayersControl(overlayGroups = c("green","red")) %>%
  addSidebyside(layerId = "sidecontrols",
                rightId = "baseid",
                leftId = "cartoid")

Filter by Group & Export Issues

Problem:
The filter by group button does not seem to work when I use addGliffyPoints. The filter box will appear on the screen, however nothing happens when it is clicked.

Questions:

  1. How can I enable the filter by group function to work with GlifyPoints?

  2. Does leaflet.Glify only run on local machines? I have been unable to export as a webpage and via markdown? I will try shiny next.

Code:

leaflet() %>%
  addProviderTiles(provider = providers$CartoDB.Positron) %>%
  setView(lng = -95.7129, lat = 37.0902, zoom = 6)%>%
  addGlifyPoints(data = df_pts1, color = cbind(0, 0.2, 1), Opacity = 0.8, weight = 3, group = "A") %>%
  addGlifyPoints(data = df_pts2, color = cbind(1, 0.2, .5), Opacity = 0.8, weight = 3, group = "B") %>%
  addMouseCoordinates() %>%
addLayersControl(
  overlayGroups = c("A", "B"),
  options = layersControlOptions(collapsed = FALSE))

Thank you for any help!

On flexdashboard, points are invisible until we pan or zoom

WegGL points are awesome! Thanks for this amazing functionality.

I noticed some strange behavior in flexdashboard today. Upon load, points are invisible until we pan or zoom. See this SO post for pictures. A regular Rmd html_document doesn't have the same issue, or when saving htmlwidgets::saveWidget(map, "test.html"); browseURL("test.html")).

The code below can be pasted into an Rmd and knit.

---
title: "Untitled"
output: 
  flexdashboard::flex_dashboard:
    orientation: columns
    vertical_layout: fill
---

```{r setup, include=FALSE}
library(flexdashboard)
library(leaflet)
library(leafgl)
library(sf)

n = 100

df1 = data.frame(id = 1:n,
                 x = rnorm(n, 10, 3),
                 y = rnorm(n, 49, 1.8))

pts = st_as_sf(df1, coords = c("x", "y"), crs = 4326)

leaflet() %>%
  addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
  addGlPoints(data = pts, group = "pts") %>%
  setView(lng = 10.5, lat = 49.5, zoom = 6)
```

Finally, my session info:

> sessionInfo()
R version 4.1.0 (2021-05-18)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.7

Matrix products: default
BLAS:   /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.1/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils    
[5] datasets  methods   base     

other attached packages:
[1] sf_1.0-4            leafgl_0.1.1       
[3] leaflet_2.0.4.1     flexdashboard_0.5.2

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.7         compiler_4.1.0    
 [3] pillar_1.6.4       class_7.3-19      
 [5] tools_4.1.0        digest_0.6.28     
 [7] tibble_3.1.6       jsonlite_1.7.2    
 [9] evaluate_0.14      lifecycle_1.0.1   
[11] pkgconfig_2.0.3    rlang_0.4.12      
[13] DBI_1.1.1          crosstalk_1.2.0   
[15] xfun_0.28          fastmap_1.1.0     
[17] e1071_1.7-9        dplyr_1.0.7       
[19] knitr_1.36         generics_0.1.1    
[21] htmlwidgets_1.5.4  vctrs_0.3.8       
[23] tidyselect_1.1.1   classInt_0.4-3    
[25] grid_4.1.0         glue_1.5.0        
[27] R6_2.5.1           fansi_0.5.0       
[29] rmarkdown_2.11     purrr_0.3.4       
[31] magrittr_2.0.1     htmltools_0.5.2   
[33] ellipsis_0.3.2     units_0.7-2       
[35] assertthat_0.2.1   KernSmooth_2.23-20
[37] utf8_1.2.2         proxy_0.4-26      
[39] crayon_1.4.2 

Popups don't work after redraw

Love this package - thanks so much for this!

However I'm having some trouble with popups. The first time I addGlPolylines(... popup =TRUE) I get a nice popup showing the relevant row of data.

However If I remove the lines and plot some new ones, popups no longer work. I am reusing the same group id, it that the problem? What's the correct way to remove and redraw lines so that the popups work?

Another minor issue is that the map cursor remains as a hand when clicking on a line, where in leaflet it changes to a pointer, which is nicer for the user.

Thanks!

Polygons don't render (correctly)

Hi,

Thanks for working on such an amazing package! I have a bunch of layers of data to render on county level so wanted to reduce the map loading time and came across this package.

I was checking out the demos and tried this one: https://github.com/r-spatial/leafgl/blob/master/experiments/alabama_glify.R

Everything works fine (I mean there was no error when I ran the code) but the polygons didn't show up on the map:
Screen Shot 2020-04-17 at 18 03 25

I modified the 100k polygons on a map demo by using my shapefile, and got into a slightly different but probably related issue that the polygons don't show different rgb colors:
Screen Shot 2020-04-17 at 18 08 06
I'm not sure what the rgb color should be so I tried both the original rgb colors (0~255) and the original values divided by 255. Both gave the same all green-ish color on the map.

Can you pleas suggest if I misused any of the configurations? Thank you!

Add info about the leaflet.glify:::glifyDependencies() order, or create a glifyOutput() function

Hey,

Thanks for this awesome package.

If I compare these two pieces of code (after the initial bloc) :

library(mapview)
library(leaflet)
library(leaflet.glify)
library(sf)
library(colourvalues)


m = leaflet() %>%
  addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
  addGlifyPolygons(data = ch_lu, 
                   color = cols, 
                   popup = "type",
                   group = "pols") %>%
  addMouseCoordinates() %>%
  setView(lng = 8.3, lat = 46.85, zoom = 9) %>% 
  addLayersControl(overlayGroups = "pols")

This works :

ui <- fluidPage(
  leafletOutput("mymap"),
  tags$script(leaflet.glify:::glifyDependencies())
)

server <- function(input, output, session) {
  output$mymap <- renderLeaflet(m)
}

shinyApp(ui, server)

This doesn't :

ui <- fluidPage(
  tags$script(leaflet.glify:::glifyDependencies()),
  leafletOutput("mymap")
  
)

server <- function(input, output, session) {
  output$mymap <- renderLeaflet(m)
}

shinyApp(ui, server)

The reason why this does that is bcs the JS needs to be launched after the init of the leaflet.

I wonder if :

  1. You could add this warning in the documentation?

  2. You could export glifyDependencies instead of having to to ::: it

  3. Maybe create a glifyOutput() function ?

glifyOutput <- function(...){
  tagList(
    leafletOutput(...), 
    tags$script(leaflet.glify:::glifyDependencies())
  )
}

ui <- fluidPage(
  glifyOutput("mymap")
)

server <- function(input, output, session) {
  output$mymap <- renderLeaflet(m)
}

shinyApp(ui, server)

The third solution seems to be the most idiomatic and easier on the user — no dependencies to manually add, and you don't have to specify it X time if you have X maps.

Let me know if it sounds like a good idea, I'll be happy to make a PR.

Colin

Inability to Reproduce Example Code

Hi,

I really appreciate this package. However, I tried to reproduce your first example (the one without colors), and was unable to see the blue dots, only the black tiles on the leaflet map. My code was verbatim copy and paste from the first example.

Any idea why this is?

Thanks,

Jesse

setView is not automatic

I don't have a good reprex right now, but I noticed that if I create a map with just elements from this package, the map doesn't zoom in properly, for instance.

leaflet() %>%
    addTiles() %>%
    addGlPoints(data=point_data)

will be globally zoomed out. But

leaflet() %>%
    addTiles() %>%
    addGlPoints(data=point_data) %>%
    addPolygons(data=poly_data)

will be zoomed in.

Guessing this has something to do with WebGL, but it's beyond me.

Possible memory leak ?

Hi,

First of all, thank you for this great package !
I want to use leafgl to display a large shapefile (~35000 polygons) in Shiny.
The user can choose a variable to map and the map is updated through leafletProxy.
However, I notice that memory usage increase each time the user choose a new variable, here is a reproductible example.

library(shiny)
library(leaflet)
library(leafgl)
library(raster)
library(sf)

# Create 50000 pixels raster
r <- raster(extent(matrix( c(-90, -50, 90,  50), nrow=2)), nrow=500, ncol=100, 
            crs = "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0") 

Extent <- extent(r)

# Convert to sf shapefile
shp <- rasterToPolygons(r)
shp <- st_as_sf(shp)

## UI ##########
ui <- fluidPage(
  actionButton("go","go"),
  leafglOutput("map")
)

## SERVER ##########
server <- function(input, output) {
  output$map <- renderLeaflet({
    leaflet()  %>% 
      addTiles() %>% 
      fitBounds(lng1 = Extent[1],lat1 = Extent[3], lng2 = Extent[2], lat2 = Extent[4])
  })
  
  observeEvent(input$go,{
    random <- sample(1:100,50000,replace = T)
    pal = colorQuantile(rev(viridis::viridis(10)), random , n = 10)
    
    leafletProxy("map") %>%
      leafgl::removeGlPolygons(layerId = "polygons") %>%
      leafgl::addGlPolygons(layerId = "polygons",data = shp, color = ~pal(random))
  })
}

shinyApp(ui, server)

Each time I click go button, memory increase by about 100Mo.

leafglOutput not rendering points

I can make a leaflet object with addGlPoints that will work and open in a browser perfectly. But When I use the leafglOutput in a shiny app it doesn't render the points, but rather just the leaflet map with tiles. This issue occurs even when I copy and paste the leafglOutput example from your github into shiny app on my computer :

library(mapview)
library(leaflet)
library(leafgl)
library(sf)

n = 1e4
df1 = data.frame(id = 1:n,
                 x = rnorm(n, 10, 3),
                 y = rnorm(n, 49, 1.8))
pts = st_as_sf(df1, coords = c("x", "y"), crs = 4326)

m = leaflet() %>%
    addProviderTiles(provider = providers$CartoDB.DarkMatter) %>%
    addGlPoints(data = pts, group = "pts") %>%
    addMouseCoordinates() %>%
    setView(lng = 10.5, lat = 49.5, zoom = 6) %>%
    addLayersControl(overlayGroups = "pts")

ui <- fluidPage(
    leafglOutput("mymap")
)

server <- function(input, output, session) {
    output$mymap <- renderLeaflet(m)
}

shinyApp(ui, server)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.