rstudio / leaflet

R Interface to Leaflet Maps
http://rstudio.github.io/leaflet/
Other
809 stars 506 forks source link

Synchronize zoom and center of multiple maps #347

Open FrancoisGuillem opened 7 years ago

FrancoisGuillem commented 7 years ago

In package dygraphs, there is a very easy way to synchronize the zoom of multiple charts: https://rstudio.github.io/dygraphs/gallery-synchronization.html

Is there a similar mechanism in package leaflet? If not, would it be possible to have it?

timelyportfolio commented 7 years ago

mapview offers an implementation with latticeView. This pull https://github.com/environmentalinformatics-marburg/mapview/pull/53 is necessary to make it work with the newest leaflet. We have debated on whether or not the synced view should be a widget of widgets (similar to combineWidgets).

FrancoisGuillem commented 7 years ago

Thanks for the answer. I did not know about mapview. I have done a few tests and I am not sure it will solve my problem: I have two maps in a shiny gadget. The gadget contains some inputs that modifies the data shawn in each map. Maps are updated thanks to shinyproxy. Here is a toy example:

twomaps

It would be awesome if the two maps were synchronized without the need to write complicated shiny server code.

bhaskarvk commented 7 years ago

Out of curiosity why doesn't mapview's latticeView solve your problem ?

tim-salabim commented 7 years ago

The function in mapview is actually called sync. I guess you would need to update the maps (m1 & m2 for instance) and then return sync(m1, m2) in your app.

FrancoisGuillem commented 7 years ago

I can include the result of sync with renderUI and htmlOutput. But, with this approach, each time the users changes an input, the zoom and the center of the maps are reset. This can be quite annoying.

FrancoisGuillem commented 7 years ago

A less important problem is that my UI and server function are generated programmatically. In my code, each map is an autonomous component containing a leaflet map and some specific input controls. Using sync would require to rewrite a good part of my code.

synccould perfectly solve my problem if:

jcheng5 commented 7 years ago

@FrancoisGuillem To update a map instead of removing it and creating it again, you can use leafletProxy: http://rstudio.github.io/leaflet/shiny.html#modifying-existing-maps-with-leafletproxy

FrancoisGuillem commented 7 years ago

Hello,

I have finally created a new function called syncWith(). I have added it in my package leaflet.minicharts. It works in the Rstudio viewer pane, Rmarkdown documents and shiny applications. Here is an example:

library(leaflet)
library(leaflet.minicharts)
library(manipulateWidget)

map1 <- leaflet() %>% addTiles() %>% syncWith("maps")
map2 <- leaflet() %>% addTiles() %>% syncWith("maps")

combineWidgets(map1, map2, ncol = 2)

example_sync_with

marquizauv commented 6 years ago

Hello,

I have finally created a new function called syncWith(). I have added it in my package leaflet.minicharts. It works in the Rstudio viewer pane, Rmarkdown documents and shiny applications. Here is an example:

library(leaflet)
library(leaflet.minicharts)
library(manipulateWidget)

map1 <- leaflet() %>% addTiles() %>% syncWith("maps")
map2 <- leaflet() %>% addTiles() %>% syncWith("maps")

combineWidgets(map1, map2, ncol = 2)

example_sync_with

Hi @FrancoisGuillem ,

I'm trying to use your package and your syncWith() function but it is currently not working (at least on my case, R version 3.5.1). I'm reproducing your example but neither the zoom nor the movement sync between the two maps is working. Any clue? Thanks!

fionahevans commented 5 years ago

I can't get the above example to work either, was hoping to use syncWith and a shiny app.

FrancoisGuillem commented 5 years ago

Hello, I'm not sure why but the code responsible of the synchronization has been commented by a contributor of the project. I will check with him what was the issue.

Until we find an "official" solution, you can use my own copy of the package: https://github.com/FrancoisGuillem/leaflet.minicharts

fionahevans commented 5 years ago

Thanks @FrancoisGuillem !

fionahevans commented 5 years ago

FYI, I have found a workaround using rstudio/leaflet only.

I have two maps map1 and map2 rendered in shiny using renderLeaflet. The second map has no zoom control. It's bounds are changed whenever those of the the first change, using an observer function:

observe({ # Observer to respond to zoom / pan of map1 and apply to map2
    coords <- input$map1_bounds

    if (!is.null(coords)) {
      tproxy <- leafletProxy("map2") %>% 
      fitBounds(coords$west,
                coords$south,
                coords$east,
                coords$north)
    }
  })