Search code examples
angularjsangularjs-ng-repeatangularjs-orderbyhaversine

how to get distance and sort by distance in angularjs?


I'm trying to get the distance between the records and the user's position. And order it by the one closest to me. I'm using a formula similar to hacersine, but I still do not get the distance. Thanks.

My code html:

    <div ng-app="my-app" id="por_logo.html">     
      <ons-page ng-controller="PorlogoCtl">
         <div class="cliente" ng-repeat="cliente in porlogo.clientes" ng-if="cliente.estado == '1'">
      <p>{{cliente.nombre}} <span>{{distancia2}}</span></p>
      </div>       
 </ons-page>
 </div>

Similar to haversine:

function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
          var R = 6878; // Radius of the earth in km
          var dLat = deg2rad(lat2-lat1);  // deg2rad below
          var dLon = deg2rad(lon2-lon1); 
          var a = 
            Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
            Math.sin(dLon/2) * Math.sin(dLon/2)
            ; 
          var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
          var d = R * c; // Distance in km
          return d;
        };
        function deg2rad(deg) {
          return deg * (Math.PI/180)
        };

Code JS:

var app = angular.module('my-app', ['onsen']).factory('position', function( $rootScope ){

        // console.log('building position')
        var position = {};

          // 1ST / AUTO GEOLOCATION OF USER 
          // displays a popup to indicate current user location - (disabled)
          // onSuccess Callback - This method accepts a Position object, which contains the current GPS coordinates
         var onSuccess = function(position2) {

              console.log(position2.coords.latitude )
              console.log(position2.coords.longitude)

              position.latitude = position2.coords.latitude;
              position.longitude = position2.coords.longitude;
              $rootScope.$digest()
          };

        function onError(error) { // onError Callback receives a PositionError object
            // alert('code: '    + error.code    + '\n' +
                  // 'message: ' + error.message + '\n');
                  alert('No podemos acceder a su ubicación');
        }

        navigator.geolocation.getCurrentPosition(onSuccess, onError);

      return position;

    });
    app.controller("PorlogoCtl", function($scope, $http, position, $rootScope) {
      $http.get('https://viveenunclick.com/api.php/clientes?transform=1').
      success(function(data, status, headers, config) {
        $scope.porlogo = data;
        $rootScope.latitude = position.latitude;
        $rootScope.longitud = position.longitude;
        $rootScope.distancia2 = getDistanceFromLatLonInKm(position.latitude,position.longitude,$rootScope.latitude,$rootScope.longitud).toFixed(1);
        console.log($rootScope.longitud);
      }).
      error(function(data, status, headers, config) {});
    });

Post Demo in Codepen


Solution

  • the coordinates are in the data returned, you will get it by: $scope.porlogo[iteration].Latitud & $scope.porlogo[iteration].Longitud

    So to have theses, you need to iterate. You could use the iteration in the view:

     <p>{{cliente.nombre}} <span>{{distancia(cliente)}}</span></p>
    

    and in your controller, add this distancia function to return the right distance:

    Important: But if you need to use toFixed(1) which return a string (order will be by a string), you need to add parseFloat() so it will return a number and order will be right.

    $scope.distancia = function(item) {
        //it's item.Latitud & item.Longitud, from the data
        return parseFloat(getDistanceFromLatLonInKm(position.latitude,position.longitude,item.Latitud,item.Longitud).toFixed(1));
    }
    

    You can use this function too for the sort & order,

    <div class="cliente" ng-repeat="cliente in porlogo.clientes | orderBy: distancia: false">
    

    Working pen