样式里的 sprite 拿不到,图标全是方块
换成自建样式后,道路编号、机场、地铁站图标全变成空白方块,地图其余部分完全正常。
现象
地图主体渲染正常,符号图层的图标全部缺失或显示为占位方块。 网络面板里能看到三条请求,全部 404:
GET /sprites/sprite.json 404 (Not Found)
GET /sprites/sprite.png 404 (Not Found)
GET /sprites/sprite@2x.json 404 (Not Found)
控制台提示:
Error: Could not load sprite at /sprites/sprite.json
原因
MapLibre 的 sprite 字段只是一个前缀。运行时会自动拼出
sprite.json、sprite.png、sprite@2x.json、
sprite@2x.png 最多四个文件。常见错误有三种:
- 在
sprite里写成了/sprites/sprite.json,拼接后变成sprite.json.json。 - 只放了
sprite.json与sprite.png,没放@2x版本,高分屏设备加载失败。 - 样式是相对路径,而 style.json 放在
/styles/basic/下,实际请求跑到了/styles/basic/sprites/...。
排查过程
直接读样式里的字段,并手动拼出四个地址逐个访问:
console.log('sprite 配置', map.getStyle().sprite);
fetch('/sprites/sprite.json').then(function (r) { console.log('json', r.status); });
fetch('/sprites/sprite@2x.json').then(function (r) { console.log('2x json', r.status); });
sprite.json 里应包含每个图标的 x、y、
width、height、pixelRatio 字段。
缺少这些字段说明 sprite 生成工具有问题。
解决方案
样式里只写前缀,不带扩展名,并确认四个文件都在同一目录:
{
"version": 8,
"sprite": "/sprites/sprite",
"glyphs": "/fonts/{fontstack}/{range}.pbf",
"sources": {},
"layers": []
}
只有一套 1 倍图时,让 @2x 请求也能命中,用服务端重写或直接补齐文件:
# Nginx:@2x 缺失时回退到 1 倍图,避免整块 sprite 加载失败
location /sprites/ {
try_files $uri $uri @sprite_fallback;
add_header Cache-Control "public, max-age=604800";
}
location @sprite_fallback {
rewrite ^/sprites/sprite@2x\.(json|png)$ /sprites/sprite.$1 last;
}
自建图标较多时,用工具生成 sprite,而不是手写 JSON。
spritezero 一次生成四个文件:
spritezero sprite ./icons/
spritezero sprite@2x ./icons/ --ratio 2
少量图标不必走 sprite,用 addImage 逐个注册即可,
但要在图层创建之前完成:
map.loadImage('/icons/metro.png').then(function (img) {
map.addImage('metro', img.data, { pixelRatio: 2 });
map.addLayer({
id: 'metro',
type: 'symbol',
source: 'metro-points',
layout: { 'icon-image': 'metro', 'icon-size': 0.7 }
});
});
验证
四个 sprite 地址都返回 200,map.getStyle().sprite 与配置一致。
地图上的道路编号、POI 图标全部显示,不再是方块。
切到 2 倍像素比,图标仍然清晰。
只写前缀:"sprite": "/sprites/sprite.json" 是最常见的错误。
写前缀、不写扩展名,四个文件由 MapLibre 自己拼。
经纬志(2026)。《样式里的 sprite 拿不到,图标全是方块》。https://www.jingweizhi.com/cookbook/maplibre-sprite-missing.html(访问日期 2026-11-03)。