在Shiny应用程序中处理图像地图点击

时间:2018-07-25 18:00:03

标签: r shiny imagemap

我正在构建一个Shiny应用程序,其中selectInput功能将以传统的HTML select下拉菜单和可点击的图像映射的形式显示。我当前的策略是使用添加的URL参数将图像地图多边形链接回应用程序,解析该URL并更新选择。当然,这每次都会重置应用程序,这可以,但是效果不佳,并且UI闪烁也不是很优美。

我的问题是:

  • 是否有更好的方法来捕获图像点击并更新输入?
  • 如果继续执行我的解决方案,我可以延迟在selectInput上进行渲染,以便在解析URL之后才显示该渲染,以便在闪烁到之前暂时不显示默认选择。参数化选择?

这是一个演示:

screenshot

library(shiny)
ui <- fluidPage(
   sidebarLayout(
      sidebarPanel(
         selectInput("letter_select",
                     "Pick a letter:",
                     choices = c('A' = 1, 'B' = 2, 'C' = 3, 'D' = 4))
      ),
      mainPanel(
         h3('Or click a letter'),
         img(src = 'testpattern.png', usemap = '#image-map'),
         HTML('
<map name="image-map">
<area target="_self" title="A" href="?letter=1" coords=0,0,50,0,50,50,0,50" shape="poly">
<area target="_self" title="B" href="?letter=2" coords=50,0,100,0,100,50,50,50" shape="poly">
<area target="_self" title="C" href="?letter=3" coords=0,50,50,50,50,100,0,100" shape="poly">
<area target="_self" title="D" href="?letter=4" coords=50,50,100,50,100,100,50,100" shape="poly">
</map>
              ')
      )
   )
)

server <- function(input, output, session) {
  observe({
    query <- parseQueryString(session$clientData$url_search)
    if (!is.null(query[['letter']])) {
      updateSelectInput(session, 'letter_select', selected = query[['letter']])
    }
  })
}

shinyApp(ui = ui, server = server)

图片位于“ www / testpattern.png”,如下所示。

www/testpattern.png

1 个答案:

答案 0 :(得分:1)

要保持状态并防止在重新加载整个页面时闪烁将非常困难。最好的解决方法可能是捕获javascript中的事件并更新应用程序状态。接下来是一个粗略的概念证明,说明它可能如何工作。首先,我们抽象出图像映射的概念

imageMap <- function(inputId, imgsrc, opts) {
  areas <- lapply(names(opts), function(n) 
    shiny::tags$area(title=n, coords=opts[[n]], 
                     href="#", shape="poly"))
  js <- paste0("$(document).on('click', 'map area', function(evt) {
  evt.preventDefault();
  var val = evt.target.title;
  Shiny.onInputChange('", inputId, "', val);})")
  list(
    shiny::tags$img(src=imgsrc, usemap=paste0("#", inputId),
    shiny::tags$head(tags$script(shiny::HTML(js)))),
    shiny::tags$map(name=inputId, areas))
}

这将从我们传入的URL和选项列表中呈现图像和地图数据。我们添加了一些JavaScript来捕获图像地图上的点击事件。例如

imgsrc <- "https://i.stack.imgur.com/C5aoV.png"
mapopts <- list(A="0,0,50,0,50,50,0,50",
  B="50,0,100,0,100,50,50,50",
  C="0,50,50,50,50,100,0,100",
  D ="50,50,100,50,100,100,50,100")
imageMap("map1", imgsrc, mapopts)

我们可以在用户界面中使用它

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("letter_select",
                  "Pick a letter:",
                  choices = c('A', 'B', 'C', 'D'))
    ),
    mainPanel(
      h3('Or click a letter'),
      imageMap("map1", imgsrc , mapopts)
    )
  )
)

现在我们可以在服务器上侦听事件,并更改选择输入

server <- function(input, output, session) {
  observeEvent(input$map1,  {
    updateSelectInput(session, "letter_select", selected=input$map1)
  })  
}

现在您可以运行

shinyApp(ui = ui, server = server)

您会看到,单击图像中的字母时,select输入的值将更改为匹配。