以 polylineDecorator 为例的传单插件和传单代理 [英] leaflet plugin and leafletProxy with polylineDecorator as Example
问题描述
另请参考一个问题
示例 2:不显示装饰器的版本,仅显示行,使用 lefletProxy():
库(闪亮)图书馆(传单)库(htmltools)下载文件('https://raw.githubusercontent.com/bbecquet/Leaflet.PolylineDecorator/master/dist/leaflet.polylineDecorator.js','leaflet.polylineDecorator.js')polylineDecoratorPlugin <- htmlDependency('Leaflet.PolylineDecorator','1.6.0',src = normalizePath('.'),脚本 = 'leaflet.polylineDecorator.js')registerPlugin <- 功能(地图,插件){map$dependencies <- c(map$dependencies, list(plugin))地图}ui <- bootstrapPage(标签$style(type = "text/css", "html, body {width:100%;height:100%}"),传单输出(地图",宽度=100%",高度=100%"))服务器 <- 功能(输入,输出){dat <- data.frame(lat0=c(29,29.1),lat1=c(30,30.1), lng0=c(-96,-96.1),lng1=c(-95,-95.1))输出$map <- renderLeaflet({m <- 传单() %>%# addProviderTiles(providers$OpenStreetMap.BlackAndWhite) %>%setView(lat=29.762778, lng=-95.383056, zoom=8) # 休斯顿})观察({# 这不适用于代理!!!LeafletProxy('地图') %>%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("函数(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]]], {模式:[{偏移量:0,重复:20,符号:L.Symbol.arrowHead({pixelSize:15, pathOptions:{stroke:true}})}]}).addTo(this);}}",数据=数据)})}# 运行应用程序闪亮应用(用户界面 = 用户界面,服务器 = 服务器)
这是示例 2 的结果.如您所见,没有装饰器,只有行,尽管我尝试以几乎相同的方式使用 htmlwidgets::onRender
.
好吧,我可能已经确定了.
我必须做的是:
使用
leaflet
调用htmlwidgets::onRender
,而不是使用leafletProxy
.当我制作地图时,我必须预测会发生什么.当我使用
lealetProxy
添加折线时,我会约束自己添加额外的选项 need_decorator=TRUE.htmlwidgets::onRender
的回调函数应该将事件监听器添加到地图.在下面的代码中是这部分:myMap.on('layeradd', function(e) {...});
.所以装饰器会在添加层的时候添加.我们想给折线添加装饰器.所以我需要
if ('need_decorator' in lyr.options)
这个测试触发事件的层是否是我想要装饰器的折线.如果没有这个测试,折线装饰器将触发事件并进入无限循环调用自身.
下面的示例代码生成了我想要的.这对于有 javascript 经验的人来说可能很明显,但是很多像我这样的 R 用户对这种事件类型的事情没有太多经验......
我想处理折线被修改/删除的情况,但我想想法是一样的.
如果有更简单的方法,请告诉我.
库(闪亮)图书馆(传单)库(htmltools)下载文件('https://raw.githubusercontent.com/bbecquet/Leaflet.PolylineDecorator/master/dist/leaflet.polylineDecorator.js','leaflet.polylineDecorator.js')polylineDecoratorPlugin <- htmlDependency('Leaflet.PolylineDecorator','1.6.0',src = normalizePath('.'),脚本 = 'leaflet.polylineDecorator.js')registerPlugin <- 功能(地图,插件){map$dependencies <- c(map$dependencies, list(plugin))地图}ui <- bootstrapPage(标签$style(type = "text/css", "html, body {width:100%;height:100%}"),传单输出(地图",宽度=100%",高度=100%"))服务器 <- 功能(输入,输出){dat <- data.frame(lat0=c(29,29.1),lat1=c(30,30.1), lng0=c(-96,-96.1),lng1=c(-95,-95.1))输出$map <- renderLeaflet({m <- 传单() %>%registerPlugin(polylineDecoratorPlugin) %>%addProviderTiles(providers$CartoDB.Positron) %>%setView(lat=29.762778, lng=-95.383056, zoom=8) %>% # 休斯顿htmlwidgets::onRender(函数(el,x,数据){var myMap = 这个;//我必须用 map.on() 函数包装装饰添加代码//在我添加装饰器之前等待折线层被添加myMap.on('layeradd',功能(e){var lyr = e.layer;//在添加到地图的任何图层中,我寻找//'need_decorator' 属性,我告诉自己添加为选项//添加折线时if ('need_decorator' in lyr.options) {var dec = L.polylineDecorator(lyr, {模式:[{偏移量:0,重复:20,符号:L.Symbol.arrowHead({pixelSize:15, pathOptions:{stroke:true}})}]}).addTo(myMap);}});}",数据=数据)})观察({LeafletProxy('地图') %>%# 我添加了 need_decorator = TRUE 作为选项.这显示为,当# 事件被触发,javascript 中的 event.layer.options.need_decoratoraddPolylines(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))})}# 运行应用程序闪亮应用(用户界面 = 用户界面,服务器 = 服务器)
编辑(2020-04-30)openstreetmap 提供程序磁贴不再存在,所以我更改为 cartodb.确认它仍在工作.
Please refer also to a question leaflet plugin and leafletProxy.
I want to use polylineDecorator Plugin in leaflet for R.
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.
My question is how I can use leaflet plugin with R's leafletProxy()
.
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.
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)
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.
What I had to do are:
Call
htmlwidgets::onRender
withleaflet
, not withleafletProxy
. I have to anticipate what to come when I make map.When I add polylines using
lealetProxy
, i dicipline myself to add extra option need_decorator=TRUE.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.
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$CartoDB.Positron) %>%
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)
EDIT (2020-04-30) openstreetmap provider tile doesnt exist anymore, so i change to cartodb. Confirmed that it is still working.
这篇关于以 polylineDecorator 为例的传单插件和传单代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!