Ok so i have a map with some markers on it. There is a click event on the map that should get the closest marker however when the find_closest_marker(event) function runs it breaks on the map.markers.length saying that its undefined.
Here is a link to what im trying to http://jsfiddle.net/VyzFq/7/
Can anyone can please show me where I'm going wrong here.
Looks like there are a couple of problems:
1) the map.markers array hasn't been declared. declare it above the for loop, and push the markers onto the markers array.
...
var infowindow = new google.maps.InfoWindow();
var marker, i;
map.markers = []; // ADD THIS LINE
for (i = 0; i < locations.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(locations[i][1], locations[i][2]),
map: map
});
map.markers.push(marker); // ADD THIS LINE
...
2) the find_closest_point function can't see the map variable. move the find_closest_point function to the scope where you are adding the click event listener:
// CHANGE THIS LINE
google.maps.event.addListener(map, 'click', find_closest_marker);
// TO:
google.maps.event.addListener(map, 'click', function( event ) {
var lat = event.latLng.lat();
var lng = event.latLng.lng();
var R = 6371;
var distances = [];
var closest = -1;
for( i=0;i<map.markers.length; i++ ) {
var mlat = map.markers[i].position.lat();
var mlng = map.markers[i].position.lng();
var dLat = rad(mlat - lat);
var dLong = rad(mlng - lng);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(rad(lat)) * Math.cos(rad(lat)) * Math.sin(dLong/2) * Math.sin(dLong/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
distances[i] = d;
if ( closest == -1 || d < distances[closest] ) {
closest = i;
}
}
alert(map.markers[closest].title);
});
Related
I'm writing an site that shows the our stores near an address. I have the list of latitude and longitude locations of each store from a service.I found my position and marked the stores.But i cant found closest store to my location.Can u help me? :)
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: new google.maps.LatLng(40.188528, 29.060964),
zoom: 10
});
var infoWindow = new google.maps.InfoWindow;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
infoWindow.setPosition(pos);
infoWindow.setContent('Location found.');
infoWindow.open(map);
}, function() {
handleLocationError(true, infoWindow, map.getCenter());
});
} else {
// Browser doesn't support Geolocation
handleLocationError(false, infoWindow, map.getCenter());
}
downloadUrl('locations.xml', function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName('marker');
Array.prototype.forEach.call(markers, function(markerElem) {
var id = markerElem.getAttribute('id');
var name = markerElem.getAttribute('name');
var address = markerElem.getAttribute('address');
var type = markerElem.getAttribute('type');
var point = new google.maps.LatLng(
parseFloat(markerElem.getAttribute('lat')),
parseFloat(markerElem.getAttribute('lng')));
var infowincontent = document.createElement('div');
var strong = document.createElement('strong');
strong.textContent = name
infowincontent.appendChild(strong);
infowincontent.appendChild(document.createElement('br'));
var text = document.createElement('text');
text.textContent = address
infowincontent.appendChild(text);
var icon = customLabel[type] || {};
var marker = new google.maps.Marker({
map: map,
position: point,
label: icon.label
});
marker.addListener('click', function() {
infoWindow.setContent(infowincontent);
infoWindow.open(map, marker);
});
});
});
}
<markers>
<marker id="1" name="Pronet" address="Altınşehir Mahallesi, Muammer Aksoy Cd. No:45, 16120 Nilüfer/Bursa" lat="40.227127" lng="28.924318" type="Ajans"/>
<marker id="2" name="Nette" address="Fethiye Mahallesi, Bursa Cd No:1, 16140 Başiskele/Bursa" lat="40.227173" lng="28.979762" type="Ajans"/>
<marker id="3" name="Alivre" address="Osmangazi Mahallesi, Altıparmak Caddesi, No:86 Stad İş Merkezi K:6 D:15, 16050 Osmangazi/Bursa" lat="40.190341" lng="29.050251" type="Ajans"/>
You can use this function in order to find the closest marker around your position:
function rad(x) { return x * Math.PI / 180; }
function find_closest_marker(position) {
var lat = position.lat;
var lng = position.lng;
var R = 6371; // radius of earth in km
var distances = [];
var closest = -1;
for (i = 0; i < gmarkers.length; i++) {
if (gmarkers[i]) {
var mlat = gmarkers[i].position.lat();
var mlng = gmarkers[i].position.lng();
var dLat = rad(mlat - lat);
var dLong = rad(mlng - lng);
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(rad(lat)) * Math.cos(rad(lat)) * Math.sin(dLong / 2) * Math.sin(dLong / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
distances[i] = d;
if (closest == -1 || d < distances[closest]) {
closest = i;
}
}
}
return (closest);
}
However, when you initialize your markers you may put them in an array markers like this:
markers.push (newMarker);
You may use the function like this:
var closestMarker = find_closest_marker (yourPosition);
closestMarker=markers[closestMarker];
The function find_closest_marker return the case of the nearest in the array markers.
Tell me if you have some questions.
Hey guys, the function of this code is described below.
there are some predefined functions below i.e getMapOption and others
function initialize(){
var divCalcDis = $('divCalcDis');
var pdist = $('pdist');
var pTimeTaken = $('pTimeTaken');
var txtLatLon = $('divLatLon');
var lblDistance = $('lblDistance');
var mapOption = mapHandler.getMapOption(that.LonLatCoordinates[0], 15, "Default");
map = mapHandler.getMap('map_canvas', mapOption);
var renderOption = { draggable: true };
directionsDisplay = new google.maps.DirectionsRenderer(renderOption);
directionsDisplay.setMap(map);
google.maps.event.addListener(directionsDisplay, 'directions_changed', function () { for (i = 0; i < directionsDisplay.directions.routes.length; i++) {
//getting latlon
txtLatLon.innerHTML = "";
console.log(directionsDisplay.directions.routes[i].overview_path.length);
var latLng = directionsDisplay.directions.routes[i].overview_path[k];
var latLng = directionsDisplay.directions.routes[i].overview_path[directionsDisplay.directions.routes[i].overview_path.length - 1].toString();
latLng = latLng.split('(')[1];
latLng = latLng.split(')')[0];
latLng = latLng.split(' ');
latLng = latLng[0] + latLng[1];
txtLatLon.innerHTML += latLng;
}
});
startMap();
}
function startMap() {
var i=0;
google.maps.event.addListener(map, 'click', function (event) {
i++;
if(i === 1){
mapHandler.setMarker(event.latLng, map, "http://www.google.com/intl/en_us/mapfiles/ms/micons/green-dot.png", null, null, null, that.permanentMarkers, false);
that.origin = event.latLng; //comma seperated values of lat,lon
}
else if(i > 1){
mapHandler.setMarker(event.latLng, map, "http://www.google.com/intl/en_us/mapfiles/ms/micons/green-dot.png", null, null, null, that.permanentMarkers, false);
if (i === 2) {
that.dest = event.latLng; //comma seperated values of lat,lon
}
else if (i > 2) {
that.wayPTs.push({
location: that.dest,
stopover: true
});
that.dest = event.latLng;
}
that.calcRoute();
}});
};
function calcRoute() {
var divCalcDis = stringHandler._id('divCalcDis');
var pdist = stringHandler._id('pdist');
var pTimeTaken = stringHandler._id('pTimeTaken');
var txtLatLon = stringHandler._id('divLatLon');
txtLatLon.innerHTML = "";
if (!that.wayPTs.length > 1) {
this.wayPTs = null;
}
var request = this.directionsRequest(this.origin,this.dest,google.maps.DirectionsTravelMode.DRIVING,this.wayPTs,false,true,true,google.maps.DirectionsUnitSystem.METRIC);
that.directionsResponse.route(request, function (response, status) {
//console.log(response);
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
}
});
};
**
I am making a project using Google Maps API V3 Directions library in which i am creating a route when a user click some place on the map
Here is a screenshot**
Now when i drag the direction drawn line it works smoothly and giving me the latitude and longitude correctly.
Here is a screenshot
But the Problem is when i click on anyother place on the map(after dragging) the waypoint refreshes and i get the old without drag route with the next stop as you can see below
Here is a Screenshot
How to save the latLon of the waypoint so they are available after creation of new points Thx
You need to push the coordinates into the route array so they will always be available. So push when you drag and push when you click. May be this can be of assistance to you. Best of luck.
Currently if I search for a route using the DirectionsService it will return me a route with 1 or more legs, and each leg contains multiple steps. Each step seems to correspond to turns in a road. For example, if I drive 2km along street 1 and street1 is entirely a straight road, it will only contain two points (steps) that I can traverse over on that street. The first step will be where the journey along street 1 begins and the next step will be where the journey ends. This makes sense, but unfortunately I'm animating a journey along a map with a marker. This results in huge jumps on the map when there are long straight steps in the journey.
Is there any way to get more detailed steps so that the distance (by road) between each step will be more or less linear?
You can move along the straight line between vertices on the polyline.
See this example for one way to do that.
code snippet:
var map;
var directionDisplay;
var directionsService;
var stepDisplay;
var markerArray = [];
var position;
var marker = null;
var polyline = null;
var poly2 = null;
var speed = 0.000005, wait = 1;
var infowindow = null;
var myPano;
var panoClient;
var nextPanoId;
var timerHandle = null;
function createMarker(latlng, label, html) {
// alert("createMarker("+latlng+","+label+","+html+","+color+")");
var contentString = '<b>'+label+'</b><br>'+html;
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: label,
zIndex: Math.round(latlng.lat()*-100000)<<5
});
marker.myname = label;
// gmarkers.push(marker);
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
return marker;
}
function initialize() {
infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50)
});
// Instantiate a directions service.
directionsService = new google.maps.DirectionsService();
// Create a map and center it on Manhattan.
var myOptions = {
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
address = 'new york'
geocoder = new google.maps.Geocoder();
geocoder.geocode( { 'address': address}, function(results, status) {
map.setCenter(results[0].geometry.location);
});
// Create a renderer for directions and bind it to the map.
var rendererOptions = {
map: map
}
directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
// Instantiate an info window to hold step text.
stepDisplay = new google.maps.InfoWindow();
polyline = new google.maps.Polyline({
path: [],
strokeColor: '#FF0000',
strokeWeight: 3
});
poly2 = new google.maps.Polyline({
path: [],
strokeColor: '#FF0000',
strokeWeight: 3
});
}
var steps = []
function calcRoute(){
if (timerHandle) { clearTimeout(timerHandle); }
if (marker) { marker.setMap(null);}
polyline.setMap(null);
poly2.setMap(null);
directionsDisplay.setMap(null);
polyline = new google.maps.Polyline({
path: [],
strokeColor: '#FF0000',
strokeWeight: 3
});
poly2 = new google.maps.Polyline({
path: [],
strokeColor: '#FF0000',
strokeWeight: 3
});
// Create a renderer for directions and bind it to the map.
var rendererOptions = {
map: map
}
directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
var start = document.getElementById("start").value;
var end = document.getElementById("end").value;
var travelMode = google.maps.DirectionsTravelMode.DRIVING
var request = {
origin: start,
destination: end,
travelMode: travelMode
};
// Route the directions and pass the response to a
// function to create markers for each step.
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK){
directionsDisplay.setDirections(response);
var bounds = new google.maps.LatLngBounds();
var route = response.routes[0];
startLocation = new Object();
endLocation = new Object();
// For each route, display summary information.
var path = response.routes[0].overview_path;
var legs = response.routes[0].legs;
for (i=0;i<legs.length;i++) {
if (i == 0) {
startLocation.latlng = legs[i].start_location;
startLocation.address = legs[i].start_address;
// marker = google.maps.Marker({map:map,position: startLocation.latlng});
marker = createMarker(legs[i].start_location,"start",legs[i].start_address,"green");
}
endLocation.latlng = legs[i].end_location;
endLocation.address = legs[i].end_address;
var steps = legs[i].steps;
for (j=0;j<steps.length;j++) {
var nextSegment = steps[j].path;
for (k=0;k<nextSegment.length;k++) {
polyline.getPath().push(nextSegment[k]);
bounds.extend(nextSegment[k]);
}
}
}
polyline.setMap(map);
map.fitBounds(bounds);
// createMarker(endLocation.latlng,"end",endLocation.address,"red");
map.setZoom(18);
startAnimation();
}
});
}
var step = 50; // 5; // metres
var tick = 100; // milliseconds
var eol;
var k=0;
var stepnum=0;
var speed = "";
var lastVertex = 1;
//=============== animation functions ======================
function updatePoly(d) {
// Spawn a new polyline every 20 vertices, because updating a 100-vertex poly is too slow
if (poly2.getPath().getLength() > 20) {
poly2=new google.maps.Polyline([polyline.getPath().getAt(lastVertex-1)]);
// map.addOverlay(poly2)
}
if (polyline.GetIndexAtDistance(d) < lastVertex+2) {
if (poly2.getPath().getLength()>1) {
poly2.getPath().removeAt(poly2.getPath().getLength()-1)
}
poly2.getPath().insertAt(poly2.getPath().getLength(),polyline.GetPointAtDistance(d));
} else {
poly2.getPath().insertAt(poly2.getPath().getLength(),endLocation.latlng);
}
}
function animate(d) {
// alert("animate("+d+")");
if (d>eol) {
map.panTo(endLocation.latlng);
marker.setPosition(endLocation.latlng);
return;
}
var p = polyline.GetPointAtDistance(d);
map.panTo(p);
marker.setPosition(p);
updatePoly(d);
timerHandle = setTimeout("animate("+(d+step)+")", tick);
}
function startAnimation() {
eol=polyline.Distance();
map.setCenter(polyline.getPath().getAt(0));
// map.addOverlay(new google.maps.Marker(polyline.getAt(0),G_START_ICON));
// map.addOverlay(new GMarker(polyline.getVertex(polyline.getVertexCount()-1),G_END_ICON));
// marker = new google.maps.Marker({location:polyline.getPath().getAt(0)} /* ,{icon:car} */);
// map.addOverlay(marker);
poly2 = new google.maps.Polyline({path: [polyline.getPath().getAt(0)], strokeColor:"#0000FF", strokeWeight:10});
// map.addOverlay(poly2);
setTimeout("animate(50)",2000); // Allow time for the initial map display
}
//=============== ~animation funcitons =====================
// from epolys_v3.js
// http://www.geocodezip.com/scripts/v3_epoly.js
/*********************************************************************\
* .Distance() returns the length of the poly path *
* .GetPointAtDistance() returns a GLatLng at the specified distance *
* along the path. *
* The distance is specified in metres *
* Reurns null if the path is shorter than that *
* .GetIndexAtDistance() returns the vertex number at the specified *
* distance along the path. *
* The distance is specified in metres *
* Returns null if the path is shorter than that *
***********************************************************************/
google.maps.LatLng.prototype.distanceFrom = function(newLatLng) {
var EarthRadiusMeters = 6378137.0; // meters
var lat1 = this.lat();
var lon1 = this.lng();
var lat2 = newLatLng.lat();
var lon2 = newLatLng.lng();
var dLat = (lat2-lat1) * Math.PI / 180;
var dLon = (lon2-lon1) * Math.PI / 180;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180 ) * Math.cos(lat2 * Math.PI / 180 ) *
Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = EarthRadiusMeters * c;
return d;
}
// === A method which returns the length of a path in metres ===
google.maps.Polyline.prototype.Distance = function() {
var dist = 0;
for (var i=1; i < this.getPath().getLength(); i++) {
dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i-1));
}
return dist;
}
// === A method which returns a GLatLng of a point a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polyline.prototype.GetPointAtDistance = function(metres) {
// some awkward special cases
if (metres == 0) return this.getPath().getAt(0);
if (metres < 0) return null;
if (this.getPath().getLength() < 2) return null;
var dist=0;
var olddist=0;
for (var i=1; (i < this.getPath().getLength() && dist < metres); i++) {
olddist = dist;
dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i-1));
}
if (dist < metres) {
return null;
}
var p1= this.getPath().getAt(i-2);
var p2= this.getPath().getAt(i-1);
var m = (metres-olddist)/(dist-olddist);
return new google.maps.LatLng( p1.lat() + (p2.lat()-p1.lat())*m, p1.lng() + (p2.lng()-p1.lng())*m);
}
// === A method which returns the Vertex number at a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polyline.prototype.GetIndexAtDistance = function(metres) {
// some awkward special cases
if (metres == 0) return this.getPath().getAt(0);
if (metres < 0) return null;
var dist=0;
var olddist=0;
for (var i=1; (i < this.getPath().getLength() && dist < metres); i++) {
olddist = dist;
dist += this.getPath().getAt(i).distanceFrom(this.getPath().getAt(i-1));
}
if (dist < metres) {return null;}
return i;
}
html{height:100%;}
body{height:100%;margin:0px;font-family: Helvetica,Arial;}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API v3 Example: Directions Complex</title>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<script type ="text/javascript" src="scripts/v3_epoly.js"></script>
</head>
<body onload="initialize()">
<div id="tools">
start:
<input type="text" name="start" id="start" value="union square, NY"/>
end:
<input type="text" name="end" id="end" value="times square, NY"/>
<input type="submit" onclick="calcRoute();"/>
</div>
<div id="map_canvas" style="width:100%;height:100%;"></div>
</body>
</html>
I am trying to hide a selected category of google map markers when an external javascript function hidetype() is called. To no avail.
I took the general concept from: http://www.geocodezip.com/v3_MW_example_categories.html
Below is the code that extracts my marker info from mysql derived XML. I have the markers grouped by type.
downloadUrl("phpsqlajax_genxml2_snow.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var address = markers[i].getAttribute("address");
var type = markers[i].getAttribute("type");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "Some infoBubble HTML";
var Gtip = "<b>" + name + "</b>";
var icon = customIcons[type] || {};
var hover = icon.hover;
var hoverout = icon.icon;
var marker = new google.maps.Marker({
map: map,
position: point,
icon: icon.icon,
shadow: icon.shadow,
});
marker.mytype = type;
bindInfoWindow(marker, map, infoWindow, html, Gtip, hover, hoverout);
}
});
}
function hidetype(category) {
alert(category);
for (var i=0; i<markers.length; i++) {
if (markers[i].mytype == category) {
markers[i].setVisible(false);
}
}
}
An example of how I'd externally try to remove markers is:
<img onclick="hidetype('1')" src=...>
This currently spits out an alert with the passed type variable but doesn't remove the markers. Thanks in advance!
I am trying to create a polyline from google maps v3 api. I know how add polyline on click but i want to create polyline from latitude & longitude value which will be in loop. How can i do that ?
var network_url = decodeURIComponent(document.URL);
//var network_url = " http://testNetwork.com?param[]=(12.983147333223707, 77.49687217431642)¶m[]=(12.95035965289418, 77.54871391015627)";
var location_array = split_url(network_url);
for(var i = 0; i<location_array.length; i++)
{
//(12.960062579720846,%2077.48313926416017)
var loc = location_array[i] ; //==>(12.77, 24.87)
var split_arr1 = loc.split("(");
var result_split_arr1 = split_arr1[1].split( ")" );
var split_latLon = result_split_arr1[0];
var result_split = split_latLon.split(",");
var split_lat = result_split[0];
var split_lon = result_split[1];
marker = new google.maps.Marker({
position: new google.maps.LatLng(split_lat, split_lon),
map: map
});
///////////POLYLINE DRAWing /////////////////////////////
/////////////END OF POLYLINE ////////////////////
}
}
thank you.
Check out the documentation for the polyline. It takes an array of LatLng's.
Loop through your and points, throw them in an array, and pass them to the PolyLine through the constructor or .setPath().
https://developers.google.com/maps/documentation/javascript/reference#Polyline
Edit: Example. (I didn't run it).
var location_array = split_url(network_url);
var path = [];
for(var i = 0; i<location_array.length; i++)
{
//(12.960062579720846,%2077.48313926416017)
var loc = location_array[i] ; //==>(12.77, 24.87)
var split_arr1 = loc.split("(");
var result_split_arr1 = split_arr1[1].split( ")" );
var split_latLon = result_split_arr1[0];
var result_split = split_latLon.split(",");
var split_lat = result_split[0];
var split_lon = result_split[1];
var latLng = new google.maps.LatLng(split_lat, split_lon);
path.push(latLng)
marker = new google.maps.Marker({
position: latLng,
map: map
});
}
var flightPath = new google.maps.Polyline({
path: path,
strokeColor: "#FF0000",
strokeOpacity: 1.0,
strokeWeight: 2,
map: map
});
}