-
Notifications
You must be signed in to change notification settings - Fork 113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How do I make my arrowhead pointy? #114
Comments
I solved the problem myself. Hopeful this will be useful to someone else and perhaps even make it into the code: // the arrowhead is a triangle that comes to a fine point. We don't
// want the line of the arrow extending all the way to that point or
// it messes up the tip. The solution is to stop the line at the back
// of the arrowhead.
const backOfArrowHead = calcBackOfArrowHead(map, tail, tip, arrowHeadSize, arrowHeadAngle);
polyline = L.polyline([tail, backOfArrowHead], { color: 'blue' }).addTo(map);
// Add the arrowhead using Leaflet.PolylineDecorator
arrowHead = L.polylineDecorator([tail, tip], {
patterns: [
{
offset: "100%",
repeat: 0,
symbol: L.Symbol.arrowHead({ pixelSize:arrowHeadSize, pathOptions: { fillOpacity: 1, weight: 0, color: 'blue' } })
}
]
}).addTo(map); The calcBackOfArrowHead(map, tail, tip, arrowHeadSize, arrowHeadAngle) {
// Project LatLng points to pixel coordinates
var tailP = map.project(tail);
var tipP = map.project(tip);
// Calculate the vector from tail to tip in pixel coordinates
var vector = tipP.subtract(tailP);
// Normalize the vector to a unit vector (length 1)
var unitVector = vector.divideBy(vector.distanceTo([0, 0]));
// Calculate a new point some distance back from the tip
// The distance is the length of the adjacent side of a right triangle.
// This is the right half of the arrowhead, pointing up and scaled to the unit circle.
// We need the ratio d to help us find the bottom left corner, which is where
// the line of the arrow needs to stop drawing.
// |\
// |θ\
// | \ 1
// d | \
// | \
// |_____\
//
const halfArrowHeadAngleRadians = arrowHeadAngle / 2 * (Math.PI / 180); // θ
const arrowHeadRatio = arrowHeadSize * Math.cos(halfArrowHeadAngleRadians); // d
var newTipP = tipP.subtract(unitVector.multiplyBy(arrowHeadRatio));
// Unproject the new pixel point back to LatLng coordinates
var newTipLatLng = map.unproject(newTipP);
return newTipLatLng;
} |
Out of interest, another thing that can help with this problem is to change the linecap to butt, removing the rounded tip from the line. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I just want a simple triangular arrowhead that comes to a point, but when I try this:
It comes out looking like this:
Giving the arrowhead 50% opacity reveals what's happening. The line extends all the way to the tip:
Is there a way to make the line stop short so it doesn't mess up the point? I've tried calculating an artificial end point but got bogged down in conversions between pixels, degrees, and meters. This seems like it should be pretty basic, so I figure I must be missing something.
The text was updated successfully, but these errors were encountered: