Search code examples
appceleratorkml

Appcelerator alternative to KML in bencoding.map


I'm updating an Appcelerator app that used to use "bencoding.map" https://github.com/benbahrenburg/benCoding.Map/blob/master/documentation/index.md.

Now "bencoding.map" is deprecated so I updated to use the native Titanium map feature.

However I now have an issue where the "addKML" from "bencoding.map" is not available in the Titanium map api.

Does anyone know what I can use to replace the KML functionality? The code is below:

    function onkmlCompleted(){
        Ti.API.info("onkmlCompleted");
        Ti.API.info("onkmlCompleted"+JSON.stringify(mapLoadingWindow));
        mapLoadingWindow.close({animated:false});
        mapView.removeEventListener('kmlCompleted',onkmlCompleted);
    };

    mapView.addEventListener('kmlCompleted',onkmlCompleted);

    mapView.addKML({
        path:"some_file.kml", //Path to our kml file
        tag : 55, //Integer value used as the tag for all polygons and annotations. If you want use remove you need to set this to a known value.
        flyTo:false, //Will set your zoom to show all of your points added (false by default)        
        //Contains all of the details used to process overlays from your KML file
        overlayInfo:{
            title:'my kml batch key', //This identifies all of the overlay elements in your kml file. This is also used for delete or query operations.
            alpha:0.5, //Alpha value of your overlays
            lineWidth:1.2, //Line Width of your overlays
            strokeColor:'#000', //Stroke Color of your overlays
            color:'yellow', //Sets the color of all your overlays ( if left off, a random color will be selected)
            useRandomColor:true, //If true, a random color will be selected, this overrides the color provided if true              
        }
    });

Solution

  • One option would be to convert the kml data to JSON, then add the data to the native Titanium Map via the map module's methods, such as createPolygon, createPolyline, etc., as your data requires.

    I've done this using the togeojson Node.js module. Starting with Titanium 6, we can now directly access Node modules from within our projects. Assuming you are using an Alloy project:

    cd MyProject/app/assets
    npm install togeojson
    

    This will also install some other dependency modules, including xmldom, which we can use as well.

    Taking some sample KML LineString data and placing in MyProjects/app/assets, we can then convert it using the togeojson module. This will get us half way there. The Titanium Map module doesn't speak GeoJSON, but since GeoJSON is just JSON, we can iterate through it and get the data we need and then feed it that to the relevant Map module method.

    Below is an example of doing all this by sending the KML LineString data to the map's createPolyline method. Assuming this Alloy index.js controller that has a map view with the id of 'map' on it:

    //the titanium map module
    var Map = require('ti.map');
    //the node module we installed
    var togeojson = require('togeojson');
    //a dependency of togeojson which we will also use
    var DOMParser = require('xmldom').DOMParser;
    
    //with out data file in apps/assets
    var file = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, "linestring.kml");
    var kml = file.read().text;
    
    //the module requires the xml data in XML DOM, so we parse it first
    var xml = (new DOMParser()).parseFromString(kml, 'text/xml');
    
    //convert the kml to GeoJSON
    var converted = togeojson.kml(xml);
    
    //Here, we iterate through the GeoJSON file and pull out the coordinates to use to 
    //create our Map polygons, polylines, etc.  Your implementation will vary depending
    //on the data you are reading
    converted.features.forEach(function(feature){
        if(feature.geometry.type === 'LineString')
        $.map.addPolyline(Map.createPolyline({
            points: feature.geometry.coordinates,
            strokeColor: '#ff0000',
            strokeWidth: '2'
        }));
    });
    
    $.map.setRegion({
        latitude: 37.824664,
        latitudeDelta: 0.002,
        longitude: -122.364383,
        longitudeDelta: 0.002
    });