【问题标题】:R Shiny map search input boxR Shiny 地图搜索输入框
【发布时间】:2019-04-20 05:03:52
【问题描述】:

在谷歌地图中,​​搜索输入框会在用户键入时自动完成地址。有没有办法在 R Shiny 中访问自动完成值以便与映射包一起使用?

有一个javascript方法here。我尝试在下面的代码中在 R Shiny 中使用此方法。 SymbolixAU 指出使用google_map( search_box = TRUE ) 这是一个简单的解决方案。不幸的是,它在我的代码中不起作用,而且我希望搜索框与地图分开。

下面的尝试在页面上按此顺序有一个文本输入my_address、文本输出copy_of_address 和一个googleway 地图my_map

预期的行为是让用户在文本输入my_address 中输入文本,让它自动完成一个地址(这可行),地址将被复制到文本输出copy_of_address 中(这只显示输入的内容,不是自动完成的版本),最后地图将以该地址为中心。

看到输入框有自动完成地址,但是地址和地图的副本只使用用户输入的文本。

在下面的代码中,将 MyKey 替换为您的 google api 密钥(有时可以使用空字符串)。

library(shiny)
library(googleway)

key <- "MyKey"
set_key(key = key)
google_keys()

ui <- shiny::basicPage(

  div(
    textInput(inputId = "my_address", label = "")    
    ,textOutput(outputId = "copy_of_address")
    ,HTML(paste0("
          <script>
            function initAutocomplete() {
            new google.maps.places.Autocomplete(
            (document.getElementById('my_address')),
            {types: ['geocode']}
            );
            }
            </script>
            <script src='https://maps.googleapis.com/maps/api/js?key=", key,"&libraries=places&callback=initAutocomplete'
            async defer></script>
    "))
    ,google_mapOutput(outputId = "my_map")
  )

)

server <- function(input, output) {

  my_address <- reactive({
    input$my_address
  })

  output$copy_of_address <- renderText({
    my_address()
  })

  output$my_map <- renderGoogle_map({
    my_address <- my_address()
    validate(
      need(my_address, "Address not available")
    )

    df <- google_geocode(address = my_address)
    my_coords <- geocode_coordinates(df)
    my_coords <- c(my_coords$lat[1], my_coords$lng[1])

    google_map(
      location = my_coords,
      zoom = 12,
      map_type_control = FALSE,
      zoom_control = FALSE,
      street_view_control = FALSE
    )
  })

}

shinyApp(ui, server)

【问题讨论】:

  • 您是在地图上使用它,还是独立于地图(即单独的小部件)?
  • 目前我在用于地址的文本框下方有一张地图 - 所以它不独立于地图。输入后地图会以地址为中心。
  • 如果您使用google_map( search_box = TRUE ),它将在地图上放置一个搜索框并自动完成
  • here's an example of a shiny,使用搜索框,观察用户搜索的结果。
  • 有没有办法让搜索框在地图之外但仍然可以协同工作?用例是先输入地址,再显示地图。

标签: r autocomplete shiny r-leaflet googleway


【解决方案1】:

这对我来说并不容易弄清楚,但我认为我有一个合理的解决方案。最终归结为从 Google 非常 仔细复制和粘贴示例,阅读有关从 Javascript 向 Shiny 发送消息的信息,将这些想法放在一起,并在第 200 次尝试中幸运...

给予应得的荣誉:

谷歌链接:https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete

RStudio 的链接:https://shiny.rstudio.com/articles/js-send-message.html

我的潜在解决方案:

library(shiny)
library(googleway)

key <- "MyKey"
set_key(key = key)
#google_keys()

ui <- shiny::basicPage(

  div(
    textInput(inputId = "my_address", label = "Type An Address")    
    ,textOutput(outputId = "full_address")
    ,HTML(paste0(" <script> 
                function initAutocomplete() {

                 var autocomplete =   new google.maps.places.Autocomplete(document.getElementById('my_address'),{types: ['geocode']});
                 autocomplete.setFields(['address_components', 'formatted_address',  'geometry', 'icon', 'name']);
                 autocomplete.addListener('place_changed', function() {
                 var place = autocomplete.getPlace();
                 if (!place.geometry) {
                 return;
                 }

                 var addressPretty = place.formatted_address;
                 var address = '';
                 if (place.address_components) {
                 address = [
                 (place.address_components[0] && place.address_components[0].short_name || ''),
                 (place.address_components[1] && place.address_components[1].short_name || ''),
                 (place.address_components[2] && place.address_components[2].short_name || ''),
                 (place.address_components[3] && place.address_components[3].short_name || ''),
                 (place.address_components[4] && place.address_components[4].short_name || ''),
                 (place.address_components[5] && place.address_components[5].short_name || ''),
                 (place.address_components[6] && place.address_components[6].short_name || ''),
                 (place.address_components[7] && place.address_components[7].short_name || '')
                 ].join(' ');
                 }
                 var address_number =''
                 address_number = [(place.address_components[0] && place.address_components[0].short_name || '')]
                 var coords = place.geometry.location;
                 //console.log(address);
                 Shiny.onInputChange('jsValue', address);
                 Shiny.onInputChange('jsValueAddressNumber', address_number);
                 Shiny.onInputChange('jsValuePretty', addressPretty);
                 Shiny.onInputChange('jsValueCoords', coords);});}
                 </script> 
                 <script src='https://maps.googleapis.com/maps/api/js?key=", key,"&libraries=places&callback=initAutocomplete' async defer></script>"))
    ,google_mapOutput(outputId = "my_map")
    )

    )

server <- function(input, output) {

  my_address <- reactive({
    if(!is.null(input$jsValueAddressNumber)){
      if(length(grep(pattern = input$jsValueAddressNumber, x = input$jsValuePretty ))==0){
        final_address<- c(input$jsValueAddressNumber, input$jsValuePretty)
      } else{
        final_address<- input$jsValuePretty
      }
      final_address
    }
  })


  output$full_address <- renderText({
    if(!is.null(my_address())){
      my_address()
    }
  })

  output$my_map <- renderGoogle_map({
    my_address <- my_address()
    shiny::validate(
      need(my_address, "Address not available")
    )

    not_a_df <- google_geocode(address = my_address)
    my_coords <- geocode_coordinates(not_a_df)
    my_coords <- c(my_coords$lat[1], my_coords$lng[1])

    google_map(
      location = my_coords,
      zoom = 12,
      map_type_control = FALSE,
      zoom_control = FALSE,
      street_view_control = FALSE
    )
  })

}

shinyApp(ui, server)

我希望这会有所帮助。干杯! --nate

【讨论】:

  • 这也回答了你的other question 吗?
  • 没有。这是我对@Vlad 的回答。我认为这是一个好主意,并想将其放入我构建的 shinydashboard 中。但是,当我从shiny 应用程序切换到shinydashboard 时,我遇到了InvalidValueError 问题。
  • 哦,我明白了。是的,很奇怪你在仪表板中收到错误。
  • 我有一个部分解决方案。我会将其添加到我的问题中:stackoverflow.com/questions/54848254/…
  • 嗨!也许有人还在读这个:这个解决方案今天仍然有效吗?我试图模仿它,但几秒钟后我的输入窗口总是变灰并显示“Opps!出了点问题”。在文本框中。我很感激任何提示! @nate
猜你喜欢
  • 2018-12-19
  • 1970-01-01
  • 1970-01-01
  • 2018-11-01
  • 2021-04-17
  • 1970-01-01
  • 2012-12-10
  • 1970-01-01
  • 2015-07-01
相关资源
最近更新 更多