唯杰地图 logo唯杰地图
VJMAP
EN

icon-symbol

vjmap/references/symbol/icon-symbol.md 3.8 KB146 行
原文

本文回答:vjmap.Symbol 图标符号图层 —— iconImage / iconSize / iconOffset / 碰撞。

一、最小示例

await map.loadImageEx("pin", "/icons/pin.png");

const symbol = new vjmap.Symbol({
  data: map.toLngLat(features),
  iconImage: "pin",
  iconSize: 1,
  iconAnchor: "bottom",
  iconAllowOverlap: true
});
symbol.addTo(map);

二、核心参数(图标)

参数 默认 说明
iconImage — 图标名;需 sprite 或 loadImage
iconSize 1 缩放比例
iconRotate 0 旋转角(度)
iconAnchor "center" 9 向
iconOffset [0,0] 像素偏移
iconOpacity 1 透明度
iconColor — 只对 SDF 图标有效
iconHaloColor — 光晕色
iconHaloWidth 0 光晕宽度
iconAllowOverlap false 是否允许重叠
iconIgnorePlacement false 是否忽略位置冲突
iconRotationAlignment "auto" map / viewport
iconPitchAlignment "auto" map / viewport
iconPadding 2 碰撞的像素间距
iconTextFit "none" none / width / height / both
iconTextFitPadding [0,0,0,0] text-fit 的内边距

三、加载图标

// Promise 式(vjmap 扩展)
await map.loadImageEx("pin", "/icons/pin.png");
await map.loadImageEx("star", "data:image/svg+xml;base64,...");

// SDF(可改色)
map.loadImage("/icons/pin.png", (err, img) => {
  if (!err) map.addImage("pin-sdf", img, { sdf: true });
});

多图标批量:

const icons = { pin: "/a.png", star: "/b.png", dot: "/c.png" };
await Promise.all(Object.entries(icons).map(
  ([name, url]) => map.loadImageEx(name, url)
));

四、数据驱动图标

new vjmap.Symbol({
  data,
  iconImage: ["get", "icon"],                     // 按属性选图标
  iconSize: ["interpolate", ["linear"], ["zoom"], 10, 0.5, 16, 1.5],
  iconRotate: ["get", "bearing"]
});

五、旋转对齐 / 倾斜对齐

// 图标随地图旋转(道路指示最常用)
iconRotationAlignment: "map",
iconPitchAlignment: "map"

// 图标始终正对屏幕(默认)
iconRotationAlignment: "viewport",
iconPitchAlignment: "viewport"

六、碰撞与优先级

  • iconAllowOverlap: false:同层图标挤压时自动剔除;
  • iconAllowOverlap: true:全部显示;
  • symbolSortKey: ["get", "priority"]:小值优先显示。

七、图标 + 文字组合

new vjmap.Symbol({
  data,
  iconImage: "pin",
  iconAnchor: "bottom",
  textField: ["get", "name"],
  textFont: ["Arial Unicode MS Regular"],   // 官方示例用的 fontstack
  textSize: 12,
  textOffset: [0, 1],
  textAnchor: "top",
  textColor: "#000",
  textHaloColor: "#fff",
  textHaloWidth: 1
}).addTo(map);

八、可拉伸图标 icon-text-fit

让气泡图标自动适应文字宽度:

new vjmap.Symbol({
  data,
  iconImage: "bubble",
  iconTextFit: "both",
  iconTextFitPadding: [4, 8, 4, 8],   // top/right/bottom/left
  textField: ["get", "label"]
});

九、hover / click

symbol.clickLayer(e => alert(e.features[0].properties.name));
symbol.hoverPopup(f => `<b>${f.properties.name}</b>`);
symbol.hoverFeatureState();

十、更新

symbol.setData(newFc);
symbol.setIconImage(["get", "icon2"]);
symbol.setIconSize(1.5);
symbol.setProperty("iconOpacity", 0.5);

十一、常见坑

  1. 图标不显示 → sprite 里没这个名字;或 loadImage 还没完成。
  2. iconColor 无效 → 必须 SDF 图标。
  3. 挤压看不见 → iconAllowOverlap: true 硬显示。
  4. 图标在旋转地图后歪 → 要用 iconRotationAlignment: "viewport" 始终正对屏幕。
  5. 点击无响应 → hit-test 忽略了图标的边缘;扩 iconPadding。