Skip to content
This repository has been archived by the owner on May 26, 2022. It is now read-only.
Flavio Maria De Stefano edited this page Nov 3, 2016 · 3 revisions

Geo

Geographic API proxy and Map additional features like clustering - Documentation

Get current position

To retrieve current user position, use getCurrentPosition().

The method automatically raise geo.start and geo.end events, unless you pass silent: true

Geo.getCurrentPosition({
   silent: true,
   success: function(coords) {
      Ti.API.debug("You are at " + coords.latitude + ", " + coords.longitude);
   },
   error: function(err) {
      if (err.servicesDisabled === true) {
         Ti.API.error('Please activate the location services');
      } else {
         Ti.API.error("I can't localize you man: " + err);
      }
   }
});

The Object returned from the success callback is a LocationCoordinates type.

Clustering

When there are so many markers, you should cluster them.

The method is markerCluster(markers, event).

The event is retrieved from TiMap.regionchanged event, the markers could be an instance of Backbone.Collection or an Object id-indexed.

Each single marker of the collection must be in this format:

{ 
   lat: {Number}, 
   lng: {Number}, 
   id: {Number, Unique}
}

The returned value is an Array: if the marker is a cluster, an object like is passed:

{ 
   latitude: {Number}, // latitude of the marker
   longitude: {Number}, // longitude of the markers
   count: {Number}  // the number of markers clustered
}

Otherwise, the ID of the marker in your marker collections is returned.

This is a sample code to clarify his:

var TiMap = require('ti.map');
var WhateverCollection = Alloy.createCollection('whatever');

// the handler
function updateMap(event) {
   var data = Geo.markerCluster(event, WhateverCollection);
   var annotations = [];
   _.each(data, function(c){
      if (_.isNumber(c)) {
         // if the marker is a Number, we have a reference in our AlloyCollection or HashMap
         var marker = Me.get(c); 
         annotations.push(TiMap.createAnnotation({
         	id: c,
         	latitude: marker.get('lat'), longitude: marker.get('lng'),
         	title: marker.get('title'),
         }));
      } else {
         // otherwise, just create an annotation!
         annotations.push(TiMap.createAnnotation({
            latitude: c.latitude, longitude: c.longitude
         }));
      }
   });

   // finally, set the annotations
   $.mapView.setAnnotations(annotations);
}

// Fetch the collection
WhateverCollection.fetch({
   success: function() {
      updateMap(_.extend($.mapView.region, { source: $.mapView })); // Render the clusters first-time
      $.mapView.addEventListener('regionchanged', updateMap); // add the handler to update the map every time that a regionbound is changed
   }
});

You can configure the clustering with config.json configuration (T.geo), with these properties:

  • clusterPixelRadius: The clustering radius expressed in px
  • clusterRemoveOutofBB: Remove markers that are out of the bounding box to optimize memory
  • clusterMaxDelta: The value before the clustering is off.

Another example of clustering

This is another example using arrays instead of collections.

var args = $.args;

var Timap = require('ti.map');

// Private var that store all the requests
var requests = {};

function fetchRequests() {
   HTTP.getJSON('/api', { method: 'getRequests' }).then(function(data) {

      // Re-map the data from the server to Array to an HashMap (JS object)
      data.forEach(function(e) { requests[ e.id ] = e; });

      // And immediately update the annoations on the map
      updateMap(_.extend({}, $.mapView.region, { source: $.mapView }));

   });
}

// This is the method that update the annoations on the map,
// clustering it using `Geo.markerCluster`
function updateMap(e) {

   // Sorry bro.
   if (requests == null) return;

   // Using the `e` variable that contains currents informations about the event map,
   // re-cluster the pins
   var markers = Geo.markerCluster(e, requests, {
      latitude: 'latitude',
      longitude: 'longitude',
   });

   // And set the annoations in the map
   $.mapView.annotations = markers.map(function(c) {

      if (_.isNumber(c)) {
      
         // If `c` is a number, it represents an id that you have to use to obtain
         // the pin again, with its informations of latitude, longitude
         c = requests[c];
      
         return Timap.createAnnotation({
            latitude: c.latitude,
            longitude: c.longitude,
         });

      } else {

         // otherwise, this is a cluster containing latitude, longitude and count of markers in 
         return Timap.createAnnotation({
            latitude: c.latitude,
            longitude: c.longitude,
            customView: Alloy.createController('map/cluster', c).getView()
         });
      }

   });
}

///////////////
// Listeners //
///////////////

$.mapView.addEventListener('regionchanged', updateMap);

//////////
// Init //
//////////

fetchRequests();