walkerke / mapgl

R interface to Mapbox GL JS v3 and Maplibre GL JS
https://walker-data.com/mapgl
Other
84 stars 3 forks source link

set_view() doesn´t update the location of the mapboxgl_proxy() #31

Closed enriquevaa closed 1 month ago

enriquevaa commented 2 months ago

Hi Kyle,

When I try to switch the location of a mapboxgl_proxy("map") in the shiny app, it keeps the map in the original location of the proxy map.

It also doesn´t work with fly_to().

mapboxgl_proxy("map") %>% set_view(center=c (-98.20715351039499,19.047733964562703),zoom=15)

walkerke commented 2 months ago

This should work. Here's a self-contained app you can try:

library(shiny)
library(bslib)
library(mapgl)

# Function to generate random coordinates in Texas
generate_texas_coords <- function() {
  lat <- runif(1, 25.8371, 36.5007)
  lon <- runif(1, -106.6456, -93.5083)
  return(c(lon, lat))
}

ui <- page_sidebar(
  title = "Texas Coordinate Generator",
  sidebar = sidebar(
    width = 350,
    actionButton("generate", "Fly to Random Coordinates")
  ),
  card(
    full_screen = TRUE,
    card_header("Map"),
    mapboxglOutput("map")
  ),
)

server <- function(input, output, session) {

  output$map <- renderMapboxgl({
    mapboxgl(
      center = c(-97.5, 32.6),
      zoom = 10
    )
  })

  # Observer for the generate button
  observeEvent(input$generate, {
    new_coords <- generate_texas_coords()

    mapboxgl_proxy("map") |> 
      clear_markers() |> 
      fly_to(
        center = new_coords,
        zoom = 12
      ) |> 
      add_markers(data = new_coords,
                  color = "maroon")

  })  

}

shinyApp(ui, server)

Is your use of mapboxgl_proxy() tied to a reactive expression or an observer?

enriquevaa commented 1 month ago

I reviewed the bug, and it doesn´t update immediately if I use a fit_bounds() first and then I try to update the location while I call a map from my Mapbox Studio account with a reactive expression. I updated your code to show where the bug occurs. I picked three cities in Texas (where the code updates well) and one city (Puebla) attached to a Studio style, where it doesn´t update. The shiny app does well when I call another location from the reactive expression, but if I change the style and update the view (like in the city of Puebla) it gives me back to Rhode Island (where the fit_bounds is established), so I have to call it again, and then it updates location.

library(shiny)
library(bslib)
library(mapgl)

rhode_island = read_rds("data/rhode_island.rds")
cities<-c("Dallas","San Antonio","Houston","Puebla")

ui <- page_sidebar(
  title = "Coordinates Bug",
  sidebar = sidebar(
    width = 350,
    selectInput("city", "Select City",cities)
  ),
  card(
    full_screen = TRUE,
    card_header("Map"),
    mapboxglOutput("map")
  ),
)

server <- function(input, output, session) {

  output$map <- renderMapboxgl({
    mapboxgl() %>% fit_bounds(rhode_island) 
  })

  observeEvent(input$city, {
    if (input$city== "Dallas") {
      mapboxgl_proxy("map")%>% set_view(center=c ( -96.8025,32.78830),zoom=15) 
    } 

    if (input$city== "San Antonio") {
      mapboxgl_proxy("map")%>% set_view(center=c ( -98.48692,29.42575),zoom=15) 
    } 

    if (input$city== "Houston") {
      mapboxgl_proxy("map")%>% set_view(center=c (  -95.362995,29.74534),zoom=15) 
    } 

    if (input$city== "Puebla") {
      mapboxgl_proxy("map") %>% 
        set_style("mapbox://styles/enriquevaa/clz8t97i000bg01qm4f1j4y69")%>% set_view(center=c (-98.210728,19.0399585549),zoom=15) 
    } 

  })  

}

shinyApp(ui, server)
walkerke commented 1 month ago

You can get it to work by supplying bounds directly when you initialize the map rather than using fit_bounds():

library(shiny)
library(bslib)
library(mapgl)
library(tidyverse)

rhode_island = read_rds("data/rhode_island.rds")
cities<-c("Dallas","San Antonio","Houston","Puebla")

ui <- page_sidebar(
  title = "Coordinates Bug",
  sidebar = sidebar(
    width = 350,
    selectInput("city", "Select City",cities)
  ),
  card(
    full_screen = TRUE,
    card_header("Map"),
    mapboxglOutput("map")
  ),
)

server <- function(input, output, session) {

  output$map <- renderMapboxgl({
    mapboxgl(bounds = rhode_island) 
  })

  observeEvent(input$city, {
    if (input$city== "Dallas") {
      mapboxgl_proxy("map")%>% set_view(center=c ( -96.8025,32.78830),zoom=15) 
    } 

    if (input$city== "San Antonio") {
      mapboxgl_proxy("map")%>% set_view(center=c ( -98.48692,29.42575),zoom=15) 
    } 

    if (input$city== "Houston") {
      mapboxgl_proxy("map")%>% set_view(center=c (  -95.362995,29.74534),zoom=15) 
    } 

    if (input$city== "Puebla") {
      mapboxgl_proxy("map") %>% 
        set_style(mapbox_style("dark")) %>% set_view(center=c (-98.210728,19.0399585549),zoom=15) 
    } 

  })  

}

shinyApp(ui, server)

I think the issue you're experiencing has something to do with set_style(), which does some reconfiguration of the map the way it works. I'm not exactly sure why, but this workaround should work for the time being.