line
本文回答:
vjmap.Polyline线图元 —— 宽度 / 虚线 / 渐变 / 图案 / 动画。
一、最小示例
const polyline = new vjmap.Polyline({
data: map.toLngLat(featureCollection),
lineColor: "#f00",
lineWidth: 3,
isHoverPointer: true,
isHoverFeatureState: true
});
polyline.addTo(map);
二、核心参数(驼峰式)
| 参数 | 默认 | 说明 |
|---|---|---|
data |
— | GeoJSON LineString 或 FeatureCollection |
lineColor |
#000 |
线颜色 |
lineWidth |
1 | 线宽(像素) |
lineOpacity |
1 | 透明度 |
lineCap |
butt |
端点样式:butt / round / square |
lineJoin |
miter |
连接样式:bevel / round / miter |
lineMiterLimit |
2 | miter 阈值(d.ts 里的 lineMiterMimit 是拼写错误:该选项被静默忽略,polyline.setLineMiterMimit() 抛 TypeError;运行时改用 map.setLineMiterLimit(poly.getLayerId(), v)) |
lineRoundLimit |
1.05 | round 阈值 |
lineOffset |
0 | 平行偏移(像素) |
lineBlur |
0 | 模糊 |
lineDasharray |
— | 虚线数组 [实,虚,实,虚,...](单位 = 线宽倍数) |
linePattern |
— | 平铺图案(图像名) |
lineGradient |
— | 沿线渐变(需 source lineMetrics: true) |
lineTranslate |
[0,0] |
平移(像素) |
lineTranslateAnchor |
map |
map/viewport |
lineGapWidth |
0 | 平行双线间距 |
lineSortKey |
— | 同层排序 |
isHoverPointer |
false | hover 改 cursor |
isHoverFeatureState |
false | hover 自动 setFeatureState |
三、虚线
new vjmap.Polyline({
data,
lineColor: "#00f",
lineWidth: 2,
lineDasharray: [2, 4] // 2 倍线宽实线,4 倍线宽虚线
});
复杂虚线:
lineDasharray: [1, 2, 5, 2] // 实1 空2 实5 空2
四、渐变线(沿线颜色)
// 必须在 source 上加 lineMetrics
map.addSource("route", { type: "geojson", data: lineFeatures, lineMetrics: true });
const poly = new vjmap.Polyline({
sourceId: "route",
data: undefined,
lineWidth: 6,
lineGradient: [
"interpolate", ["linear"], ["line-progress"],
0, "#0f0",
0.5, "#ff0",
1, "#f00"
]
});
注:设了 lineGradient 时 lineColor 被忽略(两者可共存);lineGradient 与 linePattern 互斥,源必须 lineMetrics: true。
⚠️ 复用外部 sourceId 时,poly.remove() 会连源及该源上的所有图层一起删(内部 removeSourceEx);只删本层用 map.removeLayer(poly.getLayerId())。
五、线型图案(沿线平铺)
await map.loadImageEx("pattern", "/images/line-pattern.png");
new vjmap.Polyline({
data,
lineWidth: 20,
linePattern: "pattern"
});
六、粗细随 zoom
lineWidth: [
"interpolate", ["linear"], ["zoom"],
10, 1,
14, 3,
18, 8
]
七、按属性变色
lineColor: [
"match", ["get", "level"],
"main", "#f00",
"sub", "#0f0",
"#888"
]
八、平行双线(公路)
new vjmap.Polyline({ data, lineColor: "#000", lineWidth: 6 }).addTo(map); // 先加:底层黑色宽线
new vjmap.Polyline({ data, lineColor: "#fff", lineWidth: 2 }).addTo(map); // 后加:叠在上面的白色细线
后加的图层在上,所以先加黑线再加白线。lineGapWidth 不是"中间填色":它画的是两条 lineColor 色的边线、中间留透明空隙(单图层就能画空心双线)。
九、路径动画(流光 / 跑马灯)
方案 A:lineDasharray 动画
let offset = 0;
function animate() {
polyline.setLineDasharray([offset % 10, 4]);
offset += 0.1;
requestAnimationFrame(animate);
}
animate();
方案 B:用 symbol-placement: line 让图标沿线走(见 symbol/text-symbol)。
方案 C:createAnimateLineLayer 系列工厂一行创建动画图层:
const anim = vjmap.createAnimateLineLayer(map, path); // path = [[x,y],...]
anim.startAnimation();
anim.setSpeed(2); // 倍速
anim.stopAnimation();
anim.remove(); // source+layer 一起删
- 返回
ICreateAnimateLayerResult,键面:{sourceId, layerId, startAnimation, stopAnimation, remove, updateData, updateImages, setSpeed, polyline};createAntPathAnimateLineLayer(蚂蚁线)/createArrowAnimateLineLayer(箭头流)额外带createAnimateImages;createAnimateFillLayer返回polygon(非polyline)。 - 坑位:
createAnimateSymbolLayer(map, path)的 path 必须是点位数组[[x,y],…]——传裸坐标[x,y]抛Cannot use 'in' operator to search for 'points' in <number>(内部按数组迭代后对每个元素做'points' in item判定,数字元素直接崩)。 - 坑位:
createAnimateImages(options)的 options 实必填——需draw(ctx,w,h,opts)或drawFrame回调,无参调用抛Cannot read properties of undefined (reading 'draw');但createAntPathAnimateImages/createArrowAnimateImages可无参,各返 2 帧ImageData。
方案 D:animateVectorLayer——给已存在的线/面/符号层做帧图案轮播:
map.addGeoJSONSource("src", createLineGeoJson(path));
map.addLineLayer("lay", "src", { lineColor: "#f60", lineWidth: 6 });
const anim = vjmap.animateVectorLayer(map, "lay", {
animateImages: vjmap.createAntPathAnimateImages(), // 帧图集(ImageData[])
speed: 2, // 倍速
startAutoAnimation: true
}, /* layerType */ 0); // 0=line(line-pattern) 1=fill(fill-pattern) 2=symbol(icon-image)
anim.startAnimation(); anim.setSpeed(4); anim.stopAnimation();
anim.remove(); // 恢复原 pattern,不删图层
- 与方案 C 工厂不同:它不建层,第二参是已存在图层 id——层不在图上时内部
map.getPaintProperty(layerId,...)读getLayer→undefined直接抛Cannot read properties of undefined。返回{startAnimation, stopAnimation, remove, updateImages, setSpeed}(没有sourceId/layerId/updateData)。
十、修改 / 删除
polyline.setData(newFeatures);
polyline.setLineColor("#0af");
polyline.setLineWidth(5);
polyline.setLineDasharray([1, 2]);
polyline.setProperty("lineOpacity", 0.5);
polyline.hide();
polyline.show();
polyline.remove();
十一、事件
polyline.clickLayer(e => alert(e.features[0].properties.name));
polyline.hoverPopup(f => `<b>${f.properties.name}</b>`, { anchor: "bottom" });
polyline.hoverFeatureState();
十二、常见坑
- lineWidth 太细不显示 → < 0.5px 在高分屏可能消失;设 ≥ 1。
- lineGradient 无效 → source 未开
lineMetrics: true;或同时设了linePattern(lineColor 不影响,只是被忽略)。 - 虚线密度感觉不对 →
lineDasharray单位 = 线宽倍数,不是像素。 - hover 无效 → feature 没 id 或 id 为 0(
hoverFeatureState用if (featureId)判断,0 被忽略)。封装类不透传generateId(且 generateId 从 0 编号):FeatureCollection 须自带非 0id;或传[{points, properties}](自动id = 序号 + 1);或先自建源(promoteId)再传sourceId。 - 连线有毛刺 →
lineJoin: "round"+lineCap: "round"。