You've spent 3 weeks fighting this task...ouch!
Here's a step-by-step tutorial showing how to manage it.
Since you're in learning mode, I leave out a demo so you can learn by assembling the pieces. I also leave the arrow-tail to you as a learning experience. Good luck with your project!
Calculate some useful values about the path between P1 & P2
Create points P1 & P2 that you want to animate an arrow-line along:
var p1={x:0, y:100};
var p2={x:100, y:0};
Calculate the deltaX & deltaY representing the vector between the starting & ending points of the current path (P1 to P2):
// calculate the deltaX & deltaY of the line between point P1 & P2
var pathStarts={ x:p1.x, y:p1.y };
var pathEnds={ x:p2.x, y:p2.y };
var dx=pathEnds.x-pathStarts.x;
var dy=pathEnds.y-pathStarts.y;
Calculate the length of the path between P1 & P2:
var pathLength=Math.sqrt(dx*dx+dy*dy);
Calculate the angle of the path between P1 & P2:
var pathAngle=Math.atan2(dy,dx);
Define a variable that will tell how far along the path between P1 & P2 that the arrow-line has moved
// pct will be incremented from 0 to 100
// At 100 the arrow-line will have its arrowhead at P2
var pct=0;
Define how long the arrow-line will be:
var arrowLineLength=25;
Define how long the arrowhead will be:
var arrowLength=8;
In an animation loop:
You can create an animation loop using requestAnimationFrame
function animate(time){
// Recalculate your animation values
// In your case, recalculate the new starting & ending points
// of the arrow as it animates from P1 to P2
// Draw your arrow-line in it's newly animated position
// request another loop in the animation
requestAnimationFrame(animate);
}
Calculate the current starting & ending points of the arrow-line
// calculate how far the line has already animated
// shorten the distance by the length used by the arrowLine
var traveled=(pathLength-arrowLineLength)*pct/100;
// calculate the new starting point of the arrow-line
var x0=pathStarts.x+traveled*Math.cos(pathAngle);
var y0=pathStarts.y+traveled*Math.sin(pathAngle);
var lineStart={x:x0,y:y0};
// calculate the new ending point of the arrow-line
var x1=pathStarts.x+(traveled+arrowLineLength)*Math.cos(pathAngle);
var y1=pathStarts.y+(traveled+arrowLineLength)*Math.sin(pathAngle);
var lineEnd={x:x1,y:y1};
Clear the entire canvas:
ctx.clearRect(0,0,canvas.width,canvas.height);
Redraw the line in it's new [x0,y0],[x1,y1] position:
(See the function below which shows how to draw an arrowLine)
drawLineWithArrowhead(lineStart,lineEnd,arrowLength);
Increase the pct for the next loop in the animation
pct++;
When you finish animating between P1 & P2 (when pct==100)...
Go back to the first set of instructions and calculate useful values about the path between P2 & P3.
How to draw an arrow-line between 2 points:
(See previous answer here for a demo)
function drawLineWithArrowhead(p0,p1,headLength){
// constants (could be declared as globals outside this function)
var PI=Math.PI;
var degreesInRadians225=225*PI/180;
var degreesInRadians135=135*PI/180;
// calc the angle of the line
var dx=p1.x-p0.x;
var dy=p1.y-p0.y;
var angle=Math.atan2(dy,dx);
// calc arrowhead points
var x225=p1.x+headLength*Math.cos(angle+degreesInRadians225);
var y225=p1.y+headLength*Math.sin(angle+degreesInRadians225);
var x135=p1.x+headLength*Math.cos(angle+degreesInRadians135);
var y135=p1.y+headLength*Math.sin(angle+degreesInRadians135);
// draw line plus arrowhead
ctx.beginPath();
// draw the line from p0 to p1
ctx.moveTo(p0.x,p0.y);
ctx.lineTo(p1.x,p1.y);
// draw partial arrowhead at 225 degrees
ctx.moveTo(p1.x,p1.y);
ctx.lineTo(x225,y225);
// draw partial arrowhead at 135 degrees
ctx.moveTo(p1.x,p1.y);
ctx.lineTo(x135,y135);
// stroke the line and arrowhead
ctx.stroke();
}