首页 > 解决方案 > 在 R Shiny 应用程序中检测 Leaflet 中的左键或右键单击

问题描述

我想在 Shiny Leaflet 对象中有两个不同的操作,具体取决于多边形上是否有右键单击或左键单击。

我有两个初始化为 1 的多边形。我想在用户左键单击多边形时增加 +1 的值,并在用户右键单击时减少 -1 的值。如果在 R Shiny 中无法右键单击,则可能是双击左键。这里的目标是检测多边形上的两次不同点击,以便之后有两个不同的动作。

有一个我正在做的可复制示例:左键单击效果很好,多边形的值在左键单击时增加。现在我想让注释代码工作,以减少右键单击。

library(shiny)
library(leaflet)
library(sp)

## 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(
  titlePanel("Left or right click"),
  sidebarLayout(
    sidebarPanel(),
    mainPanel(
      leafletOutput("myMap")
    )
  )
)

server <- function(input, output) {
  ## Polygon data
  SPDF <- reactiveValues(
    df = SpatialPolygonsDataFrame(SpP, data = data.frame(
      ID = c(1, 2),
      display = c(1, 1)
    ), match.ID = FALSE)
  )

  ## generate leaflet output with two simple polygons
  output$myMap <- renderLeaflet({
    SpDf <- SPDF$df
    leaflet(options = leafletOptions( zoomControl = FALSE, minZoom = 6.2, maxZoom = 6.2, dragging = FALSE)) %>%
      addPolygons(
        data = SpDf,
        label = as.character(SpDf$display),
        layerId = SpDf$ID,
        labelOptions = labelOptions(noHide = T, textOnly = T, textsize = "15px", direction = "center")
      )
  })

  ## incremente when left click : OK
  observeEvent(input$myMap_shape_click, {
    SpDf <- SPDF$df
    SpDf$display[SpDf$ID == input$myMap_shape_click$id] <- SpDf$display[SpDf$ID == input$myMap_shape_click$id] + 1
    SPDF$df <- SpDf
  })

  ## decremente when right click (or double click if right click not possible) : HOW ?
  # observeEvent(input$??????,{
  #     SpDf <- SPDF$df
  #     # incremente when left click
  #     SpDf$display[SpDf$ID == input$myMap_shape_click$id] <- SpDf$display[SpDf$ID == input$myMap_shape_click$id] - 1
  #     SPDF$df <- SpDf
  # })
}

shinyApp(ui = ui, server = server)

标签: rshinyleafletspatial

解决方案


我终于找到了一种方法,也许不是最好的,因为我不习惯 Javascript ...

library(shiny)
library(leaflet)
library(sp)
library(shinyjs)

## 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(
  titlePanel("Left or right click"),
  useShinyjs(),
  sidebarLayout(
    sidebarPanel(),
    mainPanel(
      leafletOutput("myMap"),
      tags$script(
        "$(function(){
            $(myMap).on('contextmenu', 'path', function (e) {
              e.preventDefault();
              // get class name
              var id = $(e.currentTarget).attr('class').match(/id-\\d+/)[0];
              var right_click = {'count':Math.random(), 'id':id};
              Shiny.setInputValue('right_click', right_click);
            });
          });"
      )
    )
  )
)

server <- function(input, output) {
  ## Polygon data
  SPDF <- reactiveValues(
    df = SpatialPolygonsDataFrame(SpP, data = data.frame(
      ID = paste0("id-", 1:2),
      display = c(1, 1)
    ), match.ID = FALSE)
  )

  ## generate leaflet output with two simple polygons
  output$myMap <- renderLeaflet({
    SpDf <- SPDF$df
    leaflet(options = leafletOptions(zoomControl = FALSE, minZoom = 6.2, maxZoom = 6.2, dragging = FALSE)) %>%
      addPolygons(
        data = SpDf,
        label = as.character(SpDf$display),
        layerId = SpDf$ID,
        options = pathOptions(className = SpDf$ID), # give a CSS class per polygon so it can be get by JS
        labelOptions = labelOptions(noHide = T, textOnly = T, textsize = "15px", direction = "center")
      )
  })

  ## incremente when left click : OK
  observeEvent(input$myMap_shape_click, {
    SpDf <- SPDF$df
    SpDf$display[SpDf$ID == input$myMap_shape_click$id] <- SpDf$display[SpDf$ID == input$myMap_shape_click$id] + 1
    SPDF$df <- SpDf
  })

  ## decremente when right click
  observeEvent(input$right_click, {
    SpDf <- SPDF$df
    # incremente when left click
    SpDf$display[SpDf$ID == input$right_click$id] <- SpDf$display[SpDf$ID == input$right_click$id] - 1
    SPDF$df <- SpDf
  })
}

shinyApp(ui = ui, server = server)

推荐阅读