Google Map Marker Clusters - google-maps

i've been trying to implement a new feature on one of my Google maps (MarkerClusterer), but i am not quite there yet.
It is running OK, but not smoothly and it would be great if you would look through the code and give me any tips/advice.
I am running a test here: (Link removed)
Please let me know if you need anymore info.
Any help is appreciated :)

You seem to be doing an awful lot within the loop that creates your markers. For instance you should only need to do var markerCluster = new MarkerClusterer(...) after that loop, not within every iteration of it!
Ok, here I've simply moved that line out of your loop.
for (var i = 0; i < mapLocationsdata.businesses.length; i++) {
var businesses = mapLocationsdata.businesses[i];
var pos = new google.maps.LatLng(businesses.lat, businesses.lng);
var marker = new google.maps.Marker({
position: pos,
map: map,
title: businesses.company,
icon: placemarker[businesses.placemaker],
clickable: true,
draggable:false,
animation: google.maps.Animation.DROP
});
markers.push(marker);
(function(i, marker){
var infobox = new google.maps.InfoWindow({
content:
//This creates the content inside the popup info window when clicked
'<div class="info"><div class="info1"><h4>'
+businesses.company+
'</h4></div><div class="infotel">'
+businesses.itemAdresse+businesses.itemPostBy+businesses.itemTlf+businesses.itemEmail+businesses.itemWeb+
'</div><div class="clearfix"></div></div>',
});
//This function opens the info box and toggles the icon bounce
marker.addListener('click', function() {
infobox.open(map, marker);
toggleBounce(map, marker);
});
//This function stops the bouncs on the icon once the infowindow is closed
infobox.addListener('closeclick', function() {
toggleBounce(map, marker);
});
// POSSIBLY THIS FUNCTION COULD BE MOVED OUT OF THE LOOP TOO
//This makes them bounce when clicked
function toggleBounce() {
if (marker.getAnimation() != null) {
marker.setAnimation(null);
} else {
marker.setAnimation(google.maps.Animation.BOUNCE);
}
}
})
//The marker loop generates all of the markers
// NO IDEA WHAT THE POINT OF THIS LINE IS:
(i, marker);
//Associate the styled map with the MapTypeId and set it to display.
map.mapTypes.set('map_style', styledMap);
map.setMapTypeId('map_style');
}
var markerCluster = new MarkerClusterer(map, markers, {
gridSize: 60,
minimumClusterSize: 2,
calculator: function(markers, numStyles) {
if (markers.length >= 50) return {text: markers.length, index: 3}; // red
if (markers.length >= 5) return {text: markers.length, index: 2}; // yellow
return {text: markers.length, index: 0}; } // blue
});

Related

Google map marker click event using angular

I want create a click event using angular js google map api.
On click on the marker I want to call a function without opening the info window.
How can I do this ?
$scope.map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: { lat: parseFloat(Center_lat) , lng: parseFloat(center_lang) }
});
$scope.infowindow = new google.maps.InfoWindow({
// content: ''
});
angular.forEach($scope.panoramas, function(value, index) {
var latLang = $scope.panoramas[index].project_latLng ;
// console.log(latLang)
var LatLngArr = latLang.split(",");
var lat = LatLngArr[0];
var lang = LatLngArr[1];
console.log("lat " ,lat);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(parseFloat(lat), parseFloat(lang)),
map: $scope.map,
icon:"images/map-circle.png",
draggable:true,
label: {
color: 'black',
fontWeight: 'bold',
text: $scope.panoramas[index].panoId,
},
title: $scope.panoramas[index].panoId
});
var content = '<a ng-click="ShowCenterPano(' + index + ')" class="btn btn-default">View details</a>';
var compiledContent = $compile(content)($scope)
google.maps.event.addListener(marker, 'click', (function(marker, content, scope) {
return function() {
scope.infowindow.setContent(content);
scope.infowindow.open(scope.map, marker);
};
})(marker, compiledContent[0], $scope));
$scope.ShowCenterPano = function(index) {
// alert(JSON.stringify($scope.panoramas[index]));
}
Here Info window is opening. How can I remove the info window and directly call the ShowCenterPano() function.
Everything you want to happen when you click on the marker is inside the listener.
I think you are making your code needlessly complicated. Just put a listener on your marker marker.addListener('click', function() {}); and in this function you run ShowCenterPano()
And the reason the infowindow is opening is because you ask it to open with this line of code scope.infowindow.open(scope.map, marker);

infoWindow and center on click outside map

I have been playing around with Google Maps, and would like to center on a marker and open the appropriate infoWindow when I click on an element outside the map.
For example I have;
<div id="map"></div>
Store A
Opening Hours: 10-10
Store B
Opening Hours: 10-4
Store C
Opening Hours: 9-9
Store D.
Opening Hours: 8-9
I would like it to work, when I click on one of the stores in the list (outside of the map), it call the appropriate marker, centres on it and opens the attached infoWindow.
The infoWindow is working on marker click.
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 11,
center: {
lat: -33.800426,
lng: 142.038494
}
});
setMarkers(map);
}
// Data for the markers consisting of a name, a LatLng and a zIndex for the
// order in which these markers should display on top of each other.
var stores = [
['A', -33.771624, 142.888128, 1],
['B', -33.843956, 142.994875, 2],
['C', -33.818086, 142.995699, 3],
['C', -33.812697, 143.229200, 4],
];
function setMarkers(map) {
// Adds markers to the map.
for (var i = 0; i < stores.length; ++i) {
var store = stores[i];
const marker = new google.maps.Marker({
position: {
lat: store[1],
lng: store[2]
},
map: map,
animation: google.maps.Animation.DROP,
title: store[0],
zIndex: store[3],
});
attachStoreTitle(marker);
}
}
// Attaches an info window to a marker with the provided message. When the
// marker is clicked, the info window will open with message.
function attachStoreTitle(marker) {
var infowindow = new google.maps.InfoWindow({
content: marker.title
});
marker.addListener('click', function() {
infowindow.open(marker.get('map'), marker);
});
}
initMap()
Completed fiddle at https://jsfiddle.net/00e58pba/8/
Attach event listener to markers and then open correct infoWindow -
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
// Close all other infoboxes
for (var j = 0; j < markers.length; j++) {
markers[j].infobox.close(map);
}
// Open correct info box
markers[i].infobox.open(map, markers[i]);
}
})(marker, i));
If I've understood what you're asking, I think you should be able to do this:
marker.addListener('click', function() {
infowindow.open(marker.get('map'), marker);
marker.get('map').setCenter(this.getPosition());
});

GoogleMaps - gmaps.js with clustering and multiple cluster solution

So am I am using gmaps.js and the gmaps.js along with marker clusterer. In my case I may have multiple markers with the exact same location, but in reality represent different data. To overcome this I am trying to implement the solution found here on SO - in particular the solution by Nathan Colgate.
The idea is when max zoom has reached on a cluster it will execute the multiChoice function. I have this part working. What I cannot get to work is showing an infoWindow with that function.
My goal is to show an infoWindow on this cluster click to display information about each marker (particularly each marker's infoWindow content (this will have additional details specific to it).
JS :
//create the map
var map = new GMaps({
el: '#map_canvas_main',
lat: response.results[0].lat,
lng: response.results[0].lng,
zoom: 5,
maxZoom: 15,
panControl: false,
markerClusterer: function(map) {
markerCluster = new MarkerClusterer(map, [], {
title: 'Location Cluster',
maxZoom: 15
});
// onClick OVERRIDE
markerCluster.onClick = function(clickedClusterIcon) {
return multiChoice(clickedClusterIcon.cluster_);
}
return markerCluster;
}
});
//loop through array
for(var i = 0; i < response.results.length; i++)
{
//create marker image
var markerLoc = {
url: '/custom/plugins/gmaps/images/marker-red.png',
size: new google.maps.Size(24, 30), //size
origin: new google.maps.Point(0, 0), //origin point
anchor: google.maps.Point(9, 30) // offset point
};
//add marker
map.addMarker({
lat: response.results[i].lat,
lng: response.results[i].lng,
icon: markerLoc,
title: response.results[i].ip_address,
infoWindow: {
content: '<p>'+response.results[i].ip_address+'</p>'
//add more details later
}
});
}
//cluster function to do stuff
function multiChoice(clickedCluster)
{
//clusters markers
var markers = clickedCluster.getMarkers();
//console check
console.log(clickedCluster);
console.log(markers);
if (markers.length > 1)
{
//content of info window
var infowindow = new google.maps.InfoWindow({
content: ''+
'<p>'+markers.length+' = length</p>'+
'<p>testing blah blah</p>'
});
//show the window
//infowindow.open(??????????);
return false;
}
return true;
};
Finally figured this out playing around with it some more... it makes sense now, but didn't before. Here is the new 'display' function to be replaced by the one in the OP. Of course, there are a few other change needed yet... showing all clustered marker data in the new info window for example, but this is the gist of getting the window to work.
//cluster function to do stuff
function multiChoice(clickedCluster)
{
//clusters markers
var markers = clickedCluster.getMarkers();
if (markers.length > 1)
{
//create the info window
var infoWindow = new google.maps.InfoWindow({
content: ''+
'<p>'+markers.length+' = length</p>'+
'<p>testing blah blah</p>',
position: clickedCluster.center_
});
//display the infowindow
infoWindow.open(clickedCluster.map_);
return false;
}
return true;
};

changing z index of marker on hover to make it visible

I'm trying to make the marker i'm currently hovering on have a greater z-index than the others, so that even if it's hidden by other markers it'll gain full visibility when I hover on it.
On click of any marker i want to do the same .
google.maps.event.addListener(this.marker, 'mouseover', function() {
this.old_ZIndex = this.getZIndex(); //trying to get the current z- index
console.log(this.old_ZIndex); //this is undefined: why?
this.setZIndex(this.old_ZIndex + 100); //setting a higher z-index than all other markers
console.log("the old z index is ",this.old_ZIndex);
});
But with this i would be infinitely increase the z index .. is there some other way in which I can have the to revert back when i hover or click any other marker . .
Or is there any better way to implement it ??
'this.getZIndex()' always returns 'undefined' if you haven't previously set a zIndex on the marker, either when initialising it in the first place or by using the setOption() function.
Your script may also not work 100% if there are more than 100 markers.
I've put together a very simple map below that contains 2 markers, slightly overlapping. On hover of one of the markers it will set the zIndex to the highest needed to bring it to the top, then return it back to what it was previously on mouseout:
var map;
var markers = new Array();
var highestZIndex = 0;
function initialize() {
/* SETUP MAP */
var myLatlng = new google.maps.LatLng(52.06768, -1.33758);
var mapOptions = {
center: myLatlng,
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
/* ADD 1st MARKER */
var markerOptions = {
position: new google.maps.LatLng(52.06768, -1.32058),
map: map,
zIndex:1
};
marker = createMarker(markerOptions, false);
marker.set("myZIndex", marker.getZIndex());
google.maps.event.addListener(marker, "mouseover", function() {
getHighestZIndex();
this.setOptions({zIndex:highestZIndex+1});
});
google.maps.event.addListener(marker, "mouseout", function() {
this.setOptions({zIndex:this.get("myZIndex")});
});
/* ADD 2nd MARKER */
var markerOptions = {
position: new google.maps.LatLng(52.06768, -1.33758),
map: map,
zIndex:2
};
marker = createMarker(markerOptions, false);
marker.set("myZIndex", marker.getZIndex());
google.maps.event.addListener(marker, "mouseover", function() {
getHighestZIndex();
this.setOptions({zIndex:highestZIndex+1});
});
google.maps.event.addListener(marker, "mouseout", function() {
this.setOptions({zIndex:this.get("myZIndex")});
});
}
function createMarker(markerOptions) {
var marker = new google.maps.Marker(markerOptions);
markers.push(marker);
return marker;
}
function getHighestZIndex() {
// if we haven't previously got the highest zIndex
// save it as no need to do it multiple times
if (highestZIndex==0) {
if (markers.length>0) {
for (var i=0; i<markers.length; i++) {
tempZIndex = markers[i].getZIndex();
if (tempZIndex>highestZIndex) {
highestZIndex = tempZIndex;
}
}
}
}
return highestZIndex;
}
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
zIndex: 1
});
google.maps.event.addListener(marker, 'mouseover', function () {
this.setOptions({zIndex:10});
});
google.maps.event.addListener(marker, 'mouseout', function () {
this.setOptions({zIndex:1});
});
I think the easiest way is to use CSS instead of Javascript:
.your-custom-marker-class {
z-index: 100;
}
.your-custom-marker-class:hover {
z-index: 101;
}
This does mean you have to use CustomOverlays (https://developers.google.com/maps/documentation/javascript/customoverlays#introduction) instead of default markers, but that has some other advantages too, if you want to customize layout, etc.
So this question was a year ago but I figured something out and thought others might appreciate it. There's even icon rollovers involved as a bonus. I'm dealing with thousands of bus and train stops being shown so this turned out to be pretty efficient for me.
google.maps.event.addListener(marker, 'mouseover', function () {
if (this.getIcon() === busnot) { this.setIcon(busovr); }
if (this.getIcon() === lrtnot) { this.setIcon(lrtovr); }
$.each($.grep(markers, function (item) { return item.getZIndex() == 10 }), function (i, e) { e.setOptions({ zIndex: 1 }); });
this.setOptions({zIndex:10});
});
google.maps.event.addListener(marker, 'mousemove', function () {
if (this.getIcon() === busnot) { this.setIcon(busovr); }
if (this.getIcon() === lrtnot) { this.setIcon(lrtovr); }
$.each($.grep(markers, function (item) { return item.getZIndex() == 10 }), function (i, e) { e.setOptions({ zIndex: 1 }); });
this.setOptions({ zIndex: 10 });
});
google.maps.event.addListener(marker, 'mouseout', function () {
if (this.getIcon() === busovr) { this.setIcon(busnot); }
if (this.getIcon() === lrtovr) { this.setIcon(lrtnot); }
$.each($.grep(markers, function (item) { return item.getZIndex() == 10 }), function (i, e) { e.setOptions({ zIndex: 1 }); });
});
The way I did it was to have one variable(highestZ) set the zIndex for all my markers(in my case i did it with polylines) and increments, and one variable to temporarily hold the z-index of whichever marker i "mouseover" on:
Set the variables as global:
var highestZ = 1; //set 1 for the first z-index
var tmpZIndex = 0;
Then when building/initializing your marker options just add this
zIndex : highestZ++ //this sets the z-index for the marker and increments it for the next one
Sample (i did mine in a loop) :
var routePath = new google.maps.Polyline({
strokeWeight: 5,
zIndex : highestZ++ //set zIndex and increment it
});
And finally just do mouseover and mouseout event handlers like this:
google.maps.event.addListener(routePath, "mouseover", function() {
tempZIndex = routePath.zIndex; //set "this" z-index value to tempZIndex for mouseout
routePath.setOptions({
zIndex: highestZ + 1 //set the z-index to the highest z-index available plus 1 for it to be the topmost marker on mouseover
});
});
google.maps.event.addListener(routePath, "mouseout", function() {
routePath.setOptions({
zIndex: tempZIndex //set the z-index back to it's original set upon mouseover earlier
});
My answer is probably simple, and general and of course incomplete to focus on the problem only, hopefully you can work it further to fit your project.

Multiple polylines and infowindows with Google Maps V3

I have a map with multiple polylines and would like to open a line-specific-infowindow when clicking the line.
So far my code only shows the content of the last iteration.
I found two very nice examples of what I want but after hours of trying I am still no further.
Example 1: http://srsz750.appspot.com/api3/polylines-multiple.html
Example 2: http://www.geocodezip.com/v3_GenericMapBrowser.asp?filename=flights090414.xml
So your are my last shot :-S
Here is my code that shows only the content of the last iteration:
for (var i = 0; i < locations.length; i++) {
var route = locations[i]; // locations is an array of route-arrays.
//route is an array with details. route[0] contains the description.
var imageStart = 'img/rijder.png';
var polyOptions = {
strokeColor: '#0000FF',
strokeOpacity: 1.0,
strokeWeight: 3
}
poly = new google.maps.Polyline(polyOptions, info);
var path = poly.getPath();
//line text
var info = route[0];
google.maps.event.addListener(poly, 'click', function(event) {
infowindow.setContent(info);
infowindow.position = event.latLng;
infowindow.open(map);
});
//startmarker
var startLatLng = new google.maps.LatLng(route[1], route[2]);
var smarker = new google.maps.Marker({
position: startLatLng,
map: map,
icon: imageStart,
title: route[7],
html: route[0]
});
path.push(startLatLng);
//starttext
google.maps.event.addListener(smarker, "click", function () {
infowindow.setContent(this.html);
infowindow.open(map, this);
});
//endmarker
var endLatLng = new google.maps.LatLng(route[4], route[5]);
var emarker = new google.maps.Marker({
position: endLatLng,
map: map,
icon: imageEnd,
title: route[8],
html: route[3]
});
path.push(endLatLng);
//endtext
google.maps.event.addListener(emarker, "click", function () {
infowindow.setContent(this.html);
infowindow.open(map, this);
});
//close line and put on the map
poly.setMap(map);
}
}
And here is the code I would expect to work but all lines disappeared (only the relevant code, I also added a mouseover function):
//line text
google.maps.event.addListener(poly, 'click', (function(event,index){
return function(){
var routeinfw = locations[index];
var inf = routeinfw[0];
infowindow.setContent(inf);
infowindow.position = mouselocation;
infowindow.open(map);
};
})(event,i));
//starticon
Just like in the example you posted, create a function to create the click events listeners and call it from inside the locations loop:
function createInfoWindow(poly,content) {
google.maps.event.addListener(poly, 'click', function(event) {
infowindow.content = content;
infowindow.position = event.latLng;
infowindow.open(map);
});
}
And you can call this at the end of the loop:
createInfoWindow(poly,info);