I am trying to build a map-based site that identifies a user's geolocation, draws a marker at his/her position, and then uses that marker/location to click on a data layer (in this case, a GeoJSON layer). Essentially, the user's location should trigger an infowindow automatically if he or she is located on an area delineated by the geojson file. Ideally, each time the user changes location it will be clicking the map to check this GeoJSON layer for info.
So far, I can get the user's location successfully. The map centers on that location. And manual clicks on the GeoJSON layer also populate the info window correctly. But it's not clicking automatically when getting the user location.
I've seen lots of examples where a forced click on a marker takes place, but I can't seem to find one that clicks a data layer. Unfortunately I'm more of a GIS person assigned to a coding job on this, which is way out of my league, so I'm struggling to figure out where I'm going wrong with this.
Here's the script, perhaps I'm making a mistake here:
$<script type="text/javascript">
//centers the map on Iowa City
var map,
currentPositionMarker,
mapCenter = new google.maps.LatLng(41.661354, -91.534729),
map;
function initializeMap()
{
map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: 18,
center: mapCenter,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
map.data.loadGeoJson('test2.json');
map.data.setStyle({
strokeColor: '#2687bf',
strokeWeight: 5
});
map.data.addListener('click', function(event) {
document.getElementById('info-box').textContent =
event.feature.getProperty('description');
});
}
function locError(error) {
// the current position could not be located
alert("The current position could not be found!");
}
function setCurrentPosition(pos) {
currentPositionMarker = new google.maps.Marker({
map: map,
draggable: true,
position: new google.maps.LatLng(
pos.coords.latitude,
pos.coords.longitude
),
title: "Current Position"
});
new google.maps.event.trigger( 'test2.json', 'click' );
map.panTo(new google.maps.LatLng(
pos.coords.latitude,
pos.coords.longitude
));
}
function displayAndWatch(position) {
// set current position
setCurrentPosition(position);
// watch position
watchCurrentPosition();
}
function watchCurrentPosition() {
var positionTimer = navigator.geolocation.watchPosition(
function (position) {
setMarkerPosition(
currentPositionMarker,
position
);
});
}
function setMarkerPosition(marker, position) {
marker.setPosition(
new google.maps.LatLng(
position.coords.latitude,
position.coords.longitude)
);
}
function initLocationProcedure() {
initializeMap();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(displayAndWatch, locError);
} else {
alert("Your browser does not support the Geolocation API");
}
}
$(document).ready(function() {
initLocationProcedure();
});
</script>
</head>
<body>
<div id="map_canvas" style="height:600px;"></div>
<div id="info-box" style="height:250px;">INFO</div>
</body>
</html>
And here are links to my JSON and full HTML file for this:
https://sites.google.com/site/ecocritkml/coding
The JSON is obviously specific to Iowa City, Iowa, but it could be modified easily in a text editor. Any ideas would be really helpful here.
I think I got it.
I had to use a few tricks (some maybe a little dirty)
I put a 500ms delay with setTimeout; this could have been done more elegantly, no doubt
I make a temporary polygon, because it permits to use containsLocation()
I don't invoke a click, but there is a loop over the polygon features, I read the description there, and set it to the div
..
<!doctype html>
<html lang="en">
<head>
<title>Google maps</title>
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src=http://maps.google.com/maps/api/js?v=3&sensor=true&language=en"></script>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map_canvas {
height: 100%;
}
#info-box {
background-color: white;
border: 1px solid black;
bottom: 30px;
height: 20px;
padding: 10px;
position: absolute;
left: 30px;
}
</style>
<script type="text/javascript">
//centers the map on Iowa City
var map,
currentPositionMarker,
mapCenter = new google.maps.LatLng(41.661354, -91.534729),
map;
function initializeMap() {
map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: 18,
center: mapCenter,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
map.data.loadGeoJson('test2.json');
map.data.setStyle({
strokeColor: '#2687bf',
strokeWeight: 5
});
map.data.addListener('click', function(event) {
document.getElementById('info-box').textContent = event.feature.getProperty('description');
});
}
function locError(error) {
// the current position could not be located
}
function setCurrentPosition(pos) {
currentPositionMarker = new google.maps.Marker({
map: map,
draggable: true,
position: new google.maps.LatLng(
pos.coords.latitude,
pos.coords.longitude
),
title: "Current Position"
});
// Wait half a second, then take a loop of the features, see if the marker is inside one of them
setTimeout(function() {
map.data.forEach(function(feature){
var figure = feature.getGeometry();
if(figure.getType() == 'Polygon') {
// make a temporary polygon, see if the marker is inside
var tempPolygon = new google.maps.Polygon({
paths: figure.getAt(0).getArray(), // #see http://stackoverflow.com/questions/33249127/using-containslocation-with-a-google-maps-data-polygon
map: null
});
if(google.maps.geometry.poly.containsLocation(currentPositionMarker.getPosition(), tempPolygon)) {
// marker is inside this feature
// invoke a click. well, just pretend ...
document.getElementById('info-box').textContent = feature.getProperty('description');
}
}
var b;
})
}, 500);
map.panTo(new google.maps.LatLng(
pos.coords.latitude,
pos.coords.longitude
));
}
function displayAndWatch(position) {
// set current position
setCurrentPosition(position);
// watch position
watchCurrentPosition();
}
function watchCurrentPosition() {
var positionTimer = navigator.geolocation.watchPosition(function (position) {
setMarkerPosition(
currentPositionMarker,
position
);
});
}
function setMarkerPosition(marker, position) {
marker.setPosition(
new google.maps.LatLng(
position.coords.latitude,
position.coords.longitude
)
);
// now we see if the marker is inside one of the polygons
var a = 0;
}
function initLocationProcedure() {
initializeMap();
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(displayAndWatch, locError);
}
else {
// alert("Your browser does not support the Geolocation API");
}
}
$(document).ready(function() {
initLocationProcedure();
});
</script>
</head>
<body>
<div id="map_canvas" style="height:600px;"></div>
<div id="info-box" style="height:250px;">INFO</div>
</body>
</html>
Related
I am trying to make an animated google map using data from .csv. The path should move with increase in time. Also, I should find path till the time period entered on the text box. So with my current code if I enter the time period in the text box so I get the full path, not the path covered till the particular time period value entered in the text box. I have made the code using these links-: https://github.com/duncancumming/maps/blob/master/animatedPaths/animated%20csv.html and Animation of Google Maps Polyline with respect to time increase.
Below is my code. Pls let me know where I am going wrong. Thanks a lot in advance!Probably the "timetill" value in drawline() is getting undefined, I am not sure.
<!DOCTYPE html>
<html>
<head>
<title>Animated path via a csv file</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map, #wrapper {
height: 100%;
margin: 0px;
padding: 0px;
position: relative;
}
#over_map {
position: absolute;
top: 10px;
left: 40%;
z-index: 99;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js">
</script>
<script>
var allCoords = [];
var map, route, marker;
function getCoords() {
$.ajax({
url: 'subject1.csv',
dataType: 'text',
success: function(data) {
var lines = data.split(/[\r\n]+/);
lines.forEach(function(line){
allCoords.push(line.split(','));
});
var bounds = new google.maps.LatLngBounds();
allCoords.forEach(function(coords){
bounds.extend(new google.maps.LatLng(coords[0], coords[1]));
});
map.fitBounds(bounds);
drawLine();
}
});
}
function drawLine(timetill) {
console.log(timetill)
route = new google.maps.Polyline({
path: [],
geodesic : true,
strokeColor: '#FF0000',
strokeOpacity: 0.7,
strokeWeight: 2,
editable: false,
map:map
});
marker = new google.maps.Marker({
map: map,
icon: "http://maps.google.com/mapfiles/ms/micons/blue.png"
});
for (var i = 0; i < allCoords.length; i++) {
if(timetill!=undefined && timetill!="" &&
timetill<allCoords[i].time){
break;
}
window.setTimeout(updatePath, 50 * i, allCoords[i]);
}
}
function updatePath(coords) {
console.log(coords);
var latLng = new google.maps.LatLng(coords[0], coords[1]);
route.getPath().push(latLng);
marker.setPosition(latLng);
}
function initialize() {
map = new google.maps.Map(document.getElementById("map"), {
center: {lat: 30.6010548, lng: -96.3534677},
zoom: 24,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
getCoords();
}
google.maps.event.addDomListener(window, 'load', initialize);
function plotTill(value){
console.log(value)
route.setMap(null)
marker.setMap(null);
drawLine(value)
}
</script>
</head>
<body>
<div id="wrapper">
<div id="map"></div>
<div id="over_map">
<input type="text" placeholder="Enter second ex: 2" id="search_box"
onchange="plotTill(this.value)" />
</div>
</div>
</body>
</html>
My .csv file is stored on the local machine and this is how my .csv file looks-: The third column is for time.
30.6011525,-96.3546702,1
30.6011525,-96.3546703,2
30.6011525,-96.3546703,3
30.6011525,-96.3546703,4
30.6011525,-96.3546703,5
30.6011525,-96.3546703,6
30.6011525,-96.3546703,7
30.6011525,-96.3546703,8
30.6011525,-96.3546703,9
30.6011525,-96.3546703,10
30.6011525,-96.3546703,11
ok, here's a working example that I think does mostly what you're wanting. I've reduced the time between each update of the line to 5 milliseconds.
function getCoords() {
$.ajax({
url: 'toyotav2.csv',
dataType: 'text',
success: function(data) {
var lines = data.split(/[\r\n]+/);
lines.forEach(function(line){
allCoords.push(line.split(','));
});
setUpLine();
}
});
}
function setUpLine() {
route = new google.maps.Polyline({
path: [],
geodesic : true,
strokeColor: '#FF0000',
strokeOpacity: 0.7,
strokeWeight: 2,
editable: false,
map:map
});
marker = new google.maps.Marker({
map: map,
position: {lat: 0, lng: 0},
visible: false,
icon: "https://maps.google.com/mapfiles/ms/micons/blue.png"
});
}
function drawLine(timetill) {
for (var i = 0; i < allCoords.length; i++) {
if (timetill < allCoords[i][2]){
break;
}
window.setTimeout(updatePath, 5 * i, allCoords[i]);
}
}
function updatePath(coords) {
var latLng = new google.maps.LatLng(coords[0], coords[1]);
route.getPath().push(latLng);
marker.setPosition(latLng);
}
function initialize() {
map = new google.maps.Map(document.getElementById("map"), {
center: {lat: 30.6010548, lng: -96.3534677},
zoom: 18,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
getCoords();
}
google.maps.event.addDomListener(window, 'load', initialize);
function plotTill(value) {
route.setPath([]);
marker.setVisible(true);
drawLine(parseInt(value, 10));
}
Some key distinctions:
You're referring to allCoords[i].time, but nowhere does a property called time get created on the 2D array of coordinates allCoords. What you've got is an array that looks like:
[
[30.6011525,-96.3546702,1],
[30.6011525,-96.3546703,2],
]
... so to refer to the time value, you just need to specify allCoords[i][2] to get the 3rd element.
You didn't specify a position when creating the Marker, which is required. I've just set it to {0,0}, but also specified its visible property to false to begin with, but set it to visible when you start drawing the line.
When you read the value from the input field, you're getting it as a text value. I use parseInt() to make sure it's converted to an integer. Otherwise you run the risk of a value like "16" being used for comparisons like timetill<allCoords[i].time. So "16" < 2 whereas 16 > 2. Use parseInt to make sure you've got a Number, not a string.
Instead of setting the map to null for the marker and polyline, just clear the path.
I've also split out the drawLine function, so you create the marker and polyline straight after the ajax response, but only start drawing the line in response to the user input.
I've searched the web but can't seem to locate an answer for my issue. I believe I'm close but just can't get this to work as intended.
I'd like to plot an array of locations on a google map and start with the DROP animation, then when a user clicks a point, I'd like it to bounce.
My current code does 1/2 the job, however, when you click it's targeting the last value in my array. The BOUNCE animation works but it doesn't seem to be applied to all values in my array. Can you point at what I'm missing in the code?
Thanks for all the help!
<html>
<head>
<!-- styles put here, but you can include a CSS file and reference it instead! -->
<style type="text/css">
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
<script type="text/javascript">
// Create a map variable
var map;
var markers = [];
// Function to initialize the map within the map div
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 40.74135, lng: -73.99802},
zoom: 10
});
// Create a single latLng literal object.
var locations = [
{title: 'Beer', location: new google.maps.LatLng(47.666633, -122.371453)},
{title: 'Home', location: new google.maps.LatLng(47.613141, -122.320587)},
{title: 'Work', location: new google.maps.LatLng(47.624812, -122.315134)}
];
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < locations.length; i++) {
var position = locations[i].location;
var title = locations[i].title;
var marker = new google.maps.Marker({
map: map,
position: position,
title: title,
animation: google.maps.Animation.DROP,
id: i
});
bounds.extend(marker.position);
google.maps.event.addListener(marker, 'click', function(){
if (marker.getAnimation() !== null) {
marker.setAnimation(null);
} else {
marker.setAnimation(google.maps.Animation.BOUNCE);
}
});
// markers.push(marker);
}
map.fitBounds(bounds);
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=&v=3&callback=initMap">
</script>
</body>
</html>
One option would be to use this inside the click event listener function to reference the clicked marker.
google.maps.event.addListener(marker, 'click', function(){
if (this.getAnimation() !== null) {
this.setAnimation(null);
} else {
this.setAnimation(google.maps.Animation.BOUNCE);
}
});
(you can also use function closure)
I have put together this script (note: I'm using jQuery 1.11.2) that gets lat long coordinates from a PHP operation (used for something else) and displays a map with a customized marker and infowindow that includes HTML for formatting the information that is displayed.
<script src="https://maps.googleapis.com/maps/api/js?v=3.20&sensor=false"></script>
<script type="text/javascript">
var maplat = 41.36058;
var maplong = 2.19234;
function initialize() {
// Create a Google coordinate object for where to center the map
var latlng = new google.maps.LatLng( maplat, maplong ); // Coordinates
var mapOptions = {
center: latlng,
zoom: 3,
mapTypeId: google.maps.MapTypeId.ROADMAP,
scrollwheel: false,
streetViewControl: false,
zoomControl: false,
mapTypeControl: false,
disableDoubleClickZoom: true
};
map = new google.maps.Map(document.getElementById("map-canvas"),mapOptions);
// CREATE AN INFOWINDOW FOR THE MARKER
var content = 'This will show up inside the infowindow and it is here where I would like to show the converted lat/long coordinates into the actual, human-readable City/State/Country'
; // HTML text to display in the InfoWindow
var infowindow = new google.maps.InfoWindow({
content: content,maxWidth: 250
});
var marker = new google.maps.Marker( {
position: latlng,
map: map,
title: "A SHORT BUT BORING TITLE",
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
infowindow.open(map,marker);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
What I'm trying to achieve is to do a reverse geocode on the coordinates stored in the latlng variable and get back the results of that in a "City, State, Country" format and insert that into the HTML for the informarker stored in the "content" variable.
Have tried multiple approaches without success. Please note that I've deliberately left out the reverse geocoding script I tried to use for clarity purposes.
Edit: I've adjusted the script presented here to comply with the rules about it being clear, readable and that it actually should work. I also include a link to a CodePen so that you can see it in action: Script on CodePen
Regarding including the script for reverse geocoding, what I did was a disaster, only breaking the page and producing "undefined value" errors. I'd like to learn the correct way of doing this by example, and that's where the wonderful StackOverflow community comes in. Thanks again for your interest in helping me out.
Use a node instead of a string as content , then you may place the geocoding-result inside the content, no matter if the infoWindow is already visible or not or when the result is available(it doesn't even matter if the InfoWindow has already been initialized, a node is always "live").
Simple Demo:
function initialize() {
var geocoder = new google.maps.Geocoder(),
latlng = new google.maps.LatLng(52.5498783, 13.42520);
map = new google.maps.Map(document.getElementById('map-canvas'), {
zoom: 18,
center: latlng
}),
marker = new google.maps.Marker({
map: map,
position: latlng
}),
content = document.createElement('div'),
infoWin = new google.maps.InfoWindow({
content: content
});
content.innerHTML = '<address>the address should appear here</address>';
google.maps.event.addListener(marker, 'click', function() {
infoWin.open(map, this);
});
geocoder.geocode({
location: latlng
}, function(r, s) {
if (s === google.maps.GeocoderStatus.OK) {
content.getElementsByTagName('address')[0].textContent = r[0].formatted_address;
} else {
window.alert('Geocoder failed due to: ' + status);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?v=3"></script>
<div id="map-canvas"></div>
Here's how I would do it:
function reverseGeocoder(lat, lng, callback) {
var geocoder = new google.maps.Geocoder();
var point = new google.maps.LatLng(parseFloat(lat), parseFloat(lng));
geocoder.geocode({"latLng" : point }, function(data, status) {
if (status == google.maps.GeocoderStatus.OK && data[0]) {
callback(null, data[0].formatted_address);
} else {
console.log("Error: " + status);
callback(status, null);
}
});
};
And basically you would call the function like:
reverseGeocoder(lat, lng, function(err, result){
// Do whatever has to be done with result!
// EDIT: For example you can pass the result to your initialize() function like so:
initialize(result); // And then inside your initialize function process the result!
});
I'm trying to build a website that shows a map and on top of it I want to display a button that takes you to your current location.
I'm using Google maps service to pull out the map, I also manage to get the user location by itself so all the JavaScript seems to be working fine but when add the function getlocation to the code and try to call it from the HTML it doesn't work. I believe that is probably not finding the function and I can't figure out why?
I will leave the code below:
<script>
var map;
function initialize() {
var miami = new google.maps.LatLng(41.85, -87.65);
var mapOptions = {
zoom: 4,
center: miami,
disableDefaultUI: true,
}
map = new google.maps.Map(document.getElementById('mymap'),
mapOptions);
var myloc = document.getElementById("try");
function getlocation () {
//code
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var pos = new google.maps.LatLng(position.coords.latitude,
position.coords.longitude);
var infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: 'Location found using HTML5.'
});
}, 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 infowindow = new google.maps.InfoWindow(options);
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
I'm using inline style for everything. I'm somehow new into this of JavaScript so if could please tell me where is my error or what else do I need to make a button from the HTML call a function on JavaScript.
In addition here is the HTML button and map div
<style>
html, body, #mymap{
height: 100%;
margin: 0px;
padding: 0px
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>
<body>
<div id="try"><button onclick="getlocation()">Click here</button></div>
<div id="mymap"></div>
</body>
If you don't understand what my question is please also comment!
This is my first question here!
google.maps.event.addListener(map, 'click', function(event) {
marker = new google.maps.Marker({position: event.latLng, map: map});
});
Need help with getting html elements interact with google maps.
I have 2 sections on a Web page. On the right side of the page, I have a map showing multiple markers. On the left side of the page, I have a list with addresses which correspond to the markers in the map.
Please suggest pointers on how to highlight a marker when the corresponding address is selected from the list on the left side of the page.
Okay, I made it with hover() . Hovering over the div highlights the marker
<head>
<style>
html, body, #map-canvas {
height: 400px;
margin: 0px;
padding: 0px
}
#markers_info .marker {
height: 40px;
cursor: pointer;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?"></script>
<script>
/**
jQuery events
*/
$(document).ready(function() {
// initiate Google maps
initialize();
// make a .hover event
$('#markers_info .marker').hover(
// mouse in
function () {
// first we need to know which <div class="marker"></div> we hovered
var index = $('#markers_info .marker').index(this);
markers[index].setIcon(highlightedIcon());
},
// mouse out
function () {
// first we need to know which <div class="marker"></div> we hovered
var index = $('#markers_info .marker').index(this);
markers[index].setIcon(normalIcon());
}
);
});
/**
Google Maps stuff
*/
var markerData = [ // the order of these markers must be the same as the <div class="marker"></div> elements
{lat: 50.84498605, lng: 4.349977747, title: 'Manneken Pis'},
{lat: 50.84848913, lng: 4.354053363, title: 'Jeanneke Pis'},
{lat: 50.84673465, lng: 4.352466166, title: 'Grand Place'}
];
var map;
var markers = [];
var mapOptions = {
zoom: 15,
center: new google.maps.LatLng(50.84673465,4.352466166), // Brussels, Belgium
mapTypeId: google.maps.MapTypeId.ROADMAP
};
function initialize() {
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
for (var i=0; i<markerData.length; i++) {
markers.push(
new google.maps.Marker({
position: new google.maps.LatLng(markerData[i].lat, markerData[i].lng),
title: markerData[i].title,
map: map,
icon: normalIcon()
})
);
}
}
// functions that return icons. Make or find your own markers.
function normalIcon() {
return {
url: 'http://1.bp.blogspot.com/_GZzKwf6g1o8/S6xwK6CSghI/AAAAAAAAA98/_iA3r4Ehclk/s1600/marker-green.png'
};
}
function highlightedIcon() {
return {
url: 'http://steeplemedia.com/images/markers/markerGreen.png'
};
}
//google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
<div id="markers_info">
<div class="marker">Manneken Pis, 50.84498605,4.349977747</div>
<div class="marker">Jeanneke Pis, 50.84848913,4.354053363</div>
<div class="marker">Grand Place, 50.84673465,4.352466166</div>
</div>
</body>