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:
xxxxxxxxxx
1
// arrow = shaft + tip
2
//
3
// t argument indicates in % how big should be shaft part in drawn arrow
4
// t should be in range from 0 to 1
5
// t can be interpreted as: t = shaftLength / arrowLength
6
//
7
const drawArrow = (context, x1, y1, x2, y2, t = 0.9) => {
8
const arrow = {
9
dx: x2 - x1,
10
dy: y2 - y1
11
};
12
const middle = {
13
x: arrow.dx * t + x1,
14
y: arrow.dy * t + y1
15
};
16
const tip = {
17
dx: x2 - middle.x,
18
dy: y2 - middle.y
19
};
20
context.beginPath();
21
context.moveTo(x1, y1);
22
context.lineTo(middle.x, middle.y);
23
context.moveTo(middle.x + 0.5 * tip.dy, middle.y - 0.5 * tip.dx);
24
context.lineTo(middle.x - 0.5 * tip.dy, middle.y + 0.5 * tip.dx);
25
context.lineTo(x2, y2);
26
context.closePath();
27
context.stroke();
28
};
29
30
31
// Usage example:
32
33
const canvas = document.querySelector('#my-canvas');
34
const context = canvas.getContext('2d');
35
36
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:

In this section, you can find quick solution organized in more clear way.
xxxxxxxxxx
1
2
<html>
3
<head>
4
<style>
5
6
#my-canvas { border: 1px solid gray; }
7
8
</style>
9
</head>
10
<body>
11
<canvas id="my-canvas" width="200" height="200"></canvas>
12
<script>
13
14
function drawLine(context, x1, y1, x2, y2) {
15
context.beginPath();
16
context.moveTo(x1, y1);
17
context.lineTo(x2, y2);
18
context.stroke();
19
}
20
21
function drawHead(context, x1, y1, x2, y2, filled) {
22
var dx = x2 - x1;
23
var dy = y2 - y1;
24
context.beginPath();
25
context.moveTo(x1 + 0.5 * dy, y1 - 0.5 * dx); // https://dirask.com/posts/jMqM0j
26
context.lineTo(x1 - 0.5 * dy, y1 + 0.5 * dx); // https://dirask.com/posts/1GoW61
27
context.lineTo(x2, y2);
28
context.closePath();
29
filled ? context.fill() : context.stroke();
30
}
31
32
// Draws arrow on the canvas.
33
//
34
// context - drawing context
35
// x1, y1 - arrow staring point
36
// x2, y2 - arrow ending point
37
// arrow - (optional) arrow head size (from 0 to 1 - relatively measured to arrow size)
38
// filled - (optional) if true, the arrow head should be filled with some color
39
//
40
function drawArrow(context, x1, y1, x2, y2, arrow, filled) {
41
if (arrow == null) {
42
arrow = 0.1;
43
}
44
var t = 1.0 - arrow;
45
var dx = x2 - x1;
46
var dy = y2 - y1;
47
var middleX = dx * t + x1;
48
var middleY = dy * t + y1;
49
drawLine(context, x1, y1, middleX, middleY);
50
drawHead(context, middleX, middleY, x2, y2, filled);
51
}
52
53
54
// Usage example:
55
56
var canvas = document.querySelector('#my-canvas');
57
var context = canvas.getContext('2d');
58
59
drawArrow(context, 10, 50, 170, 150); // context, x1, y1, x2, y2, (arrow: default=0.1 - arrow head size from 0 to 1)
60
61
</script>
62
</body>
63
</html>
In this section, you will see how to draw arrows using different styles.

Source code:
xxxxxxxxxx
1
2
<html>
3
<head>
4
<style>
5
6
#my-canvas { border: 1px solid gray; }
7
8
</style>
9
<script>
10
11
function drawLine(context, x1, y1, x2, y2) {
12
context.beginPath();
13
context.moveTo(x1, y1);
14
context.lineTo(x2, y2);
15
context.stroke();
16
}
17
18
function drawHead(context, x1, y1, x2, y2, filled) {
19
var dx = x2 - x1;
20
var dy = y2 - y1;
21
context.beginPath();
22
context.moveTo(x1 + 0.5 * dy, y1 - 0.5 * dx); // https://dirask.com/posts/jMqM0j
23
context.lineTo(x1 - 0.5 * dy, y1 + 0.5 * dx); // https://dirask.com/posts/1GoW61
24
context.lineTo(x2, y2);
25
context.closePath();
26
filled ? context.fill() : context.stroke();
27
}
28
29
// Draws arrow on the canvas.
30
//
31
// context - drawing context
32
// x1, y1 - arrow staring point
33
// x2, y2 - arrow ending point
34
// arrow - (optional) arrow head size (from 0 to 1 - relatively measured to arrow size)
35
// filled - (optional) if true, the arrow head should be filled with some color
36
//
37
function drawArrow(context, x1, y1, x2, y2, arrow, filled) {
38
if (arrow == null) {
39
arrow = 0.1;
40
}
41
var t = 1.0 - arrow;
42
var dx = x2 - x1;
43
var dy = y2 - y1;
44
var middleX = dx * t + x1;
45
var middleY = dy * t + y1;
46
drawLine(context, x1, y1, middleX, middleY);
47
drawHead(context, middleX, middleY, x2, y2, filled);
48
}
49
50
</script>
51
</head>
52
<body>
53
<canvas id="my-canvas" width="400" height="200"></canvas>
54
<script>
55
56
// Usage example:
57
58
var canvas = document.querySelector('#my-canvas');
59
var context = canvas.getContext('2d');
60
61
drawEmptyArrow(context, 10, 5, 170, 100, 0.04, 'blue', 0.2); // 0.2px line width, 4% shaft
62
drawEmptyArrow(context, 10, 30, 170, 125, 0.15, 'orange', 4); // 4px line width, 15% shaft
63
drawEmptyArrow(context, 10, 90, 170, 185, 0.4, 'gold', 1.5); // 1.5px line width, 40% shaft
64
65
drawFilledArrow(context, 210, 5, 370, 100, 0.04, 'blue', 0.2); // 0.2px line width, 4% shaft
66
drawFilledArrow(context, 210, 30, 370, 125, 0.15, 'orange', 4); // 4px line width, 15% shaft
67
drawFilledArrow(context, 210, 90, 370, 185, 0.4, 'gold', 1.5); // 1.5px line width, 40% shaft
68
69
70
// Helper methods:
71
72
function drawEmptyArrow(context, x1, y1, x2, y2, arrow, color, width) {
73
context.lineWidth = width;
74
context.strokeStyle = color;
75
drawArrow(context, x1, y1, x2, y2, arrow, false);
76
}
77
78
function drawFilledArrow(context, x1, y1, x2, y2, arrow, color, width) {
79
context.lineWidth = width;
80
context.fillStyle = color;
81
context.strokeStyle = color;
82
drawArrow(context, x1, y1, x2, y2, arrow, true);
83
}
84
85
</script>
86
</body>
87
</html>