我有一个闪亮的应用程序,里面有一张现有的传单地图。我希望能够在渲染后通过
shinyjs
包使用自定义 JavaScript 来操作此地图。一个最小的例子如下:
app.R
# packages ----------------------------------------------------------------
library(dplyr)
library(leaflet)
library(shiny)
library(shinyjs)
# ui ----------------------------------------------------------------------
ui <- fluidPage(
useShinyjs(),
extendShinyjs(script = "my_js.js"),
leafletOutput(outputId = "map", height = "80vh"),
tags$hr(),
tags$p("Button to run the JS code"),
actionButton(inputId = "go", label = "Add a Marker")
)
# server ------------------------------------------------------------------
server <- function(input, output, session){
# define a simple map
output$map <- renderLeaflet({
leaflet() %>%
addProviderTiles("CartoDB.Positron")
})
# observe the go button and run the shinyjs.addMarker function
observeEvent(
eventExpr = input$go,
handlerExpr = js$addMarker()
)
}
# run ---------------------------------------------------------------------
shinyApp(ui = ui, server = server)
my_js.js
shinyjs.addMarker = function(){
// get the map - this bit doesn't work!
var map = document.getElementById('map');
// create a marker and add to map
var marker = new L.marker([53, -1]).addTo(map);
// really I'd be going off and querying an API, or doing
// something else for which there is no handy R function.
};
问题实际上是如何在创建地图对象后访问它。显然,在这个示例中,我只是添加一个标记,我可以使用
leafletProxy()
来完成此操作,但实际上我想查询 API 并在用户执行操作时将额外的数据带到地图上。
您可以使用
htmlwidtget
的onRender()
功能到达地图对象。然后,您可以将其保存到全局变量(通过在创建变量时跳过 var
关键字)。这在 JavaScript 代码中的任何地方都可用。
output$map <- renderLeaflet({
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
htmlwidgets::onRender("
function(el,x) {
map = this;
}
")
})
您的 my_js.js 将如下所示:
shinyjs.addMarker = function(){
// create a marker and add to map
var marker = new L.marker([53, -1]).addTo(map);
// really I'd be going off and querying an API, or doing
// something else for which there is no handy R function.
};