Here is a way to sync the two leaflet maps, but unfortunately it does not work in RStudio Viewer. This does work in Chrome and Firefox. There are lots of ways to make this much more robust. I tried to add comments in the R
code below to explain what is happening.
---
title: "How to sync 2 leaflet maps"
author: "me"
date: "2 April 2016"
output: html_document
---
```{r SETUP, include=FALSE}
# get the latest htmlwidgets
# devtools::install_github("ramnathv/htmlwidgets")
library("htmlwidgets")
library("htmltools")
library("mapview")
library("sp")
# load example data
data(meuse)
coordinates(meuse) <- ~x+y
proj4string(meuse) <- CRS("+init=epsg:28992")
```
```{r MAPS}
mapView(meuse, zcol="copper")@map # MAP 1
mapview(meuse, zcol="soil")@map # MAP 2
```
```{r}
# crudely add the leaflet-sync plugin
# attachDependency with the rawgit gave me
# errors so just do this for now
# could easily add to a package
# or make a mini package to import this
# dependency
tags$script(
type="text/javascript",
src="https://cdn.rawgit.com/turban/Leaflet.Sync/master/L.Map.Sync.js"
)
```
```{r}
# this is one of the new htmlwidgets methods
# to add some code after all htmlwidgets are rendered
# this is very useful since we need all htmlwidgets rendered
# before we can sync
onStaticRenderComplete(
'
var leaf_widgets = Array.prototype.map.call(
document.querySelectorAll(".leaflet"),
function(ldiv){
return HTMLWidgets.find("#" + ldiv.id);
}
);
// make this easy since we know only two maps
leaf_widgets[0].sync(leaf_widgets[1]);
leaf_widgets[1].sync(leaf_widgets[0]);
'
)
```
Here is how we can do the same thing in straight R
code.
# http://stackoverflow.com/questions/36373842/synchronizing-two-leaflet-maps-in-r-rmarkdown
# get the latest htmlwidgets
# devtools::install_github("ramnathv/htmlwidgets")
library("htmlwidgets")
library("htmltools")
library("mapview")
library("sp")
# load example data
data(meuse)
coordinates(meuse) <- ~x+y
proj4string(meuse) <- CRS("+init=epsg:28992")
map1 <- mapView(meuse, zcol="copper")@map # MAP 1
map2 <- mapview(meuse, zcol="soil")@map # MAP 2
tagList(
tags$head(tags$script(
type="text/javascript",
src="https://cdn.rawgit.com/turban/Leaflet.Sync/master/L.Map.Sync.js"
)),
map1,
map2,
onStaticRenderComplete(
'
var leaf_widgets = Array.prototype.map.call(
document.querySelectorAll(".leaflet"),
function(ldiv){
return HTMLWidgets.find("#" + ldiv.id);
}
);
// make this easy since we know only two maps
leaf_widgets[0].sync(leaf_widgets[1]);
leaf_widgets[1].sync(leaf_widgets[0]);
'
)
) %>%
browsable
And if you want it side-by-side, here is the basic way to accomplish. We could leverage shiny::fluidPage
, fluidRow
, and column
to get boostrap, but the css
/js
is really heavy for just side-by-side placement.
# get the latest htmlwidgets
# devtools::install_github("ramnathv/htmlwidgets")
library("htmlwidgets")
library("htmltools")
library("shiny")
library("mapview")
library("sp")
# load example data
data(meuse)
coordinates(meuse) <- ~x+y
proj4string(meuse) <- CRS("+init=epsg:28992")
map1 <- mapView(meuse, zcol="copper")@map # MAP 1
map2 <- mapview(meuse, zcol="soil")@map # MAP 2
tagList(
tags$head(tags$script(
type="text/javascript",
src="https://cdn.rawgit.com/turban/Leaflet.Sync/master/L.Map.Sync.js"
)),
tags$div(style="display:inline;width:50%;float:left;",map1),
tags$div(style="display:inline;width:50%;float:left;",map2),
onStaticRenderComplete(
'
var leaf_widgets = Array.prototype.map.call(
document.querySelectorAll(".leaflet"),
function(ldiv){
return HTMLWidgets.find("#" + ldiv.id);
}
);
// make this easy since we know only two maps
leaf_widgets[0].sync(leaf_widgets[1]);
leaf_widgets[1].sync(leaf_widgets[0]);
'
)
) %>%
browsable