Dynamic Load of Heatmap Data based on Map Bounds, Performance Issue - google-maps

I have implemented a simple page that uses a listener to determine when a google maps bounds have changed because of zoom or pan. I am dynamically loading json data for a weighted heatmap summarized by the area visible in the map. It is working all except for the fact that I am not properly clearing the previous data from the heatmap on each call to the listener. Performance begins to degrade after the 4th or 5th call to fetch new data. I tried setting heatmap to null. What else is needed to maintain performance?
var map, heatmap;
var heatMapData = [];
function initMap() {
var uluru = { lat: 32.673363, lng: -97.399290 };
map = new google.maps.Map(document.getElementById('map'), {
zoom: 14,
center: uluru
});
google.maps.event.addListener(map, "bounds_changed", function () {
heatmap = null;
var bounds = map.getBounds();
//TODO: implement async request
var Httpreq = new XMLHttpRequest(); // a new request
var boxRequest = 'HeatMapData?lmin=' + bounds.f.f + '&lmax=' + bounds.f.b + '&lnmin=' + bounds.b.b + '&lnmax=' + bounds.b.f;
Httpreq.open("GET", boxRequest, false);
Httpreq.setRequestHeader("Content-type", "application/json")
var heatMapJSON = Httpreq.responseText;
heatMapData = [];
var parsedJSON = JSON.parse(heatMapJSON);
for (var i = 0; i < parsedJSON.length; i++) {
heatMapData.push({ location: new google.maps.LatLng(parsedJSON[i].Lat, parsedJSON[i].Lon), weight: parsedJSON[i].weight })
};
console.info('map points: ' + parsedJSON.length.toString());
heatmap = new google.maps.visualization.HeatmapLayer({
data: heatMapData,
map : map
});
});

if (heatmap != null) {
heatmap.setMap(null);
};

Related

Algolia search, displaying all results even when radius set

So I want to search by lat and lng within 5km radius, despite limiting hits per page to 10, it is still displaying all markers on map and there are 96, why isn't this working properly?
var APPLICATION_ID = '**';
var SEARCH_ONLY_API_KEY = '**';
var INDEX_NAME = 'locations';
var PARAMS = { hitsPerPage: 10 };
// Client + Helper initialization
var algolia = algoliasearch(APPLICATION_ID, SEARCH_ONLY_API_KEY);
var algoliaHelper = algoliasearchHelper(algolia, INDEX_NAME, PARAMS);
algoliaHelper.setQueryParameter('aroundLatLng', '53.552472, -2.807663');
algoliaHelper.setQueryParameter('aroundRadius', 5000);
algoliaHelper.search();
// Map initialization
var markers = [];
//alert("heelo");
algoliaHelper.on('result', function(content) {
renderHits(content);
var i;
// Add the markers to the map
for (i = 0; i < content.hits.length; ++i) {
var hit = content.hits[i];
var marker = new google.maps.Marker({
position: {lat: hit.longitude, lng: hit.latitude},
map: map,
label: hit.slug,
animation: google.maps.Animation.DROP
});
markers.push(marker);
}
});
function renderHits(content) {
$('#container').html(JSON.stringify(content, null, 2));
}
});
How a very weird reason if I delete:
algoliaHelper.setQueryParameter('aroundLatLng', '53.552472, -2.807663');
algoliaHelper.setQueryParameter('aroundRadius', 5000);
algoliaHelper.search();
It still brings back all records, does anyone have a clue why is this happening?

Google maps Spiderfier, map unresponsive after setmap(null)

I have a function that loads my map to keep my map static.
<script>
var delArray = new Array();
var gm;
var map;
var iw;
var oms;
window.onload = function(){
gm = google.maps;
map = new gm.Map(document.getElementById('map_canvas'), {
mapTypeId: gm.MapTypeId.TERRAIN,
center: new gm.LatLng(-29.335205, 24.793563),
scrollwheel: false,
zoom: 6
});
iw = new gm.InfoWindow();
oms = new OverlappingMarkerSpiderfier(map,
{markersWontMove: true, markersWontHide: true});
}
</script>
I then use another function to construct my spiderfier data.
<script>
function spider(mapData){
var usualColor = 'eebb22';
var spiderfiedColor = 'ffee22';
var iconWithColor = function(color) {
return 'http://chart.googleapis.com/chart?chst=d_map_xpin_letter&chld=pin|+|' +
color + '|000000|ffff00';
}
var shadow = new gm.MarkerImage(
'https://www.google.com/intl/en_ALL/mapfiles/shadow50.png',
new gm.Size(37, 34), // size - for sprite clipping
new gm.Point(0, 0), // origin - ditto
new gm.Point(10, 34) // anchor - where to meet map location
);
oms.addListener('click', function(marker) {
iw.setContent(marker.desc);
iw.open(map, marker);
});
oms.addListener('spiderfy', function(markers) {
for(var i = 0; i < markers.length; i ++) {
markers[i].setIcon(iconWithColor(spiderfiedColor));
markers[i].setShadow(null);
}
iw.close();
});
oms.addListener('unspiderfy', function(markers) {
for(var i = 0; i < markers.length; i ++) {
markers[i].setIcon(iconWithColor(usualColor));
markers[i].setShadow(shadow);
}
});
var bounds = new gm.LatLngBounds();
for (var i = 0; i < mapData.length; i ++) {
var datum = mapData[i];
var loc = new gm.LatLng(datum[0], datum[1]);
bounds.extend(loc);
var marker = new gm.Marker({
position: loc,
title: datum[2],
animation: google.maps.Animation.DROP,
map: map,
icon: iconWithColor(usualColor),
shadow: shadow
});
marker.desc = datum[3];
oms.addMarker(marker);
delArray.push(marker);
}
map.fitBounds(bounds);
// for debugging/exploratory use in console
window.map = map;
window.oms = oms;
}
</script>
And Another to remove markers from the map:
<script>
function delMe(){
if(delArray){
for(i =0; i <= delArray.length; i++){
delArray[i].setMap(null);
}
this.delArray = new Array();
}
}
</script>
My map data (mapData) comes from a php script and passed on via Jason. And that's also where I call my delete function right before I call my spider (map) function. This I do to clear the map before I pass the new data.
$( document ).ready(function() {
delMe();
var pdata = $js_array;
spider(pdata);
});
Now, my problem is that all data is displaying perfectly but after calling the delMe() function it clears the markers 100% but then my map become unresponsive it's not loading new data when calling the spider() function with new data.
I can overcome this problem by reloading/creating the map again, but I want to avoid that and only use a static map. And if I don't delete markers it just fill the map with 100's of markers mixing the old and new.
I am a bit of a noob when it comes to javascript/jquery, any help will be much appreciated!.
It looks like you're missing an OMS removeMarker call in your delMe function, which should go something like this:
function delMe(){
if (delArray){
for (i =0; i <= delArray.length; i++){
oms.removeMarker(delArray[i]);
delArray[i].setMap(null);
}
this.delArray = [];
}
}
(It's possible you have other problems too, but here's a start).
It's not clear from what you write, but are you using the JS developer console? Google '[your browser] developer console' for more info — it lets you see if errors are causing your map to become unresponsive.

Google Map Route Arrow Line

I currently have these codes to load GPX File into Google Maps
function loadGPXFileIntoGoogleMap(map, filename) {
$.ajax({url: filename,
dataType: 'xml',
success: function(data) {
var parser = new GPXParser(data, map);
parser.setTrackColour('#ff0000'); // Set the track line colour
parser.setTrackWidth(5); // Set the track line width
parser.setMinTrackPointDelta(0.001); // Set the minimum distance between track points
parser.centerAndZoom(data);
parser.addTrackpointsToMap(); // Add the trackpoints
parser.addWaypointsToMap(); // Add the waypoints
}
});
}
$(document).ready(function() {
var mapOptions = {
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map'), mapOptions);
loadGPXFileIntoGoogleMap(map, '" . base_url('gps/ajax/request/trace') . "');
});
Everything is good but I want to replace it with arrow lines instead of straight line. Is it possible? If yes, please help me to do it.
In order to add arrows to the polylines created by the GPXParser, you need to modify that library to give access to the polylines, see the two lines and the function added to that library below. Then get the polylines and add the arrows to them as below.
working example (based off the example in the gpxviewer documentation referenced above)
Changes to the code from the example in the documentation:
function loadGPXFileIntoGoogleMap(map, filename) {
$.ajax({url: filename,
dataType: "xml",
success: function(data) {
var parser = new GPXParser(data, map);
parser.setTrackColour("#ff0000"); // Set the track line colour
parser.setTrackWidth(5); // Set the track line width
parser.setMinTrackPointDelta(0.001); // Set the minimum distance between track points
parser.centerAndZoom(data);
parser.addTrackpointsToMap(); // Add the trackpoints
// ******************** added *******************************
var polylines = parser.getPolylines();
// documentation on pre-defined symbols and repeated symbols:
// https://developers.google.com/maps/documentation/javascript/symbols
// Define a symbol using a predefined path (an arrow)
// supplied by the Google Maps JavaScript API.
var lineSymbol = {
path: google.maps.SymbolPath.FORWARD_OPEN_ARROW,
strokeColor: '#00FF00',
strokeOpacity: 1.0
};
for (var i=0; i<polylines.length; i++) {
polylines[i].setOptions({
icons: [{
icon: {
path: google.maps.SymbolPath.FORWARD_CLOSED_ARROW,
strokeColor:'#0000ff',
fillColor:'#0000ff',
fillOpacity:1,
scale: 3
},
repeat:'100px'
}]
});
}
// *****************************end added**********************
parser.addWaypointsToMap(); // Add the waypoints
}
});
}
Changes to the loadgpx.js library:
function GPXParser(xmlDoc, map) {
this.xmlDoc = xmlDoc;
this.map = map;
this.trackcolour = "#ff00ff"; // red
this.trackwidth = 5;
this.mintrackpointdelta = 0.0001
this.polylines = []; // **added**
}
// return a reference to the array of polylines **added function**
GPXParser.prototype.getPolylines = function() {
return this.polylines;
}
GPXParser.prototype.addTrackSegmentToMap = function(trackSegment, colour,
width) {
var trackpoints = trackSegment.getElementsByTagName("trkpt");
if(trackpoints.length == 0) {
return;
}
var pointarray = [];
// process first point
var lastlon = parseFloat(trackpoints[0].getAttribute("lon"));
var lastlat = parseFloat(trackpoints[0].getAttribute("lat"));
var latlng = new google.maps.LatLng(lastlat,lastlon);
pointarray.push(latlng);
for(var i = 1; i < trackpoints.length; i++) {
var lon = parseFloat(trackpoints[i].getAttribute("lon"));
var lat = parseFloat(trackpoints[i].getAttribute("lat"));
// Verify that this is far enough away from the last point to be used.
var latdiff = lat - lastlat;
var londiff = lon - lastlon;
if(Math.sqrt(latdiff*latdiff + londiff*londiff)
> this.mintrackpointdelta) {
lastlon = lon;
lastlat = lat;
latlng = new google.maps.LatLng(lat,lon);
pointarray.push(latlng);
}
}
var polyline = new google.maps.Polyline({
path: pointarray,
strokeColor: colour,
strokeWeight: width,
map: this.map
});
this.polylines.push(polyline); // **added
}

google maps over query limit

I know that similar questions have been posted but I have not found and answer in any of them as it relates to my particular issue.
I have a javascript that uses google maps to place customer zipcodes on a map. The problem I am have is similar to what others have already posted – I get a “over query limit” error.
I have tried different setups using setTimeOut to try to send google the data within the allowable time intervals but I can’t get it to work.
Here is my action:
function initialize()
{
var rowNum = 0 ;
var rowColor = "" ;
var latlng = new google.maps.LatLng(27.91425, -82.842617);
var myOptions =
{
zoom: 7,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
geocoder = new google.maps.Geocoder();
data.forEach(function(mapData,idx)
{
window.setTimeout(function()
{
geocoder.geocode({ 'address': mapData.address}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
title: mapData.title,
icon: getIcon(mapData.type)
});
var contentHtml = "<div style='width:250px;height:90px'><strong>"+mapData.title+"</strong><br />"+mapData.address+"</div>";
var infowindow = new google.maps.InfoWindow({
content: contentHtml
});
google.maps.event.addListener(marker, 'click', function()
{
infowindow.open(map,marker);
});
marker.locid = idx+1;
marker.infowindow = infowindow;
markers[markers.length] = marker;
if (idx%2 == 0)
{
rowColor = 'style="background-color:#00FFFF;"' ;
}
else
{
rowColor = 'style="background-color:#FFFFFF;"' ;
}
var sideHtml = '<div ' + rowColor + ' class="loc" data-locid="'+marker.locid+'"><b>'+mapData.title+'</b><br/>';
sideHtml += mapData.address + '</div>';
$("#locs").append(sideHtml);
//Are we all done? Not 100% sure of this
if(markers.length == data.length) doFilter();
}
else
{
// alert("Geocode was not successful for the following reason: " + status);
}
}, 3000);
});
});
When I run my page using this action, I get back 11 markers even though I have many more than that in my JSON string. The window.setTimeout has absolutely no effect – I’m obviously doing something wrong here.
I would appreciate any help on this matter.
Thanks,
I found the answer to my question. I found the following code on the Web and modified it to my needs.
With it, you can load many markers without getting Over Query Limit from Google.
I have tested it with over 100 markers and it works beautifully. The page does not freeze up at all.
I am certain some of you guys can do something much more elegant and efficient but this is a good starting point.
<script type="text/javascript">
//<![CDATA[
// display ani gif
loadingGMap() ;
// delay between geocode requests - at the time of writing, 100 miliseconds seems to work well
var delay = 100;
// ====== Create map objects ======
var infowindow = new google.maps.InfoWindow();
var latlng = new google.maps.LatLng(27.989551,-82.462235);
var mapOptions =
{
zoom: 7,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var geo = new google.maps.Geocoder();
var map = new google.maps.Map(document.getElementById("map"), mapOptions);
var bounds = new google.maps.LatLngBounds();
// ====== Geocoding ======
function getAddress(search, next)
{
geo.geocode({address:search}, function (results,status)
{
// If that was successful
if (status == google.maps.GeocoderStatus.OK)
{
// Lets assume that the first marker is the one we want
var p = results[0].geometry.location;
var lat = p.lat();
var lng = p.lng();
// Output the data
var msg = 'address="' + search + '" lat=' +lat+ ' lng=' +lng+ '(delay='+delay+'ms)<br>';
//document.getElementById("messages").innerHTML += msg;
// Create a marker
createMarker(search,lat,lng);
}
// ====== Decode the error status ======
else
{
// === if we were sending the requests to fast, try this one again and increase the delay
if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT)
{
nextAddress--;
delay++;
}
else
{
var reason = "Code "+status;
var msg = 'address="' + search + '" error=' +reason+ '(delay='+delay+'ms)<br>';
// document.getElementById("messages").innerHTML += msg;
}
}
next();
}
);
}
// ======= Function to create a marker
function createMarker(add,lat,lng)
{
var contentString = add;
if (add=='EOF')
{
stopLoadingGMap() ;
}
var addArray = add.split(' ');
var zipcode = addArray.pop();
var zipcode = add.match(/\d{5}/)[0] ;
var image = 'icons/sm_02.png';
var marker = new MarkerWithLabel(
{
position: new google.maps.LatLng(lat,lng),
map: map,
icon: image,
labelContent: zipcode,
labelAnchor: new google.maps.Point(50, 0),
labelClass: "labels", // the CSS class for the label
labelStyle: {opacity: 0.75},
zIndex: Math.round(latlng.lat()*-100000)<<5
});
google.maps.event.addListener(marker, 'click', function()
{
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
bounds.extend(marker.position);
}
// ======= An array of locations that we want to Geocode ========
// use static or build dynamically
// use as many markers as you need – I’ve test with over 100
var addresses = var data = [
{‘StreetAddress1 City State Zipcode’},
{‘StreetAddress2 City State Zipcode’},
{‘StreetAddress3 City State Zipcode’},
{‘StreetAddress14 City State Zipcode’},
…
{‘EOF’},
];
// ======= Global variable to remind us what to do next
var nextAddress = 0;
// ======= Function to call the next Geocode operation when the reply comes back
function theNext()
{
if (nextAddress < addresses.length)
{
setTimeout('getAddress("'+addresses[nextAddress]+'",theNext)', delay);
nextAddress++;
}
else
{
// We're done. Show map bounds
map.fitBounds(bounds);
}
}
// ======= Call that function for the first time =======
theNext();
// This Javascript is based on code provided by the
// Community Church Javascript Team
// http://www.bisphamchurch.org.uk/
// http://econym.org.uk/gmap/
//]]>
</script>

How can I check if google map is already loaded

I am working in a project to provide a map to mobile phone. For now I am trying on a iPhone.
It works fine, and when I load my first page I can see a map with my position, and the market is refreshed each 10 sec and move to my next position.
Some time when I change of page and I come back to the first page, the map is not full displayed. If I move the map, it move but some image of the map is still not displayed.
Also I am working with jquery mobe.
I also noticed that each time I return to the first map, the map is reloaded.
Is there a way to load the map once?
So how can i check that my map is already loaded?
Here is my code
$('#home').live('pagebeforeshow', function(e){
// Resize #mapHome (#mapHome = Sreen hight - footer - header)
$('#mapHome').css('height', Resize.content()-2 +'px');
// extract les id des modules existants
navigator.geolocation.getCurrentPosition(function(position){
showMap('mapHome',position.coords.latitude, position.coords.longitude);
//console.log(position.coords.latitude, position.coords.longitude);
},
function(){
//error
},
{
enableHighAccuracy : true,
maximumAge : 30000
//maximumAge:Infinity
});
// Place and move the marker regarding to my position and deplacement
var track_id = "me";
Tracking.watch_id = navigator.geolocation.watchPosition(
// Success
function(position){
console.log('WatchPosition called');
var lat = position.coords.latitude;
var long = position.coords.longitude;
var latLng = new Array();
latLng[0] = lat;
latLng[1] = long;
//Tracking.myCoordinates.push(lat,long);
Tracking.myCoordinates.push(latLng);
addMarker(lat, long);
},
// Error
showError,
{
frequency: 1000
});
})
I just changed that line to
$('#home').live('pageshow', function(e){... code...}
And it semas to be better but I am not sure-
Here is the code of my function showMap()
function showMap(canvas,lat,long){
var latLng = new google.maps.LatLng(lat,long);
// Google Map options var myOptions = {
zoom: 19,
//zoomControl : 1,
center: latLng,
mapTypeId: google.maps.MapTypeId.ROADMAP////ROADMAP, SATELLITE, HYBRID and TERRAIN };
// Create the Google Map, set options Tracking.mapy = new google.maps.Map(document.getElementById(canvas), myOptions);
}
And here is the code addMarker()
function addMarker(lat, long){
Tracking.mapBounds = new google.maps.LatLngBounds();
// Clean previous markers
for (var i = 0; i < Tracking.markers.length; i++ ) {
Tracking.markers[i].setMap(null);
}
// Add the owner's marker
var latitudeAndLongitude = new google.maps.LatLng(lat, long);
var image = "img/iconGoogleMap/phones.png";
marker = new google.maps.Marker({
title : 'me',
//animation: google.maps.Animation.DROP, //BOUNCE
position: latitudeAndLongitude,
map : Tracking.mapy,
icon : image
});
Tracking.markers.push(marker);
//Tracking.markers.push(marker);
//console.log(localStorage.getItem('mapToDisplay'));
/* ADDING MODULES MAKERS */
// Store the ID of available module.
modulesJSON = Modules.get('bipme');
for (var i = 0; i < modulesJSON['modules'].length; i++) {
console.log('module id = ' +modulesJSON['modules'][i].id);
console.log('Module ' + modulesJSON['modules'][i].id + ' position : ' + ModulesPos.module(modulesJSON['modules'][i].id));
nlatLong = ModulesPos.module(modulesJSON['modules'][i].id).split(",");
var LatitudeAndLongitudeModules = new google.maps.LatLng(nlatLong[0],nlatLong[1]);
var image = "img/iconGoogleMap/" + modulesJSON['modules'][i].profile + "-" + modulesJSON['modules'][i].iconColor + ".png";
marker = new google.maps.Marker({
title : modulesJSON['modules'][i].pseudo,
//animation: google.maps.Animation.DROP, //BOUNCE
position: LatitudeAndLongitudeModules,
map : Tracking.mapy,
icon : image
});
Tracking.mapBounds.extend(LatitudeAndLongitudeModules);
Tracking.markers.push(marker);
};
By the way, is there a way to create a button, from which I can manually refresh the map?