Google Heat Maps displaying red blocks - javascript

Some data is producing Google Heat Maps to display red blocks instead of the Heat Layer. I checked my information but I couldn't find anything wrong, here is my code:
for (i = 0; i < markers.length; i++) {
if (markers[i].lat != " ") {
mar.push(markers[i]);
var weightedLoc = {
location: new google.maps.LatLng(mar[j].lat,mar[j].lon),
weight: mar[j].Intensity
};
heat.push(weightedLoc);
j++;
}
}
var mapOptions = {
zoom: 10,
center: new google.maps.LatLng(mar[0].lat, mar[0].lon)
};
map = new google.maps.Map(document.getElementById('dvMap'), mapOptions);
var pointArray = new google.maps.MVCArray(heat);
heatmap = new google.maps.visualization.HeatmapLayer({
data: heat
});
heatmap.setMap(map);
My data is in this json format:
[
{"lat":"-0.05487","lon":"-78.45286","Intensity":"1.86"},
{"lat":"-0.09377","lon":"-78.45136","Intensity":"2"},
{"lat":"-0.05489","lon":"-78.45283","Intensity":"0.6"}
]
Thanks!

weight has to be of type number, currently it's a string.
Convert it via :
weight: parseFloat(mar[j].Intensity)
proof of concept fiddle
code snippet:
function initialize() {
var markers = [{
"lat": "-0.05487",
"lon": "-78.45286",
"Intensity": "1.86"
}, {
"lat": "-0.09377",
"lon": "-78.45136",
"Intensity": "2"
}, {
"lat": "-0.05489",
"lon": "-78.45283",
"Intensity": "0.6"
}];
var heat = [];
for (i = 0; i < markers.length; i++) {
if (markers[i].lat != " ") {
// mar.push(markers[i]);
var weightedLoc = {
location: new google.maps.LatLng(markers[i].lat, markers[i].lon),
weight: parseFloat(markers[i].Intensity)
};
heat.push(weightedLoc);
// j++;
}
}
var mapOptions = {
zoom: 12,
center: new google.maps.LatLng(markers[0].lat, markers[0].lon)
};
map = new google.maps.Map(document.getElementById('dvMap'), mapOptions);
var pointArray = new google.maps.MVCArray(heat);
heatmap = new google.maps.visualization.HeatmapLayer({
data: heat
});
heatmap.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#dvMap {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=visualization"></script>
<div id="dvMap"></div>

When I experienced this problem, it was because I was accidentally passing empty strings values into the LatLng constructors.
See below:
for (i = 0; i < coords.length; i++) {
var lat = coords[i]
var long = coords[++i]
points.push(new google.maps.LatLng(lat, long)); //<-- no checks on lat, long
}
// heatmap layer
heatmap = new google.maps.visualization.HeatmapLayer({
data: points,
map: map
});
I discovered that there was a potential for lat or long to be empty, so I made the following change:
if (!lat.isEmpty() && !long.isEmpty()) {
points.push(new google.maps.LatLng(lat, long));
}
If the accepted answer does not solve your problems, check to ensure that all of the points you are passing to the heat map are valid.

Related

method fitBounds() only zooms to single marker

I have rendered a map with markers, which are saved as long lat values in a local xlsx file.
My aim is to automatically zoom to all markers, which are loaded via an input file button. For this I am using the fitbounds() method from googlemaps API.
Partial Example
function handleFile(e) {
//Get the files from Upload control
var files = e.target.files;
var i, f;
//Loop through files
for (i = 0, f = files[i]; i != files.length; ++i) {
var reader = new FileReader();
var name = f.name;
reader.onload = function (e) {
var data = e.target.result;
var result;
var workbook = XLSX.read(data, { type: 'binary' });
var sheet_name_list = workbook.SheetNames;
sheet_name_list.forEach(function (y) { /* iterate through sheets */
//Convert the cell value to Json
var roa = XLSX.utils.sheet_to_json(workbook.Sheets[y]);
if (roa.length > 0) {
result = roa;
}
});
//create global infoWindow object
var infoWindow = new google.maps.InfoWindow();
var i, newMarker;
var gmarkers = [];
//loop over json format
for (i = 0, length = result.length; i < length; i++) {
var data = result[i];
//extract Lat Long values from result
latLng = new google.maps.LatLng(data.Latitude, data.Longitude);
//creating a marker and putting it on the map
newMarker = new google.maps.Marker({
position: latLng,
map: map
});
gmarkers.push(newMarker);
}
for (var i=0; i < gmarkers.length; i++) {
bounds = new google.maps.LatLngBounds();
loc = new google.maps.LatLng(gmarkers[i].position.lat(), gmarkers[i].position.lng());
bounds.extend(loc);
}
map.fitBounds(bounds);
}
}
}
};
reader.readAsArrayBuffer(f);
}
But if I run my html file, it zooms just to one marker. I suppose that it is the first marker of the gmarkers array.
However I want to achieve following result, with the full extent of my uploaded marker:
In my main.html you can see my initMap() function and the function which is called if the document is ready. In the document ready function the handlefunction () is called.
var map;
//Change event to dropdownlist
$(document).ready(function(){
a = $('#input-id').fileinput({
'showUpload': false,
'showPreview': false,
'showCaption': false
});
a.change(handleFile);
});
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 48.7758459, lng: 9.1829321},
zoom: 3,
mapTypeControl: false
});
}
You have a typo in your code. Move the initialization of the bounds outside the loop.
for (var i=0; i < gmarkers.length; i++) {
bounds = new google.maps.LatLngBounds();
loc = new google.maps.LatLng(gmarkers[i].position.lat(), gmarkers[i].position.lng());
bounds.extend(loc);
}
map.fitBounds(bounds);
should be:
bounds = new google.maps.LatLngBounds();
for (var i=0; i < gmarkers.length; i++) {
loc = new google.maps.LatLng(gmarkers[i].position.lat(), gmarkers[i].position.lng());
bounds.extend(loc);
}
map.fitBounds(bounds);
proof of concept fiddle
code snippet:
var result = [{
Latitude: 37.4419,
Longitude: -122.1419
}, {
Latitude: 37.44,
Longitude: -122.14
}, {
Latitude: 40.44,
Longitude: -75.14
}]
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 gmarkers = [];
//loop over json format
for (i = 0, length = result.length; i < length; i++) {
var data = result[i];
//extract Lat Long values from result
latLng = new google.maps.LatLng(data.Latitude, data.Longitude);
//creating a marker and putting it on the map
newMarker = new google.maps.Marker({
position: latLng,
map: map
});
gmarkers.push(newMarker);
}
bounds = new google.maps.LatLngBounds();
for (var i = 0; i < gmarkers.length; i++) {
loc = new google.maps.LatLng(gmarkers[i].position.lat(), gmarkers[i].position.lng());
bounds.extend(loc);
}
map.fitBounds(bounds);
}
google.maps.event.addDomListener(window, "load", initialize);
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>
This is another approach for your problem within 35 lines of code.
Make sure you pass the JSON object the right way and that you declare your classes within the appropriate lexical scope.
Make sure the JSON Object returns something like this:
const coords = [
{lat: 42.4, lng: 1.55},
{lat: 43.42, lng: 2.48},
{lat: 45.43, lng: 4.9}
];
Note I have changed result to a more meaningful coords array of objects.
// Create your markers without worrying about scope and without extensive For Loops
const markers = coords.map((coord) => {
return new google.maps.Marker({
position: new google.maps.LatLng(coord.lat, coord.lng),
map: map,
animation: google.maps.Animation.DROP
});
})
// Declare your bounds outside the map method (previous for loop)
const bounds = new google.maps.LatLngBounds();
// Iterate through markers and return coords for expanded viewport
markers.forEach((loc) =>{
loc = new google.maps.LatLng(loc.position.lat(), loc.position.lng());
return bounds.extend(loc);
});
map.fitBounds(bounds);
}

Google Maps API - Toggle Marker Visibility

How do I toggle the visibility of a subset of markers in Google Maps API?
I have two sets of marker location data. Want to add a button to toggle visibility of each set independently.
Full code below for convenience. I have a button code in the header.
<button onclick="toggleMELocations()">Toggle ME Locations</button>`
The button is showing up, but clicking does not yield the expected result (ME locations disappearing).
The relevant function is "toggleMELocations." I am trying to say that if ME locations are currently visible, make them invisible. And vice versa.
Any help is much appreciated.
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {
lat: 40,
lng: -95
},
styles: [{
stylers: [{
saturation: -100
}]
}]
});
setMarkers(map);
}
function toggleMELocations() {
if (MEs) {
for (i in MEs) {
var visibility = (MEs[i].getVisible() == true) ? false : true;
MEs[i].setVisible(visibility);
}
}
}
// MEC locations
var MEs = [
['aaa', 36.07, -75.79],
['bbb', 40.07, -83.79]
];
// CC locations
var Concentras = [
['xxx', 38.01, -75.55],
['yyy', 30.10, -90.3]
];
function setMarkers(map) {
// Adds markers to the map.
for (var i = 0; i < MEs.length; i++) {
var ME = MEs[i];
var marker = new google.maps.Marker({
position: {
lat: ME[1],
lng: ME[2]
},
icon: 'http://maps.google.com/mapfiles/ms/icons/green-dot.png',
map: map,
title: ME[0]
});
}
for (var i = 0; i < Concentras.length; i++) {
var Concentra = Concentras[i];
var marker = new google.maps.Marker({
position: {
lat: Concentra[1],
lng: Concentra[2]
},
icon: 'http://maps.google.com/mapfiles/ms/icons/red-dot.png',
map: map,
title: Concentra[0]
});
}
}
Firstly getVisible() is not a valid function.
You need to add a global variable defined: var addedMEs = [];
This acts as an array of markers that have been added to the map in the setMarkers method. We change the setMarkers method to include a line which will add a marker object to the array defined above:
for (var i = 0; i < MEs.length; i++) {
var ME = MEs[i];
var marker = new google.maps.Marker({
position: {
lat: ME[1],
lng: ME[2]
},
icon: 'http://maps.google.com/mapfiles/ms/icons/green-dot.png',
map: map,
title: ME[0]
});
addedMEs.push(marker);
}
Then we need to remove the getVisible() method as it is invalid. we change this line to:
var bounds = map.getBounds();
var visibility = (bounds.contains(addedMEs[i].position) == true) ? false : true;
addedMEs[i].setVisible(visibility);
And it works. :]
Here is the JSFiddle to try: https://jsfiddle.net/cmjcs5eL/13/

Recenter map with multiple markers

I display multiple markers on a map. The list of locations is built with PHP:
$myData .= '["'.$Name.'", '.$lat.', '.$blon.'],';
Then I use JS to plot markers on the map.
function initMap() {
var map = new google.maps.Map(document.getElementById("map"), {
zoom: 12,
center: {lat: 32.99999999, lng: -95.2222328}
});
setMarkers(map);
}
var stores = ['.$myData.'];
function setMarkers(map) {
for (var i = 0; i < stores.length; i++) {
var store = stores[i];
var marker = new google.maps.Marker({
position: {lat: store[1], lng: store[2]},
map: map,
title: restaurant[0]
});
}
}
I need to re-center the map on map load. Should I try to average lat/lon coords from $myData array and replace center coords in initMap or is there a better way?
In this story: It's better to get average lat/long coordinates from the back-end (or calculate it on a front-end, but before you initialize a GoogleMap), so your map will be loaded in the right place and will not "tremble".
But you still may have a problem with zooming, and there are a few solutions. Most difficult is calculate again, but maybe you can try something of it (and it may make an interesting effect on page loading):
A. Zoom in from the space. Set smallest zoom and after google.API calculates bounding box — zoom in!
B. Show preloader screen over the map. In this case, you can calculate average lat/long using google.API too. It's the easiest way, but not so smooth and cool.
create an empty bounds object (a google.maps.LatLngBounds)
add all your markers to it
use it to center and zoom your map
function setMarkers(map) {
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < stores.length; i++) {
var store = stores[i];
var marker = new google.maps.Marker({
position: {lat: store[1], lng: store[2]},
map: map,
title: restaurant[0]
});
bounds.extend(marker.getPosition());
}
map.fitBounds(bounds);
}
code snippet:
function initMap() {
var map = new google.maps.Map(document.getElementById("map"), {
zoom: 12,
center: {
lat: 32.99999999,
lng: -95.2222328
}
});
setMarkers(map);
}
var stores = [
["store 1", 42, -72],
["store 2", 41, -74]
];
function setMarkers(map) {
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < stores.length; i++) {
var store = stores[i];
var marker = new google.maps.Marker({
position: {
lat: store[1],
lng: store[2]
},
map: map,
title: store[0]
});
bounds.extend(marker.getPosition());
}
map.fitBounds(bounds);
}
google.maps.event.addDomListener(window, "load", initMap);
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map"></div>
Here is how I do it (a small snippet of my code) in jQuery, just pass your map into the function:
function (mapInfo) {
var noMarkers = false;
if (!mapInfo.markers || mapInfo.markers.length === 0) {
noMarkers = true;
var marker = new google.maps.Marker({
position: { lat: YOUR_DESIRED_HOME_POINT, lng: YOUR_DESIRED_HOME_POINT },
optimized: false
});
mapInfo.markers.push(marker);
}
var bounds = new google.maps.LatLngBounds();
// Create bounds from markers
$.each(mapInfo.markers, function (index, item) {
var latlng = mapInfo.markers[index].getPosition();
bounds.extend(latlng);
});
// Google wants to zoom ALL the way in for only one marker, so if there is only one, we'll back it out a bit
if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
var adjustBy = noMarkers ? 20.5 : 0.005;
var extendNortheast = new google.maps.LatLng(bounds.getNorthEast().lat() + adjustBy, bounds.getNorthEast().lng() + adjustBy);
var extendSouthwest = new google.maps.LatLng(bounds.getNorthEast().lat() - adjustBy, bounds.getNorthEast().lng() - adjustBy);
bounds.extend(extendNortheast);
bounds.extend(extendSouthwest);
}
google.maps.event.addListenerOnce(mapInfo.map, 'bounds_changed', function () {
var zoom = mapInfo.map.getZoom();
if (zoom > 18) {
mapInfo.map.setZoom(16);
}
});
mapInfo.map.fitBounds(bounds);
}

Unexplained extra Polyline drawn - Google Maps API v3

I have a strange scenario with regards to a Polyline that is being drawn on the map. Before I post the code, I'll first demonstrate what happens when I make use of the normal direction services (Both calculates the resulting disctance the same = Total Distance: 62.734 km):
Now, when I draw the directions myself - this straight line appears out of nowhere:
Code snippet:
<script type="text/javascript">
var markers = [
{
"lat": '-26.2036247253418',
"lng": '28.0086193084717'
}
,
{
"lat": '-26.1259479522705',
"lng": '27.9742794036865'
}
,
{
"lat": '-25.8434619903564',
"lng": '28.2100086212158'
}
];
window.onload = function () {
var mapOptions = {
center: new google.maps.LatLng(markers[0].lat, markers[0].lng),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var labels = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
var labelIndex = 0;
var totalDistance = 0;
var map = new google.maps.Map(document.getElementById("dvMap"), mapOptions);
var infoWindow = new google.maps.InfoWindow();
var lat_lng = new Array();
var latlngbounds = new google.maps.LatLngBounds();
//var image = 'https://developers.google.com/maps/documentation/javascript/examples/full/images/beachflag.png';
for (i = 0; i < markers.length; i++) {
var data = markers[i]
var myLatlng = new google.maps.LatLng(data.lat, data.lng);
lat_lng.push(myLatlng);
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title: data.title,
label: labels[labelIndex++ % labels.length],
//icon: image
});
latlngbounds.extend(marker.position);
(function (marker, data) {
// google.maps.event.addListener(marker, "click", function (e) {
// infoWindow.setContent(data.description);
// infoWindow.open(map, marker);
// });
})(marker, data);
}
map.setCenter(latlngbounds.getCenter());
map.fitBounds(latlngbounds);
//***********ROUTING****************//
//Initialize the Path Array
var path = new google.maps.MVCArray();
//Initialize the Direction Service
var service = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer({
setMap: map
});
//Set the Path Stroke Color
var poly = new google.maps.Polyline({ map: map, strokeColor: '#4986E7' });
//Loop and Draw Path Route between the Points on MAP
for (var i = 0; i < lat_lng.length; i++) {
if ((i + 1) < lat_lng.length) {
var src = lat_lng[i];
var des = lat_lng[i + 1];
path.push(src);
//poly.strokeColor = '#'+Math.floor(Math.random()*16777215).toString(16);
poly.setPath(path);
service.route({
origin: src,
destination: des,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}, function (result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(result);
var myroute = directionsDisplay.directions.routes[0];
var distance = 0;
for (i = 0; i < myroute.legs.length; i++) {
distance += myroute.legs[i].distance.value;
//for each 'leg'(route between two waypoints) we get the distance and add it to the total
}
for (var i = 0, len = result.routes[0].overview_path.length; i < len; i++) {
path.push(result.routes[0].overview_path[i]);
//console.log(result.routes[0].legs[0].distance);
}
totalDistance += distance;
document.getElementById('total').innerHTML = (totalDistance / 1000) + ' km';
}
});
}
}
}
</script>
<div id="dvMap"></div>
<div><p>Total Distance: <span id="total"></span></p></div>
Ok, so to solve the problem. Just remove the following line:
Reference: Google Documentation - Simple Polylines
And like that, the line is gone:
Aren't you also drawing a line between the first and last poly?
You should only draw lines between poly0 and poly1, poly1 and poly2 etc. but not poly100 and poly0 (if poly100 is the last one)
That would explain the straight line going from point B to A completing the shape. you don't want to complete the shape, so stop drawing. is there no function you can set to not complete the shape?
I only know of a very expensive work around and that is to trace back in reverse order from B to A along the same route. But that is probably not what you are looking for

show JSON parsed data in javascript loop for maps markers

I'm trying to get the markers longitude and latitude and display them on the map but I'm not getting any result, my parser.php file is working and fetching the data from the database i just need to format it into javascript
<script type="text/javascript">
function initialize() {
var mapOptions = {
center: { lat: -25.363882, lng: 131.044922},
zoom: 14
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
$.getJSON('parser.php', function(items) {
for (var i = 0; i < items.length; i++) {
(function(item) {
addMarker(item.lat, item.lon);
})(items[i]);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
parser.php output
[{"0":"33.880561","lat":"33.880561","1":"35.542831","lon":"35.542831"},{"0":"-25.363882","lat":"25.363882","1":"131.044922","lon":"131.044922"}]
Your problem is that the lat and lon values from your PHP are strings. I'm assuming (because your question doesn't include it at this stage) your addMarker function isn't converting those strings to the numeric objects that the google Maps expects for lat/lng values.
Try simply wrapping those in parseFloat() before passing them to the Maps API, e.g.
addMarker(parseFloat(item.lat), parseFloat(item.lon));
Alternatively you could do this in the addMarker function itself (which is probably better).
You need to add the marker to the map. The way your code is currently structured the map is local to the initialize function and there is no way to pass that value to the addMarker function.
You have two options:
pass the "map" variable into the addMarker function
function initialize() {
var mapOptions = {
center: {
lat: -25.363882,
lng: 131.044922
},
zoom: 14
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
$.getJSON('parser.php', function (items) {
for (var i = 0; i < items.length; i++) {
(function (item) {
addMarker(item.lat, item.lon, map);
})(items[i]);
}
});
}
proof of concept fiddle
working code snippet:
function initialize() {
var mapOptions = {
center: {
lat: -25.363882,
lng: 131.044922
},
zoom: 14
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
// $.getJSON('parser.php', function (items) {
var items = [{
"0": "33.880561",
"lat": "33.880561",
"1": "35.542831",
"lon": "35.542831"
}, {
"0": "-25.363882",
"lat": "25.363882",
"1": "131.044922",
"lon": "131.044922"
}];
for (var i = 0; i < items.length; i++) {
(function(item) {
addMarker(item.lat, item.lon, map);
})(items[i]);
}
// });
}
var bounds = new google.maps.LatLngBounds();
function addMarker(lat, lng, map) {
var latlng = new google.maps.LatLng(lat, lng);
bounds.extend(latlng);
var marker = new google.maps.Marker({
position: latlng,
map: map
});
map.fitBounds(bounds);
return marker;
}
google.maps.event.addDomListener(window, 'load', initialize);
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map-canvas" style="width:750px; height:450px; border: 2px solid #3872ac;"></div>
make the "map" variable global.
var map; // global variable, outside of any function definition
function initialize() {
var mapOptions = {
center: {
lat: -25.363882,
lng: 131.044922
},
zoom: 14
};
// initialize the global variable (no "var")
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
$.getJSON('parser.php', function (items) {
for (var i = 0; i < items.length; i++) {
(function (item) {
addMarker(item.lat, item.lon);
})(items[i]);
}
});
}
working code snippet:
var map;
function initialize() {
var mapOptions = {
center: {
lat: -25.363882,
lng: 131.044922
},
zoom: 14
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
// $.getJSON('parser.php', function (items) {
var items = [{
"0": "33.880561",
"lat": "33.880561",
"1": "35.542831",
"lon": "35.542831"
}, {
"0": "-25.363882",
"lat": "25.363882",
"1": "131.044922",
"lon": "131.044922"
}];
for (var i = 0; i < items.length; i++) {
(function(item) {
addMarker(item.lat, item.lon);
})(items[i]);
}
// });
}
var bounds = new google.maps.LatLngBounds();
function addMarker(lat, lng) {
var latlng = new google.maps.LatLng(lat, lng);
bounds.extend(latlng);
var marker = new google.maps.Marker({
position: latlng,
map: map
});
map.fitBounds(bounds);
return marker;
}
google.maps.event.addDomListener(window, 'load', initialize);
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div id="map-canvas" style="width:750px; height:450px; border: 2px solid #3872ac;"></div>

Categories

Resources