使用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 Orientation的ngCordova
插件来获取magneticHeading
,现在我不知道如何使用它以及bearing
function在哪里。
$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 point
和magnetingHeading
之间的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,结果( x
和y
)是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,你可以看到一个简单的平面坐标系统。 你可以移动和旋转you
和point of interest
。 即使你旋转“你”,“你”中的箭头也会始终指向poi
。 这是因为我们弥补了我们自己的轮换。
https://plnkr.co/edit/OJBGWsdcWp3nAkPk4lpC?p=preview
注意Plunckr中的“零”位置总是在北方。 检查您的应用程序以查看您的“零”位置。 相应地调整它,你的脚本将工作。
希望这可以帮助 :-)