We propose a useful function for drawing curved arrows. See this example:
Source code of the function that draws a curved arrow:
function drawCurvedArrow(startPointX, startPointY,
endPointX, endPointY,
quadPointX, quadPointY,
lineWidth,
arrowWidth,
color) {
// BEST PRACTICE: the function changes color and lineWidth -> save context!
ctx.save();
ctx.strokeStyle = color;
ctx.lineWidth = lineWidth;
// angle of the end tangeant, useful for drawing the arrow head
var arrowAngle = Math.atan2(quadPointX - endPointX, quadPointY - endPointY) + Math.PI;
// start a new path
ctx.beginPath();
// Body of the arrow
ctx.moveTo(startPointX, startPointY);
ctx.quadraticCurveTo(quadPointX, quadPointY, endPointX, endPointY);
// Head of the arrow
ctx.moveTo(endPointX - (arrowWidth * Math.sin(arrowAngle - Math.PI / 6)),
endPointY - (arrowWidth * Math.cos(arrowAngle - Math.PI / 6)));
ctx.lineTo(endPointX, endPointY);
ctx.lineTo(endPointX - (arrowWidth * Math.sin(arrowAngle + Math.PI / 6)),
endPointY - (arrowWidth * Math.cos(arrowAngle + Math.PI / 6)));
ctx.stroke();
ctx.closePath();
// BEST PRACTICE -> restore the context as we saved it at the beginning
// of the function
ctx.restore();
}
This function takes as parameters the start and end points, the control point of the curve, the arrow width, the width of the arrow head.
It computes the angle of the arrow at its endpoint (line 14) in order to compute the rotated endpoints of the two lines of the arrow head (lines 24 and 29).
Notice that once again, as we modify the context properties (color, lineWidth) in the body of the function, we save and restore the context at the beginning / end of the function.