All of my markers are coming from an AJAX call and are accurately placed on the map. However, the initial view is fully zoomed out, along the equator, in North America.
I know the solution lays somewhere with bounds.extend and map.fitBounds but apparently I'm doing it wrong.
I've always had an issue with this, so hopefully someone can help elevate this thorn in my side:
var map;
var markers = [];
var home_marker;
function initialize() {
// Display a map on the page
if ( document.contains(document.getElementById("map_canvas")) ) {
bounds = new google.maps.LatLngBounds();
map = new google.maps.Map(document.getElementById("map_canvas"), {
zoom: 12,
center: new google.maps.LatLng(48.4222, -123.3657)
});
// a new Info Window is created
infoWindow = new google.maps.InfoWindow();
// Event that closes the InfoWindow with a click on the map
google.maps.event.addListener(map, 'click', function() {
infoWindow.close();
});
// Add Home Marker
home_marker = new google.maps.Marker({
position: new google.maps.LatLng(user_address_lat, user_address_lng),
map: map,
icon: '/images/map-icon-your-home.png'
});
}
}
function displayMarkers( properties ) {
// this variable sets the map bounds and zoom level according to markers position
var bounds = new google.maps.LatLngBounds();
// For loop that runs through the info on markersData making it possible to createMarker function to create the markers
for (var i = 0; i < properties.length; i++){
var latlng = new google.maps.LatLng(properties[i]['latitude'], properties[i]['longitude']);
var price_current = properties[i]['price_current'];
var bedrooms = properties[i]['bedrooms'];
var total_baths = properties[i]['total_baths'];
var listing_id = properties[i]['listing_id'];
createMarker( latlng, price_current, bedrooms, total_baths, matrix_unique_ID );
// Marker’s Lat. and Lng. values are added to bounds variable
bounds.extend(latlng);
}
// Finally the bounds variable is used to set the map bounds
// with API’s fitBounds() function
map.fitBounds(bounds);
}
function createMarker( latlng, price, bedrooms, bathrooms, matrix_id ) {
var formatted_price = accounting.formatMoney(price, '$', 0);
var marker = new google.maps.Marker({
map: map,
position: latlng,
icon: '/images/map-icon.png'
});
google.maps.event.addListener(marker, 'click', function() {
// Variable to define the HTML content to be inserted in the infowindow
var iwContent = '<div class="row"><div class="small-12 columns"><img src="http://www.mywebsite.com/properties/'+listing_id+'/image-'+matrix_id+'-1.jpg"></div></div>' +
'<div class="row"><div class="small-12 columns"><p class="price-current text-center">'+formatted_price+'</p></div></div><hr>' +
'<div class="row"><div class="small-6 columns"><p class="bedrooms"><span class="fw-semi-bold">Beds:</span> '+bedrooms+'</p></div>' +
'<div class="small-6 columns"><p class="total-baths"><span class="fw-semi-bold">Baths:</span> '+bathrooms+'</p></div></div>';
// including content to the infowindow
infoWindow.setContent(iwContent);
// opening the infowindow in the current map and at the current marker location
infoWindow.open(map, marker);
});
}
// Sets the map on all markers in the array.
function setMapOnAll(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
// Removes the markers from the map, but keeps them in the array.
function clearMarkers() {
setMapOnAll(null);
}
// Deletes all markers in the array by removing references to them.
function deleteMarkers() {
clearMarkers();
markers = [];
}
Make a new Part to your script or make a new one, and code it specificly to change zoom in camera ammount and, add ui button for it.
Related
I have a problem with my map. I'm using the google maps funtion LatLngBounds() in order to calculate the center between two given points.
I'm able to get the location and I consoled.log the value (even if, for some reason the values are empty, I'm still able to print them to the map) so I'm able to place my markers on the map, but for some reason, when I add the function for the bound, I break the map, I get an error and I'm only able to see a marker (one marker.
Here's my code:
var locs;
function initMap() {
var locations_two = [
['<div class=""><p>Vancouver</p></div>', 49.27597, -123.1185, 1],
['<div class=""><p>Ottawa</p></div>', 45.3683, -75.70258]
];
locs = new google.maps.Map(document.getElementById('locs'), {
center: {lat: 49.276873, lng: -123.118948},
zoom: 4
});
var image = $myimage;
var infowindow = new google.maps.InfoWindow();
var marker_two, i;
var bounds = new google.maps.LatLngBounds();
for (i = 0; i < locations_two.length; i++) {
var mybond = locations_two[i];
var myLatLng = new google.maps.LatLng(mybond[1], mybond[2]);
marker_two = new google.maps.Marker({
position: myLatLng,
map: locs,
icon: image
});
bounds.extend(myLatLng);
google.maps.event.addListener(marker_two, 'click', (function(marker, i) {
return function() {
infowindow.setContent(locations_two[i][0]);
infowindow.open(map, marker);
}
})(marker_two, i));
map.fitBounds(bounds);
}
}
As I said, I declared the variable var bounds = new google.maps.LatLngBounds(); before the loop and then I use the two other google map function in order to call the map.fitBounds(bounds); at the very end, to center my map but I get this error:
Uncaught (in promise) TypeError: Cannot read property 'fitBounds' of undefined
Which doesn't make sense for me because the bounds variable is actually defined? Any thoughts?
With the posted code I get a javascript error (in Chrome):
Uncaught (in promise) ReferenceError: map is not defined
Your google.maps.Map object is named locs, not map. This line:
map.fitBounds(bounds);
should be:
locs.fitBounds(bounds);
proof of concept fiddle
code snippet:
var locs;
function initMap() {
var locations_two = [
['<div class=""><p>Vancouver</p></div>', 49.27597, -123.1185, 1],
['<div class=""><p>Ottawa</p></div>', 45.3683, -75.70258]
];
locs = new google.maps.Map(document.getElementById('locs'), {
center: {
lat: 49.276873,
lng: -123.118948
},
zoom: 4
});
var infowindow = new google.maps.InfoWindow();
var marker_two, i;
var bounds = new google.maps.LatLngBounds();
for (i = 0; i < locations_two.length; i++) {
var mybond = locations_two[i];
var myLatLng = new google.maps.LatLng(mybond[1], mybond[2]);
marker_two = new google.maps.Marker({
position: myLatLng,
map: locs,
});
bounds.extend(myLatLng);
google.maps.event.addListener(marker_two, 'click', (function(marker, i) {
return function() {
infowindow.setContent(locations_two[i][0]);
infowindow.open(map, marker);
}
})(marker_two, i));
locs.fitBounds(bounds);
}
}
html,
body,
#locs {
height: 100%;
margin: 0;
padding: 0;
}
<div id="locs"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap" async defer></script>
I am developing an application which consist in bulky wastes' signalements where each citizen could inform authorities about the place to collect them.
Datas (addresses and coordinates) are stocked into firebase and I'm working on the display of markers in a google map.
Here is the code:
jQuery(function($) {
// Asynchronously Load the map API
var script = document.createElement('script');
script.src = "//maps.googleapis.com/maps/api/js?&callback=initialize";
document.body.appendChild(script);
});
function initialize() {
var map;
var bounds = new google.maps.LatLngBounds();
var mapOptions = {
mapTypeId: 'roadmap'
};
// Display a map on the page
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
map.setTilt(45);
markers: findMarkers();
console.log(markers);
console.log(markers.length);
// Info Window Content
var infoWindowContent = [
['<div class="info_content">' +
'<p>' + 'adresse' +'</p>' + '</div>'],
];
// Display multiple markers on a map
var infoWindow = new google.maps.InfoWindow(), marker, i;
// Loop through our array of markers & place each one on the map
for( i = 0; i < markers.length; i++ ) {
var position = new google.maps.LatLng(markers[i][1].lat(), markers[i][1].lng());
bounds.extend(position);
marker = new google.maps.Marker({
position: position,
map: map,
title: markers[i][0]
});
// Allow each marker to have an info window
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infoWindow.setContent(infoWindowContent[i][0]);
infoWindow.open(map, marker);
}
})(marker, i));
}
var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function(event) {
this.setZoom(14);
google.maps.event.removeListener(boundsListener);
});
}
function findMarkers(){
markers = [];
var data = firebase.database();
var dataRef = firebase.database().ref("signalement/");
dataRef.on("child_added", function(data) {
var key = data.key;
const signalement = data.val();
const adresse = signalement.adresse;
const coordonnees = signalement.coordonnees;
var marker = [adresse, coordonnees];
markers.push( marker );
});
// Multiple Markers
return markers;
}
</script>
</head>
<body>
<div id="map_wrapper">
<div id="map_canvas" class="mapping"></div>
</div>
</html>
Problem comes from the console.log(markers.length); which is equal to 0 ! While the previous console.log(markers); shows the object.
Maybe a syntax error of var marker?
Anyway.
Someone to help me for this case?
Thanks
Looks like the problem is with the firebase data callback. Since you have set the callback for google map api callback=initialize the marker data is not ready from the firebase by the time it executes the function.
I would rather do something like this (keeping in mind that firebase callback takes longer than the google map script being loaded & map has dependency on the data from firebase).
jQuery(function($) {
// Asynchronously Load the map API
var script = document.createElement('script');
script.src = "//maps.googleapis.com/maps/api/js?&callback=findMarkers";
document.body.appendChild(script);
});
function initialize(markers) {
var map;
var bounds = new google.maps.LatLngBounds();
var mapOptions = {
mapTypeId: 'roadmap'
};
// Display a map on the page
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
map.setTilt(45);
console.log(markers);
console.log(markers.length);
// Info Window Content
var infoWindowContent = [
['<div class="info_content">' +
'<p>' + 'adresse' +'</p>' + '</div>'],
];
// Display multiple markers on a map
var infoWindow = new google.maps.InfoWindow(), marker, i;
// Loop through our array of markers & place each one on the map
for( i = 0; i < markers.length; i++ ) {
var position = new google.maps.LatLng(markers[i][1].lat(), markers[i][1].lng());
bounds.extend(position);
marker = new google.maps.Marker({
position: position,
map: map,
title: markers[i][0]
});
// Allow each marker to have an info window
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infoWindow.setContent(infoWindowContent[i][0]);
infoWindow.open(map, marker);
}
})(marker, i));
}
var boundsListener = google.maps.event.addListener((map), 'bounds_changed', function(event) {
this.setZoom(14);
google.maps.event.removeListener(boundsListener);
});
}
function findMarkers(){
markers = [];
var data = firebase.database();
var dataRef = firebase.database().ref("signalement/");
dataRef.on("child_added", function(data) {
var key = data.key;
const signalement = data.val();
const adresse = signalement.adresse;
const coordonnees = signalement.coordonnees;
var marker = [adresse, coordonnees];
markers.push( marker );
});
// send prepared marker array to map initialize function
intialize(markers);
}
I receive json data from a server and need to add them to a google map. It works fine, however, I only see one marker and I assume every time I add a marker it changes it to new coordinates and doesnt add an extra marker. How can I define markers as an array?
$.getJSON(url, function(data) {
var entry = data.feed.entry;
$(entry).each(function(){
for (var prop in this["gsx$instruments"]) {
//alert(this["gsx$instruments"][prop]);
listContacts(this["gsx$instruments"][prop])
var myLatLng = {lat: Number(this["gsx$ycor"][prop]), lng: Number(this["gsx$xcor"][prop])};
var map = new google.maps.Map(document.getElementById('googleMap'), {
zoom: 13,
center: myLatLng
});
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: this["gsx$instruments"][prop]
});
}
// Column names are name, age, etc.
//$('.results').prepend('<h2>'+this.gsx$instruments.$t+'</h2><p>'+this.gsx$type.$t+'</p>');
});
});
Add a new function addMarker and use that function to include markers also keep the map variable outside the ajax call as well. updated code below
var map = new google.maps.Map(document.getElementById('googleMap'), {
zoom: 13,
center: {lat: LAT, lng: LONG}
});
function addMarker(position, map, title){
var marker = new google.maps.Marker({
position: position,
map: map,
title: title
});
}
$.getJSON(url, function(data) {
var entry = data.feed.entry;
$(entry).each(function(){
for (var prop in this["gsx$instruments"]) {
//alert(this["gsx$instruments"][prop]);
listContacts(this["gsx$instruments"][prop])
var myLatLng = {lat: Number(this["gsx$ycor"][prop]), lng: Number(this["gsx$xcor"][prop])};
addMarker(myLatLng,map,this["gsx$instruments"][prop]);
}
// Column names are name, age, etc.
//$('.results').prepend('<h2>'+this.gsx$instruments.$t+'</h2><p>'+this.gsx$type.$t+'</p>');
});
});
Essentially, you first need to add the markers to an array of markers
Suppose you have JSON providing the markers and supposing each marker has a name and coordinates attributes
function formatMarkers (){
// Loop through all of the JSON entries provided in the response
for (var i = 0; i < markersArray.length; i++) {
var markers = markersArray[i];
// Create popup windows for each record
var contentString = '<p><b>Name</b>: ' + markers.name + '</p>';
// Converts each of the JSON records into Google Maps Location format
formattedMarkers.push({
latlon: new google.maps.LatLng( markers.coordinates[1], markers.coordinates[0] ),
message: new google.maps.InfoWindow({
content: contentString,
maxWidth: 320
}),
username: markers.name
});
}
return formattedMarkers;
}
Then you need to render each of them
formattedMarkers.forEach(function (n) {
var marker = new google.maps.Marker({
position: n.latlon,
map: map,
icon: icon
});
// For each marker created, add a listener that checks for clicks
google.maps.event.addListener(marker, 'click', function () {
// When clicked, open the selected marker's message
n.message.open(map, marker);
});
marker.setMap(map);
}
I hope I've been helpful.
I have been playing around with the twitter API getting random tweets or even geo tagged tweets and also with the google maps API. However I want to combine this two and try and show geo tagged tweets on a google map. Here is my code for getting the geo tagged Tweets which work fine.
var geo = (geo.coordinates[0], geo.coordinates[1])
//var geo = (34.052234, -118.243685)
client.get('search/tweets', { q:string.teamname, geocode: geo, count: 5},
function searchTweets(err, data, response) {
for(var index in data.statuses){
var tweet = data.statuses[index];
console.log(tweet.text);
console.log(tweet.geo.coordinates)
}
});
On a different file, I generated a map based on Longitude and Latitude, and I had the understanding that once I had retrieved the coordinates for the tweets, I could represent the tweets on a Google Map in the same way. However, my code is not working. My question is, how would I combine both pieces of code to generate a map which is marked with geo located Tweets?
function initialize() {
var myLatlng = new google.maps.LatLng(geo.coordinates[0], geo.coordinates[1]);
var mapOptions = {
center: myLatlng
zoom: 10,
}
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title:"Tweet});
var infowindow = new google.maps.InfoWindow({
content: 'Geo tagged Tweet',
maxWidth:200 });
infowindow.open(map,marker);
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker); });
}
google.maps.event.addDomListener(window, 'load', initialize);
I would do something like this (untested - I'm just writing down some thoughts).
1) You should strip down init so that it just contains the map set up. Ensure map is declared outside of the function, and include a call to the function that fetches your data using the lat/lng data.
var map;
function initialize() {
var lat = geo.coordinates[0];
var lng = geo.coordinates[1]
var myLatlng = new google.maps.LatLng(lat, lng);
var mapOptions = { center: myLatlng, zoom: 10 }
map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
getData(lat, lng, processData);
}
2) You wrap your data fetching code in a new function declaration, which accepts lat/lng data, and a callback.
function getData(lat, lng, callback) {
client.get('search/tweets', { q:string.teamname, geocode: geo, count: 5},
function searchTweets(err, data, response) {
callback(data.statuses);
}
)
};
3) Process the tweet information. For each tweet create a marker (add the marker to an array of markers) and update the map
function processData(data) {
var markers = [];
for (var i = 0, l = data.length; i < l; i++) {
var marker = new google.maps.Marker({
id: i,
position: myLatlng(data[i].geo.coordinates[0], data[i].geo.coordinates[1),
map: map,
title: "Tweet"
});
markers.push(marker);
var infowindow = new google.maps.InfoWindow({
content: data[i].text,
maxWidth: 200
});
infowindow.open(map, marker);
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map, marker);
});
}
}
I have a forloop that has a call to a function inside of it. Within that function, I'm pushing values to an array called markers.
Is there a way to access the values of the markers array outside of the forloop?
Here's the code:
<script type="text/javascript">
// arrays to hold copies of the markers and html used by the side_bar
// because the function closure trick doesnt work there
var map = null;
geocoder = new google.maps.Geocoder();
var side_bar_html = "";
var icon = '';
var markers = [];
function codeAddress(this_address,index,callback) {
geocoder.geocode( { 'address': this_address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
callback.call(window,index,results[0].geometry.location)
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
function initialize() {
// create the map
var myOptions = {
zoom: 3,
center: new google.maps.LatLng(46.90, -121.00),
mapTypeControl: true,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
google.maps.event.addListener(map, 'click', function() {
infowindow.close();
});
for (var i = 0; i < businesses.length; i++) {
codeAddress(businesses[i].address,i,function(i,point){
var description = businesses[i].description;
if(businesses[i].business_type == "Wine"){
//http://chart.apis.google.com/chart?chst=d_map_pin_letter&chld=A|00CC99|000000
icon = 'http://google-maps-icons.googlecode.com/files/wineyard.png';
}else if(businesses[i].business_type == "Golf"){
icon = 'http://google-maps-icons.googlecode.com/files/golf.png';
}else{
icon = 'http://google-maps-icons.googlecode.com/files/festival.png';
}
var marker = createMarker(point,businesses[i].name,description,icon);
// put the assembled side_bar_html contents into the side_bar div
document.getElementById("side_bar").innerHTML = side_bar_html;
});//End codeAddress-function
}//End for-loop
console.log(markers);
var markerCluster = new MarkerClusterer(map, markers);
}
// A function to create the marker and set up the event window function
function createMarker(latlng, name, html,icon) {
var contentString = html;
var marker = new google.maps.Marker({
position: latlng,
map: map,
icon: icon,
zIndex: Math.round(latlng.lat()*-100000)<<5
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
// save the info we need to use later for the side_bar
markers.push(marker);
// add a line to the side_bar html
side_bar_html += '<a href="javascript:myclick(' + (markers.length-1) + ')">' + name + '<\/a><br />'+html+'<br />';
}
var infowindow = new google.maps.InfoWindow({
size: new google.maps.Size(150,50)
});
// This function picks up the click and opens the corresponding info window
function myclick(i) {
google.maps.event.trigger(markers[i], "click");
}
</script>
As you can see, the last line says "var markerCluster = new MarkerClusterer(map, markers);" This is where I want to be able to access the information from.
Thanks!
The problem is you're not accounting for the asynchronous nature of the call to codeAddress. You're calling that function in a loop, which is triggering a series of calls to the Google Maps API.
You are running this line:
var markerCluster = new MarkerClusterer(map, markers);
...even before the callbacks have been triggered.
To fix, maintain a counter. Each time the callback is triggered increase that counter by 1. Once it is equal to businesses.length you know all the addresses have been geo-coded, and all markers have been added to the array. Now you can create the MarkerCluster.
Yes, Declare it before the for loop.
var markers
for(....
Bring the definition of the marker outside of the for loop ...
var markers = new Array ();
for (var i = 0; i < businesses.length; i++) {
markers[i] = ...