I'm facing an issue with the open method on infoWindow object.
I want to set all my map utility objects dynamically but when the open method is called it raises me an error because the infoWindow object associated is undefined.
Here is my code :
// Markers & infoWindows
var markers = [];
var infoWindows = [];
for(var i=0; i<myList.length; i++) {
markers.push(
new google.maps.Marker({
position: myList[i].coord,
map: map,
title: myList[i].city
})
);
infoWindows.push(
new google.maps.InfoWindow({
content: myList[i].address
})
);
markers[i].addListener('click', function() {
infoWindows[i].open(map, markers[i]);
});
}
[ Where myList is just an arry of JSON formated objects. ]
All the markers and infoWindows are well set. I can access their properties and print them to the console.
But as I said the infoWindows[i] is typed undefined so the open method isn't found. A contrario I can access and print the content attribute of this infoWindows[i] object. Seems weird to me...
If someone is able to explain me I will be happy :)
Related question: Google Maps JS API v3 - Simple Multiple Marker Example
When the loop completes i is left at infoWindows.length, which is past the end of the array. One way to fix it is with function closure on i:
markers[i].addListener('click', (function(i) {
return function() {
infoWindows[i].open(map, markers[i]);
}}(i)));
proof of concept fiddle
code snippet:
function initialize() {
var map = new google.maps.Map(
document.getElementById("map_canvas"), {
center: new google.maps.LatLng(37.4419, -122.1419),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var bounds = new google.maps.LatLngBounds();
// Markers & infoWindows
var markers = [];
var infoWindows = [];
for (var i = 0; i < myList.length; i++) {
markers.push(
new google.maps.Marker({
position: myList[i].coord,
map: map,
title: myList[i].city
})
);
infoWindows.push(
new google.maps.InfoWindow({
content: myList[i].address
})
);
markers[i].addListener('click', (function(i) {
return function() {
infoWindows[i].open(map, markers[i]);
}
}(i)));
bounds.extend(markers[i].getPosition());
}
map.fitBounds(bounds);
}
google.maps.event.addDomListener(window, "load", initialize);
var myList = [{
coord: {
lat: 42,
lng: -72
},
city: "Somewhere",
address: "Somewhere"
}, {
coord: {
lat: 40.7127837,
lng: -74.0059413
},
city: "New York, NY, USA",
address: "New York, NY, USA"
}, {
coord: {
lat: 40.735657,
lng: -74.1723667
},
city: "Newark, NJ, USA",
address: "Newark, NJ, USA"
}];
html,
body,
#map_canvas {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map_canvas"></div>
Related
So I have 4 maps all together on one page. I have them all working through the for loop. Now I need to add markers/ Infowindows any idea the best way to add that into the loop, thanks!
// array of lat and lng locations
let locations = [
{
lat:-33.91722,
lng:151.23064
},
{
lat:22.3193,
lng:114.1694
},
{
lat:22.3255,
lng:114.3532
},
{
lat:23.3532,
lng:115.1234
}
];
let elements = ['maps', 'map-rec-one', 'map-rec-two', 'map-rec-three']; // array of html element ids
window.addEventListener('load',
function() {
for (i = 0; i < elements.length; i++) {
initMap(locations[i], elements[i]);
console.log(elements[i]);
console.log(locations[i])}
}, false);
function initMap(location, element) {
console.log(location)
console.log(element)
map = new google.maps.Map(document.getElementById(element), {zoom:4, center: location});
}
One option would be to add the information for the markers to your array.
(if you want the same markers on each map, you can simplify the array or have a separate array for the markers)
let locations = [{
lat: -33.91722,
lng: 151.23064,
markers: [{
lat: -33.91722,
lng: 151.23064,
info: "this is a marker at -33.91722,151.23064"
}, {
lat: -33.8722,
lng: 151.03064,
info: "this is a marker at -33.8722,151.03064"
},
{
lat: -33.5722,
lng: 151.03064,
info: "this is a marker at -33.5722,151.03064"
}
]
},
{
lat: 22.3193,
lng: 114.1694,
markers: [{
lat: 22.3193,
lng: 114.1694,
info: "this is a marker at 22.3193,114.1694"
}]
},
{
lat: 22.3255,
lng: 114.3532
},
{
lat: 23.3532,
lng: 115.1234
}
];
Then in your initMap function, add those markers to the map:
function initMap(location, element, infowindow) {
console.log(location)
console.log(element)
map = new google.maps.Map(document.getElementById(element), {
zoom: 4,
center: location
});
if (location.markers) {
for (var i = 0; i < location.markers.length; i++) {
createMarker(location.markers[i], map, infowindow);
}
}
}
createMarker function:
function createMarker(location, map, infowindow) {
let marker = new google.maps.Marker({
position: location,
map: map
});
google.maps.event.addListener(marker, 'click', function(evt) {
infowindow.setContent(location.info);
infowindow.open(map, marker);
})
}
proof of concept fiddle
code snippet:
// The following example creates complex markers to indicate beaches near
// Sydney, NSW, Australia. Note that the anchor is set to (0,32) to correspond
// to the base of the flagpole.
function initialize() {
// array of lat and lng locations
let locations = [{
lat: -33.91722,
lng: 151.23064,
markers: [{
lat: -33.91722,
lng: 151.23064,
info: "this is a marker at -33.91722,151.23064"
}, {
lat: -33.8722,
lng: 151.03064,
info: "this is a marker at -33.8722,151.03064"
},
{
lat: -33.5722,
lng: 151.03064,
info: "this is a marker at -33.5722,151.03064"
}
]
},
{
lat: 22.3193,
lng: 114.1694,
markers: [{
lat: 22.3193,
lng: 114.1694,
info: "this is a marker at 22.3193,114.1694"
}]
},
{
lat: 22.3255,
lng: 114.3532
},
{
lat: 23.3532,
lng: 115.1234
}
];
let elements = ['maps', 'map-rec-one', 'map-rec-two', 'map-rec-three']; // array of html element ids
window.addEventListener('load',
function() {
for (i = 0; i < elements.length; i++) {
initMap(locations[i], elements[i], new google.maps.InfoWindow());
console.log(elements[i]);
console.log(locations[i])
}
}, false);
function initMap(location, element, infowindow) {
console.log(location)
console.log(element)
map = new google.maps.Map(document.getElementById(element), {
zoom: 4,
center: location
});
if (location.markers) {
for (var i = 0; i < location.markers.length; i++) {
createMarker(location.markers[i], map, infowindow);
}
}
}
function createMarker(location, map, infowindow) {
let marker = new google.maps.Marker({
position: location,
map: map
});
google.maps.event.addListener(marker, 'click', function(evt) {
infowindow.setContent(location.info);
infowindow.open(map, marker);
})
}
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#maps,
#map-rec-one,
#map-rec-two,
#map-rec-three {
height: 100%;
width: 25%;
float: right;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<!DOCTYPE html>
<html>
<head>
<title>Complex Marker Icons</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initialize&libraries=&v=weekly" defer></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<div id="maps"></div>
<div id="map-rec-one"></div>
<div id="map-rec-two"></div>
<div id="map-rec-three"></div>
</body>
</html>
I have 2 markers on a map. I want to make those two markers visible on the map when some event happens. But when I add restriction option on map fitBounds does not show markers. When I remove restriction option it seems to work correctly.
Here is the sample code:
var map, markers;
var locations = [{
lat: 50.8503396,
lng: 4.351710300000036
},
{
lat: 49.9570366,
lng: 36.3431478
},
];
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 1,
center: {
lat: -28.024,
lng: 140.887
},
restriction: {
strictBounds: true,
latLngBounds: {
north: 85,
south: -85,
west: -180,
east: 180
},
},
});
markers = locations.map(function(location, i) {
return new google.maps.Marker({
position: location
});
});
markers.forEach(function(marker) {
marker.setMap(map);
});
}
setTimeout(function() {
var bounds = new google.maps.LatLngBounds();
markers.forEach(function(marker) {
bounds.extend(marker.position);
});
map.fitBounds(bounds);
}, 5000);
#map {
height: 400px;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap">
</script>
https://jsfiddle.net/fedman/6eoty0vm/
While this bug of google.maps.api still exists you can set map center to bounds center as a workaround.
map.fitBounds(bounds);
map.setCenter(bounds.getCenter());
This looks like a bug. It works fine with version 3.34 of the API as shown in the code below. Seems to work also fine depending on the map container height (tried with a height of 200px and it worked even with the latest versions).
I have opened a bug in the issue tracker.
var map, markers;
var locations = [{
lat: 50.8503396,
lng: 4.351710300000036
},
{
lat: 49.9570366,
lng: 36.3431478
},
];
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 1,
center: {
lat: -28.024,
lng: 140.887
},
restriction: {
strictBounds: true,
latLngBounds: {
north: 85,
south: -85,
west: -180,
east: 180
},
},
});
markers = locations.map(function(location, i) {
return new google.maps.Marker({
position: location
});
});
markers.forEach(function(marker) {
marker.setMap(map);
});
}
setTimeout(function() {
var bounds = new google.maps.LatLngBounds();
markers.forEach(function(marker) {
bounds.extend(marker.position);
});
map.fitBounds(bounds);
}, 5000);
#map {
height: 400px;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script async defer src="https://maps.googleapis.com/maps/api/js?v=3.34&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap">
</script>
I would like to ask about how to add an info window to a marker in Google Maps. The condition is, I have to create a program with multiple markers on a map. But how I can give a specified info window to each marker?
This is my code for now:
var markers = [];
var map;
var labels = 'ABCD';
var labelIndex = 0;
function initialize() {
map = new google.maps.Map(
document.getElementById("map"), {
center: new google.maps.LatLng(40.7127837, -74.0059413),
zoom: 11,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// New York, NY, USA (40.7127837, -74.0059413)
// Newark, NJ, USA (40.735657, -74.1723667)
// Jersey City, NJ, USA (40.72815749999999, -74.07764170000002)
// Bayonne, NJ, USA (40.6687141, -74.11430910000001)
addMarker({
lat: 40.7127837,
lng: -74.0059413
}, "red");
addMarker({
lat: 40.735657,
lng: -74.1723667
}, "green");
addMarker({
lat: 40.7281575,
lng: -74.0776417
}, "yellow");
addMarker({
lat: 40.6687141,
lng: -74.1143091
}, "orange");
}
google.maps.event.addDomListener(window, "load", initialize);
function addMarker(location, color) {
var marker = new google.maps.Marker({
position: location,
label: labels[labelIndex++ % labels.length],
icon: {
url: 'http://maps.google.com/mapfiles/ms/icons/' + color + '.png',
labelOrigin: new google.maps.Point(15, 10)
},
map: map
});
markers.push(marker);
}
Can someone give me a solution on how to resolve my problem?
You could do it like this:
var markers = [];
var map;
var labels = 'ABCD';
var labelIndex = 0;
function initialize() {
map = new google.maps.Map(
document.getElementById("map"), {
center: new google.maps.LatLng(40.7127837, -74.0059413),
zoom: 11,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// New York, NY, USA (40.7127837, -74.0059413)
// Newark, NJ, USA (40.735657, -74.1723667)
// Jersey City, NJ, USA (40.72815749999999, -74.07764170000002)
// Bayonne, NJ, USA (40.6687141, -74.11430910000001)
addMarker({
lat: 40.7127837,
lng: -74.0059413
}, "red", "New York is awesome!");
addMarker({
lat: 40.735657,
lng: -74.1723667
}, "green", "Newark is also cool!");
addMarker({
lat: 40.7281575,
lng: -74.0776417
}, "yellow", "Do not forget Jersey City!");
addMarker({
lat: 40.6687141,
lng: -74.1143091
}, "orange", "And not to mention Bayonne, too!");
}
google.maps.event.addDomListener(window, "load", initialize);
function addMarker(location, color, content) {
var infowindow = new google.maps.InfoWindow({
content: content
});
var marker = new google.maps.Marker({
position: location,
label: labels[labelIndex++ % labels.length],
icon: {
url: 'http://maps.google.com/mapfiles/ms/icons/' + color + '.png',
labelOrigin: new google.maps.Point(15, 10)
},
map: map
});
marker.addListener('click', function() {
infowindow.open(map, marker);
});
markers.push(marker);
}
I am using the google maps api and using grid clustering for the markers. I wanted to know if there is a way to exclude a single marker from clustering. I want a "You are here" marker that is always visible. I tried using a different array for just that marker and not including it the cluster function but that didn't work.
Does anyone have a solution for this?
Here is how i am doing the clustering
$(document).on('click', '#mapbut', function() {
var items, distances, you_are_here = [], markers_data = [], markers_data2 = [], fred, clust1, markss;
you_are_here.push({
lat : Geo.lat,
lng : Geo .lng,
animation: google.maps.Animation.DROP,
title : 'Your are here',
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 10
},
infoWindow: {
content: '<p>You are Here</p>'
}
});
function loadResults (data) {
if (data.map.length > 0) {
items = data.map;
for (var i = 0; i < items.length; i++)
{
var item = items[i];
var distances = [];
var dist2;
if (item.Lat != undefined && item.Lng != undefined)
{
markers_data.push({
lat : item.Lat,
lng : item.Lng,
title : item.Site,
infoWindow: {
content: '<p>' + item.Site + '</p><p>' + Math.round(item.distance) + ' miles away</p>'
}
});
}
}
}
map.addMarkers(markers_data);
map = new GMaps({
el: '#map',
lat: Geo.lat,
lng: Geo.lng,
zoom: 10,
mapTypeControl: false,
zoomControl: true,
zoomControlOptions: {
position: google.maps.ControlPosition.LEFT_CENTER
},
markerClusterer: function(map) {
options = {
gridSize: 50
}
clust1 = new MarkerClusterer(map,[], options);
return clust1;
},
scaleControl: true,
streetViewControl: false
});
map.addMarkers(you_are_here);
The GMaps clusters all the markers you add to it with the addMarker method (if you provide a MarkerClusterer).
One option: add your "special" marker (the one that you don't want clustered) to the map manually, so it isn't added to the MarkerClusterer:
The GMaps.map property is a reference to the Google Maps Javascript API v3 map object. So this will add a marker to the map without letting the GMaps library know about it:
you_are_here = new google.maps.Marker({
position: {lat: Geo.lat,lng: Geo.lng},
animation: google.maps.Animation.DROP,
title: 'Your are here',
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 10
},
map: map.map
});
proof of concept fiddle
code snippet:
var Geo = {
lat: 40.7281575,
lng: -74.07764
};
$(document).on('click', '#mapbut', function() {
var items, distances, you_are_here = [],
markers_data = [],
markers_data2 = [],
fred, clust1, markss;
function loadResults(data) {
if (data.map.length > 0) {
items = data.map;
for (var i = 0; i < items.length; i++) {
var item = items[i];
var distances = [];
var dist2;
if (item.Lat != undefined && item.Lng != undefined) {
markers_data.push({
lat: item.Lat,
lng: item.Lng,
title: item.Site,
infoWindow: {
content: '<p>' + item.Site + '</p><p>' + Math.round(item.distance) + ' miles away</p>'
}
});
}
}
}
map = new GMaps({
el: '#map',
lat: Geo.lat,
lng: Geo.lng,
zoom: 8,
mapTypeControl: false,
zoomControl: true,
zoomControlOptions: {
position: google.maps.ControlPosition.LEFT_CENTER
},
markerClusterer: function(map) {
options = {
gridSize: 50,
imagePath: "https://cdn.rawgit.com/googlemaps/v3-utility-library/master/markerclustererplus/images/m"
}
clust1 = new MarkerClusterer(map, [], options);
return clust1;
},
scaleControl: true,
streetViewControl: false
});
map.addMarkers(markers_data);
you_are_here = new google.maps.Marker({
position: {
lat: Geo.lat,
lng: Geo.lng
},
animation: google.maps.Animation.DROP,
title: 'Your are here',
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 10
},
infoWindow: {
content: '<p>You are Here</p>'
},
map: map.map
});
// map.addMarkers(you_are_here);
}
loadResults(data);
});
var data = {
map: [{
Lat: 40.7127837,
Lng: -74.005941,
Site: "New York, NY",
distance: 1
}, {
Site: "Newark, NJ",
Lat: 40.735657,
Lng: -74.1723667,
distance: 2
}]
};
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://rawgit.com/HPNeo/gmaps/master/gmaps.js"></script>
<script src="https://cdn.rawgit.com/googlemaps/v3-utility-library/master/markerclustererplus/src/markerclusterer.js"></script>
<input id="mapbut" type="button" value="map" />
<div id="map"></div>
To get around this is relatively simple, just after I send the markers array to MarkerClusterer I then add my location.
// Setup cluster markers
var markerCluster = new MarkerClusterer( gmap.map, options )
// add my location
gmap.addMarker({
lat: data.latitude,
lng: data.longitude
...
})
Thanks
This is what I have so far.
function init_map() {
var places = [
{ name: "Place 1", coords: new google.maps.LatLng(30.728752, -73.995525)},
{ name: "Place 2", coords: new google.maps.LatLng(30.733673, -73.990028)},
{ name: "Place 3", coords: new google.maps.LatLng(40.725778, -73.992249)}
]
var myOptions = {
zoom: 14,
center: places[0].coords,
mapTypeId: google.maps.MapTypeId.ROADMAP,
}
var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
for ( var x=0; x < places.length; x++ ){
var place = places[x];
var marker = new google.maps.Marker({
position: place.coords,
title: place.name,
icon: icon,
clickable: true,
infowindow: new google.maps.InfoWindow({content:"hello world"})
});
marker.setMap(map);
google.maps.event.addListener(marker, 'click', function() {
marker.infowindow.open(map, marker);
console.log(marker);
});
}
};
I'd like to have the default InfoWindow which you'd see when searching for an address on Google Maps appear instead of my own custom window. How is this possible?
What do you mean by its default Google content?
Also it might be better for you to create just 1 infowindow object and then share it amongst your markers.