Skip to content

Instantly share code, notes, and snippets.

@jwir3
Created May 18, 2017 15:18
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jwir3/d797037d2e1bf78a9b04838d73436197 to your computer and use it in GitHub Desktop.
Save jwir3/d797037d2e1bf78a9b04838d73436197 to your computer and use it in GitHub Desktop.
Code to create an arrowhead on an html5 canvas
/**
* Draw an arrowhead on a line on an HTML5 canvas.
*
* Based almost entirely off of http://stackoverflow.com/a/36805543/281460 with some modifications
* for readability and ease of use.
*
* @param context The drawing context on which to put the arrowhead.
* @param from A point, specified as an object with 'x' and 'y' properties, where the arrow starts
* (not the arrowhead, the arrow itself).
* @param to A point, specified as an object with 'x' and 'y' properties, where the arrow ends
* (not the arrowhead, the arrow itself).
* @param radius The radius of the arrowhead. This controls how "thick" the arrowhead looks.
*/
function drawArrowhead(context, from, to, radius) {
var x_center = to.x;
var y_center = to.y;
var angle;
var x;
var y;
context.beginPath();
angle = Math.atan2(to.y - from.y, to.x - from.x)
x = radius * Math.cos(angle) + x_center;
y = radius * Math.sin(angle) + y_center;
context.moveTo(x, y);
angle += (1.0/3.0) * (2 * Math.PI)
x = radius * Math.cos(angle) + x_center;
y = radius * Math.sin(angle) + y_center;
context.lineTo(x, y);
angle += (1.0/3.0) * (2 * Math.PI)
x = radius *Math.cos(angle) + x_center;
y = radius *Math.sin(angle) + y_center;
context.lineTo(x, y);
context.closePath();
context.fill();
}
@VladGavriuk
Copy link

Thank you!

@tsowemoo
Copy link

Thanks so much

@DavidFan-ai
Copy link

Thank you!

@iabhishekraj
Copy link

Great way to draw arrow. If my from is (100,100) and to is (450, 100) then arrow head is just more than 450. So, How to find the arrow head point?

@jwir3
Copy link
Author

jwir3 commented May 9, 2020

@codingbyraj It's been a little while since I've looked at this code, so I'll have to take a look for you. I'll see if I can check it out and answer your question this week.

@iabhishekraj
Copy link

Thank you @jwir3. I am trying too and will wait for your response.

@JohnChernoff
Copy link

yay

@Petya533665
Copy link

Petya533665 commented Jun 1, 2022

                const headSize = arrow.attrs.strokeWidth * 3;
		if (arrowAtStart) {
			const angle = Math.atan2(y2 - y1, x2 - x1);
			let delta = Math.PI / 6;
			for (let i = 0; i < 2; i++) {
				doc.moveTo(x1, y1);
				const x = x1 + headSize * Math.cos(angle + delta);
				const y = y1 + headSize * Math.sin(angle + delta);
				doc.lineTo(x, y);
				delta *= -1;
			}
		}

		if (arrowAtEnding) {
			let delta = Math.PI / 6;
			const angle = Math.atan2(y1 - y2, x1 - x2);
			for (let i = 0; i < 2; i++) {
				doc.moveTo(x2, y2);
				const x = x2 + headSize * Math.cos(angle + delta);
				const y = y2 + headSize * Math.sin(angle + delta);
				doc.lineTo(x, y);
				delta *= -1;
			}
		}
		doc.fillStroke();

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment