trafficonese / leaflet.extras

Extra functionality for leaflet R package.
https://trafficonese.github.io/leaflet.extras/
GNU General Public License v3.0
216 stars 74 forks source link

Search Clustered Markers #65

Closed BilboBaagins closed 7 years ago

BilboBaagins commented 7 years ago

Hi Bhaskar,

Thanks for your work on integrating JS Leaflet plugins into Leaflet for R.

Apologies in advance if there is an obvious solution to this, I just can't seem to get it to work I'm afraid.

So I am trying to add the search feature to my map to search for markers by name. It works perfectly when I don't invoke the clusterOptions = markerClusterOptions() option to cluster my markers. However, when I add this to the leaflet pipeline, the search feature no longer works.

The search element is still created on my map and the markers are clustered, however, when I type in the name of a marker, it is not found/recognised.

My code:

library(htmltools)
library(htmlwidgets)
library(leaflet)
library(rgdal)
library(rgeos)
library(leaflet.extras)

nh <- read.csv("pathfile/Vol_NH.csv")

m = leaflet() %>% 

addProviderTiles("OpenStreetMap.BlackAndWhite") %>%

addBootstrapDependency() %>% 

addMarkers(data = nh, popup = paste(nh$Nursing.Home), label = nh$Nursing.Home, clusterOptions = markerClusterOptions(), group ="nh") %>%

addSearchMarker(
    targetGroup = "nh",
    options = searchMarkersOptions(zoom = 10)) %>%

addControl("<P>Search for ...<br/><ul><li>Nazareth House</li><li>etc..</li></ul></P>",
             position='bottomright')

m            

Thank you.

bhaskarvk commented 7 years ago

Yes I too have noticed that, and FWIW it seems it also doesn't search polygon data. However in both cases if you convert your data to GeoJSON and use leaflet.extra's addGeoJSONv2 function then it works even with clustering enabled.

Check out the second example in http://rpubs.com/bhaskarvk/leaflet-search. Why it doesn't work with addMarkers needs to be investigated. The root cause could be the plugin itself, or may be the core leaflet package or the JS lib.

BilboBaagins commented 7 years ago

Thanks - I have already worked through your second example and have got it working.

The reason for wanting to use the method in the first example was so I could preserve the popup format which I styled using inline CSS and HTML tags (not shown in the code above).

According to issue 319 there were a few methods you highlighted for customising popups, although I can't seem to find them. If you have any info on how to do this or if you could point me in the right direction it would be much appreciated.

Basically, I don't want to use HTML table to display my feature attributes. I would rather display them using popup = paste("Name: ", nh$Nursing.Home, "<br>", "Address: ", nh$Address) etc..

Thank you for you help.

BilboBaagins commented 7 years ago

I used a work-around for this if anyone is stuck for the time being. It allowed me to search for clustered markers without converting my CSV data to GeoJSON, which allowed me to preserve my popups the way I had them styled originally.

Also, it's a grand work-around for issue 45 to search multiple groups - although there are probably much better ways of achieving this.

Basically, I added my two groups of markers to the map and clustered them. I then amalgamated both sets of points and added those to the map also - but didn't cluster them. I hid the amalgamated markers using hideGroup() when calling the map, so to the user it looks like there are only the two sets of data on the map (churches and casinos).

The addSearchMarker() is invoked on the amalgamated (and non-clustered) markers which have the same name and coordinates as both sets of markers on the map. This makes it seem as though you're searching for the clustered markers when really you're searching for the unclustered and invisible markers. It also allows you to search multiple groups, but requires you to amalgamate those datasets beforehand.

The code below should give you an idea of what I mean.

library(leaflet)
library(leaflet.extras)

churches <- read.csv(textConnection("
Church,Lat,Long
church_one,53.419857,-7.733745
church_two,53.887576,-6.869429
church_three,52.640334,-7.742052
church_four,52.610132,-6.554074
church_five,52.170134,-8.715873
church_six,53.578261,-9.693382
"))

casinos <- read.csv(textConnection("
Casino,Lat,Long
casino_1,54.487243,-6.533052
casino_2,54.267479,-8.505229
casino_3,54.094214,-9.166596
casino_4,52.332897,-7.136273
casino_5,53.265217,-6.473378
casino_6,52.252575,-7.924774
"))

both <- read.csv(textConnection("
Name, Lat, Long
church_one,53.419857,-7.733745
church_two,53.887576,-6.869429
church_three,52.640334,-7.742052
church_four,52.610132,-6.554074
church_five,52.170134,-8.715873
church_six,53.578261,-9.693382
casino_1,54.487243,-6.533052
casino_2,54.267479,-8.505229
casino_3,54.094214,-9.166596
casino_4,52.332897,-7.136273
casino_5,53.265217,-6.473378
casino_6,52.252575,-7.924774
"))

m <- leaflet() %>% addProviderTiles("Esri.WorldImagery") %>%
  addMarkers(data = churches, label = churches$Church, clusterOptions = markerClusterOptions(), group ='churches') %>%
  addMarkers(data = casinos, label = casinos$Casino, clusterOptions = markerClusterOptions(), group ='casinos') %>%
  addMarkers(data = both, label = both$Name, group ='hidden') %>%

  addSearchMarker(
    targetGroup = 'hidden',
    options = searchMarkersOptions(zoom=11, openPopup = TRUE)) %>%

  addLayersControl(
    baseGroups = c("ESRI Satellite"),
    overlayGroups = c("churches", "casinos"),
    position = "topright",
    options = layersControlOptions(collapsed = TRUE, autoZIndex = T)
) 

m %>% hideGroup("hidden")
bhaskarvk commented 7 years ago

Thanks for documenting the work around, but I think I can make it work without needing to hack around the issue. The popup options you wanted are all demoed at http://rpubs.com/bhaskarvk/geojsonv2. If you don't want a HTML table, you can simply provide a JS function that takes in a Feature and returns back the HTML element you want shown for popup.

BilboBaagins commented 7 years ago

Great. Thanks, I'll read up on that.

bhaskarvk commented 7 years ago

Closing as the discussion seems to have concluded. The conclusion is a) to searched clustered markers you need to convert the data to a GeoJSON and add it via addGeoJSONv2, alternatively add it twice with one set clustered and another set unclusted (add hidden), and set up search on the hidden unclustered markers.

This is a limitation of the plugin in.

bhaskarvk commented 7 years ago

The latest push now supports searching markers added to a Cluster.