@@ -182,6 +182,18 @@ lty2dash <- function(lty) {
182182 }
183183}
184184
185+ # ============================================================
186+ # Source id helper
187+ # ============================================================
188+
189+ # Source ids must be unique per render. clear_layer() (used by tm_remove_layer
190+ # in proxy mode) removes *layers* but not their *sources*, so reusing a source
191+ # id on a redraw collides with the still-present stale source: MapLibre keeps
192+ # the old data and the re-added layers recolour from it. .TMAP$stamp is bumped
193+ # by print.tmap() on every render, giving a fresh source id each time. Layer
194+ # ids stay stable (glid-based) so the tm_remove_layer registry keeps matching.
195+ mapgl_srcid <- function (base ) sprintf(" %s_%.0f" , base , .TMAP $ stamp * 1e6 )
196+
185197# ============================================================
186198# mapgl_polygons
187199# ============================================================
@@ -191,9 +203,6 @@ mapgl_polygons <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
191203 id , pane , group , glid , o , ... , mode ) {
192204
193205 m <- get_mapgl(facet_row , facet_col , facet_page , mode )
194- message(" == mapgl_polygons: class(m) = " , paste(class(m ), collapse = " , " ),
195- " | pane = " , pane )
196-
197206 rc_text <- frc(facet_row , facet_col )
198207 shp_is_pointer <- inherits(shpTM $ shp , " character" )
199208
@@ -204,7 +213,7 @@ mapgl_polygons <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
204213 if (pmtiles_unsupported(shpTM , mode )) return (NULL )
205214
206215 smeta <- shpTM $ smeta
207- srcname <- paste0(" layer" , pane , " _ " , .TMAP $ stamp )
216+ srcname <- mapgl_srcid( paste0(" layer" , pane ) )
208217 layername1 <- paste0(glid , " polygons_fill" )
209218 layername2 <- paste0(glid , " polygons_border" )
210219 url <- smeta $ url
@@ -222,12 +231,12 @@ mapgl_polygons <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
222231 # so there is no row-level join available at render time.
223232
224233 m | >
225- mapgl :: add_pmtiles_source(id = glid , url = url ) | >
226- mapgl :: add_fill_layer(layername1 , source = glid ,
234+ mapgl :: add_pmtiles_source(id = srcname , url = url ) | >
235+ mapgl :: add_fill_layer(layername1 , source = srcname ,
227236 source_layer = smeta $ layer ,
228237 fill_color = aes_f ,
229238 fill_opacity = aes_fo ) | >
230- mapgl :: add_line_layer(layername2 , source = glid ,
239+ mapgl :: add_line_layer(layername2 , source = srcname ,
231240 source_layer = smeta $ layer ,
232241 line_color = aes_c ,
233242 line_opacity = aes_co ,
@@ -290,7 +299,7 @@ mapgl_polygons <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
290299 ahp <- attach_hover_popup(shp2 , dt , hdt , pdt , idt , popup.format )
291300 shp2 <- ahp $ shp2
292301
293- srcname <- paste0(" layer" , pane , " _ " , .TMAP $ stamp )
302+ srcname <- mapgl_srcid( paste0(" layer" , pane ) )
294303 layername1 <- paste0(glid , " polygons_fill" )
295304 layername2 <- paste0(glid , " polygons_border" )
296305
@@ -329,7 +338,7 @@ mapgl_polygons_3d <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
329338 if (pmtiles_unsupported(shpTM , mode )) return (NULL )
330339
331340 smeta <- shpTM $ smeta
332- srcname <- paste0(" layer" , pane )
341+ srcname <- mapgl_srcid( paste0(" layer" , pane ) )
333342 layername1 <- paste0(glid , " polygons_fill" )
334343 layername2 <- paste0(glid , " polygons_border" )
335344 url <- smeta $ url
@@ -416,13 +425,13 @@ mapgl_polygons_3d <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
416425 )
417426
418427 m | >
419- mapgl :: add_pmtiles_source(id = glid , url = url ) | >
420- mapgl :: add_line_layer(layername2 , source = glid ,
428+ mapgl :: add_pmtiles_source(id = srcname , url = url ) | >
429+ mapgl :: add_line_layer(layername2 , source = srcname ,
421430 source_layer = smeta $ layer ,
422431 line_color = aes_c ,
423432 line_opacity = aes_co ,
424433 line_width = aes_lwd ) | >
425- mapgl :: add_fill_extrusion_layer(layername1 , source = glid ,
434+ mapgl :: add_fill_extrusion_layer(layername1 , source = srcname ,
426435 source_layer = smeta $ layer ,
427436 fill_extrusion_color = aes_f ,
428437 fill_extrusion_base = 0 ,
@@ -463,12 +472,23 @@ mapgl_polygons_3d <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
463472 geometry = shp
464473 )
465474
475+ # NOTE on transparency: fill-extrusion layers do NOT support per-feature alpha.
476+ # The GL spec ignores the alpha channel of fill-extrusion-color (and a long-
477+ # standing engine bug renders alpha=0 as solid black), and fill-extrusion-opacity
478+ # is per-LAYER only, not data-driven. So we honour transparency as a single
479+ # layer-wide opacity, taken as the mean of the per-feature fill_alpha values.
480+ fill_ext_opacity <- {
481+ fa <- suppressWarnings(as.numeric(shp2 $ fill_alpha ))
482+ fa <- fa [is.finite(fa )]
483+ if (! length(fa )) 1 else min(max(mean(fa ), 0 ), 1 )
484+ }
485+
466486 ahp <- attach_hover_popup(shp2 , dt , hdt , pdt , idt , popup.format )
467487 shp2 <- ahp $ shp2
468488
469- srcname <- paste0(" layer" , pane )
470- layername1 <- paste0(srcname , " polygons_fill" )
471- layername2 <- paste0(srcname , " polygons_border" )
489+ srcname <- mapgl_srcid( paste0(" layer" , pane ) )
490+ layername1 <- paste0(glid , " polygons_fill" )
491+ layername2 <- paste0(glid , " polygons_border" )
472492
473493 if (is.character(a $ height.max )) {
474494 is_perc_max <- grepl(" %$" , a $ height.max )
@@ -513,11 +533,12 @@ mapgl_polygons_3d <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
513533 line_opacity = mapgl :: get_column(" col_alpha" ),
514534 line_width = mapgl :: get_column(" lwd" )) | >
515535 mapgl :: add_fill_extrusion_layer(layername1 , source = srcname ,
516- fill_extrusion_color = mapgl :: get_column(" fill" ),
517- fill_extrusion_base = 0 ,
518- fill_extrusion_height = mapgl :: get_column(" height" ),
519- tooltip = ahp $ hdt_arg ,
520- popup = ahp $ pdt_arg ) | >
536+ fill_extrusion_color = mapgl :: get_column(" fill" ),
537+ fill_extrusion_opacity = fill_ext_opacity ,
538+ fill_extrusion_base = 0 ,
539+ fill_extrusion_height = mapgl :: get_column(" height" ),
540+ tooltip = ahp $ hdt_arg ,
541+ popup = ahp $ pdt_arg ) | >
521542 assign_mapgl(facet_row , facet_col , facet_page , mode = mode )
522543
523544 mapgl_submit_group(group , c(layername1 , layername2 ), mode , pane )
@@ -539,16 +560,16 @@ mapgl_lines <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
539560 if (shp_is_pointer ) {
540561 if (pmtiles_unsupported(shpTM , mode )) return (NULL )
541562 smeta <- shpTM $ smeta
542- srcname <- paste0(" layer" , pane )
563+ srcname <- mapgl_srcid( paste0(" layer" , pane ) )
543564 layername1 <- paste0(glid , " lines" )
544565 url <- smeta $ url
545566 get_pmt_aes <- make_get_pmt_aes(dt )
546567 aes_c <- get_pmt_aes(" col" )
547568 aes_co <- get_pmt_aes(" col_alpha" )
548569 aes_lwd <- get_pmt_aes(" lwd" )
549570 m | >
550- mapgl :: add_pmtiles_source(id = glid , url = url ) | >
551- mapgl :: add_line_layer(layername1 , source = glid ,
571+ mapgl :: add_pmtiles_source(id = srcname , url = url ) | >
572+ mapgl :: add_line_layer(layername1 , source = srcname ,
552573 source_layer = smeta $ layer ,
553574 line_color = aes_c ,
554575 line_opacity = aes_co ,
@@ -594,7 +615,7 @@ mapgl_lines <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
594615
595616 ahp <- attach_hover_popup(shp2 , dt , hdt , pdt , idt , popup.format )
596617 shp2 <- ahp $ shp2
597- srcname <- paste0(" layer" , pane , " _ " , .TMAP $ stamp )
618+ srcname <- mapgl_srcid( paste0(" layer" , pane ) )
598619 layername1 <- paste0(glid , " lines" ) # was paste0(srcname, "lines") — fixed to match legend
599620
600621 m | >
@@ -629,7 +650,7 @@ mapgl_symbols <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
629650 if (pmtiles_unsupported(shpTM , mode )) return (NULL )
630651
631652 smeta <- shpTM $ smeta
632- srcname <- paste0(" layer" , pane , " _ " , .TMAP $ stamp )
653+ srcname <- mapgl_srcid( paste0(" layer" , pane ) )
633654 layername1 <- paste0(glid , " symbols_fill" )
634655 url <- smeta $ url
635656
@@ -646,8 +667,8 @@ mapgl_symbols <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
646667 if (is.numeric(aes_size )) aes_size <- aes_size * 10
647668
648669 m | >
649- mapgl :: add_pmtiles_source(id = glid , url = url ) | >
650- mapgl :: add_circle_layer(layername1 , source = glid ,
670+ mapgl :: add_pmtiles_source(id = srcname , url = url ) | >
671+ mapgl :: add_circle_layer(layername1 , source = srcname ,
651672 source_layer = smeta $ layer ,
652673 circle_color = aes_f ,
653674 circle_opacity = aes_fo ,
@@ -714,7 +735,7 @@ mapgl_symbols <- function(a, shpTM, dt, pdt, popup.format, hdt, idt, gp,
714735
715736 ahp <- attach_hover_popup(shp2 , dt , hdt , pdt , idt , popup.format )
716737 shp2 <- ahp $ shp2
717- srcname <- paste0(" layer" , pane , " _ " , .TMAP $ stamp )
738+ srcname <- mapgl_srcid( paste0(" layer" , pane ) )
718739 layername1 <- paste0(glid , " symbols_fill" ) # was paste0(srcname, ...) — fixed
719740
720741 m | >
@@ -751,15 +772,15 @@ mapgl_raster <- function(a, shpTM, dt, gp, pdt, popup.format, hdt, idt,
751772 if (pmtiles_unsupported(shpTM , mode )) return (NULL )
752773
753774 smeta <- shpTM $ smeta
754- srcname <- paste0(" layer" , pane , " _ " , .TMAP $ stamp )
755- layername1 <- paste0(srcname , " raster" )
775+ srcname <- mapgl_srcid( paste0(" layer" , pane ) )
776+ layername1 <- paste0(glid , " raster" )
756777 url <- smeta $ url
757778
758779 m <- get_mapgl(facet_row , facet_col , facet_page , mode = mode )
759780
760781 m | >
761- mapgl :: add_pmtiles_source(id = glid , url = url , source_type = " raster" ) | >
762- mapgl :: add_raster_layer(layername1 , source = glid ) | >
782+ mapgl :: add_pmtiles_source(id = srcname , url = url , source_type = " raster" ) | >
783+ mapgl :: add_raster_layer(layername1 , source = srcname ) | >
763784 assign_mapgl(facet_row , facet_col , facet_page , mode = mode )
764785
765786 return (NULL )
@@ -795,8 +816,8 @@ mapgl_raster <- function(a, shpTM, dt, gp, pdt, popup.format, hdt, idt,
795816 if (ext $ ymax > 89.9 ) ext $ ymax <- 89
796817 rst2 <- terra :: crop(rst , ext )
797818
798- srcname <- paste0(" layer" , pane , " _ " , .TMAP $ stamp )
799- layername1 <- paste0(srcname , " raster" )
819+ srcname <- mapgl_srcid( paste0(" layer" , pane ) )
820+ layername1 <- paste0(glid , " raster" )
800821
801822 m <- get_mapgl(facet_row , facet_col , facet_page , mode = mode )
802823
0 commit comments