You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在tmap中使用动物剪影图标:解决PNG背景透明与报错问题

在tmap中添加透明背景动物剪影图标的解决方案

问题背景

想在tmap里用动物剪影当图标,但把SVG转成tmap要求的PNG时,要么带白色背景,要么触发a raster array must have exactly 3 or 4 planes报错。测试发现非0透明度背景设置有效,但alpha=0时完全失效。


原始问题代码

可运行但带白色背景的代码

library(tmap)
library(sf)
library(magick)
library(tidyverse)

nc <- st_read(system.file("shape/nc.shp", package="sf")) %>% 
  mutate(ICON="SQUIRREL") 

SQUIRREL <- image_read_svg("https://images.phylopic.org/images/2916f8fe-290a-423b-b6f7-fb975c30d518/vector.svg")
image_write(SQUIRREL,"SQUIRREL.png", flatten = T, density = 90 )

SQUIRREL_ICON <- tmap_icons("SQUIRREL.png")

tm_shape(nc)+
  tm_polygons()+
  tm_symbols(shapes = SQUIRREL_ICON, shape="ICON")

尝试透明背景的失败代码

# 尝试设置透明背景(触发报错)
SQUIRREL_OUTLINE1 <- SQUIRREL %>%
  image_background(color=rgb(0, 0, 0, 0), flatten = T)

image_write(SQUIRREL_OUTLINE1,"SQUIRREL_OUTLINE1.png", flatten = T, density = 90)
SQUIRREL_ICON_OUTLINE1 <- tmap_icons("SQUIRREL_OUTLINE1.png")

tm_shape(nc)+
  tm_polygons()+
  tm_symbols(shapes = SQUIRREL_ICON_OUTLINE1, shape="ICON")

# 尝试裁剪空白区域(背景仍存在)
SQUIRREL_OUTLINE2 <- SQUIRREL %>%
  image_trim()

image_write(SQUIRREL_OUTLINE2,"SQUIRREL_OUTLINE2.png", flatten = T, density = 90)
SQUIRREL_ICON_OUTLINE2 <- tmap_icons("SQUIRREL_OUTLINE2.png")

tm_shape(nc)+
  tm_polygons()+
  tm_symbols(shapes = SQUIRREL_ICON_OUTLINE2, shape="ICON")

透明度测试代码

# 红色不透明背景(有效)
SQUIRREL_OUTLINE_RED <- SQUIRREL %>%
  image_background(color="red", flatten = T)

image_write(SQUIRREL_OUTLINE_RED,"SQUIRREL_OUTLINE_RED.png", flatten = T, density = 90)
SQUIRREL_ICON_OUTLINE_RED <- tmap_icons("SQUIRREL_OUTLINE_RED.png")

tm_shape(nc)+
  tm_polygons()+
  tm_symbols(shapes = SQUIRREL_ICON_OUTLINE_RED, shape="ICON")

# 红色半透明背景(有效)
SQUIRREL_OUTLINE_RED_RGB05 <- SQUIRREL %>%
  image_background(color=rgb(1, 0, 0, 0.5), flatten = T)

image_write(SQUIRREL_OUTLINE_RED_RGB05,"SQUIRREL_OUTLINE_RED_RGB05.png", flatten = T, density = 90)
SQUIRREL_ICON_OUTLINE_RED_RGB05 <- tmap_icons("SQUIRREL_OUTLINE_RED_RGB05.png")

tm_shape(nc)+
  tm_polygons()+
  tm_symbols(shapes = SQUIRREL_ICON_OUTLINE_RED_RGB05, shape="ICON")

# 红色完全透明背景(失效)
SQUIRREL_OUTLINE_RED_RGB00 <- SQUIRREL %>%
  image_background(color=rgb(1, 0, 0, 0), flatten = T)

image_write(SQUIRREL_OUTLINE_RED_RGB00,"SQUIRREL_OUTLINE_RED_RGB00.png", flatten = T, density = 90)
SQUIRREL_ICON_OUTLINE_RED_RGB00 <- tmap_icons("SQUIRREL_OUTLINE_RED_RGB00.png")

tm_shape(nc)+
  tm_polygons()+
  tm_symbols(shapes = SQUIRREL_ICON_OUTLINE_RED_RGB00, shape="ICON")

解决方法

问题核心是flatten = T参数会移除PNG的alpha通道,导致tmap无法识别透明背景。修改步骤如下:

  1. 读取SVG时不要提前flatten,保留图层和alpha通道信息
  2. 导出PNG时去掉flatten = T,确保导出的是4通道(RGBA)的PNG
  3. 若SVG本身带纯色背景,用image_transparent将背景色转为透明

修改后的完整代码

library(tmap)
library(sf)
library(magick)
library(tidyverse)

nc <- st_read(system.file("shape/nc.shp", package="sf")) %>% 
  mutate(ICON="SQUIRREL") 

# 读取SVG,不进行flatten操作
SQUIRREL <- image_read_svg("https://images.phylopic.org/images/2916f8fe-290a-423b-b6f7-fb975c30d518/vector.svg")

# 若SVG有白色背景,将白色转为透明(可根据实际背景色调整)
SQUIRREL_TRANSPARENT <- SQUIRREL %>%
  image_transparent(color = "white")

# 导出PNG,去掉flatten=T,保留alpha通道
image_write(SQUIRREL_TRANSPARENT, "SQUIRREL_TRANSPARENT.png", density = 90)

# 读取为tmap图标
SQUIRREL_ICON <- tmap_icons("SQUIRREL_TRANSPARENT.png")

# 绘制地图
tm_shape(nc)+
  tm_polygons()+
  tm_symbols(shapes = SQUIRREL_ICON, shape="ICON")

简化版(SVG本身无背景时)

如果使用的SVG本身没有背景(比如示例中的phylopic剪影),可以直接导出:

SQUIRREL <- image_read_svg("https://images.phylopic.org/images/2916f8fe-290a-423b-b6f7-fb975c30d518/vector.svg")
image_write(SQUIRREL, "SQUIRREL_TRANSPARENT.png", density = 90) # 去掉flatten=T

关键说明

  • flatten=T会合并所有图层并丢弃alpha通道,当背景完全透明时,图像会变成3通道RGB格式,触发tmap的数组维度报错
  • image_transparent用于将指定纯色转为透明,适合处理自带背景的SVG
  • PNG格式默认支持alpha通道,导出时不加flatten=T就能让tmap正确识别透明背景

内容的提问来源于stack exchange,提问作者BEVAN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 19:17:31