// canvas vars
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
// animating vars
var pct=101;
var startX,startY,endX,endY,dx,dy;
// canvas styles
ctx.strokeStyle='skyblue';
ctx.fillStyle='blue';
// start animation loop running
requestAnimationFrame(animate);
// listen for mouse events
window.onmousedown=(function(e){handleMouseDown(e);});
window.onmouseup=(function(e){handleMouseUp(e);});
// constantly running loop
// will animate bullet
function animate(time){
// return if there's no bullet to animate
if(++pct>100){requestAnimationFrame(animate);return;}
// update
x=startX+dx*pct/100;
y=startY+dy*pct/100;
// draw
ctx.clearRect(0,0,cw,ch);
ctx.beginPath();
ctx.moveTo(startX,startY);
ctx.lineTo(endX,endY);
ctx.stroke();
ctx.beginPath();
ctx.arc(x,y,5,0,Math.PI*2);
ctx.fill()
// request another animation loop
requestAnimationFrame(animate);
}
function handleMouseDown(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// save ending position
startX=parseInt(e.clientX-offsetX);
startY=parseInt(e.clientY-offsetY);
// set flag
pct=101;
}
function handleMouseUp(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// save ending position and vector
endX=parseInt(e.clientX-offsetX);
endY=parseInt(e.clientY-offsetY);
dx=endX-startX;
dy=endY-startY;
// set pct=0 to start animating
pct=0;
}
body{ background-color: ivory; }
#canvas{border:1px solid red; }
<h4>Drag the mouse<br>Mousedown sets starting position,<br>Mouseup sets ending position and animates.</h4>
<canvas id="canvas" width=512 height=512></canvas>