I have a map thats populated with markers of places from a fusion table. I'm taking the users location and displaying a circle of radius 10 miles from their location. Here is my code - http://connormccarra.com/sandbox/map/. How can I use the api to count the number of markers bound by the circle and output that number in the footer?
Cheers!
Relevant code:
var map;
function Initialize() {
var MapOptions = {
zoom: 7,
center: new google.maps.LatLng(53.4125694, -8.245014),
mapTypeId: google.maps.MapTypeId.ROADMAP,
sensor: true
};
map = new google.maps.Map(document.getElementById("map_canvas"), MapOptions);
var layer = new google.maps.FusionTablesLayer({
query: {
select: 'Address',
from: '1OPU6utSjRYwJSFK-EXdaGmt2KgLTq2loVIjS3AA'
}
});
layer.setMap(map);
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var marker = new google.maps.Marker({
map: map,
position: pos,
content: 'You are here!'
});
// Add circle overlay and bind to marker
var circle = new google.maps.Circle({
map: map,
radius: 16093, // 10 miles in metres
fillColor: '#AA0000'
});
circle.bindTo('center', marker, 'position');
map.setCenter(pos);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
}
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = 'Error: The Geolocation service failed.';
} else {
var content = 'Error: Your browser doesn\'t support geolocation.';
}
var options = {
map: map,
position: new google.maps.LatLng(60, 105),
content: content
};
var count = mgr.getMarkerCount(circle);
document.getElementById("Address").innerHTML += count + "<BR>";
google.maps.event.addDomListener(window, 'load', initialize);
//Maps API loaded, now load customizations
var element = document.createElement('script');
element.src = 'template.js';
element.type = 'text/javascript';
var scripts = document.getElementsByTagName('script')[0];
scripts.parentNode.insertBefore(element, scripts);
}
The markers created by a FusionTableLayer are not real markers, there is no way to get them as a kind of list to filter them(you can't get any details for the markers, except you click them).
But you may request the FusionTableAPI with a spatial condition(via AJAX, jsonp is supported).
The syntax for the query:
SELECT COUNT() from tableId
WHERE ST_INTERSECTS('Address',CIRCLE(LATLNG(lat,lng),10000))
How to send a query : https://developers.google.com/fusiontables/docs/v1/sql-reference
Demo(using data of another FusionTable because your table is protected):
http://jsfiddle.net/doktormolle/bAtgf/
Simplest way: use the geometry library computeDistanceBetween method. If the distance from the user's location is less than 10 miles, the marker is in the circle.
I suggest you first fetch all the coordinates of your FusionTablesLayer.
Here is an example which was used in the sidebar
http://www.geocodezip.com/v3_FusionTables_AfricaMap_kml_sidebar.html
Then using a loop statement you can use the computeDistanceBetween function.
Detect If Marker is Within Circle Overlay
Related
How can you show data for individual markers?
I am able to show custom data when a mouseover occurs on a Google Maps API markerclusterer cluster but can't work out how to do the same for an individual marker (i.e. when you zoom in to a cluster until you see individual markers).
The code which shows data for the clusters is:
var markerClusterer = null;
var map = null;
var imageUrl = 'http://chart.apis.google.com/chart?cht=mm&chs=24x32&' +
'chco=FFFFFF,008CFF,000000&ext=.png';
google.maps.event.addDomListener(window, 'load', initialize);
function refreshMap() {
if (markerClusterer) {
markerClusterer.clearMarkers();
}
var markers = [];
var markerImage = new google.maps.MarkerImage(imageUrl,
new google.maps.Size(24, 32));
for (var i = 0; i < numItemsToShow; ++i) {
var latLng = new google.maps.LatLng(itemsToShow[i].lat, itemsToShow[i].long);
var marker = new google.maps.Marker({
position: latLng,
icon: markerImage
});
markers.push(marker);
}
var zoom = parseInt(document.getElementById('zoom').value, 10);
var size = parseInt(document.getElementById('size').value, 10);
var style = parseInt(document.getElementById('style').value, 10);
zoom = zoom == -1 ? null : zoom;
size = size == -1 ? null : size;
style = style == -1 ? null: style;
markerClusterer = new MarkerClusterer(map, markers, {
maxZoom: zoom,
gridSize: size,
styles: styles[style]
});
// Respond to mouseover on marker cluster
var infoWindow = new google.maps.InfoWindow();
google.maps.event.addListener(markerClusterer, 'mouseover', function (cluster) {
// do something with this cluster ...
infoWindow.setContent("Mouseover<br>"+cluster.getCenter().toUrlValue());
infoWindow.setPosition(cluster.getCenter());
infoWindow.open(map);
});
// HOW TO RESPOND TO MOUSEOVER ON INDIVIDUAL MARKER?
}
Add a click listener to the google.maps.Marker objects:
var latLng = new google.maps.LatLng(itemsToShow[i].lat, itemsToShow[i].long);
var marker = new google.maps.Marker({
position: latLng,
icon: markerImage
});
// slightly modified from Google Maps JS API v3 - Simple Multiple Marker Example
// http://stackoverflow.com/questions/3059044/google-maps-js-api-v3-simple-multiple-marker-example
google.maps.event.addListener(marker, 'click', (function(marker, i) {
return function() {
infowindow.setContent(ItemsToShow[i].lat+","+itemsToShow[i].long);
infowindow.open(map, marker);
}
})(marker, i));
This code takes a big list of (400) markers and adds it to the map, at the end, it shows the whole map including all the markers.
What I have tried to achieve is: when geolocation is available, center the map on location, zoom to level 16 and refresh the map to show it, otherwise, let the whole big map show... I have read and tried many different things, but the geolocation must happen before the map is created. I want to make it happen after. I show you my code here and the temporary link to the working site: http://studioteknik.co/brasseursillimites.com/detaillants/
function initialize()
{
var map = new google.maps.Map(document.getElementById('map-canvas'));
var bounds = new google.maps.LatLngBounds();
var infowindow = new google.maps.InfoWindow();
for (var i in locations) {
var p = locations[i];
var latlng = new google.maps.LatLng(p[1], p[2]);
bounds.extend(latlng);
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: p[0]
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(this.title);
infowindow.open(map, this);
});
}
map.fitBounds(bounds);
}
google.maps.event.addDomListener(window, 'load', initialize);
Here is a simple example of geolocation. Just add the geolocation code anywhere after the map object is created. If the user doesn't allow geolocation, the map will be shown at the default location / zoom level.
function initialize() {
var mapOptions = {
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: new google.maps.LatLng(0,0)
};
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
// Geolocation code
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
map.panTo(new google.maps.LatLng(position.coords.latitude, position.coords.longitude));
map.setZoom(16);
});
}
}
initialize();
JSFiddle demo
I have a Google map API V2 script allowing two maps of different sizes and zoom levels to move together, when one map is panned the other also moves to maintain the same center point. The smaller map has a Xhair in the center that returns to the center after it has been panned, the larger map has multiple markers.
I'm trying to upgrade the code to API V3, but the V3 maps aren't moving each other and the smaller map Xhair isn't functioning. Can someone please tell me what am I missing in the script upgrade from API V2 to API V3?
V2 code:
<script type="text/javascript">
//<![CDATA[
if (GBrowserIsCompatible()) {
function createMarker(point) {
map.addOverlay(new GMarker(point));
}
// ===== Setup The Maps =====
// Display the main map, with some controls and set the initial location
var map = new GMap2(document.getElementById("map"));
map.addControl(new GLargeMapControl());
map.addControl(new GMapTypeControl());
map.setCenter(new GLatLng(54.531283,-125.125537), 12);
// Set up three markers on the main map
createMarker(new GLatLng(54.207882,-125.661621));
createMarker(new GLatLng(49.214790,-124.054399));
createMarker(new GLatLng(49.053632,-122.352859));
// create the crosshair icon, which will indicate where we are on the minimap
// Lets not bother with a shadow
var Icon = new GIcon();
Icon.image = "xhair.png";
Icon.iconSize = new GSize(21, 21);
Icon.shadowSize = new GSize(0,0);
Icon.iconAnchor = new GPoint(11, 11);
Icon.infoWindowAnchor = new GPoint(11, 11);
Icon.infoShadowAnchor = new GPoint(11, 11);
// Create the minimap
var minimap = new GMap2(document.getElementById("minimap"));
minimap.setCenter(new GLatLng(54.531283,-125.125537), 7);
// Add the crosshair marker at the centre of the minimap and keep a reference to it
var xhair = new GMarker(minimap.getCenter(), Icon);
minimap.addOverlay(xhair);
// ====== Handle the Map movements ======
// Variables that log whether we are currently causing the maps to be moved
var map_moving = 0;
var minimap_moving = 0;
// This function handles what happens when the main map moves
// If we arent moving it (i.e. if the user is moving it) move the minimap to match
// and reposition the crosshair back to the centre
function Move(){
minimap_moving = true;
if (map_moving == false) {
minimap.setCenter(map.getCenter());
xhair.setPoint(map.getCenter());
xhair.redraw(true);
}
minimap_moving = false;
}
// This function handles what happens when the mini map moves
// If we arent moving it (i.e. if the user is moving it) move the main map to match
// and reposition the crosshair back to the centre
function MMove(){
map_moving = true;
if (minimap_moving == false) {
map.setCenter(minimap.getCenter());
xhair.setPoint(minimap.getCenter());
xhair.redraw(true);
}
map_moving = false;
}
// Listen for when the user moves either map
GEvent.addListener(map, 'move', Move);
GEvent.addListener(minimap, 'moveend', MMove);
}
// display a warning if the browser was not compatible
else {
alert("Sorry, the Google Maps API is not compatible with this browser");
}
Non-working V3 code:
<script type="text/javascript">
function createMarker(point) {
map.addOverlay(new google.maps.Marker(point));
}
// ===== Setup The Maps =====
// Display the main map, with some controls and set the initial location function initialize() {
var map = new google.maps.Map(
document.getElementById('map'), {
center: new google.maps.LatLng(54.531283,-125.125537),
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Set up three markers on the main map
var marker = new google.maps.Marker({
position: new google.maps.LatLng(54.207882,-125.661621),
map: map
});
var marker = new google.maps.Marker({
position: new google.maps.LatLng(49.214790,-124.054399),
map: map
});
var marker = new google.maps.Marker({
position: new google.maps.LatLng(49.053632,-122.352859),
map: map
});
// create the crosshair icon, which will indicate where we are on the minimap
// Lets not bother with a shadow
var Icon = new google.maps.MarkerImage();
Icon.image = "xhair.png";
Icon.iconSize = new google.maps.Size(21, 21);
Icon.shadowSize = new google.maps.Size(0,0);
Icon.iconAnchor = new google.maps.Point(11, 11);
Icon.infoWindowAnchor = new google.maps.Point(11, 11);
Icon.infoShadowAnchor = new google.maps.Point(11, 11);
// Create the minimap
var minimap = new google.maps.Map(
document.getElementById('minimap'), {
center: new google.maps.LatLng(54.531283,-125.125537),
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Add the crosshair marker at the centre of the minimap and keep a reference to it
var xhair = new google.maps.Marker(minimap.getCenter(), Icon);
minimap.addOverlay(xhair);
// ====== Handle the Map movements ======
// Variables that log whether we are currently causing the maps to be moved
var map_moving = 0;
var minimap_moving = 0;
// This function handles what happens when the main map moves
// If we arent moving it (i.e. if the user is moving it) move the minimap to match
// and reposition the crosshair back to the centre
function Move(){
minimap_moving = true;
if (map_moving == false) {
minimap.setCenter(map.getCenter());
xhair.setPoint(map.getCenter());
xhair.redraw(true);
}
minimap_moving = false;
}
// This function handles what happens when the mini map moves
// If we arent moving it (i.e. if the user is moving it) move the main map to match
// and reposition the crosshair back to the centre
function MMove(){
map_moving = true;
if (minimap_moving == false) {
map.setCenter(minimap.getCenter());
xhair.setPoint(minimap.getCenter());
xhair.redraw(true);
}
map_moving = false;
}
// Listen for when the user moves either map
google.maps.event.addListener(map, 'move', Move);
google.maps.event.addListener(minimap, 'moveend', MMove);
// google.maps.event.addDomListener(window, 'load', initialize);
google.maps.event.addDomListener(window, 'load', initialize);
The upgrade guide seems to have little information on Events, some obsolete events don't seem to be listed in the obsolete code. The V2 events: "move" and "moveend" are apparently not supported in V3, however there are similar (but not the same) V3 events; dragstart, drag, dragend, and center_changed. Since the drag events aren't compatable with additional selection buttons I'm using: I went with center_changed which works like a charm for my application.
I explored a few options for the center cross hair, but they seemed to have dead spots or jumped around when the maps were panned, so I eliminated the javascript solutions and went with a simple solution from Drew Noakes.
This is what I came up with to fix the non-working V3 code, might help someone out there.
V3 code:
<script type="text/javascript">
// ===== Setup The Maps =====
// Display the main map and set the initial location
var map = new google.maps.Map(
document.getElementById('map'), {
center: new google.maps.LatLng(54.531283,-125.125537),
zoom: 12,
zoomControl: false,
scaleControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Set up the three markers on the main map
var marker = new google.maps.Marker({
position: new google.maps.LatLng(54.207882,-125.661621),
map: map
});
var marker = new google.maps.Marker({
position: new google.maps.LatLng(49.214790,-124.054399),
map: map
});
var marker = new google.maps.Marker({
position: new google.maps.LatLng(49.053632,-122.352859),
map: map
});
// Create the minimap
var minimap = new google.maps.Map(
document.getElementById('minimap'), {
center: new google.maps.LatLng(54.531283,-125.125537),
zoom: 7,
zoomControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
// Add the crosshair marker at the centre of the minimap using html and CSS
// ====== Handle the Map movements ======
// Variables that log whether we are currently causing the maps to be moved
var map_moving = 0;
var minimap_moving = 0;
// This function handles what happens when the main map moves
// If we arent moving it (i.e. if the user is moving it) move the minimap to match
google.maps.event.addListener(map, 'center_changed', function(){
minimap_moving = true;
if (map_moving == false) {
minimap.setCenter(map.getCenter());
}
minimap_moving = false;
})
// This function handles what happens when the mini map moves
// If we arent moving it (i.e. if the user is moving it) move the main map to match
google.maps.event.addListener(minimap, 'center_changed', function(){
map_moving = true;
if (minimap_moving == false) {
map.setCenter(minimap.getCenter());
}
map_moving = false;
})
// google.maps.event.addDomListener(window, 'load', initialize);
google.maps.event.addDomListener(window, 'load', initialize);
</script>
//The HTML:
<div id="map" style="width:627px; height: 627px"></div>
<div id="container">
<div id="minimap" style="width:370px; height:370px;"></div>
<div id="xhair"><img src="../images/xhair.png" width="20" height="20" /></div>
</div>
//The CSS:
#container { position:relative; }
#map { height:100%; width:100%; }
#xhair {
position:absolute;
left:47%;
top:47%;
}
Ok I spent 2 days working on this time for some help :) Everything works fine with the code now I just need to make the marker draggable and update Lat and Lng values. At present the code captures lat and lng via current position as well as via entering a location on the web page. The value of _Lat and _lng are then submitted the a database. I need the user to be able to drag the marker to fine tune the location and update _lat and _lng prior to the database submit. I have made the marker draggable but I can't figure out how to add the dragend code so that it dynamically updates the value of lat and _lng prior to the database submit. I don't need to update anything on the web page just I need to update the _lat and _lng values that get posted to the database. Here is the existing code:
Thanks
var gmap;
var gmarker;
var geocoder;
function initialize() {
// Get here center of map - by default - San Francisco center
var center = new google.maps.LatLng(37.47, -122.25);
var mapOptions = {
center: center,
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
geocoder = new google.maps.Geocoder()
gmap = new google.maps.Map(document.getElementById("map_canvas"),
mapOptions);
// Set inner position of map to form parameters
$('input[name="_lat"]').val(37.47);
$('input[name="_lng"]').val(-122.25);
gmarker = new google.maps.Marker({
map: gmap,
position: center,
icon: '/static/internal/images/mapicon.png',
draggable: true
});
google.maps.event.addListener(gmap, 'click', function(event) {
gmarker.setPosition(event.latLng);
$('input[name="_lat"]').val(event.latLng.lat());
$('input[name="_lng"]').val(event.latLng.lng());
});
navigator.geolocation.getCurrentPosition(function(position){
var _lng = position.coords.longitude;
var _lat = position.coords.latitude;
$('input[name="_lng"]').val(_lng);
$('input[name="_lat"]').val(_lat);
var new_position = new google.maps.LatLng(_lat, _lng);
gmap.setCenter(new_position);
gmarker.setPosition(new_position);
})
}
function showAddress(address) {
if (geocoder) {
geocoder.geocode(
{'address': address},
function(results, status) {
if (status != google.maps.GeocoderStatus.OK) {
alert(address + " not found");
} else {
gmap.setCenter(results[0].geometry.location);
gmarker.setPosition(results[0].geometry.location);
$('input[name="_lat"]').val(results[0].geometry.location.lat());
$('input[name="_lng"]').val(results[0].geometry.location.lng());
}
}
);
}
}
listen to the position_changed-event of the marker:
google.maps.event.addListener(gmarker, 'position_changed', function() {
$('input[name="_lat"]').val(this.getPosition().lat());
$('input[name="_lng"]').val(this.getPosition().lng());
});
Your click event is on map it should be on marker
Change
google.maps.event.addListener(gmap, 'click', function(event) {
To
google.maps.event.addListener(gmarker, 'click', function(event) {
I have the next code to retrieve some data from a xml file. The problem is that when I want to refresh the markers, the response that I get is a duplicated marker in the map. How can I update the points without having duplicated markers?
Best regards
//<![CDATA[
// this variable will collect the html which will eventually be placed in the side_bar
var side_bar_html = "";
// arrays to hold copies of the markers and html used by the side_bar
// because the function closure trick doesnt work there
var gmarkers = [];
// global "map" variable
var map = null;
var markerclusterer = null;
// A function to create the marker and set up the event window function
function createMarker(latlng, imei, html, estado, alias, speed, timestamp) {
if(estado == 1)
image = '/artworks/icons/truck_green3.png';
else
image = '/artworks/icons/truck_red.png';
var textoLabel= "this is the text"
var contentString = html;
var marker = new MarkerWithLabel({
position: latlng,
icon: image,
// map: map,
labelContent: textoLabel,
labelAnchor: new google.maps.Point(40, 0),
labelClass: "labels", // the CSS class for the label
labelStyle: {opacity: 0.50},
zIndex: Math.round(latlng.lat()*-100000)<<5
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map,marker);
});
// save the info we need to use later for the side_bar
gmarkers.push(marker);
// add a line to the side_bar html
side_bar_html += '<a href="javascript:myclick(' + (gmarkers.length-1) + ')">' + imei + '<\/a><br>';
}
// This function picks up the click and opens the corresponding info window
function myclick(i) {
google.maps.event.trigger(gmarkers[i], "click");
}
function initialize() {
// create the map
var myOptions = {
zoom: 12,
center: new google.maps.LatLng(37.169619,-3.756981),
mapTypeControl: true,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
navigationControl: true,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
}
function getMarkers() {
google.maps.event.addListener(map, 'click', function() {
infowindow.close();
});
// Read the data from example.xml
downloadUrl("vehiculos.asp", function(doc) {
var xmlDoc = xmlParse(doc);
var markers = xmlDoc.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
// obtain the attribues of each marker
var lat = parseFloat(markers[i].getAttribute("lat"));
var lng = parseFloat(markers[i].getAttribute("lng"));
var point = new google.maps.LatLng(lat,lng);
var imei = markers[i].getAttribute("imei");
var alias = markers[i].getAttribute("alias");
var speed= markers[i].getAttribute("speed");
var timestamp= markers[i].getAttribute("timestamp");
var estado= markers[i].getAttribute("estado");
var conectado= markers[i].getAttribute("conectado");
var html="<b>"+alias+"</b><br> a una velocidad de "+speed+" km/h <br/> ultima posicion a las: "+timestamp;
// create the marker
var marker = createMarker(point,alias+" "+imei,html,estado, speed, timestamp );
}
markerCluster = new MarkerClusterer(map, gmarkers);
// put the assembled side_bar_html contents into the side_bar div
document.getElementById("side_bar").innerHTML = side_bar_html;
});
}
var infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50)
});
// Removes the overlays from the map, but keeps them in the array.
function clearOverlays() {
getMarkers(null);
}
// Deletes all markers in the array by removing references to them.
function deleteOverlays() {
clearOverlays();
getMarkers = [];
}
setInterval(clearOverlays, 3000);
setInterval(deleteOverlays, 4000);
setInterval(getMarkers, 5000);
Give your markers unique ids (maybe one of your existing attributes is already unique). If the unique id already exists, move that marker to the new location (or just don't add it again),if it doesn't, create a new marker.
If they don't move, you can also avoid duplicates by checking the distance between new markers and all your existing markers, if it is less than a "same marker" threshold (say ~0.1 meters), don't add it again.
There is a problem with your clearOverlays method (getMarkers(null) just calls getMarkers):
// Removes the overlays from the map, but keeps them in the array.
function clearOverlays() {
for (var i=0; i<gmarkers.length; i++)
{
gmarkers[i].setMap(null);
}
}