style-spec
本文回答:vjmap 样式规范基础 —— version / name / sources / layers / glyphs / sprite。
一、根结构
{
version: 8, // 必须 8
name: "my-style",
metadata: { ... }, // 任意
center: [lng, lat], // 默认中心
zoom: 10,
bearing: 0,
pitch: 0,
glyphs: "https://.../{fontstack}/{range}.pbf",
sprite: "https://.../sprite",
light: { anchor: "viewport", color: "#fff", intensity: 0.5, position: [1.15, 210, 30] },
transition: { duration: 300, delay: 0 },
sources: { /* ... */ },
layers: [ /* ... */ ]
}
二、sources
Raster(互联网瓦片 / CAD 栅格)
"cad-raster": {
type: "raster",
tiles: ["https://vjmap.com/server/api/v1/raster/xxx/{z}/{x}/{y}.png"],
tileSize: 256, // vjmap CAD 栅格(svc.rasterStyle)与多数互联网瓦片都是 256;不写默认按 512
minzoom: 0, maxzoom: 22
}
Vector(矢量瓦片)
"cad-vec": {
type: "vector",
tiles: ["https://vjmap.com/server/api/v1/mvt/xxx/{z}/{x}/{y}.pbf"]
// 或 url: "https://xxx/tilejson.json"
}
// 使用时必须指定 source-layer
{ id: "roads", type: "line", source: "cad-vec", "source-layer": "roads" }
GeoJSON
"markers": {
type: "geojson",
data: { type: "FeatureCollection", features: [...] },
// 或 data: "https://xxx.geojson"
cluster: true,
clusterRadius: 50,
clusterMaxZoom: 14,
clusterProperties: { sum: ["+", ["get", "weight"]] }
}
Image / Video / Canvas
"radar": {
type: "image",
url: "https://xxx/radar.png",
coordinates: [[lng,lat], [lng,lat], [lng,lat], [lng,lat]]
}
Raster-DEM(地形)
"dem": { type: "raster-dem", tiles: ["https://.../{z}/{x}/{y}.png"] } // encoding 省略 = "vjmaps"(即 Terrain-RGB 公式);Terrarium 编码写 encoding: "terrarium"
⚠️ 发布版的 encoding 枚举只有 "vjmaps"(默认)/ "terrarium"——写其他值(如 "terrain-rgb")校验不过(is not a valid encoding type)。
WMS / WMTS / WFS / TMS
WMS:
"wms": {
type: "raster",
tiles: ["https://xxx?bbox={bbox-epsg-3857}&srs=EPSG:3857&..."]
}
WMTS:
"wmts": {
type: "raster",
tiles: ["https://xxx?REQUEST=GetTile&...&TILEMATRIX={z}&TILECOL={x}&TILEROW={y}"]
}
TMS:
"tms": {
type: "raster",
tiles: ["https://xxx/{z}/{x}/{y}.png"],
scheme: "tms" // y 轴翻转
}
WFS(直接当 geojson):
"wfs": {
type: "geojson",
data: "https://xxx?service=WFS&request=GetFeature&outputFormat=application/json&..."
}
三、layers
通用字段:
{
id: string, // 唯一
type: "background" | "fill" | "line" | "symbol"
| "raster" | "circle" | "fill-extrusion"
| "heatmap" | "hillshade" | "sky",
source?: string, // 除 background / sky 外必填
"source-layer"?: string, // vector 必须
minzoom?: number, // 0~24 的任意数(可带小数)
maxzoom?: number,
filter?: Expression,
layout?: {...},
paint?: {...},
metadata?: any
}
四、layer / paint / layout 动态修改
// 添加
map.addLayer({ id: "x", type: "circle", source: "markers", paint: { "circle-radius": 5 } });
// 修改
map.setPaintProperty("x", "circle-color", "#f00");
map.setLayoutProperty("x", "visibility", "none");
// 过滤
map.setFilter("x", ["==", ["get", "type"], "building"]);
// 移除
map.removeLayer("x");
map.removeSource("markers");
五、glyphs / sprite
glyphs: svc.glyphsUrl(), // vjmap 内置的 URL 模板
sprite: svc.spriteUrl("mysprite") // {服务地址}sprite/{name}
- glyphs:文字字体(每 256 个字符一张 PBF)。
- sprite:图标精灵图(PNG + JSON)。
添加单张图片:
map.loadImage("https://xxx.png", (err, img) => {
if (!err) map.addImage("my-icon", img);
});
// layer 里用
{ id: "poi", type: "symbol", source: "markers", layout: { "icon-image": "my-icon" } }
六、light(3D 光照)
map.setLight({
anchor: "viewport", // 或 "map"
color: "#ffffff",
intensity: 0.5,
position: [1.15, 210, 30]
});
影响 fill-extrusion 图层的阴影。
七、transition(动画)
paint 属性变化的过渡时长在 style 根级 transition 字段配置:
{
version: 8,
transition: { duration: 300, delay: 0 },
...
}
注意 setPaintProperty(layer, name, value, options) 的第 4 参是 { validate?: boolean }(是否做样式校验),不是 transition options。运行时改 paint 会按 transition 过渡(默认 300ms,颜色 / 透明度等可插值属性会渐变);要立即生效,先把该属性的过渡设为 0:map.setPaintProperty(id, name + "-transition", { duration: 0 })(如 fill-color 对应 fill-color-transition),或在样式根级 transition: { duration: 0 }。
八、查询和导出
const style = map.getStyle(); // 完整样式
const layers = style.layers;
const sources = style.sources;
map.setStyle(newStyle); // 整个替换
map.setStyle(newStyle, { diff: true }); // 差量更新(diff 是第 2 参 options 的字段,不是 style 的字段)
九、常见坑
source-layer只在矢量瓦片里有,GeoJSON / Raster 不能填。- Layer id 重复:addLayer 会报错;先
getLayer(id)判断。 - Sprite 缺失图标 → icon-image 没显示;必须图标名在 sprite JSON 里。
glyphs缺失:带text-field的图层校验失败(use of "text-field" requires a style "glyphs" property),不是显示空方块;glyph PBF 404 则整个瓦片解析失败(该源该瓦片的所有图层都不出)。vjmap 默认用svc.glyphsUrl();自定义时记得glyphs: "https://.../{fontstack}/{range}.pbf"完整 URL。