Skip to content

Instantly share code, notes, and snippets.

@jwir3
Created May 18, 2017 15:18
Show Gist options
  • 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();
}
@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