如何在闪亮中循环观察事件?单击多边形时更改传单中的样式

Posted

技术标签:

【中文标题】如何在闪亮中循环观察事件?单击多边形时更改传单中的样式【英文标题】:How do I loop an observeEvent in shiny? to change style in leaflet when polygons are clicked 【发布时间】:2021-12-26 08:20:13 【问题描述】:

我有一个项目,我正在为之构建一个闪亮的项目。我需要根据输入创建 n 个地图(最多 99 个)。相同的多边形将显示在每张地图上,当用户点击一个多边形时,它会改变多边形的颜色。

到目前为止,我可以根据输入值创建地图数量,但我正在努力研究如何将 observeEvent 放入每个地图的循环中。

下面的例子有效,但我必须写出这两个观察事件 99 次。 请帮忙!

library(leaflet)

## create two square polygons
Sr1 <- Polygon(cbind(c(1, 2, 2, 1, 1), c(1, 1, 2, 2, 1)))
Sr2 <- Polygon(cbind(c(2, 3, 3, 2, 2), c(1, 1, 2, 2, 1)))
Srs1 <- Polygons(list(Sr1), "s1")
Srs2 <- Polygons(list(Sr2), "s2")
SpP <- SpatialPolygons(list(Srs1, Srs2), 1:2)

ui <- fluidPage(
  sliderInput("nomaps", "Number of maps:",
              min = 1, max = 5, value = 1
  ),
  uiOutput("plots")
)

change_color <- function(map, id_to_remove, data, colour, new_group)
  leafletProxy(map) %>%
    removeShape(id_to_remove) %>% # remove previous occurrence
    addPolygons(
      data = data,
      label = data$display,
      layerId = data$ID,
      group = new_group, # change group
      fillColor = colour)


server <- function(input,output,session)
  
  ## Polygon data
  rv <- reactiveValues(
    df = SpatialPolygonsDataFrame(SpP, data = data.frame(
      ID = c("1", "2"),
      display = c("1", "1")
    ), match.ID = FALSE)
  )
  
  # initialization
  output$map <- renderLeaflet(
    leaflet(options = leafletOptions( zoomControl = FALSE, minZoom = 6.2, maxZoom = 6.2, dragging = FALSE)) 
  )
  
  observe(
    
    data <- rv$df
    
      lapply(1:input$nomaps, function(i) 
      
        output[[paste("plot", i, sep = "_")]] <- renderLeaflet(
          leaflet(options = leafletOptions( zoomControl = FALSE, minZoom = 6.2, maxZoom = 6.2, dragging = FALSE))%>%
            addPolygons(
              data = data,
              label = data$display,
              layerId = data$ID,
              group = "unclicked_poly")
          
        )
      )
  )
  
  # Create plot tag list
  output$plots <- renderUI(
    
      plot_output_list <- lapply(1:input$nomaps, function(i) 
        plotname <- paste("plot", i, sep = "_")
        leafletOutput(plotname)
      )
      
      do.call(tagList, plot_output_list)
    
  )
  
  
  #first click
  observeEvent(input$plot_1_shape_click, 
    
    # execute only if the polygon has never been clicked
    req(input$plot_1_shape_click$group == "unclicked_poly")
    
    # filter data
    data <- rv$df[rv$df$ID==input$plot_1_shape_click$id,]
    
    change_color(map = "plot_1", 
                 id_to_remove =  input$plot_1_shape_click$id, 
                 data = data, 
                 colour = "yellow", 
                 new_group = "clicked1_poly")
  )

  
  
  #back to normal
  observeEvent(input$plot_1_shape_click, 
    req(input$plot_1_shape_click$group == "clicked1_poly")
    
    data <- rv$df[rv$df$ID==input$plot_1_shape_click$id,]
    
    # back to normal
    leafletProxy("plot_1") %>%
      removeShape(input$plot_1_shape_click$id) %>% # remove previous occurrence
      addPolygons(
        data = data,
        label = as.character(data$display),
        layerId = data$ID,
        group = "unclicked_poly") # back to initialize group
  )


shinyApp(ui, server)

【问题讨论】:

使用lapply(...) 并且只包含一个observeEvent()。您可以在观察者内部使用条件语句。 @YBS 我试过 lapply 但我无法让它工作,你有任何示例代码吗? 【参考方案1】:
 observe (
    lapply(1:input$nomaps, function(i) 
    
      observeEvent(input[[paste0("plot_", i,"_shape_click",sep="")]], 
        # execute only if the polygon has never been clicked
        if (input[[paste0("plot_", i,"_shape_click",sep="")]]$group == "unclicked_poly") 
        
        selected.id <- input[[paste0("plot_", i,"_shape_click",sep="")]]
        
        data <- rv$df[rv$df$ID==selected.id$id,]
        
        change_color(map = paste0("plot_", i, sep=""),
                     id_to_remove =  selected.id$id,
                     data = data,
                     colour = "yellow",
                     new_group = "clicked1_poly") 
         else 
          
          selected.id <- input[[paste0("plot_", i,"_shape_click",sep="")]]
          
          data <- rv$df[rv$df$ID==selected.id$id,]
          
              leafletProxy(paste0("plot_", i, sep="")) %>%
                removeShape(selected.id$id) %>% # remove previous occurrence
                addPolygons(
                  data = data,
                  label = as.character(data$display),
                  layerId = data$ID,
                  group = "unclicked_poly") # back to initialize group
        
      )
    )
    )

【讨论】:

【参考方案2】:

试试这个

observe(
    lapply(1:input$nomaps, function(i) 

      observeEvent(input[[paste0("plot_", i,"_shape_click")]], 
        # execute only if the polygon has never been clicked
        selected.id <- input[[paste0("plot_", i,"_shape_click")]]
        data <- rv$df[rv$df$ID==selected.id$id,]
        
        if (selected.id$group == "unclicked_poly") 
          change_color(map = paste0("plot_", i),
                       id_to_remove =  selected.id$id,
                       data = data,
                       colour = "yellow",
                       new_group = "clicked1_poly")
         else 
          leafletProxy(paste0("plot_", i)) %>%
            removeShape(selected.id$id) %>% # remove previous occurrence
            addPolygons(
              data = data,
              label = as.character(data$display),
              layerId = data$ID,
              group = "unclicked_poly") # back to initialize group
        
      )
    )
  )

【讨论】:

以上是关于如何在闪亮中循环观察事件?单击多边形时更改传单中的样式的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式触发 R 传单中的标记鼠标单击事件以实现闪亮

如何从shapefile传单R访问多边形信息

突出显示由选择项指向的 R 传单多边形(不单击它)

闪亮 - 在数据表中选择记录时如何突出显示传单地图上的对象?

单击反应传单 v.3.x 中的标记时如何动态更改地图缩放?

观察事件中的R闪亮updateSelectInput不起作用