method fitBounds() only zooms to single marker - javascript

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);
}

Related

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);
}

For loop through Array only shows last value, Google Map

I'm trying to place 3 markers on Google Map.
In JavaScript I wrote my loop as below
var places = ["Bondi Beach", "Coogee Beach", "Cronulla Beach"];
var lat = [-33.890542, -33.923036, -34.028249];
var lng = [151.274856, 151.259052, 151.157507];
var z=0;
for (tot=lat.length; z < tot; z++) {
var locations = [
[places[z], lat[z], lng[z]]
];
}
Then I initialized my map
var map;
var markers = [];
function init(){
map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: 10,
center: new google.maps.LatLng(-33.92, 151.25),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var num_markers = locations.length;
for (var i = 0; i < num_markers; i++) {
markers[i] = new google.maps.Marker({
position: {lat:locations[i][1], lng:locations[i][2]},
map: map,
html: locations[i][0],
id: i,
});
google.maps.event.addListener(markers[i], 'click', function(){
var infowindow = new google.maps.InfoWindow({
id: this.id,
content:this.html,
position:this.getPosition()
});
google.maps.event.addListenerOnce(infowindow, 'closeclick', function(){
markers[this.id].setVisible(true);
});
this.setVisible(false);
infowindow.open(map);
});
}
}
init();
However this output only one marker (the last one), I'm wondering what is wrong with my loop?
for (tot=lat.length; z < tot; z++) {
var locations = [
[places[z], lat[z], lng[z]]
];
}
Here you're overwriting the locations array with every iteration.
Push the new elements into the array instead.
var locations = []
for (tot=lat.length; z < tot; z++) {
locations.push([places[z], lat[z], lng[z]]);
}

Display multiple markers, variable and array problems

I try to display multiple markers on my map. I put the multiples location in adata-attribute trough my php file. Then I try to grab this information in my javascript one.
If I directly paste the coordinates, the markers appear. If I reference the data-attribute they don't. (The only difference is on the line beginning with var locations.)
This code works:
function GoogleMapsInit(){
setTimeout(function initialize() {
var emplacements = $('#iframecarte').attr("data-emplacements");
// Emplacements returns [[45.5314817,-73.1835154], [45.570004,-73.448701] ]
var mapOptions = {
zoom: 12,
center: new google.maps.LatLng(45.5580421, -73.7303025)
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var locations = [[45.5314817,-73.1835154], [45.570004,-73.448701] ];
var marker, i;
var markers = new Array();
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][0], locations[i][1]),
map: map
});
markers.push(marker);
}
}, 500);
}
This one doesn't:
function GoogleMapsInit(){
setTimeout(function initialize() {
var emplacements = $('#iframecarte').attr("data-emplacements");
// Emplacements returns [[45.5314817,-73.1835154], [45.570004,-73.448701] ]
var mapOptions = {
zoom: 12,
center: new google.maps.LatLng(45.5580421, -73.7303025)
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var locations = emplacements;
var marker, i;
var markers = new Array();
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][0], locations[i][1]),
map: map
});
markers.push(marker);
}
}, 500);
}
What is wrong with the variable locations when it references the emplacements variable so that the markers don't show?
The non-working version emplacements is a string, not an array.
Convert the string to a javascript array:
var locations = JSON.parse(emplacements);
proof of concept fiddle
code snippet:
function GoogleMapsInit() {
setTimeout(function initialize() {
var emplacements = $('#iframecarte').attr("data-emplacements");
// Emplacements returns [[45.5314817,-73.1835154], [45.570004,-73.448701] ]
var mapOptions = {
zoom: 9,
center: new google.maps.LatLng(45.5580421, -73.7303025)
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var locations = JSON.parse(emplacements);
var marker, i;
var markers = new Array();
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][0], locations[i][1]),
map: map
});
markers.push(marker);
}
}, 500);
}
GoogleMapsInit();
html,
body,
#map-canvas {
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>
<div id="map-canvas"></div>
<div id="iframecarte" data-emplacements="[[45.5314817,-73.1835154], [45.570004,-73.448701], [45.6066487,-73.712409]]"></div>

Google API multiple markers (addresses NOT latlong) displaying title (tool tip)

I'm trying to use the script made by user netbrain as found here on stackoverflow to also show the address title when the user clicks on the marker. It should be relatively simple but I'm lost.
Any ideas? I've tried numerous options but nothing seems to work. netbrain's code below:
var map;
var elevator;
var myOptions = {
zoom: 4,
center: new google.maps.LatLng(0, 0),
mapTypeId: 'roadmap'
};
map = new google.maps.Map($('#map_canvas')[0], myOptions);
var addresses = ['Norway', 'Africa', 'Asia','North America','South America'];
for (var x = 0; x < addresses.length; x++) {
$.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address='+addresses[x]+'&sensor=true', null, function (data) {
var p = data.results[0].geometry.location
var latlng = new google.maps.LatLng(p.lat, p.lng);
new google.maps.Marker({
position: latlng,
map: map
title: addresses[0]
});
});
}
This answer assumes you're only after tool tip and not the infowindow.
The variables addresses and x cannot be used within the callback as the value of x will always be 5 (in this example, see length of addresses array). Instead look at the data object like so:
var map;
var elevator;
var myOptions = {
zoom: 4,
center: new google.maps.LatLng(0, 0),
mapTypeId: 'roadmap'
};
map = new google.maps.Map($('#map_canvas')[0], myOptions);
var addresses = ['Norway', 'Africa', 'Asia','North America','South America'];
for (var x = 0; x < addresses.length; x++) {
$.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address='+addresses[x]+'&sensor=true', null, function (data) {
var p = data.results[0].geometry.location
var latlng = new google.maps.LatLng(p.lat, p.lng);
new google.maps.Marker({
position: latlng,
map: map
title: data.results[0].formatted_address
});
});
}
EDIT
For completeness the data object is the result of the geocoding API call. The formatted_address is a property of a match within the results, see https://developers.google.com/maps/documentation/geocoding/#GeocodingResponses
Use this code:
$(document).ready(function () {
var map;
var elevator;
var myOptions = {
zoom: 1,
center: new google.maps.LatLng(0, 0),
mapTypeId: 'terrain'
};
map = new google.maps.Map($('#map_canvas')[0], myOptions);
var addresses = ['Norway', 'Africa', 'Asia','North America','South America'];
for (var x = 0; x < addresses.length; x++) {
$.getJSON('http://maps.googleapis.com/maps/api/geocode/json?address='+addresses[x]+'&sensor=false', null, function (data) {
var p = data.results[0].geometry.location
var latlng = new google.maps.LatLng(p.lat, p.lng);
var marker = new google.maps.Marker({
position: latlng,
map: map
});
google.maps.event.addListener(marker, 'click', function(evt) {
var info_window = new google.maps.InfoWindow({maxWidth: 500});
info_window.setContent('Content here');
info_window.setPosition(latlng);
info_window.open(map, marker);
});
});
}
});

How do I read a variable from another function?

In the following code, it seems that the function initialize(), once triggered by socket.on('results') is unable to read the value of "array".
block content
script.
function initialize() {
var mapOptions = {
center: { lat: -30, lng: 150},
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
setMarkers(map, array);
}
function setMarkers(map, locations) {
for (var i = 0; i < locations.length; i++) {
var location = locations[i];
var myLatLng = new google.maps.LatLng(location[1], location[2]);
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: location[0]
});
}
}
google.maps.event.addDomListener(window, 'load', initialize);
div(id="map-canvas")
script.
var socket = io.connect('http://localhost:4000');
socket.on('results', function(results) {
var array = [];
results.forEach(function(item){
name = item.name;
coordinates = item.location.coordinate;
array.push([name, coordinates.latitude, coordinates.longitude]);
});
initialize();
});
Simple pass the array as a parameter when you call the initialize function.
initialize(array);
Them, in the function initialize:
function initialize(array) {REST OF THE CODE}
All code:
block content
script.
function initialize(array) {
var mapOptions = {
center: { lat: -30, lng: 150},
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
array = array || [];
setMarkers(map, array);
}
function setMarkers(map, locations) {
for (var i = 0; i < locations.length; i++) {
var location = locations[i];
var myLatLng = new google.maps.LatLng(location[1], location[2]);
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: location[0]
});
}
}
google.maps.event.addDomListener(window, 'load', initialize);
div(id="map-canvas")
script.
var socket = io.connect('http://localhost:4000');
socket.on('results', function(results) {
var array = [];
results.forEach(function(item){
name = item.name;
coordinates = item.location.coordinate;
array.push([name, coordinates.latitude, coordinates.longitude]);
});
initialize(array);
});
array variable is not visible inside initialize function. It is closured in callback anonymous function. I propose to pass array as argument:
block content
script.
function initialize(array) {
var mapOptions = {
center: { lat: -30, lng: 150},
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
array = array || [];
setMarkers(map, array);
}
function setMarkers(map, locations) {
for (var i = 0; i < locations.length; i++) {
var location = locations[i];
var myLatLng = new google.maps.LatLng(location[1], location[2]);
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: location[0]
});
}
}
google.maps.event.addDomListener(window, 'load', initialize);
div(id="map-canvas")
script.
var socket = io.connect('http://localhost:4000');
socket.on('results', function(results) {
var array = [];
results.forEach(function(item){
name = item.name;
coordinates = item.location.coordinate;
array.push([name, coordinates.latitude, coordinates.longitude]);
});
initialize(array);
});

Categories

Resources