2016-02-10 12 views
37

Desidero creare la bussola/freccia esattamente come quella che vediamo in AroundMe Mobile App che punta esattamente a un pin sulla mappa di conseguenza con la mia posizione mobile e aggiorna la freccia quando I sposta il telefono.Frecce direzionali animate stile "aroundMe" utilizzando ngCordova

Sto diventando pazzo per capire esattamente come farlo e non riesco a trovare alcuna guida o tutorial che spieghi un po '.

Quello che ho trovato on-line è una funzione portante e ho creato una direttiva attorno ad esso:

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

}); 

Sembra di aggiornare la freccia in una direzione, ma purtroppo non è la direzione giusta, perché non viene calcolato utilizzando anche la posizione mobile magneticHeading.

Così ho aggiunto il plugin ngCordova per dispositivo di orientamento per ottenere il magneticHeading e ora non so esattamente come usarlo e dove nella funzione 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)'); 
    }); 

ho provato ad aggiungere che nella dichiarazione di ritorno:

return (brng - heading) % 360; 

o:

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

implementazione di questo codice con un osservatore che vedo la freccia in movimento, ma non nella posizione esatta ... Ad esempio dalla mia posizione e il pin la freccia dovrebbe puntare a N e punta a E.

Sempre online Non riesco a trovare alcun tutorial/domanda per trovare il rilevamento tra uno lat/lng point e uno magnetingHeading.

Forse sono vicino alla soluzione ma non posso andare avanti da solo.

Ho anche provato a cercare una formula matematica ma anche c'è un enorme dolore da capire e implementare.

Spero che tu possa aiutare.

+0

Non so se questo plunker potrebbe aiutare: http://plnkr.co/edit/WC9Kspe54tlod5EOpndD – beaver

+0

@beaver grazie per il tuo commento. È fatto usando solo latitudine e longitudine, non usando la posizione mobile ... :( –

+0

Forse [questo post] (http://gis.stackexchange.com/questions/29239/calculate-bearing-between-two-decimal- coordinate GPS) potrebbe aiutarti ... o [questo] (http://stackoverflow.com/questions/11415106/issue-with-calcuating-compass-bearing-between-two-gps-coordinates) – beaver

risposta

1

È difficile dare una risposta chiara a questa domanda perché molto dipende dalla rappresentazione grafica effettiva. Ad esempio, in quale direzione indicherai dove rotate(0deg).

Posso spiegare la formula che hai trovato, che potrebbe aiutarti a risolvere il problema da solo. La parte difficile è la seguente:

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

Quello che vedete qui è Haversines formula (https://en.wikipedia.org/wiki/Haversine_formula). Normalmente uno può bastare con due serie di coordinate e calcolare l'angolo tra di esse. Quando si lavora con latitudine e longitudine questo non funzionerà perché la terra non è una superficie piana. Le prime tre righe sono Haversine e il risultato (x e y) sono coordinate sulla unit circle (https://en.wikipedia.org/wiki/Unit_circle)

Il passo successivo consiste nel calcolare l'angolo dal punto di questa circonferenza unitaria al centro.Possiamo usare il arctangant per questo. Javascript ha una funzione di supporto atan2 che semplifica questo processo. Il risultato è semplice l'angolo del tuo punto verso il centro del cerchio. In altre parole, la tua posizione verso il tuo punto di interesse. Il risultato è in radianti e deve essere convertito in gradi. (https://en.wikipedia.org/wiki/Atan2)

Una versione semplificata di una TV sistema di coordinate sarebbe simile a questa:

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

Dove poi è il punto di interesse e you è la vostra posizione.

Per compensare la propria rotazione, è necessario sottrarre la propria rotazione. Nel campione di sopra del risultato sarebbe diventato:

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

ho fatto un Plunckr in cui è possibile vedere un semplice sistema di coordinate piatta. È possibile spostare e ruotare you e point of interest. La freccia all'interno di "te" punta sempre verso lo poi, anche se si ruota "tu". Questo perché compensiamo la nostra rotazione.

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

Nota nel Plunckr che la 'posizione zero' è sempre a nord. Controlla la tua app per vedere la tua posizione 'zero'. Regola di conseguenza e il tuo script funzionerà.

Spero che questo aiuti :-)

Problemi correlati