frostzt
frostzt

Reputation: 419

Circular motion in JavaScript not working as expected

I am trying to make a point to follow a certain path using JS. But for some reason, it is going completely off the path and just following a line instead of moving in a circle.

Following is my markup, CSS, and JS:

(function() {
  window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
  const circleOne = document.getElementById('circle-one');
  const circleOnePoint = document.getElementById('circle-one-point');

  let maxX = circleOne.clientWidth - circleOnePoint.offsetWidth;
  let maxY = circleOne.clientHeight - circleOnePoint.offsetHeight;

  const duration = 4;
  const gridSize = 100;

  let start = null;

  function step(timeStamp) {
    let progress, x, y;
    if (start === null) {
      start = timeStamp;
    }

    progress = (timeStamp - start) / duration / 1000;

    x = Math.sin(progress * 2 * Math.PI);
    y = Math.cos(progress * 2 * Math.PI);

    circleOnePoint.style.left = maxX / 2 + (gridSize * x) + "px";
    circleOnePoint.style.bottom = maxY / 2 + (gridSize * y) + "px";

    if (progress >= 1) start = null;
    requestAnimationFrame(step);
  }
  requestAnimationFrame(step);
})();
.center-content {
  width: 100%;
  height: 100%;
}

#circle-one {
  opacity: 50%;
  position: absolute;
  width: 454px;
  height: 454px;
  border-radius: 50%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 0.5px solid black;
}

#circle-one-point {
  position: absolute;
  top: 50%;
  left: 100%;
  transform: translate(-50%, -50%);
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: black;
}
<div class="center-content">
  <div id="circle-one"></div>
  <div id="circle-one-point"></div>
</div>

Update this is how far I have been:

(function() {
  window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
  const circleOne = document.getElementById('circle-one');
  const circleOnePoint = document.getElementById('circle-one-point');

  let maxX = circleOne.clientWidth - circleOnePoint.offsetWidth;
  let maxY = circleOne.clientHeight - circleOnePoint.offsetHeight;

  const duration = 4;
  const gridSize = 100;

  let start = null;

  function step(timeStamp) {
    let progress, x, y;
    if (start === null) {
      start = timeStamp;
    }

    progress = (timeStamp - start) / duration / 1000;

    x = Math.sin(progress * 2 * Math.PI);
    y = Math.cos(progress * 2 * Math.PI);

    circleOnePoint.style.left = maxX / 2 + (gridSize * x) + "px";
    circleOnePoint.style.top= maxY / 2 + (gridSize * y) + "px";

    if (progress >= 1) start = null;
    requestAnimationFrame(step);
  }
  requestAnimationFrame(step);
})();
.center-content {width: 100%;height: 100%;}
.circles{position: relative;}
#circle-one {
    opacity: 50%;
    position: fixed;
    width: 454px;
    height: 454px;
    border-radius: 50%;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    border: 0.5px solid black;
    background-color: black;
}
#circle-one-point {
    position: fixed;
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background-color: green;
}
<div class="circles">
    <div id="circle-one"></div>
    <div id="circle-one-point"></div>                    
</div>

This should follow a path that I have made using the border of Circle-one but it just doesn't work that way!

Upvotes: 0

Views: 155

Answers (2)

Maksim Tikhonov
Maksim Tikhonov

Reputation: 790

You should to setup small point TOP property, because it set on init, but bottom is not set.

(function() {
  window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
  const circleOne = document.getElementById('circle-one');
  const circleOnePoint = document.getElementById('circle-one-point');
  let rect = circleOne.getBoundingClientRect();
  
  let deltaX = rect.right - rect.width;
  let deltaY = rect.bottom - rect.height;
  
  console.log(rect)
  const duration = 4;
  const gridSize = 200;

  let start = null;

  function step(timeStamp) {
    let progress, x, y;
    if (start === null) {
      start = timeStamp;
    }

    progress = (timeStamp - start) / duration / 1000;

    x = Math.sin(progress * 2 * Math.PI);
    y = Math.cos(progress * 2 * Math.PI);

    circleOnePoint.style.left = rect.width/ 2 + deltaX + (gridSize * x) + "px";
    circleOnePoint.style.top = rect.height/ 2 + deltaY + (gridSize * y) + "px";

    if (progress >= 1) start = null;
    requestAnimationFrame(step);
  }
  requestAnimationFrame(step);
})();
.center-content {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border: 1px solid red;
}

#circle-one {
  opacity: 50%;
  position: absolute;
  width: 400px;
  height: 400px;
  border-radius: 50%;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 0.5px solid black;
}

#circle-one-point {
  position: absolute;
  top: 50%;
  left: 100%;
  transform: translate(-50%, -50%);
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background-color: black;
}
<div class="center-content">
  <div id="circle-one"></div>
  <div id="circle-one-point"></div>
</div>

Upvotes: 1

Jesper
Jesper

Reputation: 207026

In your CSS you are setting the left and top properties of circle-one-point:

#circle-one-point {
  top: 50%;
  left: 100%;
  /* ... */
}

But in the script you are setting left and bottom:

circleOnePoint.style.left = maxX / 2 + (gridSize * x) + "px";
circleOnePoint.style.bottom = maxY / 2 + (gridSize * y) + "px";

Note that top will remain at 50%, which will cause the dot to stay on the same horizontal line.

One solution: Set top instead of bottom in the script:

circleOnePoint.style.left = maxX / 2 + (gridSize * x) + "px";
circleOnePoint.style.top = maxY / 2 + (gridSize * y) + "px";

Upvotes: 2

Related Questions