我在Shiny中构建了一个Leaflet应用程序,其想法是用户登录以查看可以点击的特定城市的概述。点击这些城市将放大到该特定城市。下面的代码可以帮助您实现这一目标。
我无法弄清楚的是,我还想提供一个按钮(在选择城市后出现),名为"返回查看其他城市"点击后,将重置"地图回到原来的状态。
但是,当我点击按钮时,出现以下错误:
警告:UseMethod中出错:没有适用于' metaData'的方法应用于类" NULL"
的对象
我在这里使用input$map_marker_click
来确定应用应该放大哪个城市,我认为问题的一部分是我无法将其设置回其初始状态单击后为NULL。我还有另一种方法吗?
library(shiny)
library(leaflet)
library(leaflet.extras)
library(dplyr)
cities <- data.frame(cities = c("London", "Chicago", "New York", "Philadelphia", "Los Angeles"),
lng = c(-0.118092, -87.6298, -74.0060, -75.1642, -118.2477),
lat = c(51.509865, 41.848, 40.7128, 39.9586, 34.0522),
zoom = c(11, 11, 12, 12, 10))
ui <- bootstrapPage(
tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
leafletOutput("map", width = "100%", height = "100%"),
conditionalPanel("isNaN(input.map_marker_click)", uiOutput("controls"))
)
server <- function(input, output, session) {
output$map <- renderLeaflet({
leaflet(cities, width = "100%", height = "100%") %>%
addProviderTiles("CartoDB.DarkMatter") %>%
setView(lng = -56, lat = 49.2402, zoom = 4) %>%
addPulseMarkers(lng = ~lng, lat = ~lat,
label = ~cities,
icon = makePulseIcon())
})
output$controls <- renderUI({
req(input$map_marker_click)
absolutePanel(id = "controls", top = 100, left = 50,
right = "auto", bottom = "auto", width = "auto", height = "auto",
actionButton(inputId = "reset", label = "Return to see other cities", class = "btn-primary")
)
})
observeEvent(input$map_marker_click, {
city_selected <- filter(cities, lat == input$map_marker_click$lat[1])
leafletProxy("map") %>%
clearMarkers() %>%
clearControls() %>%
setView(lng = city_selected$lng[1], lat = city_selected$lat[1], zoom = city_selected$zoom[1])
})
#I know the below is wrong, but I don't know what I'm supposed to do to "reset" the map.
observeEvent(input$reset, {
leafletProxy("map") %>%
setView(lng = -56, lat = 49.2402, zoom = 4) %>%
addPulseMarkers(lng = ~lng, lat = ~lat,
label = ~cities,
icon = makePulseIcon())
})
}
shinyApp(ui, server)
答案 0 :(得分:1)
我需要在上次data = cities
来电中添加addPulseMarkers()
。
observeEvent(input$reset, {
leafletProxy("map") %>%
setView(lng = -56, lat = 49.2402, zoom = 4) %>%
addPulseMarkers(data = cities, lng = ~lng, lat = ~lat,
label = ~cities,
icon = makePulseIcon())
})
答案 1 :(得分:1)
替代的基于反应的输出
将地图创建封装在一个函数中,这样只需一个没有代码重复的函数调用就可以更轻松地重置:
library(shiny)
library(leaflet)
library(leaflet.extras)
library(dplyr)
library(shinyjs) #for hide function
cities <- data.frame(cities = c("London", "Chicago", "New York", "Philadelphia", "Los Angeles"),
lng = c(-0.118092, -87.6298, -74.0060, -75.1642, -118.2477),
lat = c(51.509865, 41.848, 40.7128, 39.9586, 34.0522),
zoom = c(11, 11, 12, 12, 10))
ui <- bootstrapPage(
useShinyjs(),
tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
leafletOutput("map", width = "100%", height = "100%"),
conditionalPanel("isNaN(input.map_marker_click)", uiOutput("controls"))
)
server <- function(input, output, session) {
#creating the first map within a function so that reset becomes easy
base_map <- function(){
leaflet(cities, width = "100%", height = "100%") %>%
addProviderTiles("CartoDB.DarkMatter") %>%
setView(lng = -56, lat = 49.2402, zoom = 4) %>%
addPulseMarkers(lng = ~lng, lat = ~lat,
label = ~cities,
icon = makePulseIcon())
}
# reactiveVal for the map object, and corresponding output object.
react_map <- reactiveVal(base_map())
output$map <- renderLeaflet({
react_map()
})
output$controls <- renderUI({
req(input$map_marker_click)
absolutePanel(id = "controls", top = 100, left = 50,
right = "auto", bottom = "auto", width = "auto", height = "auto",
actionButton(inputId = "reset", label = "Return to see other cities", class = "btn-primary")
)
})
observeEvent(input$map_marker_click, {
city_selected <- filter(cities, lat == input$map_marker_click$lat[1])
show('controls')
leafletProxy("map") %>%
clearMarkers() %>%
clearControls() %>%
setView(lng = city_selected$lng[1], lat = city_selected$lat[1], zoom = city_selected$zoom[1])
})
# Making the entire map creation inside reactive function makes it easier to reset
observeEvent(input$reset, {
#hiding the control button
hide('controls')
# resetting the map
react_map(base_map())
})
}
shinyApp(ui, server)