Select 在 Shiny 应用程序的地图中只有一个状态
Select only one state in a map in a Shiny application
我有以下数据集:
library(rgdal)
library(leaflet)
tmp <- tempdir()
url <- "http://personal.tcu.edu/kylewalker/data/mexico.zip"
file <- basename(url)
download.file(url, file)
unzip(file, exdir = tmp)
mexico <- readOGR(dsn = tmp, layer = "mexico", encoding = "UTF-8")
pal <- colorQuantile("YlGn", NULL, n = 5)
state_popup <- paste0("<strong>Estado: </strong>",
mexico$name,
"<br><strong>PIB per c?pita, miles de pesos, 2008: </strong>",
mexico$gdp08)
基于这些数据,我构建了以下 Shiny 应用程序:
# load necessary packages
library(leaflet)
library(shiny)
library(shinydashboard)
ui <- fluidPage(
# place the contents inside a box
shinydashboard::box(
width = 12
, title = "Click on the map!"
# separate the box by a column
, column(
width = 2
, shiny::actionButton( inputId = "clearHighlight"
, icon = icon( name = "eraser")
, label = "Clear the Map"
, style = "color: #fff; background-color: #D75453; border-color: #C73232"
)
)
# separate the box by a column
, column(
width = 10
, leaflet::leafletOutput( outputId = "myMap"
, height = 850
)
)
) # end of the box
) # end of fluid page
# create the server
server <- function( input, output, session ){
# create foundational map
foundational.map <- shiny::reactive({
leaflet() %>%
#addTiles( urlTemplate = "https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png") %>%
#setView( lng = -87.567215
# , lat = 41.822582
# , zoom = 11 ) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons( data = mexico
, fillOpacity = 0
, opacity = 0.2
, color = "#000000"
, weight = 2
, layerId = mexico$states
, group = "click.list"
)
})
output$myMap <- renderLeaflet({
foundational.map()
})
click.list <- shiny::reactiveValues( ids = vector() )
shiny::observeEvent( input$myMap_shape_click, {
click <- input$myMap_shape_click
click.list$ids <- c( click.list$ids, click$id )
lines.of.interest <- mexico[ which( mexico$states %in% click.list$ids ) , ]
if( is.null( click$id ) ){
req( click$id )
} else if( !click$id %in% lines.of.interest@data$id ){
leaflet::leafletProxy( mapId = "myMap" ) %>%
addPolylines( data = lines.of.interest
, layerId = lines.of.interest@data$id
, color = "#6cb5bc"
, weight = 5
, opacity = 1
)
} # end of if else statement
}) # end of shiny::observeEvent({})
shiny::observeEvent( input$clearHighlight, {
output$myMap <- leaflet::renderLeaflet({
click.list$ids <- NULL
foundational.map()
}) # end of re-rendering $myMap
}) # end of clearHighlight action button logic
} # end of server
shiny::shinyApp( ui = ui, server = server)
这给了我一张墨西哥地图,我可以在其中 select 一个州。这很好用。但是现在如果我 select 另一个状态我有多个 select 离子。
我想要的是,当我搬到另一个州时,只有那个州是 selected。
关于如何在上面的代码中实现这一点有什么想法吗?
下面是一个工作示例。我改变了什么?
- 底部有一个
observeEvent()
,它还在 body 中重新创建了一个 reactive()
。这是不好的做法,在那种情况下最好使用 reactiveVal().
所以我添加了名为 myMap_reval
的 reactiveVal
来保存我们的地图 object.
- 我向
observeEvent()
添加了一部分,用于为选定的多边形边框着色。它现在首先检查 click.list$ids
是否为空。如果是这样,它将首先重置先前选择的多边形边框的颜色。此外,观察者现在将 click.list$ids
设置为新选择的值,而不是将其添加到向量中。
希望对您有所帮助!
library(rgdal)
library(leaflet)
tmp <- tempdir()
url <- "http://personal.tcu.edu/kylewalker/data/mexico.zip"
file <- basename(url)
download.file(url, file)
unzip(file, exdir = tmp)
mexico <- readOGR(dsn = tmp, layer = "mexico", encoding = "UTF-8")
pal <- colorQuantile("YlGn", NULL, n = 5)
state_popup <- paste0("<strong>Estado: </strong>",
mexico$name,
"<br><strong>PIB per c?pita, miles de pesos, 2008: </strong>",
mexico$gdp08)
# load necessary packages
library(leaflet)
library(shiny)
library(shinydashboard)
ui <- fluidPage(
# place the contents inside a box
shinydashboard::box(
width = 12
, title = "Click on the map!"
# separate the box by a column
, column(
width = 2
, shiny::actionButton( inputId = "clearHighlight"
, icon = icon( name = "eraser")
, label = "Clear the Map"
, style = "color: #fff; background-color: #D75453; border-color: #C73232"
)
)
# separate the box by a column
, column(
width = 10
, leaflet::leafletOutput( outputId = "myMap"
, height = 850
)
)
) # end of the box
) # end of fluid page
# create the server
server <- function( input, output, session ){
# function to create foundational map
foundational.map <- function(){
leaflet() %>%
#addTiles( urlTemplate = "https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png") %>%
#setView( lng = -87.567215
# , lat = 41.822582
# , zoom = 11 ) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons( data = mexico
, fillOpacity = 0
, opacity = 0.2
, color = "#000000"
, weight = 2
, layerId = mexico$state
, group = "click.list")
}
# reactiveVal for the map object, and corresponding output object.
myMap_reval <- reactiveVal(foundational.map())
output$myMap <- renderLeaflet({
myMap_reval()
})
# To hold the selected map region id.
click.list <- shiny::reactiveValues( ids = vector() )
shiny::observeEvent( input$myMap_shape_click, ignoreNULL = T,ignoreInit = T, {
# If already selected, first remove previous selection
if(length(click.list)>0)
{
remove_id = click.list$ids
lines.of.interest <- mexico[ which( mexico$state %in% remove_id) , ]
leaflet::leafletProxy( mapId = "myMap" ) %>%
addPolylines( data = lines.of.interest
, layerId = lines.of.interest@data$id
, color = "#000000"
, weight = 2
, opacity = 0.2)
}
# add current selection
click <- input$myMap_shape_click
click.list$ids <- click$id # we only store the last click now!
lines.of.interest <- mexico[ which( mexico$state %in% click.list$ids ) , ]
print(click)
if( is.null( click$id ) ){
req( click$id )
} else if( !click$id %in% lines.of.interest@data$id ){
leaflet::leafletProxy( mapId = "myMap" ) %>%
addPolylines( data = lines.of.interest
, layerId = lines.of.interest@data$id
, color = "#6cb5bc"
, weight = 5
, opacity = 1
)
}
}) # end of shiny::observeEvent({})
# oberver for the clearHighlight button.
shiny::observeEvent( input$clearHighlight, {
click.list$ids <- NULL
myMap_reval(foundational.map()) # reset map.
})
}
shiny::shinyApp( ui = ui, server = server)
我有以下数据集:
library(rgdal)
library(leaflet)
tmp <- tempdir()
url <- "http://personal.tcu.edu/kylewalker/data/mexico.zip"
file <- basename(url)
download.file(url, file)
unzip(file, exdir = tmp)
mexico <- readOGR(dsn = tmp, layer = "mexico", encoding = "UTF-8")
pal <- colorQuantile("YlGn", NULL, n = 5)
state_popup <- paste0("<strong>Estado: </strong>",
mexico$name,
"<br><strong>PIB per c?pita, miles de pesos, 2008: </strong>",
mexico$gdp08)
基于这些数据,我构建了以下 Shiny 应用程序:
# load necessary packages
library(leaflet)
library(shiny)
library(shinydashboard)
ui <- fluidPage(
# place the contents inside a box
shinydashboard::box(
width = 12
, title = "Click on the map!"
# separate the box by a column
, column(
width = 2
, shiny::actionButton( inputId = "clearHighlight"
, icon = icon( name = "eraser")
, label = "Clear the Map"
, style = "color: #fff; background-color: #D75453; border-color: #C73232"
)
)
# separate the box by a column
, column(
width = 10
, leaflet::leafletOutput( outputId = "myMap"
, height = 850
)
)
) # end of the box
) # end of fluid page
# create the server
server <- function( input, output, session ){
# create foundational map
foundational.map <- shiny::reactive({
leaflet() %>%
#addTiles( urlTemplate = "https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png") %>%
#setView( lng = -87.567215
# , lat = 41.822582
# , zoom = 11 ) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons( data = mexico
, fillOpacity = 0
, opacity = 0.2
, color = "#000000"
, weight = 2
, layerId = mexico$states
, group = "click.list"
)
})
output$myMap <- renderLeaflet({
foundational.map()
})
click.list <- shiny::reactiveValues( ids = vector() )
shiny::observeEvent( input$myMap_shape_click, {
click <- input$myMap_shape_click
click.list$ids <- c( click.list$ids, click$id )
lines.of.interest <- mexico[ which( mexico$states %in% click.list$ids ) , ]
if( is.null( click$id ) ){
req( click$id )
} else if( !click$id %in% lines.of.interest@data$id ){
leaflet::leafletProxy( mapId = "myMap" ) %>%
addPolylines( data = lines.of.interest
, layerId = lines.of.interest@data$id
, color = "#6cb5bc"
, weight = 5
, opacity = 1
)
} # end of if else statement
}) # end of shiny::observeEvent({})
shiny::observeEvent( input$clearHighlight, {
output$myMap <- leaflet::renderLeaflet({
click.list$ids <- NULL
foundational.map()
}) # end of re-rendering $myMap
}) # end of clearHighlight action button logic
} # end of server
shiny::shinyApp( ui = ui, server = server)
这给了我一张墨西哥地图,我可以在其中 select 一个州。这很好用。但是现在如果我 select 另一个状态我有多个 select 离子。
我想要的是,当我搬到另一个州时,只有那个州是 selected。
关于如何在上面的代码中实现这一点有什么想法吗?
下面是一个工作示例。我改变了什么?
- 底部有一个
observeEvent()
,它还在 body 中重新创建了一个reactive()
。这是不好的做法,在那种情况下最好使用reactiveVal().
所以我添加了名为myMap_reval
的reactiveVal
来保存我们的地图 object. - 我向
observeEvent()
添加了一部分,用于为选定的多边形边框着色。它现在首先检查click.list$ids
是否为空。如果是这样,它将首先重置先前选择的多边形边框的颜色。此外,观察者现在将click.list$ids
设置为新选择的值,而不是将其添加到向量中。
希望对您有所帮助!
library(rgdal)
library(leaflet)
tmp <- tempdir()
url <- "http://personal.tcu.edu/kylewalker/data/mexico.zip"
file <- basename(url)
download.file(url, file)
unzip(file, exdir = tmp)
mexico <- readOGR(dsn = tmp, layer = "mexico", encoding = "UTF-8")
pal <- colorQuantile("YlGn", NULL, n = 5)
state_popup <- paste0("<strong>Estado: </strong>",
mexico$name,
"<br><strong>PIB per c?pita, miles de pesos, 2008: </strong>",
mexico$gdp08)
# load necessary packages
library(leaflet)
library(shiny)
library(shinydashboard)
ui <- fluidPage(
# place the contents inside a box
shinydashboard::box(
width = 12
, title = "Click on the map!"
# separate the box by a column
, column(
width = 2
, shiny::actionButton( inputId = "clearHighlight"
, icon = icon( name = "eraser")
, label = "Clear the Map"
, style = "color: #fff; background-color: #D75453; border-color: #C73232"
)
)
# separate the box by a column
, column(
width = 10
, leaflet::leafletOutput( outputId = "myMap"
, height = 850
)
)
) # end of the box
) # end of fluid page
# create the server
server <- function( input, output, session ){
# function to create foundational map
foundational.map <- function(){
leaflet() %>%
#addTiles( urlTemplate = "https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png") %>%
#setView( lng = -87.567215
# , lat = 41.822582
# , zoom = 11 ) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons( data = mexico
, fillOpacity = 0
, opacity = 0.2
, color = "#000000"
, weight = 2
, layerId = mexico$state
, group = "click.list")
}
# reactiveVal for the map object, and corresponding output object.
myMap_reval <- reactiveVal(foundational.map())
output$myMap <- renderLeaflet({
myMap_reval()
})
# To hold the selected map region id.
click.list <- shiny::reactiveValues( ids = vector() )
shiny::observeEvent( input$myMap_shape_click, ignoreNULL = T,ignoreInit = T, {
# If already selected, first remove previous selection
if(length(click.list)>0)
{
remove_id = click.list$ids
lines.of.interest <- mexico[ which( mexico$state %in% remove_id) , ]
leaflet::leafletProxy( mapId = "myMap" ) %>%
addPolylines( data = lines.of.interest
, layerId = lines.of.interest@data$id
, color = "#000000"
, weight = 2
, opacity = 0.2)
}
# add current selection
click <- input$myMap_shape_click
click.list$ids <- click$id # we only store the last click now!
lines.of.interest <- mexico[ which( mexico$state %in% click.list$ids ) , ]
print(click)
if( is.null( click$id ) ){
req( click$id )
} else if( !click$id %in% lines.of.interest@data$id ){
leaflet::leafletProxy( mapId = "myMap" ) %>%
addPolylines( data = lines.of.interest
, layerId = lines.of.interest@data$id
, color = "#6cb5bc"
, weight = 5
, opacity = 1
)
}
}) # end of shiny::observeEvent({})
# oberver for the clearHighlight button.
shiny::observeEvent( input$clearHighlight, {
click.list$ids <- NULL
myMap_reval(foundational.map()) # reset map.
})
}
shiny::shinyApp( ui = ui, server = server)