javascript - 无法让 Leaflet.Spin 插件在 R Shiny 中工作

标签 javascript r shiny leaflet

我有一个 Shiny 的应用程序,它涉及在 map 上绘制大量线条。我想使用微调器向用户显示正在进行渲染。大多数 Shiny 的方法都不起作用,因为它们只在数据发送到传单时显示微调器,而不是在传单渲染时显示。 Leaflet.Spin 插件看起来很有希望,但我一直在努力让它工作。我一直在关注的例子是

https://gist.github.com/jcheng5/c084a59717f18e947a17955007dc5f92

leaflet plugin and leafletProxy with polylineDecorator as Example

如何让 js 事件正确触发并在线条(本例中的圆圈)呈现时显示 Leaflet.Spin?谢谢!

更新:微调器现在可以工作,但会为添加的每个单独的圆圈触发事件,因此如果圆圈数量减少,微调器不会正确关闭。

library(shiny)
library(leaflet)
library(htmltools) # for htmlDependency
library(htmlwidgets) # for onRender

# https://gist.github.com/jcheng5/c084a59717f18e947a17955007dc5f92
# https://stackoverflow.com/questions/52846472/leaflet-plugin-and-leafletproxy-with-polylinedecorator-as-example
spinPlugin <- htmlDependency(
  "spin.js", 
  "2.3.2",
  src = c(href = "https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2"),
  script = "spin.min.js") # there's no spin.css

leafletspinPlugin <- htmlDependency(
  "Leaflet.Spin", 
  "1.1.2",
  src = c(href = "https://cdnjs.cloudflare.com/ajax/libs/Leaflet.Spin/1.1.2"),
  script = "leaflet.spin.min.js")

registerPlugin <- function(map, plugin) {
  map$dependencies <- c(map$dependencies, list(plugin))
  map
}

# Note: Ctrl-Shift-J opens the javascript console in the browser
spin_event <- "function(el, x) {
  console.log('spin event added'); 
  var mymap = this;
  mymap.on('layerremove', function(e) {
    console.log('layerremove fired');
    mymap.spin(true);
  });
  mymap.on('layeradd', function(e) {
    console.log('layeradd fired');
    mymap.spin(false); 
  });
}"

dlat <- 1 / 111000 * 100 # degrees per metre

ui <- fluidRow(
  tags$h2("Using Leaflet.Spin in Shiny"),
  actionButton("plotbutton", label = "Show Spinner While Adding Markers"),
  leafletOutput("map")
)

server <- function(input, output, session) {
  output$map <- renderLeaflet({
    cat("renderLeaflet\n")
    leaflet() %>%
      addTiles() %>%
      setView(175.322, -37.789, zoom = 17) %>% 
      registerPlugin(spinPlugin) %>% 
      registerPlugin(leafletspinPlugin) %>% 
      onRender(spin_event) %>% 
      clearShapes() %>% # initialise spinner
      addCircles(
        lng = 175.322,
        lat = -37.789,
        radius = 0,
        opacity = 0
      )
  })

  observeEvent(input$plotbutton, {
    cat("input$plotbutton\n")
    n <- ceiling(runif(1) * 10000)
    leafletProxy("map") %>%
      clearShapes() %>% 
      addCircles(
        lng = 175.322 + (runif(n) * 2 - 1) * dlat * 6,
        lat = -37.789 + (runif(n) * 2 - 1) * dlat * 1.5,
        radius = dlat * runif(n) * dlat
      )
  })
}

shinyApp(ui = ui, server = server)

最佳答案

晚了一年,但我一直在寻找一种方法来为传单制作一个忙碌的旋转器。

我意识到您的原始代码会在 clearShapes() 上创建 x 个自旋实例。如果以下 addCircles() 的圆圈数少于 x,则会有自旋实例继续运行。

我的解决方案是使用虚拟层来监视 Javascript。在下面的示例中,一个带有 layerId = 'spinnerMarker' 的圆圈。要启动 leafletproxy 更新,该层将通过触发 JS layerremoveremoveShape(layerId = 'spinnerMarker') 移除。然后添加数据圈。通过添加一个带有 layerId = 'spinnerMarker' 的圆圈来触发 JS layeradd 来结束更新。

在 JS 中,使用 e.layer.options.layerId == 'spinnerMarker' 检查要添加或删除的层以运行 mymap.spin()

这样只有一个自旋实例在运行。

library(shiny)
library(leaflet)
library(htmltools) # for htmlDependency
library(htmlwidgets) # for onRender

# https://gist.github.com/jcheng5/c084a59717f18e947a17955007dc5f92
# https://stackoverflow.com/questions/52846472/leaflet-plugin-and-leafletproxy-with-polylinedecorator-as-example
spinPlugin <- htmlDependency(
  "spin.js", 
  "2.3.2",
  src = c(href = "https://cdnjs.cloudflare.com/ajax/libs/spin.js/2.3.2"),
  script = "spin.min.js") # there's no spin.css

leafletspinPlugin <- htmlDependency(
  "Leaflet.Spin", 
  "1.1.2",
  src = c(href = "https://cdnjs.cloudflare.com/ajax/libs/Leaflet.Spin/1.1.2"),
  script = "leaflet.spin.min.js")

registerPlugin <- function(map, plugin) {
  map$dependencies <- c(map$dependencies, list(plugin))
  map
}

# Note: Ctrl-Shift-J opens the javascript console in the browser
spin_event <- "function(el, x) {
  console.log('spin event added'); 
  var mymap = this;
  mymap.on('layerremove', function(e) {
    console.log('layerremove fired');
    if (e.layer.options.layerId == 'spinnerMarker') {
      console.log(e.layer.options.layerId);
      mymap.spin(true);
    }
  });
  mymap.on('layeradd', function(e) {
    console.log('layeradd fired');
    if (e.layer.options.layerId == 'spinnerMarker') {
      console.log(e.layer.options.layerId);
      mymap.spin(false);
    }
  });
}"

dlat <- 1 / 111000 * 100 # degrees per metre

ui <- fluidRow(
  tags$h2("Using Leaflet.Spin in Shiny"),
  actionButton("plotbutton", label = "Show Spinner While Adding Markers"),
  leafletOutput("map")
)

server <- function(input, output, session) {
  output$map <- renderLeaflet({
    cat("renderLeaflet\n")
    leaflet() %>%
      addTiles() %>%
      setView(175.322, -37.789, zoom = 17) %>% 
      registerPlugin(spinPlugin) %>% 
      registerPlugin(leafletspinPlugin) %>% 
      onRender(spin_event) %>% 
      clearShapes() %>% # initialise spinner
      addCircles(     # invisible placeholder
        lng = 175.322,
        lat = -37.789,
        radius = 0,
        opacity = 0,
        layerId = 'spinnerMarker'   # identifier, can be found in js: e.layer.options.layerId
      )
  })
  
  observeEvent(input$plotbutton, {
    cat("input$plotbutton\n")
    n <- ceiling(runif(1) * 10000)
    leafletProxy("map") %>%
      removeShape(layerId = 'spinnerMarker') %>%    # this triggers mymap.spin(true)
      clearShapes() %>% 
      addCircles(
        lng = 175.322 + (runif(n) * 2 - 1) * dlat * 6,
        lat = -37.789 + (runif(n) * 2 - 1) * dlat * 1.5,
        radius = dlat * runif(n) * dlat
      ) %>%
      addCircles(         # invisible placeholder to trigger the mymap.spin(false)
        lng = 175.322,
        lat = -37.789,
        radius = 0,
        opacity = 0,
        layerId = 'spinnerMarker'   # identifier, can be found in js: e.layer.options.layerId
      )
  })
}

shinyApp(ui = ui, server = server)

关于javascript - 无法让 Leaflet.Spin 插件在 R Shiny 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61532955/

相关文章:

r - 投{ reshape } : using variables instead of the columns' name

javascript - 为什么 "use strict"在此示例中将性能提高 10 倍?

javascript - 如何防止请求重复?

javascript - 用paperjs画一个圆圈里面有一个空心的圆圈

r - 将 data.frame 的每个单元格与其权重相乘

R如何用新的子字符串替换较长字符串中的子字符串

r - 在 `googleAuthR` 中使用来自 `googlesheets` 的 token

r - 我可以在 Shiny plot_ly 中设置 "pair"轨迹,以便在单击图例时两条轨迹出现/消失吗?

r - 如何从R Shiny 的选择输入(multiple = TRUE)动态定义公式

javascript - slider 图像需要一些时间来加载。