Подтвердить что ты не робот

Анимированные стрелки направления "aroundMe" с использованием ngCordova

Я хочу создать компас/стрелку точно так же, как тот, который мы видим в AroundMe Mobile App, который точно указывает на вывод сопоставьте с моей мобильной позицией и обновите стрелку, когда я перемещаю телефон.

Я схожу с ума, чтобы понять, как это сделать, и я не могу найти руководство или учебник, которые немного объясняют это.

То, что я нашел в Интернете, является функцией несущей, и я создал директиву вокруг нее:

app.directive('arrow', function () {

    function bearing(lat1, lng1, lat2, lng2) {
      var dLon = (lng2 - lng1);
      var y = Math.sin(dLon) * Math.cos(lat2);
      var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
      var rad = Math.atan2(y, x);
      var brng = toDeg(rad);
      return (brng + 360) % 360;
    }

    function toRad(deg) {
      return deg * Math.PI / 180;
    }

    function toDeg(rad) {
      return rad * 180 / Math.PI;
    }

    return {
    restrict: 'E',
    link: function (scope, element, attrs) {
      var arrowAngle = bearing(scope.user.position.lat, scope.user.position.lng, attrs.lat, attrs.lng);
      element.parent().css('transform', 'rotate(' + arrowAngle + 'deg)');
    }
  };

});

Кажется, обновляет стрелку в направлении, но, к сожалению, это не правильное направление, потому что оно не вычисляется с использованием также мобильной позиции magneticHeading.

Итак, я добавил плагин ngCordova для Ориентация устройства, чтобы получить magneticHeading, и теперь я точно не знаю, как его использовать и где находится функция bearing.

  $cordovaDeviceOrientation.getCurrentHeading().then(function(result) {
    var magneticHeading = result.magneticHeading;
    var arrowAngle = bearing(scope.user.position.lat, scope.user.position.lng, attrs.lat, attrs.lng, magneticHeading);
    element.parent().css('transform', 'rotate(' + arrowAngle + 'deg)');
  });

Я попытался добавить его в оператор return:

return (brng - heading) % 360;

или

return (heading - ((brng + 360) % 360));

Реализация этого кода с помощью наблюдателя Я вижу, что стрелка перемещается, но не в точном положении... Например, из моей позиции и булавки стрелка должна указывать на N и она указывает на E.

Всегда смотреть онлайн Я не могу найти учебник/вопрос, чтобы найти опору между lat/lng point и magnetingHeading.

Возможно, я близок к решению, но не могу идти дальше.

Я также пытался найти математические формулы, но даже есть огромная боль, чтобы понять и реализовать его.

Надеюсь, вы сможете помочь.

4b9b3361

Ответ 1

Трудно дать простой ответ на этот вопрос, потому что многое зависит от фактического графического представления. Например, в каком направлении вы указываете, где rotate(0deg).

Я могу объяснить найденную формулу, которая может помочь вам устранить проблему самостоятельно. Жесткая часть:

  var dLon = (lng2 - lng1);
  var y = Math.sin(dLon) * Math.cos(lat2);
  var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
  var rad = Math.atan2(y, x);

Здесь вы видите формулу Хаверсинеса (https://en.wikipedia.org/wiki/Haversine_formula). Обычно может быть достаточно двух наборов координат и вычислить угол между ними. При работе с широтой и долготой это не сработает, потому что земля не плоская. Первые три строки - Haversine, а результат (xи y) - это координаты на unit circle (https://en.wikipedia.org/wiki/Unit_circle)

Следующий шаг - рассчитать угол от точки на этом единичном круге до центра. Для этого мы можем использовать arctangant. Javascript имеет вспомогательную функцию atan2, которая упрощает этот процесс. В результате просто угол вашей точки к центру круга. Другими словами, ваша позиция по отношению к вашей точке интереса. Результат получается в радианах и должен быть преобразован в градусы. (https://en.wikipedia.org/wiki/Atan2)

Упрощенная версия с плоской системой координат будет выглядеть так:

var deltaX = poi.x - you.x;
var deltaY = you.y - poi.y;
var rotation = toDeg(Math.atan2(deltaX, deltaY));

bearingElement.css('transform', 'rotate(' + rotation + 'deg)');

Где poi - Точка интереса, а you - ваша позиция.

Чтобы компенсировать свое собственное вращение, вам нужно вычитать свое собственное вращение. В приведенном выше примере результат будет выглядеть следующим образом:

var deltaX = poi.x - you.x;
var deltaY = you.y - poi.y;
var rotation = toDeg(Math.atan2(deltaX, deltaY));

rotation -= you.rotation;

bearingElement.css('transform', 'rotate(' + rotation + 'deg)');

Я сделал Plunckr, в котором вы можете увидеть простую плоскую систему координат. Вы можете перемещать и поворачивать you и point of interest. Стрелка внутри "вы" всегда будет указывать на poi, даже если вы вращаете "вы". Это потому, что мы компенсируем нашу собственную ротацию.

https://plnkr.co/edit/OJBGWsdcWp3nAkPk4lpC?p=preview

Обратите внимание на Plunckr, что "нулевое" положение всегда находится на севере. Проверьте свое приложение, чтобы увидеть свою нулевую позицию. Отрегулируйте его, и ваш script будет работать.

Надеюсь, что это поможет: -)