Кривая безье через массив точек с анимацией

Кривая безье через массив точек с анимацией

by twobomb three

HTML

<button id="random">Мне повезёт!</button>
<button id="clear">Очистить</button>
<canvas id="myCanvas"></canvas>

CSS

body,html{
  height:100%;
}
#random{
  position:absolute;
  top:20px;
}
#clear{
  position:absolute;
  top:40px;
}

JavaScript

var canvas = document.querySelector("#myCanvas");
var ctx = canvas.getContext("2d");
var ctxW,ctxH,currentAnimId = 0;

canvas.width = ctxW = document.body.offsetWidth;
canvas.height = ctxH =document.body.offsetHeight;

var dots = [];

document.querySelector("#clear").addEventListener("click",()=>{
	dots = [];
  runAnimation();
});
document.querySelector("#random").addEventListener("click",()=>{//Рандомно расставить точки
	var rand = (min,max)=>{ return Math.floor(min + max *Math.random())};
  var n = rand(5,10);
  dots = [];
 	while(n--)
		dots.push([rand(0,canvas.width),rand(0,canvas.height)]);
  	runAnimation();  
});
document.querySelector("#random").dispatchEvent(new Event("click"));
canvas.addEventListener("mousedown",function(e){
	dots.push([e.offsetX,e.offsetY]);
  runAnimation();
});

function runAnimation(){
	currentAnimId++;
  let animId = currentAnimId;
  var step = 0.05;//Шаг анимации, чем меньше тем плавнее линии
  let  iTo = 0,tTo = 0; 
  (function anim(){
  	draw(iTo,tTo,step);
    tTo+=step;
    if(tTo>1){
    	tTo = 0;
      iTo++;
    }
    if(iTo >= dots.length - 1){    
  		draw(dots.length - 2,1,step);
    	return;
     }
  	if(currentAnimId == animId)
    	setTimeout(anim,1000/60);
  })();
}

function draw(iTo, tTo, stepAnim){
	ctx.clearRect(0,0,ctxW,ctxH);  
	ctx.fillText("Кликай по канвасу",10,10)
  ctx.lineWidth = 2;
  for(var i  = 0; i < dots.length;i++){
  	ctx.fillStyle = i>=iTo+1 && !(iTo == dots.length-2 && tTo  == 1)?"red":"blue";
  	ctx.beginPath();
    ctx.arc(dots[i][0],dots[i][1],10,0,Math.PI*2);
    ctx.closePath();
    ctx.fill();
  }
	if(dots.length  >= 2){
  	 for(var i  = 0; i <= iTo;i++){
     		var inxLast = i > 0?i-1:0;//Индекс предыдущей точки в массиве точек
        var inxNext = i < dots.length - 2? i+2 :i+1;   //Индекс следующей точки в массиве точек
        //Вычисляем промежуточные точки между двумя точками
  	    var control = calcControlPoints(dots[inxLast][0],dots[inxLast][1],
                         ...