admin管理员组文章数量:1206951
I'm currently using leaflet to draw a bunch of lines on a leaflet map using the canvas. However, I'm having issue draw arrows on the lines using canvas.
I have found items such as polyline decorator but it very very slow and I only want the arrows to be visible at specified zoom distance (>=13).
How would one do this using leaflet please? I don't have to have repeatable arrows but just a way to show poyline direction.
Thanks.
I'm currently using leaflet to draw a bunch of lines on a leaflet map using the canvas. However, I'm having issue draw arrows on the lines using canvas.
I have found items such as polyline decorator but it very very slow and I only want the arrows to be visible at specified zoom distance (>=13).
How would one do this using leaflet please? I don't have to have repeatable arrows but just a way to show poyline direction.
Thanks.
Share Improve this question asked Nov 14, 2018 at 19:16 LiamLiam 4931 gold badge5 silver badges32 bronze badges3 Answers
Reset to default 16I know this answer is a little too late but It works with a good performance and without any plugin.
You can change the icon(which currently is a triangle arrow(▶)) to any thing you want and its initial direction should be toward right(the zero degree angle).
You can also change the number of arrows to be shown(in this example it's 5)
CSS code :
.arrow-icon {
width: 14px;
height: 14px;
}
.arrow-icon > div {
margin-left: -1px;
margin-top: -3px;
transform-origin: center center;
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
}
And here is the Javascript code.The getArrows
function accepts array of coordinates of polyline(and optional parameter color and optional parameter number of arrows per line) and returns an array of markers(just copy and paste everything) :
function getArrows(arrLatlngs, color, arrowCount, mapObj) {
if (typeof arrLatlngs === undefined || arrLatlngs == null ||
(!arrLatlngs.length) || arrLatlngs.length < 2)
return [];
if (typeof arrowCount === 'undefined' || arrowCount == null)
arrowCount = 1;
if (typeof color === 'undefined' || color == null)
color = '';
else
color = 'color:' + color;
var result = [];
for (var i = 1; i < arrLatlngs.length; i++) {
var icon = L.divIcon({ className: 'arrow-icon', bgPos: [5, 5], html: '<div style="' + color + ';transform: rotate(' + getAngle(arrLatlngs[i - 1], arrLatlngs[i], -1).toString() + 'deg)">▶</div>' });
for (var c = 1; c <= arrowCount; c++) {
result.push(L.marker(myMidPoint(arrLatlngs[i], arrLatlngs[i - 1], (c / (arrowCount + 1)), mapObj), { icon: icon }));
}
}
return result;
}
function getAngle(latLng1, latlng2, coef) {
var dy = latlng2[0] - latLng1[0];
var dx = Math.cos(Math.PI / 180 * latLng1[0]) * (latlng2[1] - latLng1[1]);
var ang = ((Math.atan2(dy, dx) / Math.PI) * 180 * coef);
return (ang).toFixed(2);
}
function myMidPoint(latlng1, latlng2, per, mapObj) {
if (!mapObj)
throw new Error('map is not defined');
var halfDist, segDist, dist, p1, p2, ratio,
points = [];
p1 = mapObj.project(new L.latLng(latlng1));
p2 = mapObj.project(new L.latLng(latlng2));
halfDist = distanceTo(p1, p2) * per;
if (halfDist === 0)
return mapObj.unproject(p1);
dist = distanceTo(p1, p2);
if (dist > halfDist) {
ratio = (dist - halfDist) / dist;
var res = mapObj.unproject(new Point(p2.x - ratio * (p2.x - p1.x), p2.y - ratio * (p2.y - p1.y)));
return [res.lat, res.lng];
}
}
function distanceTo(p1, p2) {
var x = p2.x - p1.x,
y = p2.y - p1.y;
return Math.sqrt(x * x + y * y);
}
function toPoint(x, y, round) {
if (x instanceof Point) {
return x;
}
if (isArray(x)) {
return new Point(x[0], x[1]);
}
if (x === undefined || x === null) {
return x;
}
if (typeof x === 'object' && 'x' in x && 'y' in x) {
return new Point(x.x, x.y);
}
return new Point(x, y, round);
}
function Point(x, y, round) {
this.x = (round ? Math.round(x) : x);
this.y = (round ? Math.round(y) : y);
}
Then simply draw leaflet polyline(just works for array of latLng
coordinates not array of array of coordinates):
// array of coordinates
var mylatlngs = [
[55.555, 33.33],
[..., ...],
[..., ...],
[..., ...],
[..., ...],
...
];
var polyline = L.polyline(mylatlngs, { color: 'red' }).addTo(map);
// draw 5 arrows per line
L.featureGroup(getArrows(mylatlngs, 'red', 5,map)).addTo(map);
In PolylineDecorator main page exists link to Leaflet.TextPath, as a lightweight alternative. I assume it is similar with "getArrows" function implementation, that have been proposed early.
nAviD's answer (13) works for me, but the "▶" should be replaced with the decoded character [1]: https://i.sstatic.net/YjnbWU6x.png
本文标签: javascriptLeaflet Polyline ArrowsStack Overflow
版权声明:本文标题:javascript - Leaflet Polyline Arrows - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738721293a2108762.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论