唯杰地图 logo唯杰地图
VJMAP
EN

style-spec

vjmap/references/map-style/style-spec.md 5.7 KB222 行
原文

本文回答: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 的字段)

九、常见坑

  1. source-layer 只在矢量瓦片里有,GeoJSON / Raster 不能填。
  2. Layer id 重复:addLayer 会报错;先 getLayer(id) 判断。
  3. Sprite 缺失图标 → icon-image 没显示;必须图标名在 sprite JSON 里。
  4. glyphs 缺失:带 text-field 的图层校验失败(use of "text-field" requires a style "glyphs" property),不是显示空方块;glyph PBF 404 则整个瓦片解析失败(该源该瓦片的所有图层都不出)。vjmap 默认用 svc.glyphsUrl();自定义时记得 glyphs: "https://.../{fontstack}/{range}.pbf" 完整 URL。