经纬志
首页 / 实战手册 / MapLibre 样式与图层

样式里的 sprite 拿不到,图标全是方块

先看结论

换成自建样式后,道路编号、机场、地铁站图标全变成空白方块,地图其余部分完全正常。

最后验证 2026-11-03 · 多技术栈 · 更新 2026-10-29 · 引用本文

现象

地图主体渲染正常,符号图层的图标全部缺失或显示为占位方块。 网络面板里能看到三条请求,全部 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)。