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]]);
}
Related
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);
}
I'm doing an application with google maps API that have a JSON with the marker's coordinates. Then I draw polylines between the markers. I also implemented a function with a onclick event that creates a new marker inside the polyline. This marker has to show information of the previous marker in the polyline (the one taked of the JSON, not a clicked one). But I don't know how to take the previous vertex(marker) of a selected polyline.
Code:
(function() {
window.onload = function() {
var options = {
zoom: 3,
center: new google.maps.LatLng(37.09, -95.71),
mapTypeId: google.maps.MapTypeId.HYBRID,
noClear: true,
panControl: true,
scaleControl: false,
streetViewControl:false,
overviewMapControl:false,
rotateControl:false,
mapTypeControl: true,
zoomControl: false,
};
var map = new google.maps.Map(document.getElementById('map'), options);
// JSON
$.getJSON("loc.js", function(json) {
console.log(json);
});
//Marker type
var markers = [];
var arr = [];
var pinColor = "FE7569";
var pinImage = new google.maps.MarkerImage("http://labs.google.com/ridefinder/images/mm_20_red.png" + pinColor,
new google.maps.Size(21, 34),
new google.maps.Point(0,0),
new google.maps.Point(10, 34));
// JSON loop
for (var i = 0, length = json.length; i < length; i++) {
var data = json[i],
latLng = new google.maps.LatLng(data.lat, data.lng);
arr.push(latLng);
// Create markers
var marker = new google.maps.Marker({
position: latLng,
map: map,
icon: pinImage,
});
infoBox(map, marker, data);
//Polylines
var flightPath = new google.maps.Polyline({
path: json,
geodesic: true,
strokeColor: '#FF0000',
strokeOpacity: 1.0,
strokeWeight: 2,
map:map
});
infoPoly(map, flightPath, data);
//Calculate polylines distance
google.maps.LatLng.prototype.kmTo = function(a){
var e = Math, ra = e.PI/180;
var b = this.lat() * ra, c = a.lat() * ra, d = b - c;
var g = this.lng() * ra - a.lng() * ra;
var f = 2 * e.asin(e.sqrt(e.pow(e.sin(d/2), 2) + e.cos(b) * e.cos
(c) * e.pow(e.sin(g/2), 2)));
return f * 6378.137;
}
google.maps.Polyline.prototype.inKm = function(n){
var a = this.getPath(n), len = a.getLength(), dist = 0;
for (var i=0; i < len-1; i++) {
dist += a.getAt(i).kmTo(a.getAt(i+1));
}
return dist;
}
}
function infoBox(map, marker, data) {
var infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker, "click", function(e) {
salta(data.tm);
});
(function(marker, data) {
google.maps.event.addListener(marker, "click", function(e) {
salta(data.tm);
});
})(marker, data);
}
//Create onclick marker on the polyline
function infoPoly(map, flightPath, data){
google.maps.event.addListener(flightPath, 'click', function(event) {
mk = new google.maps.Marker({
map: map,
position: event.latLng,
});
markers.push(mk);
map.setZoom(17);
map.setCenter(mk.getPosition());
});
}
function drawPath() {
var coords = [];
for (var i = 0; i < markers.length; i++) {
coords.push(markers[i].getPosition());
}
flightPath.setPath(coords);
}
// Fit these bounds to the map
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < arr.length; i++) {
bounds.extend(arr[i]);
}
map.fitBounds(bounds);
//dist polylines
distpoly = flightPath.inKm();
distpolyround = Math.round(distpoly);
};
})();
If I click in the blue arrow, I create a marker on that point of the polyline. I that marker it takes the values of the previous one.
You can use the geometry library .poly namespace isLocationOnEdge method to determine which segment of the polyline the clicked point (new marker) is on.
//Create onclick marker on the polyline
function infoPoly(map, flightPath, data) {
google.maps.event.addListener(flightPath, 'click', function(event) {
mk = new google.maps.Marker({
map: map,
position: event.latLng,
});
markers.push(mk);
map.setZoom(17);
map.setCenter(mk.getPosition());
// find line segment. Iterate through the polyline checking each line segment.
// isLocationOnEdge takes a google.maps.Polyline as the second argument, so make one,
// then use it for the test. The default value of 10e-9 for the tolerance didn't work,
// a tolerance of 10e-6 seems to work.
var betweenStr = "result no found";
var betweenStr = "result no found";
for (var i=0; i<flightPath.getPath().getLength()-1; i++) {
var tempPoly = new google.maps.Polyline({
path: [flightPath.getPath().getAt(i), flightPath.getPath().getAt(i+1)]
})
if (google.maps.geometry.poly.isLocationOnEdge(mk.getPosition(), tempPoly, 10e-6)) {
betweenStr = "between "+i+ " and "+(i+1);
}
}
(function(mk, betweenStr) {
google.maps.event.addListener(mk, "click", function(e) {
infowindow.setContent(betweenStr+"<br>loc:" + this.getPosition().toUrlValue(6));
infowindow.open(map, mk);
// salta(data.tm);
});
})(mk, betweenStr);
google.maps.event.trigger(mk,'click');
});
proof of concept fiddle
code snippet:
var infowindow = new google.maps.InfoWindow();
(function() {
window.onload = function() {
var options = {
zoom: 3,
center: new google.maps.LatLng(37.09, -95.71),
mapTypeId: google.maps.MapTypeId.HYBRID,
};
var map = new google.maps.Map(document.getElementById('map'), options);
//Marker type
var markers = [];
var arr = [];
var pinColor = "FE7569";
var pinImage = "http://labs.google.com/ridefinder/images/mm_20_red.png";
// JSON loop
for (var i = 0, length = json.length; i < length; i++) {
var data = json[i],
latLng = new google.maps.LatLng(data.lat, data.lng);
arr.push(latLng);
// Create markers
var marker = new google.maps.Marker({
position: latLng,
map: map,
icon: pinImage,
});
infoBox(map, marker, data);
//Polylines
var flightPath = new google.maps.Polyline({
path: json,
geodesic: true,
strokeColor: '#FF0000',
strokeOpacity: 1.0,
strokeWeight: 2,
map: map
});
infoPoly(map, flightPath, data);
}
function infoBox(map, marker, data) {
var infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(marker, "click", function(e) {
infowindow.setContent("tm:" + data.tm + "<br>loc:" + this.getPosition().toUrlValue(6));
infowindow.open(map, marker);
// salta(data.tm);
});
(function(marker, data) {
google.maps.event.addListener(marker, "click", function(e) {
infowindow.setContent("tm:" + data.tm + "<br>loc:" + this.getPosition().toUrlValue(6));
infowindow.open(map, marker);
// salta(data.tm);
});
})(marker, data);
}
//Create onclick marker on the polyline
function infoPoly(map, flightPath, data) {
google.maps.event.addListener(flightPath, 'click', function(event) {
mk = new google.maps.Marker({
map: map,
position: event.latLng,
});
markers.push(mk);
map.setZoom(17);
map.setCenter(mk.getPosition());
// find line segment. Iterate through the polyline checking each line segment.
// isLocationOnEdge takes a google.maps.Polyline as the second argument, so make one,
// then use it for the test. The default value of 10e-9 for the tolerance didn't work,
// a tolerance of 10e-6 seems to work.
var betweenStr = "result no found";
for (var i = 0; i < flightPath.getPath().getLength() - 1; i++) {
var tempPoly = new google.maps.Polyline({
path: [flightPath.getPath().getAt(i), flightPath.getPath().getAt(i + 1)]
})
if (google.maps.geometry.poly.isLocationOnEdge(mk.getPosition(), tempPoly, 10e-6)) {
betweenStr = "between " + i + " and " + (i + 1);
}
}
(function(mk, betweenStr) {
google.maps.event.addListener(mk, "click", function(e) {
infowindow.setContent(betweenStr + "<br>loc:" + this.getPosition().toUrlValue(6));
infowindow.open(map, mk);
// salta(data.tm);
});
})(mk, betweenStr);
google.maps.event.trigger(mk, 'click');
});
}
function drawPath() {
var coords = [];
for (var i = 0; i < markers.length; i++) {
coords.push(markers[i].getPosition());
}
flightPath.setPath(coords);
}
// Fit these bounds to the map
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < arr.length; i++) {
bounds.extend(arr[i]);
}
map.fitBounds(bounds);
//dist polylines
distpoly = flightPath.inKm();
distpolyround = Math.round(distpoly);
};
})();
var json = [{
lat: 38.931808,
lng: -74.906606,
tm: 0
}, {
lat: 38.932442,
lng: -74.905147,
tm: 1
}, {
lat: 38.93311,
lng: -74.903473,
tm: 2
}, {
lat: 38.933777,
lng: -74.901671,
tm: 3
}, {
lat: 38.930739,
lng: -74.912528,
tm: 1000
}];
html,
body,
#map {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<div id="map"></div>
INITIALIZING
When you are creating those markers in the for loop, add them to a map [Data structure] that you define (empty) before the loop. In the map markers will be stored. Their keys - concatenated lat/lng.
var initial_markers = {}; //before for loop
initial_markers[data.lat+"-"+data.lng] = marker; //after each marker initialization
Count them, so you know how many there are initial_marker_count, because you cannot get length of size of a map[data structure]
DETECTION
When you have clicked on a polyline, I don't think you can get exactly the part of polyline that is clicked, so you need to get it yourself. The steps are:
Get the coordinate of click event
Loop through the markers
Take their coordinates
Check if the clicked point on the map is on the line between those two points
If is, take the first of those two points
DETECTION PSEUDOCODE
var prev_marker;
for (var i=initial_markers; i<initial_marker_count-2; i++) {
if( isPointOnLine(initial_markers[i], initial_markers[i+1], clicked_point) {
prev_marker = initial_markers[i];
break;
}
}
The only reason I am saying that this is pseudocode, is because I don't know hor to find if point is on the line between two points in Google maps. And you should write that isPointOnLine() functions. Apart from that - the idea is given. Hope You appreciate it.
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);
});
});
}
});
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);
});
Hi everyone I am creating an info window for each of my markers and then I pass the content to a variable in order to assigne the 4th element of the array as the content but it seems that it is not working. Any idea of how I could display the 4th element of the array in to each of the info window? Many thanks.
var infowindow = null;
function initialize() {
var latlng = new google.maps.LatLng(52.474, -1.868);
var myOptions = {
zoom: 2,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map"), myOptions);
var image = 'marker1.png';
var countries = [
['england', 51.508515 , -0.125487, 5,'this is england'],
['france', 46.227638 , 2.213749, 4,'this is france'],
['switcherland', 46.818188 , 8.227512, 3,'this is switcherland'],
['italy', 41.871940 , 12.56738, 2,'this is italy'],
['greece', 39.074208 , 21.824312, 1,'this is greece']
];
setMarkers(map, countries);
infowindow = new google.maps.InfoWindow({
content: 'hi'
});
function setMarkers(map, markers) {
for (var i = 0; i < markers.length; i++) {
var countries = markers[i];
var siteLatLng = new google.maps.LatLng(countries[1], countries[2]);
var marker = new google.maps.Marker({
position: siteLatLng,
map: map,
title: countries[0],
zIndex: countries[6],
html: countries[6]
});
google.maps.event.addListener(marker, "click", function () {
infowindow.open(map,this);
});
}
}
}
google.maps.event.addDomListener(window, 'load', initialize);
var countries
is an array of arrays. The index 4 actually points to the 5th element of the array (array indexes start at 0) so with
var contentString = countries[4]
you are getting the array, not a string!
['greece', 39.074208 , 21.824312, 1,'this is greece']
It looks as though you want the 5th element of this array (index 4)
contentString[4]
would be 'this is greece'