使用ngCordova的animation方向箭头“aroundMe”风格

我希望创build与AroundMe移动应用程序中所看到的完全相同的指南针/箭头,以便根据我的移动位置恰当地指向地图上的某个图钉,并在移动手机时更新箭头。

我疯了,才明白如何做到这一点,我找不到任何指导或教程解释一点。

我在网上find的是一个轴承function,我创build了一个指令:

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位置计算。

所以我添加了用于Device OrientationngCordova插件来获取magneticHeading ,现在我不知道如何使用它以及bearingfunction在哪里。

  $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。

总是在网上找我找不到任何教程/问题来find一个lat/lng pointmagnetingHeading之间的magnetingHeading

也许我已经接近解决scheme,但是我不能一个人前进。

我也尝试寻找一个math公式,但是即使有一个巨大的痛苦去理解和实现它。

我希望你能帮上忙。

这个问题很难给出一个简单的答案,因为很多取决于实际的graphics表示。 例如,你指向哪个方向rotate(0deg)

我可以解释你find的公式,这可能有助于你自己解决问题。 困难的部分如下:

  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); 

你在这里看到的是Haversines公式( https://en.wikipedia.org/wiki/Haversine_formula )。 通常可以用两组坐标来计算它们之间的angular度。 当处理经纬度时,这是不行的,因为地球不是一个平坦的表面。 前三行是Haversine,结果( xy )是unit circle上的坐标( https://en.wikipedia.org/wiki/Unit_circle

下一步是计算从该单位圆上的点到中心的angular度。 我们可以使用这个arctangant 。 JavaScript有一个帮助函数atan2简化了这个过程。 其结果是简单的angular度你的点的圆心。 换句话说,你对你的兴趣点的立场。 结果是弧度,需要转换为度数。 ( 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,你可以看到一个简单的平面坐标系统。 你可以移动和旋转youpoint of interest 。 即使你旋转“你”,“你”中的箭头也会始终指向poi 。 这是因为我们弥补了我们自己的轮换。

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

注意Plunckr中的“零”位置总是在北方。 检查您的应用程序以查看您的“零”位置。 相应地调整它,你的脚本将工作。

希望这可以帮助 :-)