angularjs с Leafletjs

Следующий код директивы взят из http://jsfiddle.net/M6RPn/26/. Я хочу получить json-канал, который имеет много lat и long. Я могу легко получить json с $resource или $http в Angular, но как я могу передать его этой директиве, чтобы отобразить объект на карте?

module.directive('sap', function() {
    return {
        restrict: 'E',
        replace: true,
        template: '<div></div>',
        link: function(scope, element, attrs) {
            var map = L.map(attrs.id, {
                center: [40, -86],
                zoom: 10
            });
            //create a CloudMade tile layer and add it to the map
            L.tileLayer('http://{s}.tile.cloudmade.com/57cbb6ca8cac418dbb1a402586df4528/997/256/{z}/{x}/{y}.png', {
                maxZoom: 18
            }).addTo(map);

            //add markers dynamically
            var points = [{lat: 40, lng: -86},{lat: 40.1, lng: -86.2}];
            for (var p in points) {
                L.marker([points[p].lat, points[p].lng]).addTo(map);
            }
        }
    };
});

person MomentH    schedule 19.10.2012    source источник


Ответы (4)


Я мало знаю о Leaflet или о том, что вы пытаетесь сделать, но я предполагаю, что вы хотите передать некоторые координаты из своего контроллера в свою директиву?

На самом деле есть много способов сделать это... лучший из которых включает в себя использование масштаба.

Вот один из способов передать данные из вашего контроллера в вашу директиву:

module.directive('sap', function() {
    return {
        restrict: 'E',
        replace: true,
        template: '<div></div>',
        link: function(scope, element, attrs) {
            var map = L.map(attrs.id, {
                center: [40, -86],
                zoom: 10
            });
            //create a CloudMade tile layer and add it to the map
            L.tileLayer('http://{s}.tile.cloudmade.com/57cbb6ca8cac418dbb1a402586df4528/997/256/{z}/{x}/{y}.png', {
                maxZoom: 18
            }).addTo(map);

            //add markers dynamically
            var points = [{lat: 40, lng: -86},{lat: 40.1, lng: -86.2}];
            updatePoints(points);

            function updatePoints(pts) {
               for (var p in pts) {
                  L.marker([pts[p].lat, pts[p].lng]).addTo(map);
               }
            }

            //add a watch on the scope to update your points.
            // whatever scope property that is passed into
            // the poinsource="" attribute will now update the points
            scope.$watch(attr.pointsource, function(value) {
               updatePoints(value);
            });
        }
    };
});

Вот разметка. Здесь вы добавляете атрибут pointsource, который ищет функция ссылки для настройки $watch.

<div ng-app="leafletMap">
    <div ng-controller="MapCtrl">
        <sap id="map" pointsource="pointsFromController"></sap>
    </div>
</div>

Затем в вашем контроллере у вас есть свойство, которое вы можете просто обновить.

function MapCtrl($scope, $http) {
   //here's the property you can just update.
   $scope.pointsFromController = [{lat: 40, lng: -86},{lat: 40.1, lng: -86.2}];

   //here's some contrived controller method to demo updating the property.
   $scope.getPointsFromSomewhere = function() {
     $http.get('/Get/Points/From/Somewhere').success(function(somepoints) {
         $scope.pointsFromController = somepoints;
     });
   }
}
person Ben Lesh    schedule 19.10.2012
comment
Вышеприведенный ответ был очень полезным. Единственное, чего я пытаюсь добиться, это очистить все маркеры от функции. Любая идея? - person MomentH; 07.11.2012
comment
angular не всегда срабатывает, если вы просто сбрасываете массив, повторно инициализируя его, как я уверен, вы пытались. Итак, сначала вы можете попробовать это: $scope.pointsFromController = []; что может не сработать... если это не сработает, вы можете сделать это, удалив элементы вручную: $scope.pointsFromController.splice(0, $scope.pointsFromController.length); - person Ben Lesh; 07.11.2012

Недавно я создал приложение, используя Angular JS и листовка. Очень похоже на то, что вы описали, включая данные о местоположении из файла JSON. Мое решение похоже на blesh.

Вот основной процесс.

У меня есть элемент <map> на одной из моих страниц. Затем у меня есть директива заменить элемент <map> картой Leaflet. Мои настройки немного отличаются, потому что я загружаю данные JSON в Factory, но я адаптировал их для вашего варианта использования (извините, если есть ошибки). В Директиве загрузите файл JSON, затем выполните цикл по каждому из ваших местоположений (вам потребуется настроить файл JSON совместимым образом). Затем отобразите маркер на каждой широте/долготе.

HTML

<map id="map" style="width:100%; height:100%; position:absolute;"></map>

Директива

app.directive('map', function() {
return {
    restrict: 'E',
    replace: true,
    template: '<div></div>',
    link: function(scope, element, attrs) {

        var popup = L.popup();
        var southWest = new L.LatLng(40.60092,-74.173508);
        var northEast = new L.LatLng(40.874843,-73.825035);            
        var bounds = new L.LatLngBounds(southWest, northEast);
        L.Icon.Default.imagePath = './img';

        var map = L.map('map', {
            center: new L.LatLng(40.73547,-73.987856),
            zoom: 12,
            maxBounds: bounds,
            maxZoom: 18,
            minZoom: 12
        });



        // create the tile layer with correct attribution
        var tilesURL='http://tile.stamen.com/terrain/{z}/{x}/{y}.png';
        var tilesAttrib='Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.';
        var tiles = new L.TileLayer(tilesURL, {
            attribution: tilesAttrib, 
            opacity: 0.7,
            detectRetina: true,
            unloadInvisibleTiles: true,
            updateWhenIdle: true,
            reuseTiles: true
        });
        tiles.addTo(map);

        // Read in the Location/Events file 
        $http.get('locations.json').success(function(data) {
            // Loop through the 'locations' and place markers on the map
            angular.forEach(data.locations, function(location, key){

                var marker = L.marker([location.latitude, location.longitude]).addTo(map);

            });
        });
    }
};

Пример файла JSON

{"locations": [     
{   
    "latitude":40.740234, 
    "longitude":-73.995715
    }, 
{   
    "latitude":40.74277, 
    "longitude":-73.986654
    },
{   
    "latitude":40.724592, 
    "longitude":-73.999679
    }
]} 
person Brett DeWoody    schedule 14.03.2013

Директивы и mvc в angularJs — это разные технологии. Директивы обычно выполняются при загрузке страницы. Директивы больше предназначены для работы с html и xml. Когда у вас есть JSON, лучше всего использовать для работы фреймворк mvc.

После того, как страница отрендерится, чтобы применить директивы, вам часто нужно выполнить $scope.$apply() или $compile, чтобы зарегистрировать изменение на странице.

В любом случае, лучший способ включить службу в директиву — использовать инфраструктуру внедрения зависимостей.

Я заметил, что в вашей директиве отсутствует область действия: true или область действия: {}. Это оказывает большое влияние на то, насколько хорошо директива работает с родительскими контроллерами.

app.directive('mapThingy',['mapSvc',function(mapSvc){
  //directive code here.

}]);

app.service('mapSvc',['$http',function($http){
 //svc work here.
}])

Директивы применяются с помощью соответствия camelCase. Я бы не стал использовать или из-за проблем с IE. Альтернативой было бы

<div map-thingy=""></div>
person Eric Rohlfs    schedule 27.03.2013

Предполагая, что в вашем контроллере вы получили

$scope.points = // here goes your retrieved data from json

и ваш шаблон директивы:

<sap id="nice-map" points="points"/>

затем внутри вашего определения директивы вы можете использовать символ "=" для настройки двунаправленной привязки между вашей областью директивы и вашей родительской областью

module.directive('sap', function() {
return {
    restrict: 'E',
    replace: true,
    scope:{
      points:"=points"
    },
    link: function(scope, element, attrs) {
        var map = L.map(attrs.id, {
            center: [40, -86],
            zoom: 10
        });
        L.tileLayer('http://{s}.tile.cloudmade.com/57cbb6ca8cac418dbb1a402586df4528/997/256/{z}/{x}/{y}.png', {
            maxZoom: 18
        }).addTo(map);

        for (var p in points) {
            L.marker([p.lat, p.lng]).addTo(map);
        }
    }
};
});

Кроме того, вместо того, чтобы добавлять маркеры прямо на карту, рекомендуется сначала добавить маркеры в L.featureGroup, а затем добавить эту L.featureGroup на карту, потому что у нее есть метод clearLayers(), который избавит вас от некоторых головных болей, когда обновление маркеров.

grupo = L.featureGroup();
grupo.addTo(map);

for (var p in points) {
    L.marker([p.lat, p.lng]).addTo(grupo);
}


// remove all markers
grupo.clearLayers();

Я надеюсь, что это поможет, ура

person Jorge Avila    schedule 30.05.2013