javascriptcanvasgeometrycoordinatescoordinate-systems

how to find coordinate of a fixed circular path that track the pointer position on canvas


enter image description here

In above Image,

My goal is wherever i move the cursor/pointer on canvas, point a1,b1 should should track the new position. so that a straight line can be drawn from centre of circle to mouse position.

How to calculate this?


Solution

  • If I understand it correctly, you want to be able to draw a line from (x,y) to (a2,b2) depending on where your cursor is. Basically you don't need to know where the cursor previously was to calculate this.

    In my example im referring to the points as following:

    How to calculate the new point B:

    Step 1: Calculate the distance from point A to C:
    distance = sqrt((Cx - Ax)^2 + (Cy - Ay)^2)

    Step 2: Calculate the fraction between the desired radius and the distance from Step 1:
    fraction = radius / distance

    Step 3: Now we just take the distance from each, X and Y coordinates and apply the fraction from Step 2 (so we basically growing / shrinking the distance to point C in order to set it to the desired radius:
    Bx = Ax + (Cx - Ax) * fraction
    By = Ay + (Cy - Ay) * fraction

    Now you have the Point B (Bx,By) which equals your point with (a2,b2) coordinates.


    Basic showcase for the calculation (not a canvas)

    // Note: In our example canvas, the top left corner has coordinates x=0 y=0
    
    // radius for pointB in pixels
    const radius = 50;
    
    // the canvas
    const canvas = document.querySelector('.canvas');
    
    // the three points
    const pointA = document.querySelector('.point.pointA');
    const pointB = document.querySelector('.point.pointB');
    const pointC = document.querySelector('.point.pointC');
    
    // spans to display coordinates
    const coordinatesA = document.querySelector('#pointA');
    const coordinatesB = document.querySelector('#pointB');
    const coordinatesC = document.querySelector('#pointC');
    
    // setup the static pointA (x,y)
    function setupPointA(x,y) {
        pointA.style.left = `${x}px`;
        pointA.style.top = `${y}px`;
      
      coordinatesA.querySelector('.x').textContent = `${x}px`;
      coordinatesA.querySelector('.y').textContent = `${x}px`;
    }
    
    // calculation for pointB (a1, b1)
    function calculatePointB() {
        // get pointA coordinates
      const aX = parseInt(pointA.style.left, 10);
      const aY = parseInt(pointA.style.top, 10);
      
      // get pointC coordinates
      const cX = parseInt(pointC.style.left, 10);
      const cY = parseInt(pointC.style.top, 10);
      
      // calculate the distance from point A to C
      const distance = Math.sqrt(Math.pow(cX - aX, 2) + Math.pow(cY - aY, 2));
      
      // get the fraction between radius and distance in order to calculate a1,b1
      const fraction = radius / distance;
      
      // calculate pointB
      const bX = aX + (cX - aX) * fraction;
      const bY = aY + (cY - aY) * fraction;
      
      pointB.style.left = `${bX}px`;
        pointB.style.top = `${bY}px`;
      
      coordinatesB.querySelector('.x').textContent = `${bX}px`;
      coordinatesB.querySelector('.y').textContent = `${bY}px`;
    }
    
    // get the cursor position for PointC (x1, y1)
    canvas.addEventListener('mousemove', (event) => { 
      const rect = canvas.getBoundingClientRect(); 
      const x = event.clientX - rect.left; 
      const y = event.clientY - rect.top; 
       
      pointC.style.left = `${x}px`;
        pointC.style.top = `${y}px`;
      
      calculatePointB();
      
      coordinatesC.querySelector('.x').textContent = `${x}px`;
      coordinatesC.querySelector('.y').textContent = `${x}px`;
    }); 
    
    setupPointA(50, 100);
    .canvas {
      width: 250px;
      height: 250px;
      border: 1px solid red;
      margin: 0 auto;
      position: relative;
    }
    
    .point {
      width: 5px;
      height: 5px;
      position: absolute;
    }
    
    .point.pointA {
      background: red;
    }
    
    .point.pointB {
      background: green;
    }
    
    .point.pointC {
      background: blue;
    }
    <div class="coordinates">
     <p id="pointA">
       x: <span class="x">0</span>
       y: <span class="y">0</span>
     </p>
     <p id="pointB">
       a1: <span class="x">0</span>
       b1: <span class="y">0</span>
     </p>
     <p id="pointC">
       x1: <span class="x">0</span>
       y1: <span class="y">0</span>
     </p>
    </div>
    <div class="canvas">
      <div class="point pointA"></div>
      <div class="point pointB"></div>
      <div class="point pointC"></div>  
    </div>