Adding a navigationControl
ifellows opened this issue · comments
Some of the users of my Shiny app don't know how to zoom when given a map. Is there any possible way to add a navigationControl to the map?
I tried:
mapdeck(
token = key,
style = 'mapbox://styles/mapbox/dark-v10'
) %>%
htmlwidgets::onRender(
"function(el, x){console.log('.');nav = new mapboxgl.NavigationControl();mapmap._map.getMap().addControl(nav, 'top-left');}"
)
This adds the control, but any scatterplots or other layers don't render properly on use of the control.
In this line
mapmap._map.getMap()
How do you get / define mapmap
?
My shiny output is defined as output$map
. I was just looking around in the javascript console for a way to get to the mapbox map object, and found mapmap
.
oh it's in a shiny.
Full reprex of the issue.
library(shiny)
library(shinydashboard)
library(mapdeck)
set_token( secret::get_secret("MAPBOX") )
ui <- dashboardPage(
header = dashboardHeader()
, sidebar = dashboardSidebar()
, body = dashboardBody(
mapdeck::mapdeckOutput(
outputId = "map"
)
)
)
server <- function( input, output ) {
output$map <- mapdeck::renderMapdeck({
mapdeck(
style = 'mapbox://styles/mapbox/dark-v10'
) %>%
htmlwidgets::onRender(
"function(el, x){console.log('.');nav = new mapboxgl.NavigationControl();mapmap._map.getMap().addControl(nav, 'top-left');}"
) %>%
add_scatterplot(
data = roads
)
})
}
shinyApp(ui, server)
The layers get 'stuck' when using the control, and only 'refresh' when interacting with the map. I've seen this behaviour somewhere before, but can't quite remember where....
@ifellows This does not work because the deck.gl layers and the mapbox basemap are not in the same WebGL context and therefore are not synchronize automatically. deckgl-and-mapbox-better-together and mapbox-deck.gl-API show how deck.gl layers can be added to the mapboxgl context with custom layers. Then you can add any mapbox control, popups etc. to the deck.gl layer.
@crazycapivara Is it possible to link the layers from the mapdeck
users perspective, or would this require a feature addition to mapdeck
itself?
@ifellows Therefore, it needs a mapbox widget to which mapdeck layers could be added, but the syntax for adding a deck layer to a mapboxgl.map
object is slighty different.
You can take a look at the low level interface r2deck, where you must write your vizualisation function in pure JavaScript. You can either use the mapbox WebGL context with r2mapbox()
or the deck.gl WebGL context with r2deck()
.
To move the Getting Started example to the mapbox context, where you can add a navigation control, it would look like this:
// arc-layer.js
function r2deckViz(map, data, options) {
const arcLayer = new deck.MapboxLayer({
id: "arc-layer",
type: deck.ArcLayer,
data: data,
getSourcePosition: data => [data.start_lon, data.start_lat],
getTargetPosition: data => [data.end_lon, data.end_lat],
getSourceColor: [64, 255, 0],
getTargetColor: [0, 128, 200]
});
map.on("load", () => {
map.addControl(new mapboxgl.NavigationControl());
map.addLayer(arcLayer);
});
}
library(r2deck)
data_url <- paste0(
"https://raw.githubusercontent.com/plotly/datasets/master/",
"2011_february_aa_flight_paths.csv"
)
flights <- data.table::fread(data_url)
head(flights)
r2mapbox(
script = "arc-layer.js",
data = flights,
lng = -87.6500532,
lat = 41.850033,
zoom = 2,
pitch = 45
)