How to draw a selected marker from a list in google maps using angularjs (Ionic) controllers?

3

I'm doing a mobile app with Ionic Framework and I have a list of places in a lugares.html view, each item has a name, address and location (coordinates). I want that when selecting an item the marker of my current and selected position is drawn. I tried to do it with a href by passing the coordinates by parameters to the map view, but it only works the first time and then the map does not appear. My doubt is in the part of "// Draw marker of place", I do not know if to put it in a function, how to call it .. I am new in this. If they need any other part of the code, they let me know. (I clarify that I am using tabs and the map is a tab and places is another). I would also like to know if I am doing it in the correct way (using the href ). I appreciate your help.

Archivo lugares.html

<ion-view view-title="Lugares">

<ion-content>
    <ion-list>

        <ion-item class="item-text-wrap" ng-repeat="item in lugares" 
                  href="#/tab/mapa/{{item.latitud}}/{{item.longitud}}">
            <h2>{{item.nombre}}</h2>
            <h3>{{item.calle}} {{item.numero}} </h3>
            <h4>{{item.latitud}}, {{item.longitud}}</h4>
        </ion-item>

    </ion-list>
</ion-content>

Map status

 .state('tabs.mapa',{
         url:'/mapa/:lat/:lng',
         views:{
            'mapa-tab':{
            templateUrl: 'templates/mapa.html',
            controller: 'ControladorMapa'
            } 
         }
 })

Map controller

.controller('ControladorMapa', function($scope, $state, $cordovaGeolocation){
  // Mapa con centro en mi posicion
  var options = {timeout: 10000,  enableHighAccuracy: true};

  $cordovaGeolocation.getCurrentPosition(options).then(function(position){

    var centro = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

    var mapOptions = {
      center: centro,
      zoom: 15,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };

    $scope.map = new google.maps.Map(document.getElementById("map"), mapOptions);
  //Marcador
  // Esperar que se cargue el mapa
  google.maps.event.addListenerOnce($scope.map, 'idle', function(){
  //Crear marker
  var marker = new google.maps.Marker({
    map: $scope.map,
    animation: google.maps.Animation.DROP,
    position: centro
  });  
  //Ventana 
  var infoWindow = new google.maps.InfoWindow({
    content: "Estás aqui!"
  });
  //Evento de ventana
  google.maps.event.addListener(marker, 'click', function () {
    infoWindow.open($scope.map, marker);
  });
  // Dibujar marker de lugar
  $scope.lat = $state.params.lat;
  $scope.lng = $state.params.lng;
  if ($scope.lat != 0 && $scope.lng != 0) {
    var marker = new google.maps.Marker({
      map: $scope.map,
      animation: google.maps.Animation.DROP,
      position: new google.maps.LatLng($scope.lat, $scope.lng)
    });   
  } 
});
}, function(error){
  console.log("No pudimos localizarte.");
});
});
    
asked by Martin 04.03.2016 в 18:13
source

1 answer

1

Remember that angular has its own life cycle and google maps work mainly with events so if you use the native API you will have to constantly be calling $scope.apply() to synchronize your view with the maps. My recommendation is that you use the angular-google-maps library that handles all those details for you.

Making a map with a marker is very simple

places.html

<ion-view view-title="Lugares">

<ion-content>
    <ion-list>

        <ion-item class="item-text-wrap" ng-repeat="item in lugares" 
                  ui-sref="tabs.mapa({lat: item.latitud, lng: item.longitud})">
            <h2>{{item.nombre}}</h2>
            <h3>{{item.calle}} {{item.numero}} </h3>
            <h4>{{item.latitud}}, {{item.longitud}}</h4>
        </ion-item>

    </ion-list>
</ion-content>

Notice that I changed the href of your items by ui-sref to handle the states. This is a good practice because if you modify the configuration of these you do not have to change the code in the view so that they work again.

controller

.controller('ControladorMapa', function($scope, $state, $cordovaGeolocation, uiGmapGoogleMapApi) {
  // Mapa con centro en mi posicion
  var options = {timeout: 10000,  enableHighAccuracy: true};

  $cordovaGeolocation.getCurrentPosition(options).then(function(position) {
        uiGmapGoogleMapApi.then(function() {
            $scope.map = {
                center: {
                    latitude: position.coords.latitude,
                    longitude: position.coords.longitude
                },
                zoom: 15           
            };

            $scope.marker = {
                idKey: 1,
                coordinates: {
                    latitude: position.coords.latitude,
                    longitude: position.coords.longitude
                },
                options: {
                    animation: google.maps.Animation.DROP,
                    icon:'url/icon.png'
                },
                click: function () {
                   $scope.showWindow = true;
                }
            };

            $scope.showWindow = false;
        });   

    }, function(error){
        console.log("No pudimos localizarte.");
    });
});

Notice that I call the function uiGmapGoogleMapApi.then(...) , the reason for this is because you are using an animation ( google.maps.Animation.DROP ) that is a native object of the maps and because:

  

Ensure that angular-google-maps does not start processing any policy until the Google Maps SDK is fully loaded!

mapa.html

<ui-gmap-google-map center="map.center" zoom="map.zoom">
    <ui-gmap-marker idKey="marker.idKey" click="marker.click"
        coords="marker.coordinates" options="marker.options">
        <ui-gmap-window coords="marker.coordinates" show="showWindow">
            <div>Estás aqui!</div>
        </ui-gmap-window>
    </ui-gmap-marker>
</ui-gmap-google-map>

If you want to use the info-window with dynamic content you have to use the directive ng-non-bindable because angular-google-maps compile them manually. Read a more detailed explanation at SO article .

Do not forget configure the library in case you need to change the behavior of all your maps

.config(function(uiGmapGoogleMapApiProvider) {
    uiGmapGoogleMapApiProvider.configure({
        key: 'your api key',
        libraries: 'weather,geometry,visualization'
    });
});    
    
answered by 19.04.2016 / 15:34
source