Aye*_*azo 37 javascript google-maps angularjs ionic-framework ngcordova
我希望创建一个指南针/箭头,就像我们在AroundMe移动应用程序中看到的那样,指向地图上的一个引脚与移动位置相对应,并在我移动手机时更新箭头.
我很难理解如何做到这一点,我找不到任何解释它的指南或教程.
我在网上找到的是一个轴承功能,我围绕它创建了一个指令:
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)');
}
};
});
Run Code Online (Sandbox Code Playgroud)
它似乎在一个方向更新箭头但不幸的是它不是正确的方向,因为它不是使用移动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)');
});
Run Code Online (Sandbox Code Playgroud)
我试着在return语句中添加它:
return (brng - heading) % 360;
Run Code Online (Sandbox Code Playgroud)
要么:
return (heading - ((brng + 360) % 360));
Run Code Online (Sandbox Code Playgroud)
实现这个代码与守望我看到的箭头移动,但不是在准确的位置...例如从我的位置与销的箭头应指向ñ和它指向Ë.
总是在线查找我找不到任何教程/问题来找到a lat/lng point
和a 之间的方位magnetingHeading
.
也许我接近解决方案,但我无法独自前进.
我也试图寻找数学公式,但即使理解和实施它也会有巨大的痛苦.
我希望你能提供帮助.
很难对这个问题给出简单的答案,因为很大程度上取决于实际的图形表示。例如,您指向哪个方向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);
Run Code Online (Sandbox Code Playgroud)
您在这里看到的是半正弦公式(https://en.wikipedia.org/wiki/Haversine_formula)。通常,只要有两组坐标就足够了,并计算它们之间的角度。当使用纬度和经度时,这将不起作用,因为地球不是平坦的表面。前三行是半正矢,结果 (x
和) 是( https://en.wikipedia.org/wiki/Unit_circle )y
上的坐标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)');
Run Code Online (Sandbox Code Playgroud)
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)');
Run Code Online (Sandbox Code Playgroud)
我制作了一个 Plunkr,您可以在其中看到一个简单的平面坐标系。您可以移动和you
旋转point of interest
。poi
即使您旋转“您”,“您”内部的箭头也将始终指向。这是因为我们补偿了自己的轮换。
https://plnkr.co/edit/OJBGWsdcWp3nAkPk4lpC?p=preview
请注意,在 Plunkr 中,“零”位置始终位于北方。检查您的应用程序以查看您的“零”位置。相应地调整它,您的脚本就会起作用。
希望这可以帮助 :-)