google maps js api blocks ui when adding markers - javascript

I have a problem with google maps on mobile browsers.
The project I'm working on requires about 500 markers to be shown on a map, but when adding them, the ui freezes.
I'm using markerclusterer to add markers, and performance is fine once the markers are on the page. Is there a way to add the markers asynchronously, or to pause adding markers once the user starts scrolling?
This is the code we're using:
var mcOptions = { gridSize: 50, maxZoom: 15, zoomOnClick: false };
var mc = new MarkerClusterer(context.map, [], mcOptions);
getMarkerLocations().then(function(branches){
branches.forEach(function(branch) => {
var marker = new google.maps.Marker({
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 2,
strokeColor: 'red',
fillColor: 'red',
strokeWeight: 2,
fillOpacity: 1
},
position: new google.maps.LatLng(branch.Latitude, branch.Longitude),
visible: true
});
mc.addMarker(marker);
});
});
Thank you geocodezip, that worked like a charm! For anyone else with the same problem, here's how I fixed it:
.then(function(branches){
var loopFunction = function(branchesToAdd) => {
if (branchesToAdd.length === 0) return;
var item = branchesToAdd.pop();
var marker = new google.maps.Marker({
....
});
mc.addMarker(marker);
setTimeout(function(){loopFunction(branchesToAdd)}, 30);
};
loopFunction(branchesToShow);
});

Add the markers asynchronously, use setTimeout to schedule the addition of each marker, which will give the browser some time to render and respond to the UI.

Related

javascript google maps semantic zoom

I am currently trying to implement semantic zooming similar to the way shown in Mike Bostock demonstrates in this d3 example with the circle markers in the javascript google maps api. I cannot figure out how to change styles (radius, opacity) of these markers after they have already been created on the zoom action. Is there a way to do this without removing them and then recreating them with a different size?
// Overlay for eruptions
for (var eruption in eruptions) {
var coordinates = new google.maps.LatLng(eruptions[eruption].Latitude, eruptions[eruption].Longitude);
var eruptionCircle = new google.maps.Circle({
class: 'marker eruption',
strokeColor: ERUPTION_COLOR,
strokeOpacity: marker_border_opacity(),
strokeWeight: 2,
fillColor: ERUPTION_COLOR,
fillOpacity: marker_opacity(),
map: map,
center: coordinates,
radius: eruption_size(eruptions[eruption].VEI),
});
ERUPTIONS.push(eruptionCircle);
}
map.addListener('zoom_changed', function() {
var zoomLevel = map.getZoom();
// TODO - need to find a way of semantically zooming on these markers
});
You can use setOption
eruptionCircle.setOptions({radius: eruption_size(yourNewRadius)});
You have a mistake too (remove the last , form option this way
var eruptionCircle = new google.maps.Circle({
class: 'marker eruption',
strokeColor: ERUPTION_COLOR,
strokeOpacity: marker_border_opacity(),
strokeWeight: 2,
fillColor: ERUPTION_COLOR,
fillOpacity: marker_opacity(),
map: map,
center: coordinates,
radius: eruption_size(eruptions[eruption].VEI)
});

Infowindows without markers with the Google Maps JavaScript API

I am using the Google Maps JavaScript API to create a heatmap layer. I would like to add mouseover events to 100+ locations on the map that will display an infowindow. This would get pretty cluttered if I used markers for every event, so I was hoping to find a way to eliminate markers altogether (although I did throw together an ugly mess of a solution in which a button will show/hide those markers). My first thought was to use the LatLngBounds. As a simple example:
var infowindow = new google.maps.InfoWindow(
{ content: "some info",
size: new google.maps.Size(50,50)
});
var southWest = new google.maps.LatLng(-31.203405,125.244141);
var northEast = new google.maps.LatLng(-25.363882,131.044922);
var loc = new google.maps.LatLngBounds(southWest,northEast);
google.maps.event.addListener(loc, 'mouseover', function() {
infowindow.open(map);
});
google.maps.event.addListener(loc, 'mouseout', function() {
infowindow.close();
});
For whatever reason, though, the mouseover event never seems to happen. Is there a problem with the code? Is there a better way to do this than by using LatLngBounds?
First of all, you should make a new rectangle with your bounds:
var southWest = new google.maps.LatLng(-31.203405,125.244141);
var northEast = new google.maps.LatLng(-25.363882,131.044922);
var loc = new google.maps.LatLngBounds(southWest,northEast);
var rectangle = new google.maps.Rectangle({
bounds: loc,
editable: false,
draggable: false,
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35
});
rectangle.setMap(map);
And then just use an event listener on that rectangle
google.maps.event.addListener(rectangle, 'mouseover', openInfoWindow);
function openInfoWindow(event) {
var ne = rectangle.getBounds().getNorthEast();
var sw = rectangle.getBounds().getSouthWest();
var content = 'Infowindow content';
// Set the info window's content and position.
infoWindow.setContent(contentString);
infoWindow.setPosition(ne);
infoWindow.open(map);
}

Google Maps API - Click event doesn't work, Mouseover does?

First post here, usually a reader not a poster but here goes!
Having a bit of trouble with 'click' events using the Google Maps API.
Here's the scenario:
Marker is placed on map, click event added to marker, works fine.
Another marker is added to the map directly on top of the existing marker with no click event. The click event for the original marker now no longer works! However, if I change the 'click' event to a 'mouseover' it works fine.
Code for first Marker:
var marker1 = new google.maps.Marker({
position: marker1[0],
map: map,
draggable: false,
icon: new google.maps.MarkerImage('img/' + type + '.png',
new google.maps.Size(16, 16),
new google.maps.Point(0,0),
new google.maps.Point(8, 8)
)
});
Code for Marker that gets overlayed on existing marker:
var marker2 = new google.maps.Marker({
position: position,
map: map,
icon: {
path: google.maps.SymbolPath.CIRCLE,
fillOpacity: 0,
strokeOpacity: 1.0,
strokeColor: '#72008F',
strokeWeight: 3.0,
scale: 10
}
});
Code for Listener:
google.maps.event.addListener(marker, 'click', function(event) {
$("#IDhere").html("Some HTML here");
});
I solved my problem by way of work-around.
The issue as I see it was that defining the 'clickable' marker using "new google.maps.MarkerImage" made it part of the google maps canvas element.
Then when Markers defined using "google.maps.SymbolPath.CIRCLE" came along and were put on top of the clickable marker they are separate elements confined into Divs layered on top of the map Canvas element.
Therefor as #geocodezip rightly pointed out, the clickable marker (part of google maps canvas) was being hidden by the other marker in its Div.
My solution was to change the way i created the clickable marker. I used another Circle Symbol path and gave it a zIndex of 99999 so always on top.
Marker1 now looks like this
var marker = new google.maps.Marker({
position: marker1[0],
map: map,
draggable: false,
zIndex: 99999,
icon: {
path: google.maps.SymbolPath.CIRCLE,
fillOpacity: 1,
fillColor: type,
strokeOpacity: 1,
strokeColor: '#000',
strokeWeight: 1 ,
scale: 5
}
});

in relation to loading jquery into a particular div

Could someone help me with this code?
In my Rails project (I don't think it matters what project it is) I have a header that is fixed in position, called 'fixed_header'. There are links on this page, which load new pages underneath, when clicked.
One of the pages which loads, when clicked, has a div called 'map_canvas'. I want the code in my 'fixed_header' page to check for the existence of a div called 'map_canvas', and then, if it is there, load a map into it.
My code below is taken from snippets throughout my application, which work, but I can't make it work for this particular thing. Any help would be appreciated.
<script>
//Is 'ready' the code to use? This code is in 'fixed_header'
//My idea is that, once
//a link in 'fixed_header' is clicked, a new page loads
//underneath the header. The div 'map_canvas' is
//searched for and the function activates if it is found.
$(document).on("ready", function () {
if ($("#map_canvas").length > 0) {
initialize_google_maps();
}
});
function initialize_google_maps() {
var currentlatlng = new google.maps.LatLng(user_latitude, user_longitude);
var zoom = 10;
var myOptions = {
zoom: zoom,
center: currentlatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP, // ROADMAP, SATELLITE, HYBRID
streetViewControl: false
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
var marker = new google.maps.Marker({
map: map,
position: currentlatlng,
icon: {
oppacity: 0
}
});
var circle = new google.maps.Circle({
map: map,
fillOpacity: 0,
strokeWeight: 2,
strokeOpacity: 0.7,
radius: 10000,
});
circle.bindTo('center', marker, 'position');
}
</script>
Because you want to check the div existence in real time when user clicks on link the you should change your code
$(document).on("ready", function () {
if ($("#map_canvas").length > 0) {
initialize_google_maps();
}
});
as below
$('a').live('click',function() {
if ($("#map_canvas").length > 0) {
initialize_google_maps();
}
}
use the anchor selector according to your link classes or ids.

Google Maps Marker Events displaying wrong infromation

I am having trouble with my Google Maps web app, i am trying to add markers to a map and then when the user clicks on that marker, the name of marker appears.
I store information about each marker in an array like so:
var citymap = {};
citymap['edinburgh'] = {
center: new google.maps.LatLng(55.934120, -3.226569),
population: 284,
image:clueImage,
color: '#ff0000',
elementId:'clue1'
};
citymap['clue2'] = {
center: new google.maps.LatLng(55.970783, -3.164594),
population: 284,
image:clueImage,
color: '#ff0000',
elementId:'clue2'
}
citymap['clue4'] = {
center: new google.maps.LatLng(55.939583, -3.202092),
population: 284,
image:clueImage,
color: '#ff0000',
elementId:'clue3'
}
citymap['clue9'] = {
center: new google.maps.LatLng(0, 0),
population: 284,
image:clueImage,
color: '#ff0000',
elementId:'clue1'
}
I then loop through the array and add the marker to the map:
for (var city in citymap) {
var playerMarker = new google.maps.Marker({
position: citymap[city].center,
map: map,
icon: citymap[city].image
});
google.maps.event.addListener(playerMarker, "click", function() {
var elementConnected = citymap[city].elementId;
console.log(elementConnected);
});
}
Everything works as intended, however when I click on any of the markers, they all log the value of the last marker in the array. I know this is because thats where the loop finished, but I can not think of a way of making this work.
Help would be very helpful!
I think this is the universal "closure" problem in Javascript that people have. Someone might give a better way of doing this, but I think you need something like this:
google.maps.event.addListener(playerMarker, "click", (function() {
return function () {
var elementConnected = citymap[city].elementId;
console.log(elementConnected);
};
})(city));
Or if possible, depending on what else you're doing inside the click event, maybe this:
google.maps.event.addListener(playerMarker, "click", (function(elementId) {
return function () {
var elementConnected = elementId;
console.log(elementConnected);
};
})(citymap[city].elementId));

Categories

Resources