For each location I'm adding a png icon.
In my database I have many entries with the same lat and lng. Is there a way I can find the entries with the duplicate lat and lng and apply a different icon?
function displayStores(result){
if (result.length > 0){
for (i=0;i<result.length;i++){
//Append Store Address on Sidebar
var html = getEmbedHTML(i+1,result[i].name,result[i].address,result[i].distance);
$("#divStores").append(html);
//place a marker
var image = 'images/number_' + parseInt(i+1) + '.png';
var latlng = new google.maps.LatLng(result[i].lat,result[i].lng);
var marker = new google.maps.Marker({
position: latlng,
map: map,
icon: image
});
var msg = 'Location : ' + result[i].name + '<br/> ';
msg = msg + 'Address : ' + result[i].address + '<br/> ';
attachMessage(marker, msg);
}
} else {
$("#divStores").html('No Stores Found');
}
}
You can sort the points and compute the difference. When it's greater then 0 then you can change the icon.
Related
I'm working on simple App which provide for our clients our branches location, I use now a snapshot of the map, but I want to show the location on real map (Pan) not just an image.
I use Intel XDK platform (HTML/Javascribt)
This is the code I use:
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
var output = document.getElementById("mapp");
function success(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
output.innerHTML = '<p>Latitude is ' + latitude + '° <br>Longitude is ' + longitude + '°</p>';
var img = new Image();
img.src = "https://maps.googleapis.com/maps/api/staticmap?center=" + latitude + "," + longitude + "&zoom=13&size=400x400&sensor=false";
output.appendChild(img);
};
output.innerHTML = "<p>Locating…</p>";
navigator.geolocation.getCurrentPosition(success, onError);
I found the answer, just by changing success function to:
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var bangalore = { lat: 12.97, lng: 77.59 };
var map = new google.maps.Map(document.getElementById('mapp'), {
zoom: 14,
center: bangalore
});
var beachMarker = new google.maps.Marker({
position: bangalore,
map: map,
});
For now, on a button click I have it so that it takes in data from two textboxes, and uses it to
1) append tweets to a panel, and
2) drop pins on a map.
My next step is to have it so that on the button click, it geodecodes a location, and does the same thing. I feel like my jquery.click function is getting really big, and wanted to know if there was a standard way to "separate" it out to make it look prettier and more readable. Can you typically have javascript functions within a jquery file that are called upon, or what is the way to go?
Here is my current jquery file. As you can see it's very big but what happens is straight forward: searchbutton on click takes some values, and sets up a new map in that location, then I access my web server's information, append it to a panel, and also drop pins on a map.
$(function () {
$("#search-button").click(function() {
// variables for google maps
var LatValue = parseFloat($("#searchLat").val());
var LonValue = parseFloat($("#searchLon").val());
var myLatLng = {lat: LatValue, lng: LonValue};
var map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 12,
center: myLatLng
});
$.getJSON(
"http://localhost:3000/tw",
{
geoSearchWord: $("#searchme").val(),
geoSearchWordLat: $("#searchLat").val(),
geoSearchWordLon: $("#searchLon").val(),
geoSearchWordRad: $("#searchRadius").val()
}
).done(function (result) {
$("#fromTweets").empty();
console.log(result);
for (i = 0; i < result.statuses.length; i++) {
//Print out username and status
$("#fromTweets").append('<b>' + "Username: " + '</b>' + result.statuses[i].user.screen_name + '<br/>');
$("#fromTweets").append('<b>' + "Tweet: " + '</b>' + result.statuses[i].text + '<br/>');
$("#fromTweets").append('<b>' + "Created at: " + '</b>' + result.statuses[i].created_at + '<br/>');
if (result.statuses[i].geo !== null) {
//Print out the geolocation
$("#fromTweets").append('<b>' + "GeoLocation: " + '</b>' + "Lat: " + result.statuses[i].geo.coordinates[0] + " Lon: " + result.statuses[i].geo.coordinates[1] + '<br/>'+ '<br/>');
//dropping a new marker on the map for each tweet that has lat/lon values
//Multiplying by i * 0.0005 to space them out in case they are from the same gelocation while still holding
//the integrity of their location.
LatValue = parseFloat(result.statuses[i].geo.coordinates[0] + i*0.0005);
LonValue = parseFloat(result.statuses[i].geo.coordinates[1] + i*0.0005);
myLatLng = {lat: LatValue, lng: LonValue};
var newMarker = new google.maps.Marker({
position: myLatLng,
map: map,
animation: google.maps.Animation.DROP,
});
} else {
$("#fromTweets").append('<b>' + "GeoLocation: " + '</b>' + "Cannot be identified" + '<br/>' + '<br/>')
}
}
});
});
The most simple and obvious thing you can do it so split your code by extracting independent logical blocks to functions:
Just something like this:
var map;
function combineTweetsAjaxRequestData()
{
return {
geoSearchWord: $("#searchme").val(),
geoSearchWordLat: $("#searchLat").val(),
geoSearchWordLon: $("#searchLon").val(),
geoSearchWordRad: $("#searchRadius").val()
};
}
function createGMap()
{
return new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 12,
center: {
lat: parseFloat($("#searchLat").val()),
lng: parseFloat($("#searchLon").val())
}
});
}
function createGMarker(coords)
{
var coordsFixed = {
lat: parseFloat(coords[0] + i * 0.0005),
lng: parseFloat(coords[1] + i * 0.0005)
};
return new google.maps.Marker({
position: coordsFixed,
map: map,
animation: google.maps.Animation.DROP,
});
}
function clearInfo() {
$("#fromTweets").empty();
}
function appendInfo(title, text)
{
$("#fromTweets").append('<b>' + title + ':</b> ' + text + '<br/>');
}
function processTweet(tw)
{
appendInfo('Username', tw.user.screen_name);
appendInfo('Tweet', tw.text);
appendInfo('Created at', tw.created_at);
if (tw.geo !== null) {
var twCoords = tw.geo.coordinates;
appendInfo('GeoLocation', "Lat: " + twCoords[0] + " Lon: " + twCoords[1]);
createGMarker(twCoords);
} else {
appendInfo('GeoLocation', "Cannot be identified")
}
}
function loadTweets() {
$.getJSON(
"http://localhost:3000/tw",
combineTweetsAjaxRequestData()
).done(function (result) {
clearInfo();
console.log(result);
result.statuses.forEach(processTweet);
});
}
$(document).ready(function () {
map = createGMap();
$("#search-button").click(function() {
loadTweets();
});
});
Now, it can be easily read as a text. Your code should be readable and understandable from the first glance. Even better, if a non-developer can read it and understand some basic concepts.
What happens when the page is loaded? We create a Google map control and load tweets
How do we load tweets? We make a AJAX request by combining request data from inputs
What happens when it is loaded? We clear out current information and process every tweet
How do we process a single tweet? We output some basic information. Then, we output geolocation if it is available. Otherwise, we output an error.
Now, if you need to add information to another source, you won't extend or modify your loadTweets method - you will extend or modify appendInfo method, because the logics of information output is encapsulated here.
I am currently plotting multiple points on a map, using addresses from an object. The program loops over the object, geocodes the address, and plots a marker for each location.
The problem I am having is when a user clicks on a place in a list, the map is to pan to that location. The API has a panTo() function that accepts lat, lng values, but the results, i.e. results[0].geometry.location, from the geocode function are not available outside of it.
Question
How do I somehow retrieve the lat, lng from the results, maybe append them to the existing data object, and use them outside the function, so I am able to use them in the panTo() function?
[The lat/lng values are output in html data attributes]
Click handler
$('.place').on('click', function() {
$this = $(this);
lat = $this.data('lat');
lng = $this.data('lng');
map.panTo(new google.maps.LatLng(lat, lng));
});
Data
var locations = [
{
id: 'place1',
postcode: 'B1 1AA'
},
{
id: 'place2',
postcode: 'CB9 8PU'
}
];
Code
for (i = 0; i < locations.length; i++) {
geocoder.geocode({'address': locations[i].postcode}, function(results, status) {
if(status == google.maps.GeocoderStatus.OK) {
marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map
});
} else {
console.log('Geocode was not successful ' + status);
}
}); // end geocode
$(places).append(
'<li class="place" data-id="'+locations[i].id+'" data-lat="<!--lat to go here-->" data-lng="<!--lng to go here-->">'+
'<div class="place-wrap">'+
'<h2>'+locations[i].name+'</h2>'+
'<p class="territory">'+locations[i].territory+'<p>'+
'</div>'+
'</li>'
);
} // end for
Give this a go. The IIFE is there to enclose the index so you don't keep hitting the last index of the locations array due to the asynchronous nature of geocode.
for (i = 0, l = locations.length; i < l; i++) {
(function(i) { // index passed in as parameter
geocoder.geocode({ address: locations[i].postcode }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map
});
$('#places').append(
'<li class="place" data-id="' + locations[i].id + '" data-lat="' + results[0].geometry.location.lat() + '" data-lng="' + results[0].geometry.location.lng() + '">' +
'<div class="place-wrap">' +
'<h2>' + locations[i].name + '</h2>' +
'<p class="territory">' + locations[i].territory + '<p>'+
'</div>' +
'</li>'
);
} else {
console.log('Geocode was not successful ' + status);
}
});
}(i)); // index passed in to IIFE
}
I have been trying for hours and also referred to a post in this forum but failed. I have a large number of markers, up to 1000 markers on the map. It slows down my map when I try to move the map's position. So I need to set an interval of markers to be shown on the map. Let's say with interval of 10 when there are more than 300 markers. How can I do that? Below is my code :
var trace_markers= [];
var pins = [];
var pin;
function Trace_Pin(Lat, Long, immat, type, site, vitesse, date){
pin = {
latitude: document.getElementById('Lat'),
longitude: document.getElementById('Long'),
immat: document.getElementById('immat'),
date: document.getElementById('date'),
type: document.getElementById('type'),
site: document.getElementById('site'),
speed: document.getElementById('vitesse')
};
pins.push(pin);
ListPin();}
function ListPin()
{
var image_trace = new google.maps.MarkerImage('http://maps.google.com/mapfiles/kml/pal3/icon61.png',
new google.maps.Size(32, 32),
new google.maps.Point(0,0),
new google.maps.Point(16, 16));
if (pins.length > 200){
for ( var i=0; i< pins.length ;i+10){
var vehlatlng = new google.maps.LatLng(pins[i].latitude, pins[i].longitude) ;
var trace_marker = new google.maps.Marker({
map: map,
position: vehlatlng,
icon: image_trace });
trace_marker.tooltip_html = '<div class="tooltip">' + 'Date : ' + pins[i].date + '<br>' + 'Vitesse : ' + pins[i].vitesse + ' km/h' + '<br>' + '<\/div>';
trace_markers.push(trace_marker);
trace_marker.setMap(map);
Liste_Points.push(trace_marker.getPosition());
TraceBounds.extend(trace_marker.position); }
}
if (pins.length < 200){
for ( var i=0;i< pins.length ;i++){
var vehlatlng = new google.maps.LatLng(pins[i].latitude, pins[i].longitude) ;
var trace_marker = new google.maps.Marker({
map: map,
position: vehlatlng,
icon: image_trace });
trace_marker.tooltip_html = '<div class="tooltip">' + 'Date : ' + pins[i].date + '<br>' + 'Vitesse : ' + pins[i].vitesse + ' km/h' + '<br>' + '<\/div>';
trace_markers.push(trace_marker);
trace_marker.setMap(map);
Liste_Points.push(trace_marker.getPosition());
TraceBounds.extend(trace_marker.position); }
}
// Evenement MouseOver
//-----------------------------------------------------
google.maps.event.addListener(map, 'mouseover', function() {
showTooltip(trace_marker);
});
}
// ------------------------------------------------------------------------------------
//**************************************************************************************
// On joint les points du parcours
//**************************************************************************************
// ------------------------------------------------------------------------------------
function Trace_Route() {
if (route) { route.setMap(null); }
if (Liste_Points.length > 1) {
route = new google.maps.Polyline({
path: Liste_Points,
strokeColor: "#FF0000",
strokeOpacity: 1.0,
strokeWeight: 2});
route.setMap(map);
}
}
Create an array where you have all your markers (300 of them).
Lets assume that is called
allMarkersArray[]
When you create a marker you do not set the map, but you leave it null so it won't be shown on the map. When you want to show the markers you do some math. Lets say that you want to show only the 1/30 (10 out of 300) of the markers. You create another array
shownMarketsArray[]
where you place the markers you want to show and when you put them there you set the map
marker.setMap(map)
Now the criteria of which markers will be shown, and which markers will remain hidden are up to you. If you want the 1/30 of the markers just have a for loop
for(var i = 0; i < allMarketsArray.length/30; i++)
You should take some precautions though (i.e. the array is too small and you want to show all of them).
UPDATE
if (pins.length > 200){
for ( var i=0; i< pins.length ;i+10){
var vehlatlng = new google.maps.LatLng(pins[i].lat, pins[i].long) ;
var trace_marker = new google.maps.Marker({
map: map,
position: vehlatlng,
icon: image_trace });
trace_marker.tooltip_html = '<div class="tooltip">' + 'Date : ' + pins[i].date + '<br>' + 'Vitesse : ' + pins[i].vitesse + ' km/h' + '<br>' + '<\/div>';
trace_markers.push(trace_marker);
trace_marker[i].setMap(map);
Liste_Points.push(trace_marker.getPosition());
TraceBounds.extend(trace_marker.position); }
}
if (pins.length < 200){
for ( var i=0;i< pins.length ;i++){
var vehlatlng = new google.maps.LatLng(pins[i].lat, pins[i].long) ;
var trace_marker = new google.maps.Marker({
map: map,
position: vehlatlng,
icon: image_trace });
trace_marker.tooltip_html = '<div class="tooltip">' + 'Date : ' + pins[i].date + '<br>' + 'Vitesse : ' + pins[i].vitesse + ' km/h' + '<br>' + '<\/div>';
trace_markers.push(trace_marker);
trace_marker[i].setMap(map);
Liste_Points.push(trace_marker.getPosition());
TraceBounds.extend(trace_marker.position); }
}
I am wanting to search a KML file to see if a particular address falls within an overlay. Presently, I have the address converting to a geocode. However, I'm not sure what code is needed to add this functionality.
Here's the present code:
function initialize() {
var infowindow = new google.maps.InfoWindow({
content: '',
suppressMapPan:true
});
var myLatlng = new google.maps.LatLng(35.910200,-84.085100);
var myOptions = {
zoom: 12,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(
document.getElementById("map_canvas"), myOptions);
var d = new Date();
var n = d.getMilliseconds();
var nyLayer = new google.maps.KmlLayer(
'http://www.cspc.net/neighborhoods/groups.kml?rand=' + n,
{ suppressInfoWindows: true, map: map});
google.maps.event.addListener(nyLayer, 'click', function(kmlEvent) {
var url = kmlEvent.featureData.snippet;
var groupName = kmlEvent.featureData.name;
var insideContent = "<div style='width:250px;'><h2>" + groupName +
"</h1><p>We have a neighborhood contact in your area! </p>" +
"<p><a href='" + url + "' target='_blank'>Get connected!</a>" +
" They look forward to hearing from you.</p><p>If you have " +
"any additional questions, please contact our " +
"<a href='http://www.cspc.net/communitylife' target='_blank'>" +
"Community Life</a> staff for more information. Betsy Palk, " +
"the Administrative Assistant, may be reached at:<br/><br/>" +
"<b>Email:</b> <a href='mailto:betsypalk#cspc.net'>" +
"betsypalk#cspc.net</a><br/><b>Phone:</b> 865-291-5268<p></div>";
var clickPos = kmlEvent.latLng;
var posX = new google.maps.LatLng(clickPos.lat(), clickPos.lng());
infowindow.close();
infowindow.setPosition(posX);
infowindow.setContent(insideContent);
infowindow.open(map);
});
eventMapClick = google.maps.event.addListener(map, 'click',
function(event) {
var marker = new google.maps.Marker({ position: event.latLng });
var outsideContent = "<div style='width:250px;'><h2>Oops!</h1>" +
"<p> It seems we don't have a neighborhood contact in your " +
"area.</p><p>Please contact our <a " +
"href='http://www.cspc.net/communitylife' target= '_blank'>" +
"Community Life</a> staff for more information. " +
"Betsy Palk, the Administrative Assistant, may be reached at:" +
"<br/><br/><b>Email: </b> <a href='mailto:betsypalk#cspc.net'>" +
"betsypalk#cspc.net</a><br/><b>Phone:</b> 865-291-5268<p></div>";
infowindow.setContent(outsideContent);
infowindow.open(map, marker);
});
}
var geocoder = new google.maps.Geocoder();
function searchAddress(address) {
geocoder.geocode(
{'address': address},
function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var loc = results[0].geometry.location;
// use loc.lat(), loc.lng()
window.alert(loc);
}
else {
window.alert("Not found: " + status);
}
}
);
};
If I understand your question, I believe you want the formula to determine if a point (google.maps.LatLng) falls within one of your KML Placemark definitions (that you give names such as: Neighborhood Group 1). Within each Placemark, you define a Polygon and within each Polygon, you define a set of coordinates, which represent the vertices of the Polygon.
Using the coordinates within the Polygon and the LatLng you retrieve via geocoding, you could start with these formulas and select that one that is the best fit for you:
Fast Winding Number Inclusion of a Point in a Polygon
Point-In-Polygon Algorithm
A very similar question has also been asked here on SO: Determine the lat lngs of markers within a polygon.