Saturday 14 January 2017

A leaflet template for ionic

Leaflet is a very useful javascript library to insert map into an app. It has lots of extensions, which simplify it's use. I use it mainly in ionic's app, so I have created a repo on GitHub as a start point. It's extends the side menu template with leaflet.

The key points are:
  1. Get a GeoJson through an api call (markersApi.js)
  2. Create a map (with OSM as baselayer).
  3. Add the GeoJson to the map (using the marker-cluster library).
  4. Add a marker on tap.

Add the map to the html

To add leaflet map in ionic (and angular) there is a directive to simplify it: angular-leaflet-directive (or you can use ui-leaflet). In the html you can just put:

<leaflet data-tap-disabled="true" defaults="map.defaults" id="map" layers="map.layers" lf-center="map.center"></leaflet>


And after you have incluse in the app's model dependencies, the angular-leaflet directive, and have defined an object in the controller as $scope.map which contains the center point when load the map, the layer to load and some optional parameter you can see the map.
 
//set the property of the map
$scope.map = {
             center: {
                lat: 46,
                lng: 11,
                zoom: 8
             },
             defaults: {
                zoomControl: false,
                attributionControl: true
             },
             layers: {
                baselayers: {
                    xyz: {
                        name: 'OpenStreetMap (XYZ)',
                        url: 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
                        type: 'xyz',
                        zoomControl: false,
                        layerOptions: {
                            attribution: '© OpenStreetMap contributors'
                        }
                    }
                }
            }
        };

You also can center the map to the actual position:
 
var options = {enableHighAccuracy: false,timeout: 20000};

//center the map on the actual position.

var setCurrentPosition = function () {
   $ionicLoading.show({
   template: '',
   duration: 7000
   });
   $cordovaGeolocation.getCurrentPosition(options).then(function (position) {
      if (position) {
         $scope.map.center.lat = position.coords.latitude;
         $scope.map.center.lng.longitude = position.coords.longitude;
         } else {}
       }).catch(function (err) {}).finally(function () {
         $ionicLoading.hide();
       });
};

Add markers to the marker

The markers are in a GeoJson format, so they are among throughout the L.GeoJSON layer:
 
//create a marker cluster layer
var markers = L.markerClusterGroup();

/*
*When the view enter:
* get the map.
* get the markers form the api.
* create the geojson layer
* add the geojson layer to the marker cluster layer
* add the marker cluster layer to the map
*
*/
$scope.$on("$ionicView.enter", function (scopes, states) {
   leafletData.getMap("map").then(function (map) {
   map.invalidateSize();
   markersApi.getPoints().then(function (resp) {
      var geojson = new L.GeoJSON(resp, {
          
         onEachFeature: function (feature, layer) {
            //open a ionic modal on click 
            layer.on('click', function (e) {
            $scope.map.center.lat = feature.geometry.coordinates[1];
            $scope.map.center.lng = feature.geometry.coordinates[0];
            $scope.feature = feature;
            $scope.openLayersModal();
            });
           }
      });
   markers.addLayer(geojson);
   map.addLayer(markers);
}, function (err) {
      console.log('ERROR', err.status);
});
});

Add a marker on tap

To add a marker on tap,  you can add this code:

var setMarker = function (latlng) {
   if (!newMarker) {
     newMarker = new L.marker(latlng).addTo(map);
   } else {
      newMarker.setLatLng(latlng).update();
   }
};
var newMarker = null;
map.on('click', function (e) {
setMarker(e.latlng);
});



the repo is available on GitHub at this link.

NOTE: angular-leaflet use leaflet at version 0.7.7 so the marker-cluster is the old version as you can see in the bower.json file.

No comments:

Post a Comment