以polylineDecorator为例的leaflet插件和leafletProxy [英] leaflet plugin and leafletProxy with polylineDecorator as Example

查看:1703
本文介绍了以polylineDecorator为例的leaflet插件和leafletProxy的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

另请参阅问题传单插件和leafletProxy .

我想在R的传单中使用 polylineDecorator插件.

I want to use polylineDecorator Plugin in leaflet for R.

遵循有关如何使用R中的传单插件的说明,如果我将方法与leaflet()一起使用,则可以使用它.请参阅第一个示例,该示例按我的要求工作.但是,如果我尝试对leafletProxy()使用相同的方法,那么它什么也没做,只能得到没有装饰器的行.请参阅第二个示例.

Following instruction for how to use leaflet plugin from R, I can use it if I use the approach togeher with leaflet(). See the first example, which works as i wanted. But if i try to use the same approach with leafletProxy(), it just doesn't do anything I only get line without decorator. See the second example.

我的问题是我如何在R的leafletProxy()中使用传单插件.

My question is how I can use leaflet plugin with R's leafletProxy().

示例1 :有效的版本,不使用lefletProxy.

Example 1: Version that works, not using the lefletProxy.

library(shiny)
library(leaflet)
library(htmltools)

download.file(
          'https://raw.githubusercontent.com/bbecquet/Leaflet.PolylineDecorator/master/dist/leaflet.polylineDecorator.js', 
          'leaflet.polylineDecorator.js')

polylineDecoratorPlugin <- htmlDependency('Leaflet.PolylineDecorator',
                                          '1.6.0',
                      src = normalizePath('.'), 
                      script = 'leaflet.polylineDecorator.js')

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


ui <- bootstrapPage( 
            tags$style(type = "text/css", "html, body {width:100%;height:100%}"), 
            leafletOutput("map", width = "100%", height = "100%")
            )

server <- function(input, output) {
  dat <- data.frame(lat0=c(29,29.1),lat1=c(30,30.1), lng0=c(-96,-96.1),lng1=c(-95,-95.1))
  output$map <- renderLeaflet({
      m <- leaflet() %>%
#        addProviderTiles(providers$OpenStreetMap.BlackAndWhite) %>%
        setView(lat=29.762778, lng=-95.383056, zoom=8)  %>% # Houston
        registerPlugin(polylineDecoratorPlugin) %>%
        addPolylines(lat=c(dat$lat0[1], dat$lat1[1]), lng=c(dat$lng0[1],dat$lng1[1])) %>%
        addPolylines(lat=c(dat$lat0[2], dat$lat1[2]), lng=c(dat$lng0[2],dat$lng1[2])) %>%
        htmlwidgets::onRender("function(el,x,data) {
                            for(var i=0; i < data.lat0.length; i++) {
                              var dec = L.polylineDecorator([[data.lat0[i],data.lng0[i]],[data.lat1[i],data.lng1[i]]], {
                              patterns: [
                              {offset: 0, repeat: 20, symbol: L.Symbol.arrowHead({pixelSize:15, pathOptions:{stroke:true}})}
                              ]
                              }).addTo(this);
                            }
                            }",
                            data=dat)

  })
}

# Run the application 
shinyApp(ui = ui, server = server)

这就是我从上面的代码中得到的,这正是我所期望的.

Here's what I get from the code above, and this is what I expected.

示例2 :使用lefletProxy(),该版本不显示装饰器,仅显示行:

Example 2: Version that does not show the decorator, just line, using lefletProxy():

library(shiny)
library(leaflet)
library(htmltools)

download.file(
          'https://raw.githubusercontent.com/bbecquet/Leaflet.PolylineDecorator/master/dist/leaflet.polylineDecorator.js', 
          'leaflet.polylineDecorator.js')

polylineDecoratorPlugin <- htmlDependency('Leaflet.PolylineDecorator',
                                          '1.6.0',
                      src = normalizePath('.'), 
                      script = 'leaflet.polylineDecorator.js')

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


ui <- bootstrapPage( 
            tags$style(type = "text/css", "html, body {width:100%;height:100%}"), 
            leafletOutput("map", width = "100%", height = "100%")
            )

server <- function(input, output) {
  dat <- data.frame(lat0=c(29,29.1),lat1=c(30,30.1), lng0=c(-96,-96.1),lng1=c(-95,-95.1))
  output$map <- renderLeaflet({
      m <- leaflet() %>%
#        addProviderTiles(providers$OpenStreetMap.BlackAndWhite) %>%
        setView(lat=29.762778, lng=-95.383056, zoom=8)  # Houston
    })
  observe({
    # THIS DOESNT WORK with PROXY!!!
    leafletProxy('map') %>%
    registerPlugin(polylineDecoratorPlugin) %>%
    addPolylines(lat=c(dat$lat0[1], dat$lat1[1]), lng=c(dat$lng0[1],dat$lng1[1])) %>%
    addPolylines(lat=c(dat$lat0[2], dat$lat1[2]), lng=c(dat$lng0[2],dat$lng1[2])) %>%
    htmlwidgets::onRender("function(el,x,data) {
                          for(var i=0; i < data.lat0.length; i++) {
                            var dec = L.polylineDecorator([[data.lat0[i],data.lng0[i]],[data.lat1[i],data.lng1[i]]], {
                            patterns: [
                            {offset: 0, repeat: 20, symbol: L.Symbol.arrowHead({pixelSize:15, pathOptions:{stroke:true}})}
                            ]
                            }).addTo(this);
                          }
                          }",
                          data=dat)
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

这是示例2的结果.您看到没有装饰器,只有几行,尽管我尝试使用htmlwidgets::onRender的方式几乎相同.

And here is the the results from example 2. As you see there is no decorator, only lines, though i attempted to use htmlwidgets::onRender pretty much the same way.

推荐答案

好的,我可能已经确定了.

Alright, I may have nailed it down.

我要做的是:

  1. 使用leaflet而不是leafletProxy调用htmlwidgets::onRender.制作地图时,我必须预料会发生什么.

  1. Call htmlwidgets::onRender with leaflet, not with leafletProxy. I have to anticipate what to come when I make map.

当我使用lealetProxy添加折线时,我会严格遵守以添加额外的选项Need_decorator = TRUE.

When I add polylines using lealetProxy, i dicipline myself to add extra option need_decorator=TRUE.

htmlwidgets::onRender的回调函数应将事件侦听器添加到地图.在下面的代码中,这部分是myMap.on('layeradd', function(e) {...} );.因此,将在添加图层时添加装饰器.

Call back function for htmlwidgets::onRender should add event listener to the map. in the code below it is this part: myMap.on('layeradd', function(e) {...} );. So the decorator is going to be added when layer is added.

我们要向多段线添加装饰器.因此,如果触发事件的图层是我想要装饰的折线,那么我需要进行此测试.没有此测试,折线装饰器将触发事件并进入调用自身的无限循环.

We want to add decorator to polyline. So i need if ('need_decorator' in lyr.options) this testing if the layer which triggered event was polyline that i want to have decorator. Without this test, polyline decorator is going to trigger the event and goes infinite loop of calling itself.

下面的示例代码生成了我想要的.对于具有JavaScript经验的人来说,这可能是显而易见的,但是像我这样的很多R用户对这种事件没有太多的经验……

Sample code below generates what I wanted. This may have been obvious to people with experience with javascript, but a lot of R user like me don't have much experience with this event kind of thing...

我想处理折线被修改/删除的情况,但是我想想法是一样的.

I want to deal with cases when polyline got modified/deleted, but I guess idea would be the same.

请告诉我是否有更简单的方法.

Please let me know if there is simpler way to do this.

library(shiny)
library(leaflet)
library(htmltools)

download.file(
  'https://raw.githubusercontent.com/bbecquet/Leaflet.PolylineDecorator/master/dist/leaflet.polylineDecorator.js', 
  'leaflet.polylineDecorator.js')

polylineDecoratorPlugin <- htmlDependency('Leaflet.PolylineDecorator',
                                          '1.6.0',
                                          src = normalizePath('.'), 
                                          script = 'leaflet.polylineDecorator.js')

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


ui <- bootstrapPage( 
  tags$style(type = "text/css", "html, body {width:100%;height:100%}"), 
  leafletOutput("map", width = "100%", height = "100%")
)

server <- function(input, output) {
  dat <- data.frame(lat0=c(29,29.1),lat1=c(30,30.1), lng0=c(-96,-96.1),lng1=c(-95,-95.1))
  output$map <- renderLeaflet({
    m <- leaflet() %>%
      registerPlugin(polylineDecoratorPlugin) %>%
      addProviderTiles(providers$OpenStreetMap.BlackAndWhite) %>%
      setView(lat=29.762778, lng=-95.383056, zoom=8) %>%  # Houston
      htmlwidgets::onRender(
        "function(el,x,data) {
          var myMap = this;

          // I have to wrap the decoration addition code with map.on() function
          // wait for polyline layer to be added before i add decorator    
          myMap.on('layeradd',
            function(e) {
              var lyr = e.layer;
              // among whatever layers added to the map, i look for
              // 'need_decorator' property which i tell myself to add as an options
              // when adding polyline
              if ('need_decorator' in lyr.options) {

                var dec = L.polylineDecorator(lyr, {
                  patterns: [
                    {offset: 0, repeat: 20, symbol: L.Symbol.arrowHead({pixelSize:15, pathOptions:{stroke:true}})}
                  ]
                }).addTo(myMap);
              }
            }
          );
        }",
      data=dat)
  })
  observe({
    leafletProxy('map') %>%
      # I am adding need_decorator = TRUE as an option.  This shows up as, when 
      # event got triggered, event.layer.options.need_decorator in Javascript
      addPolylines(lat=c(dat$lat0[1], dat$lat1[1]), lng=c(dat$lng0[1],dat$lng1[1]), options = list(need_decorator = T)) %>%
      addPolylines(lat=c(dat$lat0[2], dat$lat1[2]), lng=c(dat$lng0[2],dat$lng1[2]), options = list(need_decorator = T)) 

    })
  }

# Run the application 
shinyApp(ui = ui, server = server)

这篇关于以polylineDecorator为例的leaflet插件和leafletProxy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆