mapgl icon indicating copy to clipboard operation
mapgl copied to clipboard

(Request) Catch and wrap vectors in "literal" within style helpers

Open mhpob opened this issue 2 months ago • 0 comments

Some expressions -- I know of match and step, at least, but possibly more -- can accept arrays if they are wrapped in ["literal", [...]]

https://docs.mapbox.com/style-spec/reference/expressions/#types-literal

Catching nested vectors supplied to the helper functions and wrapping them with list("literal", c()) could allow these functions to take a list of vectors as input. How it works currently:

match_expr(
          column = "column",
          values = c("a", "b"),
          # These *need* to be designated as "literal"
          stops = list(
            list("literal", c(0, -1)),
            list("literal", c(1, 0))
          ),
          default = list(list("literal", c(0, 0)))
   )

Idea would be to accept something more "R-native", along the lines of:

match_expr(
          column = "col",
          values = c("a", "b"),
          stops = list(c(0, -1), c(1, 0)),
          default = c(0, 0)
   )

Reproducible example in current context:

library(mapgl)
library(sf)
library(dplyr)
# Define the bounding box for Washington DC (approximately)
bbox <- st_bbox(
  c(
    xmin = -77.119759,
    ymin = 38.791645,
    xmax = -76.909393,
    ymax = 38.995548
  ),
  crs = st_crs(4326)
)

# Generate 30 random points within the bounding box
random_points <- st_as_sf(
  data.frame(
    id = 1:30,
    lon = runif(30, bbox["xmin"], bbox["xmax"]),
    lat = runif(30, bbox["ymin"], bbox["ymax"])
  ),
  coords = c("lon", "lat"),
  crs = 4326
)

icons <- c("music", "bar", "theatre", "bicycle")
random_points <- random_points |>
    mutate(icon = sample(icons, n(), replace = TRUE))

# Map with icons
mapboxgl(style = mapbox_style("light")) |>
    fit_bounds(random_points, animate = FALSE) |>
    add_symbol_layer(
        id = "points-of-interest",
        source = random_points,
        icon_image = c("get", "icons"),
        icon_allow_overlap = TRUE,
        text_field = get_column("icons"),
        text_anchor = "center",
        text_offset = match_expr(
          column = "icons",
          values = c("music", "bar", "theatre", "bicycle"),
          # These *need* to be designated as "literal"
          stops = list(
            list("literal", c(0, -1)),
            list("literal", c(1, 0)),
            list("literal", c(1, 1)),
            list("literal", c(-1, 0))
          ),
          default = list(list("literal", c(0, 0)))
     
   )
  )

mhpob avatar Oct 08 '25 14:10 mhpob