【问题标题】:leaflet plugin and leafletProxy传单插件和传单代理
【发布时间】:2017-08-28 21:45:40
【问题描述】:

我已将传单TextPath 插件添加到类似于this example 的闪亮应用程序中。这很好用:

output$fullscreen_map <- renderLeaflet({
  points <- points_reactive()

  points %>%
    leaflet() %>% 
    addTiles() %>%
    fitBounds(~min(lon), ~min(lat), ~max(lon), ~max(lat)) %>%
    registerPlugin(textPathPlugin) %>%
    onRender("function(el, x, data) {
                data = HTMLWidgets.dataframeToD3(data);
                data = data.map(function(val) { return [val.lat, val.lon]; });
                var layer = L.polyline(data);
                layer.on('mouseover', function () {
                this.setText('  ►  ', {repeat: true, attributes: {fill: 'blue'}});
                });
                layer.on('mouseout', function () {
                this.setText(null);
                });
                layer.addTo(this);
    }", data = points)

})

根据docs,我现在想使用leafletProxy(),以便在响应式数据源更改时不会重绘整个地图。唉,使用下面的sn-p代码

leafletProxy("fullscreen_map", data = points) %>%
  onRender("function(el, x, data) {
              data = HTMLWidgets.dataframeToD3(data);
              data = data.map(function(val) { return [val.lat, val.lon]; });
              var layer = L.polyline(data);
              layer.on('mouseover', function () {
              this.setText('  ►  ', {repeat: true, attributes: {fill: 'blue'}});
              });
              layer.on('mouseout', function () {
              this.setText(null);
              });
              layer.addTo(this);
  }", data = points)

没有按预期工作。我认为这是因为 onRender 仅在发生新渲染时才被调用,而 leafletProxy 的全部意义在于不重新渲染?如果这是正确的,有没有办法使用其他方法来做到这一点?

【问题讨论】:

  • 这是一个有趣的问题... Shiny 具有非常强大的事件处理能力,所以我认为诀窍是找出在脚本中绑定的正确位置。在没有 WME 的情况下解决这个问题有点棘手。你介意发一个吗?
  • 在我看来它应该可以工作。如果对 javascript 进行细微调整修复它,我不会感到惊讶,但需要进行 MWE 并且现在没有时间。
  • 您是否尝试过重新启动闪亮的服务器并再次运行它?在过去的几天里,我遇到了一些莫名其妙的可怕问题,但通过重新启动解决了。值得一试。
  • @yosukesabai 你能发布一个最小的可重现示例吗?
  • 是的,今晚我会做的

标签: r shiny leaflet


【解决方案1】:

它可能类似于下面的内容,尽管会有更简洁的方法。

我所做的是使用 LeafletProxy 从points_reactive() 函数添加折线层,同时将组设置为reactive。我曾经听过地图的layeradd事件,如果添加了reactive组的图层,我添加了textPath。

output$fullscreen_map <- renderLeaflet({
  points <- points_reactive()

  points %>%
    leaflet() %>% 
    addTiles() %>%
    fitBounds(~min(lon), ~min(lat), ~max(lon), ~max(lat)) %>%
    registerPlugin(textPathPlugin) %>%
    onRender("function(el, x, data) {
              var mymap = this;

              mymap.on('layeradd',
                function(e) {
                  console.log(e);
                  var layer = e.layer;

                  if (layer.groupname == 'reactive') {
                    layer.on('mouseover', function () {
                      this.setText('  ►  ', {repeat: true, attributes: {fill: 'blue'}});
                    });
                    layer.on('mouseout', function () {
                      this.setText(null);
                    });
                  }
                }
              );

            }", data = points)

  })

  observeEvent(input$clickme,{
               points <- points_reactive()

               leafletProxy('fullscreen_map') %>%
                 addPolylines(lng=points$lon, lat=points$lat, group='reactive')

  }
)
}

【讨论】:

    【解决方案2】:

    文档说:影响 renderLeaflet 表达式的活动输入和表达式将导致整个地图从头开始重绘并重置地图位置和缩放级别。

    听起来你必须深入挖掘 Leaflet 或自己触发 LeafletProxy,并确保数据源不会改变,通过使用两个数据源......(也许“代理”在这里用词不当。)

    看看这些插件是否可以提供帮助:https://leafletjs.com/plugins#dynamiccustom-data-loading

    【讨论】:

    • 我试图了解 onrender 的工作原理,以及是否可以更新它以响应其他事件。 onRender 将代码存储在小部件的jsHooks[['render']] 中。请参阅此处附近的行,以及 addHook 函数。 github.com/ramnathv/htmlwidgets/blob/master/R/… 。然后这个存储的代码在 javascript 代码中处理,在 inst/www/htmlwidgets.js github.com/ramnathv/htmlwidgets/blob/master/inst/www/… 中的两个位置。我认为另一个对evalAndRun 的调用可以从 js 代码中的某个地方进行,但不能从这里移开...
    • 这是正确的方向吗?仍然需要了解整个闪亮系统是如何工作的,我是这些交互式工具开发的新手......
    猜你喜欢
    • 2019-03-21
    • 2016-05-09
    • 2017-09-22
    • 2014-08-03
    • 2018-04-30
    • 2020-04-14
    • 2020-09-20
    • 1970-01-01
    • 2015-05-24
    相关资源
    最近更新 更多