This applet simply draws an arrow when you click and drag on it. That's all.
Suppose we want to draw an arrow between and . The basic idea is that we determine two points L and R a fixed distance below on either side of the line from to along a perpendicular direction to it. We then connect L, , and R with lines and we have our arrow.

Determining a direction perpendicular to a line or a vector is straightforward. If the vector drawn from to is the vector perpendicular to it is , that is, you swap the x and y components and make one of them negative(this makes the dot product of the two vectors zero).
Once you have the points L, R and the bottom of the arrowhead B you can draw the arrowhead in other ways. Shown below is an arrow that looks more like an actual arrow. This was obtained by connecting B, L, , and R with quadratic bezier curves instead of lines.

Here is the relevant code. The commented-out portion draws the arrow in the above figure.
function drawArrow(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
const length = Math.sqrt(dx * dx + dy * dy);
const unit_vec = { x: dx / length, y: dy / length };
const perp_unit_vec = { x: unit_vec.y, y: -unit_vec.x };
const head_back = { x: x2 - _head * unit_vec.x, y: y2 - _head * unit_vec.y };
const head_left = {
x: head_back.x + (_base / 2) * perp_unit_vec.x,
y: head_back.y + (_base / 2) * perp_unit_vec.y,
};
const head_right = {
x: head_back.x - (_base / 2) * perp_unit_vec.x,
y: head_back.y - (_base / 2) * perp_unit_vec.y,
};
_ctx.beginPath();
_ctx.moveTo(x1, y1);
_ctx.lineTo(x2, y2);
_ctx.moveTo(head_left.x, head_left.y);
_ctx.lineTo(x2, y2);
_ctx.lineTo(head_right.x, head_right.y);
_ctx.stroke();
/*
fill(0);
beginShape();
vertex(head_back.x, head_back.y);
quadraticVertex(head_left.x, head_left.y, x2, y2);
quadraticVertex(head_right.x, head_right.y,head_back.x, head_back.y);
endShape();
*/
}