Расчетная точка на Круге - PullRequest
1 голос
/ 25 марта 2020

Мне известно множество статей по этой теме c на Inte rnet, но мне не удалось решить мою проблему. Я думаю, что мои тригонометрические вычисления верны, но, возможно, я что-то напутал в JavaScript.

Моя цель - вычислить точку на окружности (x, y), чтобы я мог переместить мои sliderHead в эта позиция. Для этого мне нужно вычислить угол между точками нажатия и щелчком на моем круге - для этого я использую atan2. Далее я использую простую тригонометрию для вычисления фактических значений X и Y:

let y = -Math.ceil(radius * Math.cos(deg));
let x = Math.ceil(radius * Math.sin(deg));   

Я понимаю, что мне нужно инвертировать cosine и sine, потому что моя начальная позиция на самом деле на 90 градусов, а не 0 и я включаю CLOCKWISE, а не COUNTERCLOCKWISE, что предполагает математика.

Начальные значения равны 0, поскольку начальное значение sliderHead находится в центре круга. Начальное значение не является действительным 0, 0px, но является центром родительского элемента div .

Как вы увидите на картинке ниже, я не делаю это правильно, слайдерHead находится за решеткой.

enter image description here

Вот код, где я вычисляю точку x, y:

 testCalc(event) {
        let deg = Math.atan2(event.pageY - this.centerY, event.pageX - this.centerX);

        console.log(deg);

        let radius = this.options.radius;

        let y = -Math.ceil(radius * Math.cos(deg));
        let x = Math.ceil(radius * Math.sin(deg));      

        return {
            "x": x + "px",
            "y": y + "px"
        };

    }

А вот расположение элемента sliderHead внутри моего HTML: enter image description here

Вот как я перевожу sliderHead:

    moveSliderHeadPosition(point) {
           this.sliderHead.style.transform = "translate(" + point["x"] + "," + point["y"] + ")";
   } 

Как уже говорилось, я исчерпал все свои варианты, пытаясь решить эту проблему.

Ответы [ 2 ]

1 голос
/ 25 марта 2020

Приятно использовать atan2! Глядя на ваш код, он кажется мне правильным, хотя, возможно, это так же просто, как необходимость вычитать половину размера sliderHead?

Вот пример, который я собрал, чтобы проверить его:

function showCoords(event) {
  var x = event.clientX;
  var y = event.clientY;
  var xn = x / window.innerWidth;
  var yn = y / window.innerHeight;
  var result = Math.atan2(x, y);
  var coor = `X: ${x}, Y: ${y} > X1: ${xn.toFixed(2)}, Y1: ${yn.toFixed(
    2
  )} ~ ${result.toFixed(
    2)}`;
  document.getElementById("demo").innerHTML = coor;
}

function moveGrabber(event) {
  // get our grabber and track as well as their bounding rectangles
  var grabber = document.querySelector(".grabber");
  var grabberRect = grabber.getBoundingClientRect();
  var track = document.querySelector(".track");
  var trackRect = track.getBoundingClientRect();
  var trackRadius = trackRect.width / 2;

  // get our window center
  var windowCenterX = window.innerWidth / 2;
  var windowCenterY = window.innerHeight / 2;

  // get the angle around the window center
  var x = event.clientX;
  var y = event.clientY;
  var angle = Math.atan2(x - windowCenterX, y - windowCenterY);

  // get the point on the circle
  var circleX = Math.sin(angle) * trackRadius + windowCenterX;
  var circleY = Math.cos(angle) * trackRadius + windowCenterY;

  // subtract half the size of the grabber so that it is centered on the track
  var posX = circleX - grabberRect.width / 2;
  var posY = circleY - grabberRect.height / 2;

  grabber.style.left = `${posX}px`;
  grabber.style.top = `${posY}px`;
}

function moveGrabberWithX(event) {
  // get our grabber and track as well as their bounding rectangles
  var grabber = document.querySelector(".grabber");
  var grabberRect = grabber.getBoundingClientRect();
  var track = document.querySelector(".track");
  var trackRect = track.getBoundingClientRect();
  var trackRadius = trackRect.width / 2;

  // get the mouse position and the normalized version in the range of [0,1]
  var x = event.clientX;
  var xn = x / window.innerWidth;

  // get the center of the window
  var windowCenterX = window.innerWidth / 2;
  var windowCenterY = window.innerHeight / 2;

  // get the point on the circle
  // this uses the normalized x position of the mouse [0,1]
  // and multiplies it by 2PI which gives you a circle
  var circleX = Math.sin(xn * Math.PI * 2) * trackRadius + windowCenterX;
  var circleY = Math.cos(xn * Math.PI * 2) * trackRadius + windowCenterY;

  // subtract half the size of the grabber so that it is centered on the track
  var posX = circleX - grabberRect.width / 2;
  var posY = circleY - grabberRect.height / 2;

  grabber.style.left = `${posX}px`;
  grabber.style.top = `${posY}px`;
}
html,
body {
  margin: 0px;
  padding: 0px;
}
.center {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100vw;
  height: 100vh;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: gray;
}

.track {
  width: 300px;
  height: 300px;
  background: rgb(13, 88, 134);
  border-radius: 50%;
}

.grabber {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 25px;
  height: 25px;
  background: coral;
  border-radius: 50%;
}

.label {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  /* display: flex; */
}
p {
  background: darkgray;
  font-family: "Courier New", Courier, monospace;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Static Template</title>
    <link rel="stylesheet" href="styles.css" />
    <script src="script.js"></script>
  </head>
  <body>
    <div class="center" onmousemove="moveGrabber(event); showCoords(event);">
      <div class="track" />
      <div class="grabber" />
    </div>
    <div class="label">
      <p id="demo" />
    </div>
  </body>
</html>
0 голосов
/ 25 марта 2020

Попробуйте умножить или разделить вычисленный угол на 57.2957795 (преобразование между градусами и радианами).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...