Это было непростое решение. Я использовал тригонометрию, чтобы найти координаты точек.
function calculateArrow(tp, hp, thickness, headSize) {
// basic info
// angle between 0,0 and the head
const a = Math.atan2(hp[0] - tp[0], hp[1] - tp[1]);
// half the width
const halfW = thickness / 2;
// half the head size
const halfH = headSize / 2;
const halfPi = Math.PI / 2;
// output :)
const arrow = [
[0,0], [0,0], [0,0], [0,0], [0,0], [0,0]
];
// here comes the trig!
// point 1
arrow[0][0] = Math.cos(a + halfPi) * halfW + tp[0]; // x
arrow[0][1] = Math.sin(a + halfPi) * halfW + tp[1]; // y
// point 2
arrow[1][0] = Math.cos(a - halfPi) * halfW + tp[0];
arrow[1][1] = Math.sin(a - halfPi) * halfW + tp[1];
// point 3
arrow[2][0] = (hp[0] - Math.cos(a) * halfH) + Math.cos(a + halfPi) * halfH;
arrow[2][1] = (hp[1] - Math.sin(a) * halfH) + Math.sin(a + halfPi) * halfH;
// point 4
arrow[3][0] = (hp[0] - Math.cos(a) * halfH) + Math.cos(a + halfPi) * halfW;
arrow[3][1] = (hp[1] - Math.sin(a) * halfH) + Math.sin(a + halfPi) * halfW;
// point 5
arrow[4][0] = (hp[0] - Math.cos(a) * halfH) + Math.cos(a - halfPi) * halfW;
arrow[4][1] = (hp[1] - Math.sin(a) * halfH) + Math.sin(a - halfPi) * halfW;
// point 6
arrow[5][0] = (hp[0] - Math.cos(a) * halfH) + Math.cos(a - halfPi) * halfH;
arrow[5][1] = (hp[1] - Math.sin(a) * halfH) + Math.sin(a - halfPi) * halfH;
return arrow;
}