线的箭头
这里我们来介绍下怎样实现线的箭头效果,这里主要介绍四种需求下的箭头的实现
VectorLayer的自带箭头
使用起来比较简单,配置LineString的arrowStyle
和arrowPlacement
即可,可以用来进行简单的箭头需求
注意箭头的颜色和线条的样式是一样的,不可独立的配置箭头的样式的
js
const layer = new maptalks.VectorLayer("layer").addTo(map);
const line = new maptalks.LineString(getFeatureCoordinates(0), {
arrowStyle: "classic",
arrowPlacement: "point", // 'vertex-last', //vertex-first, vertex-last, vertex-firstlast, point,
symbol: {
lineColor: "red",
},
}).addTo(layer);
LineStringLayer进行贴图
LineStringLayer 属于webgl图层,在包 maptalks-gl
里. 这个效果最好
WARNING
linePatternGap
这个参数只有webgl图层里支持,VectorLayer里不支持的
复杂的道路效果我们可以进行创建多个路线并配置不同的样式来实现
js
const lineLayer = new maptalks.LineStringLayer("line").addTo(groupLayer);
const line1 = new maptalks.LineString(getFeatureCoordinates(1), {
symbol: {
lineStrokeColor: [1, 1, 1],
lineStrokeWidth: 2,
lineWidth: 26,
lineColor: "#000",
},
}).addTo(lineLayer);
const line2 = new maptalks.LineString(
getFeatureCoordinates(1).map((c) => {
return [...c, 0.1];
}),
{
symbol: {
linePatternFile: "./../assets/image/arrow.png",
// linePatternDx: 0,
linePatternGap: 1,
// linePatternAnimSpeed: 0.1,
lineWidth: 24,
},
},
).addTo(lineLayer);
顶点箭头且可交互
有时我们不仅需要箭头,且箭头可以点击交互这样的需求,这时我们可以为每个顶点创建个Marker来实现
TIP
箭头的偏转角度计算用了 geolib 第三方库
js
const line3 = new maptalks.LineString(getFeatureCoordinates(2), {
symbol: {
lineWidth: 16,
lineColor: "black",
},
}).addTo(layer);
const vertexs = line3.getCoordinates();
for (let i = 0, len = vertexs.length; i < len; i++) {
let c = vertexs[i];
let c1 = vertexs[i],
c2 = vertexs[i + 1];
if (i === len - 1) {
c1 = vertexs[i - 1];
c2 = vertexs[i];
}
c1 = c1.toArray();
c2 = c2.toArray();
const rotationZ = getMarkerRotation(c1.slice(0, 2), c2.slice(0, 2));
const point = new maptalks.Marker(c, {
properties: {
rotationZ,
},
symbol: {
markerRotation: rotationZ,
markerVerticalAlignment: "middle",
markerFile: "./../assets/icon/arrow.png",
markerWidth: 20,
markerHeight: 20,
},
}).addTo(layer);
arrows.push(point);
}
updateArrowRotation();
WARNING
当地图旋转时我们需要更新Marker的 markerRotation
js
function updateArrowRotation() {
const bearing = map.getBearing();
arrows.forEach((arrow) => {
const rotationZ = arrow.getProperties().rotationZ;
arrow.updateSymbol({
markerRotation: rotationZ + bearing,
});
});
}
map.on("rotate", (e) => {
updateArrowRotation();
});
等距箭头且箭头可交互
在箭头可交互的基础上我们希望箭头分布是等距的,路径的切割我们使用了第三方库 lineseg
js
const line3 = new maptalks.LineString(getFeatureCoordinates(3), {
symbol: {
lineWidth: 16,
lineColor: "blue",
},
}).addTo(layer);
const vertexs = line3.getCoordinates();
const coordinates = vertexs.map((c) => {
return c.toArray();
});
const chunks = lineseg.lineSeg(coordinates, { segDistance: 100 });
function createMarker(c, c1, c2) {
const rotationZ = getMarkerRotation(c1.slice(0, 2), c2.slice(0, 2));
const point = new maptalks.Marker(c, {
properties: {
rotationZ,
},
symbol: {
markerRotation: rotationZ,
markerVerticalAlignment: "middle",
markerFile: "./../assets/icon/arrow.png",
markerWidth: 20,
markerHeight: 20,
},
}).addTo(layer);
arrows.push(point);
}
for (let i = 0, len = chunks.length; i < len; i++) {
const chunk = chunks[i];
const chunkLen = chunk.length;
let c = chunk[chunkLen - 1];
let c1 = chunk[chunkLen - 2],
c2 = chunk[chunkLen - 1];
createMarker(c, c1, c2);
if (i === 0) {
c = chunk[0];
c1 = c;
c2 = chunk[1];
createMarker(c, c1, c2);
}
}
扩展
这里简单介绍了几种的箭头的实现,其他的效果你可以根据这里提供的思路进行不断的组合来实现,这里只是提供一些 思路