Angular JS - 使用地理位置对集合进行排序

Posted

技术标签:

【中文标题】Angular JS - 使用地理位置对集合进行排序【英文标题】:Angular JS - sorting a collection using geolocation 【发布时间】:2014-10-04 04:17:17 【问题描述】:

我正在呈现包含坐标数据(经度、纬度)的商店位置集合。我想使用用户的地理位置对结果进行排序——特别是按最近的商店位置排序。就上下文而言,该应用程序旨在让人们更容易使用他们想要的 iPhone 找到 Apple Store(加拿大):

http://www.applestoreinventory.com

我正在使用 angularjs-geolocation 包装器 (https://github.com/arunisrael/angularjs-geolocation) 来获取访问者的纬度/经度,但我不确定如何使用用户的地理位置(一旦获取)以及 Angular 的 orderBy 指令来动态地使用收藏。 (我想按壁橱的距离进行排序,这是我习惯用 javascript 计算的东西。)这可能是一个简单的问题,但是对于 Angular 来说是新手,我仍在努力了解自己的方位。到目前为止,这是控制器:

angular.module('InventoryApp')
  .controller('searchController', ['$scope', 'searchService', 'geolocation', function(scope, searchService, geolocation)

    scope.model_ids = model_ids;
    scope.store_ids = store_ids;
    scope.address = '';
    scope.find = '';
    scope.position = null;

    scope.refreshLocation = function () 
        geolocation.getLocation().then(function(data)
          scope.coords =  lat:parseFloat(data.coords.latitude.toFixed(6)), lng:parseFloat(data.coords.longitude.toFixed(6)) ;       
        var geocoder = new google.maps.Geocoder();
        var latlng = new google.maps.LatLng(scope.coords.lat, scope.coords.lng);
        geocoder.geocode( 'latLng': latlng , function (results, status) 
            if (status == google.maps.GeocoderStatus.OK) 
                if (results[0]) 
                    scope.address = results[0].formatted_address;
                 else 
                    scope.address = 'Address not found';
                
             else 
                scope.address = 'Geocoder failed due to: ' + status;
            
            scope.$digest();
        );
        );
    ;

        scope.search = function () 
          searchService.update().success(function (stores) 
            scope.stores = stores;
          );      
        ;

        scope.refreshLocation();
    scope.search();

  ])

  .factory('searchService', ['$http', function(http)     
      return 
        update: function () 
          return http.get('/inventory');
        
      
  ])

那么,关于如何在 Angular JS 中构建它有什么想法吗?

【问题讨论】:

您可以计算到每个商店的距离并按距离排序。 是的,这就是我的想法。我知道如何计算距离,但在 Angular 控制器的上下文中,如何做到这一点?在 Backbone 中,这很简单——我只需为邻近度创建一个计算属性,然后对其进行排序。在 Angular JS 中,我只是不知道如何处理它。 【参考方案1】:

我认为 AngularJS 没有太大的不同。我做了一个例子。它使用 Google Places API 进行搜索。需要地图(map = new google.maps.Map),因为没有它,places API 就无法工作。如果您的地理位置被禁用,它将不起作用。它使用 Google 地图几何 API 以米为单位计算距离,并使用 orderBy 过滤器对商店进行排序。

    <!doctype html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.js"></script>
        <script src="https://raw.githubusercontent.com/arunisrael/angularjs-geolocation/master/dist/angularjs-geolocation.min.js"></script>
        <script src="http://maps.google.com/maps/api/js?sensor=false&v=3&libraries=geometry,places"></script>
        <style>
            .check-yes 
                background-color: green;
            
        </style>
    </head>
    <body ng-app="plunker">
        <div id="map-canvas"></div>

        <div  ng-controller="searchController">
            Search for: <input type="text" ng-model="searchText"> <button ng-click="search()">Search</button>
            <ul>
                <li ng-repeat="store in stores | orderBy:'distance'">
                    store.name (store.distance metres)
                </li>
            </ul>
        </div>
        <script>
            var app = angular.module('plunker', ['geolocation']);
            app.controller('searchController', ['$scope', 'searchService', 'geolocation', function(scope, searchService, geolocation)

                scope.address = '';
                scope.find = '';
                scope.position = null;
                scope.stores = [];
                scope.searchText = '';

                scope.refreshLocation = function () 
                    geolocation.getLocation().then(function(data)
                        scope.coords =  lat:parseFloat(data.coords.latitude.toFixed(6)), lng:parseFloat(data.coords.longitude.toFixed(6)) ;       
                        var geocoder = new google.maps.Geocoder();
                        var latlng = new google.maps.LatLng(scope.coords.lat, scope.coords.lng);
                        scope.position = latlng;
                        scope.search();
                        geocoder.geocode( 'latLng': latlng , function (results, status) 
                            if (status == google.maps.GeocoderStatus.OK) 
                                if (results[0]) 
                                    scope.address = results[0].formatted_address;
                                 else 
                                    scope.address = 'Address not found';
                                
                             else 
                                scope.address = 'Geocoder failed due to: ' + status;
                            
                            scope.$digest();
                        );
                    );
                ;

                scope.search = function () 
                    if (!scope.position) 
                        alert('Please share your location to search');   
                    
                    searchService.update(setStores, scope.position, scope.searchText);      
                ;

                var setStores = function (stores) 
                    scope.stores = stores;
                    calculateDistance();
                    scope.$apply();
                

                var calculateDistance = function () 
                    for (var id in scope.stores) 
                        var store = scope.stores[id];
                        var storeLocation = new google.maps.LatLng(store.geometry.location.lat(), store.geometry.location.lng());
                        var distance = google.maps.geometry.spherical.computeDistanceBetween(scope.position, storeLocation);
                        store.distance = parseInt(distance);
                    
                

                scope.refreshLocation();
            ]).factory('searchService', ['$http', function(http)     
                return 
                    update: function (callback, position, text) 
                        var url = 'https://maps.googleapis.com/maps/api/place/nearbysearch/json';

                        var params = 
                            location: position,
                            radius: 2500,
                            types: ['store']
                        ;

                        if (text) 
                            params['name'] = text;
                        
                        map = new google.maps.Map(document.getElementById('map-canvas'), 
                            center: position,
                            zoom: 15
                        );

                        var service = new google.maps.places.PlacesService(map);
                        service.nearbySearch(params, callback);
                    
                
            ]);
        </script>
    </body>
</html>

【讨论】:

以上是关于Angular JS - 使用地理位置对集合进行排序的主要内容,如果未能解决你的问题,请参考以下文章

JAVA-初步认识-常用对象API(集合框架-Map集合-存储自定义对象)

js_sort()对数组元素进行排序

单击屏幕上的任意位置关闭所有 Angular JS Bootstrap 弹出窗口?

Java中如何对集合排序

如何在angular js中对登录服务进行base64编码

如何使用 Lodash.js 对集合/数组进行反透视?