ionic2 and google maps messing with back button pop - google-maps

I have a page that will display a google map in ionic2 with the latlong that I pass through to the page, it won't always be the same latlong.
The problem is when I hit this page, it loads fine, I then click the back button in the toolbar and it goes back fine, if I go again into the map screen it loads without issue, click back again no problem, however if I do another back button action from that parent view to go to the home screen all that happens is the briefly flashes the home screen then loads the original screen in view with no content or buttons loaded.
As soon as I disable my new google.maps.Map code everything runs fine.
My code:
//below all the imports
declare var google;
//at the top of the class
longitude: any;
latitude: any;
#ViewChild('map') mapElement: ElementRef;
//in the constructor
this.longitude = navParams.get('longitude');
this.latitude = navParams.get('latitude');
//call map load on page load
ionViewDidLoad() {
setTimeout(() => {
this.loadMap();
},100);
}
loadMap() {
let latLng = new google.maps.LatLng(this.latitude, this.longitude);
let mapEle = this.mapElement.nativeElement;
let mapOptions = {
center: latLng,
zoom: 15
}
//this.map
let map = new google.maps.Map(mapEle, mapOptions);
let marker = new google.maps.Marker({
map: map,
position: map.getCenter()
});
google.maps.event.addListenerOnce(map, 'idle', () => {
mapEle.classList.add('show-map');
});
}
So in summary:
View A - push to view B
View B (list of locations) - push to view C with a lat and long parameter
View C (google map displaying the lat long) - pop back to view B
View B can push view C again no problem
View C can pop back to view B no problem
View B pop back to view A - renders a blank view B and there is no longer the back button visible.
I have a feeling that for some reason when I pop back to view B from C it clears the view stack so that would mean view B to A has an issue and it just renders a blank view B....as soon as I disable the logic to create a new google.maps.Map everything works again as expected and I can pop back to View A without issue.
Edit: Upon further investigating it seems that view A does load, the constructor is called etc. but almost immediately view B renders and it's constructor is called....almost as if popping back to view A causing the button click that called view B initially from view A to fire again? or that intent to execute again...
I've been up for 2 nights trying to figure this out and it all works perfectly fine when I disable google maps on view C.

I changed my loadMap() function to the below:
loadMap() {
let latLng = new google.maps.LatLng(this.latitude, this.longitude);
let mapOptions = {
center: latLng,
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
let marker = new google.maps.Marker({
map: this.map,
animation: google.maps.Animation.DROP,
position: this.map.getCenter()
});
}
I also moved this.loadMap(); from the IonViewDidLoad() function and instead put it in ionViewDidEnter() function.
Not sure what google map library you are using but I am not using any ionic library I am instead importing google maps API into the index.html page using this:
<script src="https://maps.google.com/maps/api/js?key=[YOUR KEY]"></script>

Related

need to add multiple markers using custom google map api

i was checking out the google map api to integrate in my website.
made this page with what ever i could understand so far.
everything is working fine but there is just one thing, that i want three markers on the same map.
when i am adding more than one markers then the map stops working.
test link : http://goo.gl/X9q92s
you will have a better understanding if u see my link.
this is the code that i got from google map api.
and i edited it to get grey scale map with my desired marker box.
i just want to add two more....
Please help.
<script>
function initialize() {
var myLatlng = new google.maps.LatLng(-25.363882,131.044922);
var mapOptions = {
zoom: 4,
center: myLatlng
}
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Hello World!'
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
You should place your "new marker" code into its own function, like so:
function LoadMarkers(name, lat, lng) {
var MarkerLatLng = new google.maps.LatLng(lat, lng);
var MarkerOption = { map: map, position: MarkerLatLng, title: name};
var Marker = new google.maps.Marker(MarkerOption);
}
Putting this into its own function allows you to "refresh" the markers with ease, by simply invoking the function with a timer or some other event. A program I'm working on refreshes the map every few seconds, as my data source is constantly changing with new/removed/updated records that should be reflected immediately on the map. I think this is a great way to do this.
Then, in your program, you can create a loop that shoots the information for each marker in by invoking the LoadMarkers function. I've recently fallen in love with SqlDataReader.
Your loop would iterate through a SqlDataReader and each record read will invoke the script like so:
InvokeScript("LoadMarkers", New Object() {name, lat, lng})
This is a great moment to also add an InfoWindow for each marker.
var infowindow = new google.maps.InfoWindow(
{
content: "Content here"
});
As well as a click listener for the InfoWindows. ;)
google.maps.event.addListener(Marker, 'click', function () {
typeof infoWindowsOpenCurrently !== 'undefined' && infoWindowsOpenCurrently.close(); //If there is an InfoWindow currently open, close it
infowindow.open(map, Marker); //Open a new one for the selected marker
infoWindowsOpenCurrently = infowindow; //Set the new info window to the temporary variable
});
Some might not like this method of using a loop. I like it because I can "personalize" each marker for each record, while personalizing each of their InfoWindows too. In my code above, assume that "name" is a unique ID that lets you specify a specific marker for later use, such as identifying which marker was clicked and which InfoWindow is currently open.

Google Map not rendering correctly after first view with Backbone.js

Im creating a mobile app with Phonegap, Backbone.js, Require.js and PageSlider (https://github.com/ccoenraets/PageSlider).
I want to display a simple Google Map with a marker. The template looks like:
<div class='main-content' id='map-container'>
<a href="geo:51.903679,-8.468274">
<div id="map-canvas"></div>
</a>
</div>
Here is the view:
define(function (require) {
"use strict";
var $ = require('jquery'),
_ = require('underscore'),
Backbone = require('backbone'),
tpl = require('text!tpl/Map.html'),
side_nav = require('text!tpl/SideNav.html'),
template = _.template(tpl),
map, myLatlng, mapOptions, marker;
return Backbone.View.extend({
initialize: function () {
this.render();
},
initMap: function () {
myLatlng = new google.maps.LatLng(51.903679, -8.468274);
mapOptions = {
center: myLatlng,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(this.$el.find('#map-canvas')[0],
mapOptions);
marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: 'Christians Brothers College Cork'
});
},
render: function () {
this.$el.html(template({side_nav:side_nav}));
this.initMap();
},
});
});
Here is a link to the app. When you click on "location", the map renders perfectly. But when you navigate anywhere else, then back to location, only a tiny portion of the map can be seen in the top left hand corner.
I tried doing, which was suggested here:
google.maps.event.trigger(map, 'resize').
but to no avail. Any ideas?
Your view works on a node not appended to the DOM, thus without size, a situation Google Map is not very fond of. It is your router, via PageSlider, that does append the node after your render function has occurred.
Here is a demo of your predicament : http://jsfiddle.net/3C7g3/
You have several options to solve it:
call google.maps.event.trigger(map, 'resize') after the node is inserted into the DOM (this bit of code corresponds to your router entry for the map)
// assuming you stored the map object in your view
require(["app/views/Map"], function (Map) {
var view = new Map();
slider.slidePage(view.$el);
google.maps.event.trigger(view.map, 'resize');
});
http://jsfiddle.net/3C7g3/1/
insert the node into DOM before calling render. In your case, that probably means removing render from the view.initialize and calling view.render after container.append(page); in your slidePageFrom method.
http://jsfiddle.net/3C7g3/2/
a more hackish way would be to temporarily add the element to the DOM, apply Google Maps, and then remove it from the DOM
initMap: function () {
// assuming a temp class that hides the element. For example,
// .temp {position: absolute; visibility:hidden; }
this.$el.addClass('temp');
$('body').append(this.$el);
// ...
this.$el.remove();
this.$el.removeClass('temp');
}
http://jsfiddle.net/3C7g3/3/

Google map in a tab created with angularjs is not centered

I have the following problem:
I'm working in an aplication to book hotels that has tabs ("Hotel Details", "Map", "Reviews") in the overview page. the tabs are created with angularjs.
also, in the page I have the hotel address that is a link to the "Map" tab.
When I click on the "Map" tab, the google map is rendering ok. But, when I click on the hotel address, the "Map" tab opens but the map is not centered. If I refresh the page, it appears centered.
this is the code that process the map:
$scope.loadMap = function (targetID){
var latitude = $scope.latitude;
var longitude = $scope.longitude;
if(latitude && longitude && document.getElementById(targetID) != null ){
var center = new google.maps.LatLng(latitude, longitude);
var map_options = {
zoom: 13,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// create map
var map = new google.maps.Map(document.getElementById(targetID), map_options);
// configure marker
var marker_options = {
map: map,
position: center,
title: $scope.hotelName
};
// create marker
var marker = new google.maps.Marker(marker_options);
var infoWindow = new google.maps.InfoWindow();
window.setTimeout(function(){
google.maps.event.trigger(map, 'resize');
},2000);
}
}
Can you help me, please?
I've had this very problem when I was creating maps using Leaflet.js. I was trying to initialize the map inside of my angular service and it was loading very strangely. It appears you are trying to do the same thing, but you're doing it inside of your controller, rather than a service, but the effect is the same thing.
The problem is timing. Your controller is run before the DOM finishes loading and before angular has a chance to scan through the DOM to build out your Map page partial. Because of that, the page is only partially loaded when you call $scope.loadMap, which loads the google map, as you would expect. The problem is that once Angular finishes scanning the DOM partial, it modifies the DOM and then loads it into the view. When this happens, the google map has already been initialized to its default size based on the previous state of the DOM, and doesn't resize properly when angular is finished with the DOM.
Ok, that was a long explanation, but here's how you fix it:
You should do all of your map initialization inside of a directive's linking function. You could create a directive called something like app.directive('hotelMap'), which would initialize your map using the $scope.latitude and $scope.longitude variables from your controller.
link: function(scope, elem, attrs){
var center = new google.maps.LatLng(scope.latitude, scope.longitude);
var map_options = {
zoom: 13,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// create map
var map = new google.maps.Map(document.getElementById(targetID), map_options);
// configure marker
var marker_options = {
map: map,
position: center,
title: $scope.hotelName
};
// create marker
var marker = new google.maps.Marker(marker_options);
var infoWindow = new google.maps.InfoWindow();
}
And then in your map partial, you would have an element that looks something like <div hotel-map></div>. This fixes your problem, because your map will never be initialized until Angular has finished scanning/modifying the DOM and has finished rendering your partial. That way, the map's containing element will be at its final size/position and the map will be loaded into the element's center properly. Give it a try and let me know if that works.

Google Maps randomly crashed when enable browser's location tracking, why?

You can go to the live website to see how the problem occurred.
Steps to see the error are following
Go to the live website.
Enable you browser's location tracking.
Click one the the place name, it will open a new tab. It will display Google Map and center the map at the location that you clicked based on URL parameter.
The problem is sometimes it's not working randomly, it's showing plain grey background instead of showing the map.
If you try to refresh or click the place name again. The map might working.
But if you suddenly zoom out, it will crashed. You need to click the marker or dragging the map around, then you can zoom out with no problem.
All these problems are not occurred when you turn off the browser's location tracking.
Try it.
PS. Don't worry about 2 or 3 last digits of parameter. it has nothing
to do with this problem, I have tested it several times). The console log is not throw any errors also.
This is my code that involved when browser's location tracking is enabled. My full code is on JSFiddle.
function initialize() {
var myOptions = { zoom: 12, mapTypeId: google.maps.MapTypeId.ROADMAP };
map = new google.maps.Map(document.getElementById("map"), myOptions);
var infoWindow2 = new google.maps.InfoWindow({ content: '<div style="overflow:hidden;" id="currentInfoWindow"><p>You are here !!!</p></div>' });
// Try W3C Geolocation (Preferred)
if(navigator.geolocation) { // BEGIN IF USER ENABLE
browserSupportFlag = true;
navigator.geolocation.getCurrentPosition(function(position) { //getCurrentPosition
querystring = window.location.search.substr(1);
console.log(querystring);
element = querystring.split(",");
if (querystring) {
clickedLocation = new google.maps.LatLng(element[0],element[1]);
map.setCenter(clickedLocation);
map.setZoom(18);
} else {
initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
}
//Set map center to be the user's location
map.setCenter(initialLocation);
//Place the marker of current position
var markerCurrent = new google.maps.Marker({
position: initialLocation,
map: map,
title:"You are here !!!",
icon : 'assets/frontend/images/yourmarker.png'
});
// Attaching a click event to the current marker
google.maps.event.addListener(markerCurrent, "click", function(e) {
infoWindow.close();
this.getMap().setCenter(this.getPosition());
map.setZoom(12);
infoWindow2.open(map, markerCurrent);
});
// IF NOT SUPPORT OR ENABLE >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
} // End getCurrentPosition
, function() { handleNoGeolocation(browserSupportFlag); });
} // END IF Browser doesn't support Geolocation
else {
//Other code here.
}
Currently you will never run into this branch:
else {
initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
}
because there is always a QUERY_STRING.
Because of that initialLocation is not set, but you use it as argument for setCenter() .
changing this line:
clickedLocation = new google.maps.LatLng(element[0],element[1]);
into
initialLocation = new google.maps.LatLng(element[0],element[1]);
...should fix it.

Open Google Maps infowindows automatically for all of the markers and markerclusters

I have Google Map created with version of Google Maps api v3. It's "standard" Google Map, filled with markers and clusters. Every marker and cluster have it's own InfoWindow, showed when end user click on it.
What I need is that when map is loaded, to open all of InfoWindows of all markers and clusters showed on map.
Right now, they are showed only when I click on them:
google.maps.event.addListener(markerGreenCluster, 'clusterclick', function(markerGreenCluster) {
var content = '';
var info = new google.maps.MVCObject;
info.set('position', markerGreenCluster.center_);
var infowindow = new google.maps.InfoWindow();
aIWgreen.push(infowindow);
var center = markerGreenCluster.getCenter();
var size = markerGreenCluster.getSize();
var markers = markerGreenCluster.getMarkers();
// more code goes here...
})
I noticed that problem is in cluster definition, and method markerGreenCluster.getSize(); It returns number of grupped markers, and it can return it after whole map is loaded, or something like that.
Can you help me how can I achieve that all of InfoWindows are open (showed) when map is loaded?
the infowindows only open on click because you're only creating them on the click event listener. Move the code creating the infowindows out of the click handler, into a window load event handler instead.
To do this, what I do is create a InfoWindows object and stored it into the marker. Something like this
function CreateMarker(Lat, Lng, Title, Content) {
var aInfoWin = new google.maps.InfoWindow({
content: Content,
position: new google.maps.LatLng(Lat,Lng)
});
var aMarker = new StyledMarker({
title: Title,
position: new google.maps.LatLng(Lat,Lng),
MyInfoWin: aInfoWin
});
aMarker.MyInfoWin.open();
}
You can access to the Marker InfoWindows where you like (events, code,.....) like the other properties.
Code non tested, only to get the idea
Regards