EN
JavaScript - draw arrow on canvas element
8
points
In this short aritcle, we would like to show how to draw arrow on canvas element using JavaScript.
By default there is not available defaul mechanism to draw array and it is necessary to create own one - what was presented in the article.
Quick solution:
// arrow = shaft + tip
//
// t argument indicates in % how big should be shaft part in drawn arrow
// t should be in range from 0 to 1
// t can be interpreted as: t = shaftLength / arrowLength
//
const drawArrow = (context, x1, y1, x2, y2, t = 0.9) => {
const arrow = {
dx: x2 - x1,
dy: y2 - y1
};
const middle = {
x: arrow.dx * t + x1,
y: arrow.dy * t + y1
};
const tip = {
dx: x2 - middle.x,
dy: y2 - middle.y
};
context.beginPath();
context.moveTo(x1, y1);
context.lineTo(middle.x, middle.y);
context.moveTo(middle.x + 0.5 * tip.dy, middle.y - 0.5 * tip.dx);
context.lineTo(middle.x - 0.5 * tip.dy, middle.y + 0.5 * tip.dx);
context.lineTo(x2, y2);
context.closePath();
context.stroke();
};
// Usage example:
const canvas = document.querySelector('#my-canvas');
const context = canvas.getContext('2d');
drawArrow(context, 10, 50, 170, 150, 0.9); // A=(10, 50) B=(170, 150) t=90% is shaft part share
Note: the above quick solution has better performance than solution based on trigonometric functions.
Preview:

Practical example
In this section, you can find quick solution organized in more clear way.
// ONLINE-RUNNER:browser;
<!doctype html>
<html>
<head>
<style>
#my-canvas { border: 1px solid gray; }
</style>
</head>
<body>
<canvas id="my-canvas" width="200" height="200"></canvas>
<script>
function drawLine(context, x1, y1, x2, y2) {
context.beginPath();
context.moveTo(x1, y1);
context.lineTo(x2, y2);
context.stroke();
}
function drawHead(context, x1, y1, x2, y2, filled) {
var dx = x2 - x1;
var dy = y2 - y1;
context.beginPath();
context.moveTo(x1 + 0.5 * dy, y1 - 0.5 * dx); // https://dirask.com/posts/jMqM0j
context.lineTo(x1 - 0.5 * dy, y1 + 0.5 * dx); // https://dirask.com/posts/1GoW61
context.lineTo(x2, y2);
context.closePath();
filled ? context.fill() : context.stroke();
}
// Draws arrow on the canvas.
//
// context - drawing context
// x1, y1 - arrow staring point
// x2, y2 - arrow ending point
// arrow - (optional) arrow head size (from 0 to 1 - relatively measured to arrow size)
// filled - (optional) if true, the arrow head should be filled with some color
//
function drawArrow(context, x1, y1, x2, y2, arrow, filled) {
if (arrow == null) {
arrow = 0.1;
}
var t = 1.0 - arrow;
var dx = x2 - x1;
var dy = y2 - y1;
var middleX = dx * t + x1;
var middleY = dy * t + y1;
drawLine(context, x1, y1, middleX, middleY);
drawHead(context, middleX, middleY, x2, y2, filled);
}
// Usage example:
var canvas = document.querySelector('#my-canvas');
var context = canvas.getContext('2d');
drawArrow(context, 10, 50, 170, 150); // context, x1, y1, x2, y2, (arrow: default=0.1 - arrow head size from 0 to 1)
</script>
</body>
</html>
Arrow styles
In this section, you will see how to draw arrows using different styles.

Source code:
// ONLINE-RUNNER:browser;
<!doctype html>
<html>
<head>
<style>
#my-canvas { border: 1px solid gray; }
</style>
<script>
function drawLine(context, x1, y1, x2, y2) {
context.beginPath();
context.moveTo(x1, y1);
context.lineTo(x2, y2);
context.stroke();
}
function drawHead(context, x1, y1, x2, y2, filled) {
var dx = x2 - x1;
var dy = y2 - y1;
context.beginPath();
context.moveTo(x1 + 0.5 * dy, y1 - 0.5 * dx); // https://dirask.com/posts/jMqM0j
context.lineTo(x1 - 0.5 * dy, y1 + 0.5 * dx); // https://dirask.com/posts/1GoW61
context.lineTo(x2, y2);
context.closePath();
filled ? context.fill() : context.stroke();
}
// Draws arrow on the canvas.
//
// context - drawing context
// x1, y1 - arrow staring point
// x2, y2 - arrow ending point
// arrow - (optional) arrow head size (from 0 to 1 - relatively measured to arrow size)
// filled - (optional) if true, the arrow head should be filled with some color
//
function drawArrow(context, x1, y1, x2, y2, arrow, filled) {
if (arrow == null) {
arrow = 0.1;
}
var t = 1.0 - arrow;
var dx = x2 - x1;
var dy = y2 - y1;
var middleX = dx * t + x1;
var middleY = dy * t + y1;
drawLine(context, x1, y1, middleX, middleY);
drawHead(context, middleX, middleY, x2, y2, filled);
}
</script>
</head>
<body>
<canvas id="my-canvas" width="400" height="200"></canvas>
<script>
// Usage example:
var canvas = document.querySelector('#my-canvas');
var context = canvas.getContext('2d');
drawEmptyArrow(context, 10, 5, 170, 100, 0.04, 'blue', 0.2); // 0.2px line width, 4% shaft
drawEmptyArrow(context, 10, 30, 170, 125, 0.15, 'orange', 4); // 4px line width, 15% shaft
drawEmptyArrow(context, 10, 90, 170, 185, 0.4, 'gold', 1.5); // 1.5px line width, 40% shaft
drawFilledArrow(context, 210, 5, 370, 100, 0.04, 'blue', 0.2); // 0.2px line width, 4% shaft
drawFilledArrow(context, 210, 30, 370, 125, 0.15, 'orange', 4); // 4px line width, 15% shaft
drawFilledArrow(context, 210, 90, 370, 185, 0.4, 'gold', 1.5); // 1.5px line width, 40% shaft
// Helper methods:
function drawEmptyArrow(context, x1, y1, x2, y2, arrow, color, width) {
context.lineWidth = width;
context.strokeStyle = color;
drawArrow(context, x1, y1, x2, y2, arrow, false);
}
function drawFilledArrow(context, x1, y1, x2, y2, arrow, color, width) {
context.lineWidth = width;
context.fillStyle = color;
context.strokeStyle = color;
drawArrow(context, x1, y1, x2, y2, arrow, true);
}
</script>
</body>
</html>