Синхронизация двух карт листовок в R / Rmarkdown
Буклет JS позволяет синхронизировать две карты. Смотрите пример синхронизированных листовок здесь.
Я хотел бы реализовать синхронизированные карты листовок в R
и более конкретно в Rmarkdown/knitr
,
Предпочтительно, карты должны показываться рядом друг с другом по горизонтали (как в примере).
Вот минимальная Rmarkdown (.Rmd
) Пример двух карт, которые я хотел бы синхронизировать. Решение не должно основываться на mapview
пакет. Любое решение действительно приветствуется (-:
---
title: "How to sync 2 leaflet maps"
author: "me"
date: "2 April 2016"
output: html_document
---
```{r SETUP, include=FALSE}
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
```
2 ответа
Обратите внимание, что мы реализовали ответ, предоставленный @timelyportfolio в пакете mapview, так что теперь этого легко достичь, используя mapview::sync()
, Увидеть ?mapview::sync
для инструкций и примеров.
Вот способ синхронизации двух листовок, но, к сожалению, он не работает в RStudio Viewer. Это работает в Chrome и Firefox. Есть много способов сделать это намного более надежным. Я пытался добавить комментарии в R
код ниже, чтобы объяснить, что происходит.
---
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]);
'
)
```
Вот как мы можем сделать то же самое в прямой R
код.
# http://stackru.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
И если вы хотите, чтобы это было рядом, вот основной способ сделать это. Мы могли бы использовать shiny::fluidPage
, fluidRow
, а также column
чтобы получить бустрап, но css
/js
действительно тяжело только для параллельного размещения.
# 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