Find the point on bezier curve based on given X or Y (HTML SVG PATH)

this gives us a point on the curve by passing x or y of current point

by dm89

HTML

<svg id="svg" viewBox="0 0 300 150" width="300" height="150" style="width:600px;height: auto">
    <path class="ruler" d="M 10,0 L 10,300"></path>
    <path class="ruler" d="M 20,0 L 20,300"></path>
    <path class="ruler" d="M 30,0 L 30,300"></path>
    <path class="ruler" d="M 40,0 L 40,300"></path>
    <path class="ruler" d="M 50,0 L 50,300"></path>
    <path class="ruler" d="M 60,0 L 60,300"></path>
    <path class="ruler" d="M 70,0 L 70,300"></path>
    <path class="ruler" d="M 80,0 L 80,300"></path>
    <path class="ruler" d="M 90,0 L 90,300"></path>
    <path class="ruler" d="M 100,0 L 100,300"></path>
    <path class="ruler" d="M 110,0 L 110,300"></path>
    <path class="ruler" d="M 120,0 L 120,300"></path>
    <path class="ruler" d="M 130,0 L 130,300"></path>
    <path class="ruler" d="M 140,0 L 140,300"></path>
    <path class="ruler" d="M 150,0 L 150,300"></path>
    <path class="ruler" d="M 160,0 L 160,300"></path>
    <path class="ruler" d="M 170,0 L 170,300"></path>
    <path class="ruler" d="M 180,0 L 180,300"></path>
    <path class="ruler" d="M 190,0 L 190,300"></path>
    <path class="ruler" d="M 200,0 L 200,300"></path>
    <path class="ruler" d="M 210,0 L 210,300"></path>
    <path class="ruler" d="M 220,0 L 220,300"></path>
    <path class="ruler" d="M 230,0 L 230,300"></path>
    <path class="ruler" d="M 240,0 L 240,300"></path>
    <path class="ruler" d="M 250,0 L 250,300"></path>
    <path class="ruler" d="M 260,0 L 260,300"></path>
    <path class="ruler" d="M 270,0 L 270,300"></path>
    <path class="ruler" d="M 280,0 L 280,300"></path>
    <path class="ruler" d="M 290,0 L 290,300"></path>
    <path class="ruler" d="M 300,0 L 300,300"></path>
    <path class="ruler" d="M 0,10 L 600,10"></path>
    <path class="ruler" d="M 0,20 L 600,20"></path>
    <path class="ruler" d="M 0,30 L 600,30"></path>
    <path class="ruler" d="M 0,40 L 600,40"></path>
    <path class="ruler" d="M 0,50 L 600,50"></path>
    <path class="ruler" d="M 0,60 L...

SCSS

*{
  margin:0;
  padding:0;
  box-sizing:border-box;
}
body{
   background-color: #333;
   color:#ccc;
}
svg{
    border: solid 1px #247a1f;;
    margin: 50px 0 0 50px;
    path{
      &.ruler{
        stroke-linejoin: round;
        stroke-linecap: round;
        stroke-width: 0.5;
        stroke-opacity:1;
        stroke: #4a4a4a;
        stroke-dashoffset: 0;
        display: block;
        fill: none;
        fill-opacity: 0.0;
        &:nth-of-type(5n){
          stroke-width: 0.5;
          stroke: #747070;
        }
      }
      &.draw{
        stroke: #3ca19d;
      }
      &.control{
        stroke: #a139a0;
      }
    }
}

JavaScript

//lets make some  points

var p0 = {x:50,y:100},  // The first point on curve  
    c0 = {x:150,y:0},   // Controller for p0
    c1 = {x:150,y:150}, // Controller for p1
    p1 = {x:250,y:50};  // The last point on curve

// Apply points to SVG and create the curve and controllers :

var path  =  document.getElementById('path'),
	ctrl1 =  document.getElementById('ctrl1'),
    ctrl2 =  document.getElementById('ctrl2'),
    D = 'M ' + p0.x + ' ' + p0.y +
    'C ' + c0.x + ' ' + c0.y +', ' + c1.x + ' ' + c1.y + ', ' + p1.x + ' ' + p1.y;
    
path.setAttribute('d',D);
ctrl1.setAttribute('d','M'+p0.x+','+p0.y+'L'+c0.x+','+c0.y);
ctrl2.setAttribute('d','M'+p1.x+','+p1.y+'L'+c1.x+','+c1.y);

// Lets test the "Bezier Function" 

var t = 0, point = document.getElementById('point');

setInterval(function(){

  var p = Bezier(p0,c0,c1,p1,t);
  point.setAttribute('cx',p.x);
  point.setAttribute('cy',p.y);

  t += 0.01;
  if(t>=1) t=0;

},50);


// OK ... Now tring to get "y" on cruve based on mouse "x" : 

var svg = document.getElementById('svg'),
	point2 = document.getElementById('point2');

svg.onmousemove = function(e){

	var x = (e.pageX - 50)/2,  
  		y = (e.pageY - 50)/2;
   // "-50" because of "50px margin" on the left side 
   // and "/2" because the svg width is 300 units and 600 px => 300 = 600/2    
  
  // Get the x,y by mouse x
  var p = YBX(p0,c0,c1,p1,x); 
  
  point2.setAttribute('cx',p.x);
  point2.setAttribute('cy',p.y);  
} 

/*
 * Get new x,y on curve by given x
 * @params a,b,c,d {x:x,y:y}
 * @params x 
 * @return {{x:new x on cruve ,y: new y on cruve}}
 */
function YBX(a,b,c,d,x){
	
    a = a.x;
    b = b.x;
    c = c.x;
    d = d.x;

	// Lets expand this 
    // x = a * (1-t)³ + b * 3 * (1-t)²t + c * 3 * (1-t)t² + d * t³
    //------------------------------------------------------------
    // x = a - 3at + 3at² - at³ 
    //       + 3bt - 6bt² + 3bt³
    //             + 3ct² - 3ct³
    //                    + dt³
   ...