Titanium Alloy - How to run procedure after screen created - google-maps

I'm trying to update the current location on map view. I get the current location in controller:
var updateCurrentLocation = function updateCurrentLocation(e){
Ti.API.info("Update current location on map");
$.map.setLocation({
latitude: e.coords.latitude,
longitude: e.coords.longitude,
latitudeDelta: 1,
longitudeDelta: 1
});
}
But the problem is that at this time the code run, the map view has not been created yet, so it cannot update the current location.
Can any one suggest some technique to solve this problem?
Thank you!

Are you not creating the map in the same controller? If you are just place the code after the map code, but that is obvious so I will assume you have thought of that.
Why not set the coords to the current user coords when you create the Map?
Worst case scenario, you can use setTimer(, timer ms) to call a function after a set amount of time if you wanted to call the updateCurrentLocation function after 500 milliseconds. This is not ideal.

starting up the map controller
function showMap() {
// create the new controller and pass in the
// model object as an argument 'item'
var ctrl = Alloy.createController('MapView', {
'item' : args.item // <-- pass is information + coords for map
});
setTimeout(function() {
args.photoListTab.open(ctrl.mainWindow);
}, 200);
}
in map controller
// get the photo object from the parameters
var coords = args.item.custom_fields.coordinates[0];
var locationString = args.item.custom_fields.location_address;
// create annotation
var annotation = Alloy.Globals.Map.createAnnotation({
latitude : Number(coords[1]),
longitude : Number(coords[0]),
title : args.item.custom_fields.location_string,
myid : args.item.id
});
complete solution here https://github.com/aaronksaunders/testInClass

Eventually I found there is a event call "complete" on the Map View. So, to do anything that you want to happen after the map loaded, in Map controller, use:
$.map.addEventListener('complete', function(e) {
Ti.API.info("Map controller: on Map complete");
$.trigger('complete', e); // Trigger event for other controller can listen too.
// And you can do other logic here.
});
Reference from Titanium Doc

Related

GoogleMapsEvent vs google.maps.event

I am in the process of upgrading from Ionic 2 beta to RC3. In doing so, I also update the version of Google Maps to "google-maps": "^3.2.1". The Change in Google Maps, is that now it uses a GoogleMap object instead of google.maps.Map (see here).
I have been using google.maps.event., but now need to update it to use GoogleMapsEvent (I think). Because I get the following error on ionic serve:
Cannot find name 'google'.
google.maps.event.addListenerOnce(that.map, 'bounds_changed', function (event) {
let position: CameraPosition = that.map.getCameraPosition();
let zoom: number = position.zoom;
setTimeout(function () {
// let center: GoogleMapsLatLng = that.map.getCenter();
google.maps.event.trigger(that.map, 'resize');
// that.map.setCenter(center);
that.map.setZoom(zoom);
}, 100);
});
But GoogleMapsEvent does not have a addListenerOnce or trigger method.
Question
How do I update the code above to use GoogleMapsEvent instead of google.maps.event?
Thanks
From the documentation, this is how you can add eventlisteners.
// create a new map by passing HTMLElement
let element: HTMLElement = document.getElementById('map');
let map = new GoogleMap(element);
// listen to MAP_READY event
map.one(GoogleMapsEvent.MAP_READY).then(() => console.log('Map is ready!'));

How to get dragged point on the DirectionsRenderer

I use google maps for drawing my route. I setup only 2 points (start and end). The problem is that I will have to send the route to the next page.
I know that I can catch event:
google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {
$("#full-route-json").val(encode64(JSON.stringify(directionsDisplay.directions.routes[0])));
});
But it will return all steps.
How to get the data only for my start and end points and dragged point like this:
AFAIK there is no implemented method to access these points(markers).
But these markers are stored inside a property of the DirectionsRenderer-instance.
The following code will give you these detail(please note that this code works now, but it may fail when the API changes)
google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {
var that=this;
setTimeout(function(){//we need a short delay
for(var k in that){//iterate over all properties
if(typeof that[k].markers!='undefined'){//find the desired property
var markers=that[k].markers,arr=[];
for(var i=0;i<markers.length;++i){//collect the data
arr.push(markers[i].position.toString());
}
alert(arr.join(',\n'));
}
}},100)
});

How to let user point their position in my Google maps application?

I want let user mark their position in our google maps application and then save it to our database, then it can be showed in our google maps application in the next time.
If you want to save the position where the user clicked you can use a "click" listener to get the latitude and longitude of the click with code like this then send it to your server using an Ajax style call where it can be stored in the database.
var clickListener = GEvent.addListener(map,"click",
function (overlay,latlng,overlaylatlng) {
alert(latlng);
});
This code is for v2 of the Google Maps API. Version 3 should have something similar.
An options is to try geolocation first and let the browser pinpoint them. If the browser doesn't support geolocation or an error occurs you can fall back onto them manually adding their position.
var geolocation = null; // holds the latlng object
navigator.geolocation.getCurrentPosition( geolocation_success_init, geolocation_error_init, {enableHighAccuracy: false, timeout: 10000} );
function geolocation_success_init( position ) {
geolocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
initialize_map();
}
function geolocation_error_init( error ){
initialize_map();
}
when you create your map check for geolocation
if ( geolocation ) {
marker = new google.maps.Marker({
position: geolocation,
map:.map,
title: "Your Location"
});
}

Google Maps v3 OverlayView.getProjection()

I cannot seem to figure out why the object returned by getProjection() is undefined. Here is my code:
// Handles the completion of the rectangle
var ne = recBounds.getNorthEast();
var sw = recBounds.getSouthWest();
$("#map_tools_selat").attr( 'value', sw.lat() );
$("#map_tools_nwlat").attr( 'value', ne.lat() );
$("#map_tools_selng").attr( 'value', ne.lng() );
$("#map_tools_nwlng").attr( 'value', sw.lng() );
// Set Zoom Level
$("#map_tools_zoomlevel").attr( 'value', HAR.map.getZoom()+1 );
document.getElementById("map_tools_centerLat").value = HAR.map.getCenter().lat();
document.getElementById("map_tools_centerLong").value = HAR.map.getCenter().lng();
// All this junk below is for getting pixel coordinates for a lat/lng =/
MyOverlay.prototype = new google.maps.OverlayView();
MyOverlay.prototype.onAdd = function() { }
MyOverlay.prototype.onRemove = function() { }
MyOverlay.prototype.draw = function() { }
function MyOverlay(map) { this.setMap(map); }
var overlay = new MyOverlay(HAR.map);
var projection = overlay.getProjection();
// END - all the junk
var p = projection.fromLatLngToContainerPixel(recBounds.getCenter());
alert(p.x+", "+p.y);
My error is: Cannot call method 'fromLatLngToContainerPixel' of undefined
Actually, i the reason why this happens is because the projection object is created after the map is idle after panning / zooming. So, a better solution is to listen on the idle event of the google.maps.Map object, and get a reference to the projection there:
// Create your map and overlay
var map;
MyOverlay.prototype = new google.maps.OverlayView();
MyOverlay.prototype.onAdd = function() { }
MyOverlay.prototype.onRemove = function() { }
MyOverlay.prototype.draw = function() { }
function MyOverlay(map) { this.setMap(map); }
var overlay = new MyOverlay(map);
var projection;
// Wait for idle map
google.maps.event.addListener(map, 'idle', function() {
// Get projection
projection = overlay.getProjection();
})
I kind of figured out what was going on. Even though it is still not crystal clear why this happens, I know that I had to instantiate the variable "overlay" right after instantiating my google map (HAR.map). So I practically moved that code snippet into my HAR class and now i use:
HAR.canvassOverlay.getProjection().fromLatLngToContainerPixel( recBounds.getCenter() );
So now, every time I create a map via my class "HAR" I also have a parallel OverlayView object within my class.
The Error could have been with losing scope of my class object, but I think it was more of the map event "projection_changed" not being fired. I got a hint from the map API docs for map class, under method getProjection():
"Returns the current Projection. If the map is not yet initialized (i.e. the mapType is still null) then the result is null. Listen to projection_changed and check its value to ensure it is not null."
If you are getting the similar issue, make sure that you assign your overlayView.setMAP( YOUR_MAP_OBJECT ) closely after instantiating the map object.

How to get markers after calling drive directions in Google Maps API?

I just started working using Google Maps API yesterday, and trying to set up drive directions to my map. My problem is: when I call the function load,
// [...]
gdir = new GDirections(map, directionsPanel);
// [...]
gdir.load("from: " + fromAddress + " to: " + toAddress);
it returns a map whose markers are not draggable. So, I need to make them draggable in order to recalculate the directions, but I can't get the markers objects.
Someone knows how can I do it?
You need to add a handler on the GDirections object for the addoverlay event:
GEvent.addListener(gdir, "addoverlay", onGDirectionsAddOverlay);
When your onGDirectionsAddOverlay handler is called you can iterate through the new markers and replace them with draggable copies:
for (var i = 0; i <= gdir.getNumRoutes(); i++)
{
var originalMarker = gdir.getMarker(i);
latLngs[i] = originalMarker.getLatLng();
icons[i] = originalMarker.getIcon();
newMarkers[i] = new GMarker(latLngs[i], { icon: icons[i], draggable: true, title: 'Kan flyttes' });
map.addOverlay(newMarkers[i]);
// add stuff to your newMarkers[i] drag end event...
// ...
//Bind 'click' event to original markers 'click' event
copyClick(newMarkers[i], originalMarker);
// Now we can remove the original marker safely
map.removeOverlay(originalMarker);
}
You can find a working example of this here (source).