对于来自不同编程语言背景的人来说,反应值可能是一种诅咒;) 未来的任务(简化为SO) - 我想在新国家位于地图边界内时下载新文件。在下面的示例中,您需要一个shapefile,例如:http://thematicmapping.org/downloads/TM_WORLD_BORDERS_SIMPL-0.3.zip UI尽可能简单:
library(leaflet)
library(shiny)
fluidPage(leafletOutput("mymap"))
服务器并不过分复杂(但是;)
library(shiny)
library(DT)
library(leaflet)
library(rgdal)
library(maptools)
library(rgeos)
countries<- readShapeSpatial("TM_WORLD_BORDERS_SIMPL-0.3.shp")
displayed<-c("United Kingdom")
server <- function(input, output,session) {
output$mymap <- renderLeaflet({
leaflet(countries) %>%
addTiles() %>%
setView(lng=-0.1294984,lat=51.4992921,zoom=10)
})
pointsInBounds <- reactive({
if (is.null(input$mymap_bounds))
return(NULL)
bounds <- input$mymap_bounds
N<- bounds$north
S<-bounds$south
E<-bounds$east
W<-bounds$west
BB = matrix(c(W,E,E,W,W,N,N,S,S,N), nrow=5,ncol=2)
BB = SpatialPolygons(list(Polygons(list(Polygon(BB)),1)))
as.vector(countries[which(gIntersects(countries,BB,byid=TRUE)),]$NAME)
})}
因此pointsinbounds()
告诉我哪些国家/地区可见,displayed
是已下载内容的列表(以避免重新下载)。
我想要实现的是添加(并保持)pointsinbounds()
到displayed
列表并观察displayed
列表是否发生变化(仅在新国家位于边界内时触发下载) 。我设法通过unique(c(displayed,pointsinbounds()))
添加到列表中,但它不会永久存储它 - 当我离开法国时,它会从列表中删除法国。同样,只要pointsinbounds()
更改,它就会做出反应,而我只想在总列表更改时做出反应,以避免在您移回同一个国家/地区时重新计算。
有什么想法吗?
答案 0 :(得分:4)
根据您的需要,您可以使用以下两个选项之一。
1)将值存储到reactiveValues()中。在这种情况下,国家/地区列表将在该会话期间保持不变。
2)将值存储在全局值中,并且它在会话之间是持久的,并且可以在会话/用户之间访问(您可以将赋值放在global.R中)。
编辑:在选项2中,添加了用于检测新国家/地区的代码。
注意:在下面的示例中,我添加了一个控件来监控国家/地区列表。
选项1的示例
library(shiny)
library(DT)
library(leaflet)
library(rgdal)
library(maptools)
library(rgeos)
ui <- fluidPage(leafletOutput("mymap") ,
verbatimTextOutput('myCountries'))
countries <- readShapeSpatial("TM_WORLD_BORDERS_SIMPL-0.3.shp")
displayed <- c("United Kingdom")
server <- function(input, output, session) {
r <- reactiveValues()
observe({
r$displayed <- unique(c(r$displayed, pointsInBounds()))
})
output$mymap <- renderLeaflet({
leaflet(countries) %>%
addTiles() %>%
setView(lng = -0.1294984,
lat = 51.4992921,
zoom = 10)
})
output$myCountries <- renderPrint({
r$displayed
})
pointsInBounds <- reactive({
if (is.null(input$mymap_bounds)) {
return(NULL)
}
bounds <- input$mymap_bounds
N <- bounds$north
S <- bounds$south
E <- bounds$east
W <- bounds$west
BB = matrix(c(W, E, E, W, W, N, N, S, S, N), nrow = 5, ncol = 2)
BB = SpatialPolygons(list(Polygons(list(Polygon(
BB
)), 1)))
as.vector(countries[which(gIntersects(countries, BB, byid = TRUE)),]$NAME)
})
}
shinyApp(ui, server)
选项2的示例
library(shiny)
library(DT)
library(leaflet)
library(rgdal)
library(maptools)
library(rgeos)
ui <- fluidPage(leafletOutput("mymap") ,
verbatimTextOutput('myCountries'))
countries <- readShapeSpatial("TM_WORLD_BORDERS_SIMPL-0.3.shp")
if (!exists('displayed')){
displayed <<- c("United Kingdom")
}
server <- function(input, output, session) {
observe({
current.coutries <- pointsInBounds()
new.countries <- current.coutries[ ! (current.coutries %in% displayed) ]
# DOWNLOAD new.countries
displayed <<- unique(c(displayed, pointsInBounds()))
})
output$mymap <- renderLeaflet({
leaflet(countries) %>%
addTiles() %>%
setView(lng = -0.1294984,
lat = 51.4992921,
zoom = 10)
})
output$myCountries <- renderPrint({
pointsInBounds()
displayed
})
observeEvent(input$mymap_bounds, {})
pointsInBounds <- reactive({
if (is.null(input$mymap_bounds)) {
return(NULL)
}
bounds <- input$mymap_bounds
N <- bounds$north
S <- bounds$south
E <- bounds$east
W <- bounds$west
BB = matrix(c(W, E, E, W, W, N, N, S, S, N), nrow = 5, ncol = 2)
BB = SpatialPolygons(list(Polygons(list(Polygon(
BB
)), 1)))
as.vector(countries[which(gIntersects(countries, BB, byid = TRUE)),]$NAME)
})
}
shinyApp(ui, server)