Google Maps not correctly initialising within Angular directive - javascript

I am trying to use the Google Maps API to display a map within an Angular site but it appears to not initialise correctly.
My html page uses bootstrap nav nav-tabs and I use an Angular controller to switch between them.
<ul class="nav navbar-nav">
<li ng-class="{ active:myCtrl.isSet('map') }">
<a href ng-click="myCtrl.setTab('map')">Show Map</a>
</li>
</ul>
With one of the tabs containing only the google map canvas element - set up using an angular directive
Module.directive('mapPage', function() {
return {
restrict: 'E',
template: '<div id="map-canvas"></div>'
};
});
Within my angular controller I set up a listener for the window 'load' event to initialise the map as follows:
google.maps.event.addDomListener(window, 'load', myCtrl.initMap);
myCtrl.initMap = function() {
var mapOptions = {
zoom: 12,
center: new google.maps.LatLng(55.937879, -3.241619),
};
myCtrl.map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(55.937879, -3.241619),
map: myCtrl.map
});
myCtrl.map.setCenter(new google.maps.LatLng(55.937879, -3.241619));
}
What I see on screen is the map element showing a grey area with the location marker not centered correctly (it's just off screen).
If I move the map-canvas div to the main section of my index.html page (rather than a sub page within the app) it loads correctly, so I know my Google API js code and html is correct. The map also shows if the page is resized.
It just doesn't work when used on a page that is not rendered immediately. I have tried searching for similar questions/answers but could not find this particular issue.
I have created a simple fiddle that demonstrates the issue.
http://jsfiddle.net/johntough/nc0u7h2c/5/
Any help appreciated!

The issue is, you are loading Map on window load whereas the container will appear on click. Google Map has behavior (never seen documented yet but I have observed it many time though) that if the container is hidden on load, it does not load map in there. I changed your "load" to "click" and its working. The only change is as below,
google.maps.event.addDomListener(window, 'click', myCtrl.initMap);
See fiddle and verify yourself. http://jsfiddle.net/anandgh/nc0u7h2c/6/

Related

Google Map losing its long/lat in Bootstrap tabbed interface

I am using ACF's Google Map to load a map on my page. I pretty much copied everything exactly and slightly modifying the map js with more options on it for styling purposes. I had to change mainly this part in order for the map to load:
$('a[href="#directions"]').on('shown.bs.tab',function(){
$('.hotel-map').each(function(){
// create map
map = new_map( $(this) );
google.maps.event.trigger(map, 'resize');
});
});
Using their doc ready wasn't working, the map would appear as a grey box. The code change above produces a map, however, once I click onto another tab and then back onto the tab that holds the map, the longitude and latitude seems to disappear. It loads a map that is somewhere way off.
Here's the full js code.
EDIT
This is what I updated the code to:
$(document).ready(function(){
$('.hotel-map').each(function(){
// create map
map = new_map( $(this) );
});
});
$('a[href="#directions"]').on('shown.bs.tab',function(){
// popup is shown and map is not visible
google.maps.event.trigger(map, 'resize');
center_map( map );
});
After you have triggered the map resize call the center_map(map); function (which is in the code you linked) which will center the map to your markers.

Making Google maps automatically zoom out more when displaying specified location

I've got a bootstrap website that is using google maps to display a location as the header image.
You can see the webpage here: http://www.tarmastersasphalt.com/contact.asp
The html code in the page is this:
<div id="map" class="map img-responsive">
</div>
.
The page pulls in these standard bootstrap functions in the footer:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script type="text/javascript" src="assets/plugins/gmap/gmap.js"></script>
.
and the page also calls in this function:
var ContactPage = function () {
return {
//Basic Map
initMap: function () {
var map;
$(document).ready(function(){
map = new GMaps({
div: '#map',
lat: 38.9721102,
lng: -94.1037494
});
var marker = map.addMarker({
lat: 38.9721102,
lng: -94.1037494,
title: 'Tar Masters.'
});
});
},
//Panorama Map
initPanorama: function () {
var panorama;
$(document).ready(function(){
panorama = GMaps.createPanorama({
el: '#panorama',
lat : 38.9721102,
lng : -94.1037494
});
});
}
};
}();
.
And then performs this function:
<script type="text/javascript">
jQuery(document).ready(function() {
ContactPage.initMap();
});
</script>
.
This all works fine. What I want to do is to have the google map actually appear more zoomed out when first displayed on the page. I think you can use something like this &z=nn or ,nnz in the link to accomplish this.
.
For example - if you use a browser and go directly to this URL:
https://www.google.com.au/maps/place/1426+State+Hwy+TT,+Bates+City,+MO+64011,+USA/#38.9555594,-94.1035777,17z/data=!3m1!4b1!4m2!3m1!1s0x87c11502459d838b:0xadf0c711b5a89c2a
you will see the map as it is displayed on my website. But if you go here:
https://www.google.com.au/maps/place/1426+State+Hwy+TT,+Bates+City,+MO+64011,+USA/#38.9734448,-94.1113454,13z/data=!4m2!3m1!1s0x87c11502459d838b:0xadf0c711b5a89c2a
you will see the map as I want it to appear on my website. Notice the use of ,17z in the first link, and ,13z in the second link. (BTW: I also noticed that it seemed to change the coordinate numbers.. not sure what that is all about.)
.
So my question is as follows: Is there any way to tell the gmap function that I want it to be more zoomed out upon first displaying (without having to manually zoom out once it has been displayed)?
I think I have read somewhere that you can add some invisible markers that will force google to zoom out more in order to display all markers in the visable area.. but I am not sure how to accomplish this either.
.
Note: Please view the website on a large screen to see what I am talking about. (I use a static image as the header image when the window size get's small, because the interactiveness of the map doesn't work well with smart phone displays.. you can't scroll past the header image as it takes up the whole viewport, and all you do is move the map around, not scroll down the page.)
.
Any help will be appreciated!
you must define the zoom in the options you pass to GMaps, e.g.:
map = new GMaps({
div: '#map',
lat: 38.9721102,
lng: -94.1037494,
zoom: 10
});
(The default-value is 15)

Use Angular in javascript call function parameters

I want to display google maps in my page for every place (lieux).In my HTML page I have the function for the google maps.
<script>
function initialize(long,lat) {
var mapCanvas = document.getElementById('map_canvas');
var mapOptions = {
center: new google.maps.LatLng(long, lat),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(mapCanvas, mapOptions)
}
google.maps.event.addDomListener(window, 'load', initialize);
document.getElementById('map_canvas').style.display='block';
</script>
And I have the button to dispaly the map.
<div class="tab-pane" id="tab_b" ng-controller="LieuController as lieu">
<div class="list-group-item" ng-repeat="lieu in lieu.lieux ">
<button onclick="initialize({{lieu.x}},{{lieu.y}})">Click me</button>
<div id="map_canvas"></div>
</div>
So is it possible to call the function with the parameters like I did or is there another way?
There are several problems with your code. Technically it's possible to mix Angular and pure javascript DOM 0 events like you are trying. However..
1. If you already tried your own code, then you should have seen the error Angular throws in this case:
Interpolations for HTML DOM event attributes are disallowed.
This effectively prevents usage Angular scope data with out-of Angular world code. There is a workaround though you can take. You can render necessary data in some attributes and then use them. For example:
<button onclick="initialize(this.getAttribute('data-x'), this.getAttribute('data-y'))"
data-x="{{l.x}}" data-y="{{l.y}}">Click me</button>
2. Event if you fix above problem you will still have to address duplicated ids issue. Since your initialize function is supposed to render a map in separate containers per ngRepeat row, each with id map_canvas. And at the same time you library onload event, which calls initialize again.
google.maps.event.addDomListener(window, 'load', initialize);
3. That being said, you should not build an app with such an unsuccessful design. You should really work on understanding main AngularJS concepts and philosophy.
In your case you should probably make use of ng-click instead of onclick, define initialize in some sort of custom service, maybe write custom directive to handle each separate map rendering in proper containers.

Showing a google map in angular-ui modal?

Trying to load a simple google map within an angular-ui modal. However no luck. The data get's passed in fine, but nothing works in terms of the map... Please help.
$modalInstance.opened.then(function() {
var mapOptions = {
center: new google.maps.LatLng(34.834442, -82.3686479),
zoom: 8
};
new google.maps.Map(document.getElementById("eventMap"), mapOptions);
});
Inside the modal html:
<div class="row clearfix">
<div class="col-md-5" id="eventMap" style="display: block; height: 150px;"></div>
</div>
I tried this in the regular page HTML and worked fine...
What am I missing?
Thank you in advance!
You can use angularjs-google-maps; an AngularJS directive for Google maps that is very flexible and powerful and easy to use. I've prepared a working demo for your case:
http://plnkr.co/edit/eEtaGH?p=preview
I hope this helps.
To remove the grayness, according to https://angular-ui.github.io/angular-google-maps/#!/faq:
If rendering starts before elements are full size, google maps calculates according to the smaller size. This is most commonly the case with a hidden element (eg, ng-show). To fix this, use "ng-if" instead, as this will wait to attach to the DOM until the condition is true, which should be after everything has rendered fully.
I've modified your plunker http://plnkr.co/edit/JetUBY?p=preview to remove the grayness.
Controller:
var ModalInstanceCtrl = function ($scope, $modalInstance, lat, lng) {
$scope.render = true;
// code here
}
Template:
<map ng-if="$parent.render" center="[{{$parent.lat}}, {{$parent.lng}}]" zoom-control="true" zoom="8"> </map>
You need to trigger 'resize' event. Follow these lines:
var map = new google.maps.Map(document.getElementById("eventMap"), mapOptions);
google.maps.event.trigger(map, 'resize', function () {
// your callback content
});
I too ran Into a similar situation, where I am loading a map in an angular modal instance. I too searched many places and did't get the correct simple solution for it.
So I gone deeper and found a simple solution for this issue.
The issue is that, the map is trying to get the div from the modal before it gets loaded, and the solution is:
In your controller take a $timeout angular parameter,
function MyController($scope,$cookies,$modal,$window,roomService,$timeout) {
**** after all your model code is defined ****
$modalInstance.opened.then(function() {
function initialize() {
var latlng = new google.maps.LatLng(-34.397, 150.644);
var myOptions = {
zoom: 8,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("eventMap"),
myOptions);
}
$timeout(function() {
initialize()
}, 1000);
});
*** use the time out to make the div load and then call the map ***
}
This time out made the map to load perfectly in the modal. A simple solution.

Google Maps API 3 loading icon

Is there a way to have a loading icon while the map is loading markers? I am using google maps API 3 with javascript and cant find much information on this.
This event is now called "status_changed" per the API docs: https://developers.google.com/maps/documentation/javascript/reference#KmlLayer
It can be used like this:
google.maps.event.addListener(kmlLayer, 'status_changed', function () {
if (kmlLayer.getStatus() == google.maps.KmlLayerStatus.OK) {
// Success
}
else {
// Failure
}
});
If you're loading markers using a KmlLayer object, then you can attach a listener to the event metadata_changed which gets fired after the KmlLayer has loaded all the information.
So you can have your custom loading icon display as soon as you initialize your map, then make the call for the markers using new google.maps.KmlLayer(...). In the listener for metadata_changed you can remove the custom loading icon, or hide it from displaying. So when the KmlLayer finishes loading, then it'll run the code to remove your loading icon.
You can attach listeners by going:
google.maps.event.addListener(kmlLayerObject, 'metadata_changed', function () {
...
}
You could also "hide" the map canvas with a loading div and show it after initialization.
Another thing to be aware of is when the map is hidden on init, it may behave strangely that can be fixed by "resizing" the map:
http://groups.google.com/group/google-maps-js-api-v3/browse_thread/thread/251f20b769d116ea/ba3ca54f5e1352a2

Categories

Resources