3

I need to animate a dot to move along this line (waypoint). It needs to start from the top, move right along the red line and then go down and move along blue line and repeat.

I tried to use css but I was not able to program the dot to move along this line made in canvas

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.strokeStyle = '#FF0000';
ctx.moveTo(30, 0);
ctx.bezierCurveTo(60, 320, 150, 320, 600, 330);
ctx.stroke();
ctx.beginPath();
var ctx = canvas.getContext("2d");
ctx.moveTo(15, 0);
ctx.strokeStyle = '#000FFF';
ctx.bezierCurveTo(0, 340, 100, 350, 600, 350);
ctx.stroke();
ctx.beginPath();
var ctx = canvas.getContext("2d");
ctx.moveTo(15, 0);
ctx.strokeStyle = '#000FFF';
ctx.lineTo(30, 0);
ctx.stroke();
ctx.beginPath();
var ctx = canvas.getContext("2d");
ctx.moveTo(600, 330);
ctx.strokeStyle = '#000FFF';
ctx.lineTo(600, 350);
ctx.stroke();
<canvas id="myCanvas" height="350px;" width="600px"></canvas>
Zeina
  • 59
  • 6
Jirru
  • 93
  • 4

1 Answers1

4

To achieve this you need to calculate Waypoints like this example - jsfiddle , In your case you have a Curve and to calculate Waypoints it's little tricky but nothing impossible

  1. calculate Waypoints see this answer
  2. animat dot in loop of Waypoints array

This a small example with one line , you can add your colors or lines

jsfiddle

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var cBez1=[{x:30,y: 0},{x:60,y:320},{x:150,y:320},{x:600,y:330}];


drawBez(cBez1);

var cPoints=findCBezPoints(cBez1);
setInterval(timeanim, 1);
var indexi =0;
var opr = -1;

function timeanim()
{
 //reset view
 ctx.clearRect(0, 0, cw, ch);
 drawBez(cBez1);
 //draw dot
    ctx.fillStyle='red';
    ctx.beginPath();
    ctx.arc(cPoints[indexi].x,cPoints[indexi].y,4,0,Math.PI*2);
    ctx.fill();
    
  if(indexi + opr > cPoints.length-2 ||  indexi + opr < 0){
   opr *= -1;
  }
  indexi += opr;
}




function findCBezPoints(b){
  var startPt=b[0];
  var controlPt1=b[1];
  var controlPt2=b[2];
  var endPt=b[3];
  var pts=[b[0]];
  var lastPt=b[0];
  var tests=5000;
  for(var t=0;t<=tests;t++){
    // calc another point along the curve
    var pt=getCubicBezierXYatT(b[0],b[1],b[2],b[3], t/tests);
    // add the pt if it's not already in the pts[] array
    var dx=pt.x-lastPt.x;
    var dy=pt.y-lastPt.y;
    var d=Math.sqrt(dx*dx+dy*dy);
    var dInt=parseInt(d);
    if(dInt>0 || t==tests){
      lastPt=pt;
      pts.push(pt);
    }
  }
  return(pts);
}

// Given the 4 control points on a Bezier curve 
// Get x,y at interval T along the curve (0<=T<=1)
// The curve starts when T==0 and ends when T==1
function getCubicBezierXYatT(startPt, controlPt1, controlPt2, endPt, T) {
  var x = CubicN(T, startPt.x, controlPt1.x, controlPt2.x, endPt.x);
  var y = CubicN(T, startPt.y, controlPt1.y, controlPt2.y, endPt.y);
  return ({
    x: x,
    y: y
  });
}

// cubic helper formula
function CubicN(T, a, b, c, d) {
  var t2 = T * T;
  var t3 = t2 * T;
  return a + (-a * 3 + T * (3 * a - a * T)) * T + (3 * b + T * (-6 * b + b * 3 * T)) * T + (c * 3 - c * 3 * T) * t2 + d * t3;
}

function drawPlots(pts){
  ctx.fillStyle='red';
  // don't draw the last dot b/ its radius will display past the curve
  for(var i=0;i<pts.length-1;i++){
    ctx.beginPath();
    ctx.arc(pts[i].x,pts[i].y,1,0,Math.PI*2);
    ctx.fill();
  }
}

function drawBez(b){
  ctx.lineWidth=2;
  ctx.beginPath();
  ctx.moveTo(b[0].x,b[0].y);
  ctx.bezierCurveTo(b[1].x,b[1].y, b[2].x,b[2].y, b[3].x,b[3].y);
  ctx.stroke();
}
  <canvas id="canvas" width=700 height=600></canvas>
Mohamed Sa'ed
  • 781
  • 4
  • 13
  • this is amazing but I don't understand math where should I start. Do you have some source to learn ? @Mohamed – Kem Bardly Feb 18 '23 at 16:28