Home > Software engineering >  Inward Circular Orbit - Canvas
Inward Circular Orbit - Canvas

Time:12-13

I have a polygon that has circles on its vertices.
enter image description here

What I expect to accomplish is that every circle will be moving to the circle on its right. This is a physics concept which proves that if every circle is moving to the one on its right with a constant speed, soon they will reach the center. I'm trying to accomplish this animation, however I am able to move circles but not in the direction to the one next to it. Here's my current code that draws the polygon with circles:

function particleGenerator(n){
        const ctx = document.getElementById('poly').getContext('2d');
        ctx.reset();
        drawPolygon(ctx, 154, 71.25 , n, 50, 0, 5, 7.5);
}
  
const drawPolygon = (ctx, x, y, points, radius, rotation = 0, nodeSize = 0, nodeInset = 0) => {
    ctx.beginPath();
    ctx.moveTo(
        x   radius * Math.cos(rotation),
        y   radius * Math.sin(rotation)
    );          
    for (let i = 1; i <= points; i  = 1) {
        const angle = (i * (2 * Math.PI / points))   rotation;
        ctx.lineTo(
            x   radius * Math.cos(angle),
            y   radius * Math.sin(angle)
        );
    }
    ctx.fillStyle = "#00818A";
    ctx.fill();
    if (!nodeSize) return;
    const dist = radius - nodeInset;
    for (let i = 1; i <= points; i  = 1) {
        const angle = (i * (2 * Math.PI / points))   rotation;
        let x1 = x   dist * Math.cos(angle);
        let y1 = y   dist * Math.sin(angle);
        ctx.beginPath();         
        ctx.arc(x1, y1, nodeSize, 0, 2 * Math.PI);
        ctx.fillStyle = "#DBEDF3"
        ctx.fill();
    }
};
<button onclick="particleGenerator(4)">Click Me!</button>
<canvas id="poly">

CodePudding user response:

You can keep track of a list of corners. You generate them in order, so to get a corner's next neighbor you can do corners[i 1] || corners[0].

To move the corner in the direction of the next one, you can calculate their differences in x and y coordinates and add a percentage of that difference to a corner's current location.

Here's a running example (I did remove some of the code so I could focus on just the updating problem:

function particleGenerator(n) {
  const ctx = document.getElementById('poly').getContext('2d');
  ctx.reset();
  const originalCorners = createCorners(150, 70, n, 50);
  const corners = createCorners(150, 70, n, 50);

  const next = () => {
    corners.forEach(([x0, y0], i) => {
      const [x1, y1] = corners[i   1] || corners[0];
      
      const dx = x1 - x0;
      const dy = y1 - y0;
      
      const SPEED = 0.05;
      corners[i][0] = x0   dx * SPEED;
      corners[i][1] = y0   dy * SPEED;
    });
  }
  
  const frame = () => {
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  
    drawPolygon(ctx, originalCorners, "grey");
    drawPolygon(ctx, corners);
    drawDots(ctx, corners);
    
    next();
    requestAnimationFrame(frame);
  };
  
  frame();
    
}


const createCorners = (x, y, n, radius) => {
  const corners = [];
  
  for (let i = 1; i <= n; i  = 1) {
    const angle = (i * (2 * Math.PI / n));
    corners.push([
      x   radius * Math.cos(angle),
      y   radius * Math.sin(angle)
    ]);
  }
  
  return corners;
}



const drawPolygon = (
  ctx,
  corners,
  color = "#00818A"
) => {
  
  // Draw fill
  ctx.beginPath();
  corners.forEach((c, i) => {
    if (i === 0) ctx.moveTo(...c);
    else ctx.lineTo(...c);
  });
  ctx.fillStyle = color
  ctx.fill();
};

const drawDots = (
  ctx,
  corners,
) => {
  // Draw dots
  corners.forEach(([x, y], i, all) => {
    ctx.beginPath();
    ctx.arc(x, y, 5, 0, 2 * Math.PI);
    ctx.fillStyle = "red"
    ctx.fill();
  });
};
<input type="number" value="6" min="3" max="100">
<button onclick="particleGenerator(document.querySelector('input').valueAsNumber)">Click Me!</button>
<canvas id="poly">

  • Related