SymbolixAU / mapdeck

R interface to Deck.gl and Mapbox

Home Page:https://symbolixau.github.io/mapdeck/articles/mapdeck.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

commented

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.

commented

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
)