Reputation: 10203
I've added the leaflet TextPath plugin to a shiny app in analogy to this example. This works pretty well:
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)
})
In accordance with the docs I would now like to use leafletProxy()
so that the entire map doesn't get redrawn whenever the reactive data source changes. Alas, using the following snippet of code
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)
does not work as intended. I assume this is because onRender
is only called when a new render occurs and the whole point of leafletProxy
is to not re-render? If this is correct, is there a way to do this using other methods?
Upvotes: 11
Views: 1147
Reputation: 6244
It could be something like below, although there would be more cleaner methods.
What I did was to use leafletProxy to add polylines layer from points_reactive()
function, while setting group to be reactive
. I used listened to layeradd
event of map, and if a layer with reactive
group got added, i added the 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')
}
)
}
Upvotes: 1
Reputation: 1739
The docs say: active inputs and expressions that affect the renderLeaflet expression will cause the entire map to be redrawn from scratch and reset the map position and zoom level.
It sounds like you will have to dig deeper into Leaflet or trigger leafletProxy yourself, and make sure that the data source does not change, by using two data sources... (Perhaps "Proxy" is a misnomer here.)
Have a look and see if one of these plugins can help: https://leafletjs.com/plugins#dynamiccustom-data-loading
Upvotes: 0