Confused About Map Updates - javascript

I'm very new to using Google Maps and very new to intricate javascript. Bearing this in mind, I'm trying to create a web map, with a feed from USGS. This feed is updated every 5 minutes. I'd like to have my map refresh every 5 minutes using this same feed (which is a geojson file).
My end goal is to have this and at least one other feed displayed/updated on my map. Over the past four days, I've gone through dozens of posts, and am at the point of being overloaded and confused. Will someone please clear my fog?
The code I'm posting is 99% not my code, mostly I've added comments so I can figure out what's going on in the code.
<HTML>
<HEAD>
<TITLE>TEST OF MAP</TITLE>
<STYLE>
/* --------------------------------------------------- */
/* Set the map height explicitly to define the size of */
/* the DIV * element that contains the map. */
/* ----------------------------------------------------*/
#map {
height: 75%;
border: 5px solid green;
}
</STYLE>
</HEAD>
<SCRIPT type="text/javascript">
// --------------------------------------
// Set a refresh interval in milliseconds
// --------------------------------------
setInterval(page_refresh, 1*60000);
google.maps.event.addDomListener(window, 'load', initialize);
</SCRIPT>
<BODY>
<H1><CENTER>MAP Demo</CENTER></H1>
<DIV id="map"></DIV>
<SCRIPT>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
zoom: 2,
center: new google.maps.LatLng(35.4437,139.6380),
mapTypeId: 'terrain'
});
// ---------------------------------------------------------
// Create a <SCRIPT> tag and set the USGS URL as the source.
// ---------------------------------------------------------
var script = document.createElement('script');
// -----------------------------------------------------------------------
// Using a local copy of the GeoJSON stored on the USGS server
//
http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_hour.geojsonp
// -----------------------------------------------------------------------
script.src =
'http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_hour.geojson
p';
document.getElementsByTagName('head')[0].appendChild(script);
}
// ------------------------------------------------------------------
// Loop through the results array and place a marker for each set of
// coordinates.
// ------------------------------------------------------------------
window.eqfeed_callback = function(results) {
for (var i = 0; i < results.features.length; i++) {
var coords = results.features[i].geometry.coordinates;
var latLng = new google.maps.LatLng(coords[1],coords[0]);
var marker = new google.maps.Marker({
position: latLng,
map: map
});
}
}
</SCRIPT>
<SCRIPT async defer src="https://maps.googleapis.com/maps/api/js?
key=MY_MAP_KEY&callback=initMap">
</SCRIPT>
</BODY>
</HTML>

Though not very elegant, I used the following for the refresh. Since I'm only building a "proof of concept", refreshing the entire page is not a problem.
function timedRefresh(timeoutPeriod) {
setTimeout("location.reload(true);",timeoutPeriod);
}
window.onload = timedRefresh(60*5000);

Related

Remove google.maps.marker.AdvancedMarkerView from map

I have a map, which populates markers based on search. I'm attempting to user the newer google maps feature AdvancedMarkerView so I can fill it with custom HTML - however, as my search updates, I want to flush the old markers and place new ones when it's called for...and I can't for the life of me figure out how to? https://developers.google.com/maps/documentation/javascript/reference/advanced-markers
The following places the custom markers. It works.
const content = document.createElement('div');
content.className = 'marker-title';
content.textContent = item.title;
const marker = new google.maps.marker.AdvancedMarkerView({
map,
position: item.position,
content
});
Normally for markers, as in the old markers, I've removed them with the following code, markers.forEach((marker) => marker.setMap(null)) however this doesn't seem to work for the advanced markers. Since the marker returned when creating the advanced marker points to the element, I also tried doing a marker.remove() thinking the HTML element would be targeted, but no cigar.
I haven't been able to find any concrete examples on the Google API docs, when it comes to advanced markers, and same for others asking the same question.
There is no setMap() or other method to call on the AdvancedMarkerView class to toggle its visibility or remove it from the map.
Although it is not super clear, the documentation says:
To remove a marker from the map, set the markerView.map property to null.
Working example below:
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
center: { lat: 37.39094933041195, lng: -122.02503913145092 },
zoom: 14,
mapId: "4504f8b37365c3d0",
});
const draggableMarker = new google.maps.marker.AdvancedMarkerView({
map,
position: { lat: 37.39094933041195, lng: -122.02503913145092 },
draggable: true,
title: "This marker is draggable. Click to remove.",
});
draggableMarker.addListener("click", (event) => {
// Remove AdvancedMarkerView from Map
draggableMarker.map = null;
});
map.addListener("click", (event) => {
// Set AdvancedMarkerView position and add to Map
draggableMarker.position = event.latLng;
draggableMarker.map = map;
});
}
window.initMap = initMap;
#map {
height: 160px;
}
p {
font-family: Arial;
font-size: 0.75em;
margin: 2px 0;
}
<!DOCTYPE html>
<html>
<head>
<title>Draggable Advanced Marker</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<p>Click marker to remove it from map. Click on map to reposition / add marker.</p>
<div id="map"></div>
<script
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap&libraries=marker&v=beta"
defer
></script>
</body>
</html>

Trouble with accessing array of data in Javascript

I'm trying to write a little web app that will map some locations on a map using Google's Maps JavaScript API. Working with the API is going well, but I'm trying to manipulate their example code and I cannot get the array of data to work unless it's declared withing the Map initialization function. I've been digging for what I am not understanding about Javascript variable access, but I can't figure it out. Ideally I would like to put the array of data in a separate <script> tag so I can load it from another file, but I can't even get the data to work if placed right above the function within the same <script> tag.
I here is a simplified version of the code that I cannot get to work. It won't run because I removed my key from the call to the API, but if that's needed to find the problem I can give it out too.
<html>
<head>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
// <script src="...">
// where I really want to load let locations = .... from a file
// </script>
<script>
// where i tried to move let locations = .... without success
function initMap() {
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 2.7,
center: new google.maps.LatLng(18,0)
});
let locations = [
{
name: 'MJ Cave',
position: new google.maps.LatLng(47.517869, 19.036026)
}, {
name: 'Protec Tulum',
position: new google.maps.LatLng(20.216557, -87.460052)
}, {
name: 'Giraffe Manor',
position: new google.maps.LatLng(-1.375528, 36.744634)
}
];
function placeMarker( loc ) {
const marker = new google.maps.Marker({
position : loc.position,
map : map
});
}
// ITERATE ALL LOCATIONS. Pass every location to placeMarker
locations.forEach( placeMarker );
}
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=MYKEY&callback=initMap">
</script>
</body>
</html>
Problem solved.
Taking the new google.maps.latlng() calls out of the initMap() function was the problem because that datatype isn't necessarily defined at the time that code runs apparently. Changed the location position object to be defined by an array of two numbers and then made them into a google.maps.latlng in function. Works as desired now. For postarity here's my changed code:
<script>
let locations = [
{
name: 'MJ Cave',
position: [47.517869, 19.036026]
}, {
name: 'Protec Tulum',
position: [20.216557, -87.460052]
}, {
name: 'Giraffe Manor',
position: [-1.375528, 36.744634]
}
];
</script>
<script type="text/javascript">
function initMap() {
const infowindow = new google.maps.InfoWindow();
const map = new google.maps.Map(document.getElementById("map"), {
zoom: 2.7,
center: new google.maps.LatLng(18,0)
});
function placeMarker( loc ) {
const marker = new google.maps.Marker({
position : { lat: loc.position[0], lng: loc.position[1]},
icon: icons[loc.type].icon,
map : map
});
// ITERATE ALL LOCATIONS. Pass every location to placeMarker
locations.forEach( placeMarker );
}
</script>

Google Maps API KMZ file displaying wrong data on click event

I have a KMZ file that i load into my google maps application via link using javascript. The file works perfectly in Google Earth. The problem is in my application when i click in one of the many elements (areas): the returned description data is always from only one of the elements, not displaying the actual clicked, correct, element. This is what i've tried:
Check if the click event in the map is correct by placing a marker in the clicked position, it is correct.
Convert the data into KML using Google Earth, place it into my google drive as public, and using a direct download link from google drive in my application. It displayed the data but the error continued.
Created the most basic/blank application using just the layer to make sure anything else in my other application is interfering. Also didn't work.
The file is in this website: https://www.voanaboa.pt/codigo-drone named as "Regulamento RPA_ver_5.0.kmz”
Here's the only file that creates a basic application using the kmz file, i've removed my API key for privacy.
<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<meta name="viewport" content="initial-scale=1.0">
<meta charset="utf-8">
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 8
});
var kmlLayer = new google.maps.KmlLayer();
var src = 'https://www.voanaboa.pt/Files/downloads/Regulamento-RPA-ver-5.0.kmz';
var kmlLayer = new google.maps.KmlLayer(src, {
//suppressInfoWindows: true,
preserveViewport: false,
map: map
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=MY_API_KEY&libraries=geometry&callback=initMap"
async defer></script>
Most (but not all) of your placemarks have the same ID "ID_00000"). If I change that to be unique, the polygon's descriptions become unique:
example with unique ids
Per the KML reference, that doesn't have to be unique (it is a "stanard XML ID", but I am guessing the rendering code is assuming it is.
code snippet with updated kmz file:
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<script>
var map;
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {
lat: -34.397,
lng: 150.644
},
zoom: 8
});
var kmlLayer = new google.maps.KmlLayer();
var src = 'http://www.geocodezip.com/geoxml3_test/kmz/Regulamento-RPA-ver-5.0a.kmz';
var kmlLayer = new google.maps.KmlLayer(src, {
//suppressInfoWindows: true,
preserveViewport: false,
map: map
});
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry&callback=initMap" async defer></script>

XMLHttpResponse object loads same content on every call to open()

I'm trying to monitor the position of my vehicle in real time.
I'm using the googlemaps API to do this.
My objective is to constantly update the marker (position of my car) every three seconds without having to reload the entire map.
The vehicle's current location is saved in 'vehicle_location.txt'.
<!DOCTYPE html>
<html>
<head>
<title>Car Location</title>
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map;
var markers = [];
var timerId;
var contents;
function initMap() {
``var initial_location = {lat: 15.3647, lng: 75.1240};
//timerId = setInterval(update_map,3000);
update_map();
map = new google.maps.Map(document.getElementById('map'), {
zoom: 12,
center: initial_location,
});
addMarker(initial_location);
}
// Adds a marker to the map and push to the array.
function addMarker(location) {
var marker = new google.maps.Marker({
position: location,
map: map
});
markers.push(marker);
}
// Sets the map on all markers in the array.
function setMapOnAll(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
// Removes the markers from the map, but keeps them in the array.
function clearMarkers() {
setMapOnAll(null);
}
// Shows any markers currently in the array.
function showMarkers() {
setMapOnAll(map);
}
// Deletes all markers in the array by removing references to them.
function deleteMarkers() {
clearMarkers();
markers = [];
}
//Updates map every 3 seconds
function update_map(){
//read_file();
var req = new XMLHttpRequest();
req.onreadystatechange = function()
{
if (this.readyState == 4 && this.status == 200)
{
alert(this.responseText);
timerId = setTimeout('update_map()', 3000);
}
};
//req.addEventListener("load", reqListener);
req.open("GET", "./vehicle_location.txt", true);
req.send(null);
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js? key=YOUR_APIKEY_HERE&callback=initMap">
</script>
The problem is, 'this.responseText' has same value on every call to
req.open("GET", "./vehicle_location.txt", true)
inspite of the text file constantly changing.
I am new to js. Any help is much appreciated!
If the software is constantly updating vehicle_location.txt with no issues. Then, it could be browser cache. To override this, the simplest method is adding a random query to target URL, so browser identifies it as a new URL; thus, ignoring cache. The most commonly used is a timestamp.
var ts = new Date().getTime(); // output a unix timestamp reflecting the current date and time.
req.open("GET", "./vehicle_location.txt?t="+ts, true);
The above will generate a new URL with every new XHR request issued like:
./vehicle_location.txt?t=1483349217755
./vehicle_location.txt?t=1483349217757
./vehicle_location.txt?t=1483349217759
./vehicle_location.txt?t=1483349217760

JavaScript global variable in Google Maps

I'm making a webapp that allows people to see the location of buses on Google maps. I'm having some problems with global variables in JavaScript. window.variable doesn't work for me. Neither does defining the variable outside the all the functions works. Here is my complete client side code:
<!DOCTYPE html>
<html>
<head>
<title>Geolocation</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
// Note: This example requires that you consent to location sharing when
// prompted by your browser. If you see a blank space instead of the map, this
// is probably because you have denied permission for location sharing.
var old = [];
function getLocation()
{
$.get( "http://54.86.161.214/EC_bus_app/get_location.php", function( data ) {
old=[];
var buses = data;
var number_of_buses = buses.slice(0,1);
buses = buses.slice(2);
buses = buses.slice(0,-1);
var bus_coordinates_and_numbers = buses.split(/[ ]+/);
var length_of_array = bus_coordinates_and_numbers.length;
// Turn a single dimensional array into a multi-dimensional array
for (var index = 0; index < bus_coordinates_and_numbers.length; index+= 3)
old.push( bus_coordinates_and_numbers.slice(index, index + 3) );
console.log(old);
//initialize(old);
});
}
setInterval(getLocation, 10000);
var map;
function initialize() {
var mapOptions = {
zoom: 18
};
map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var image = "icon_97.png";
for (i=0;i<old.length; i = i + 1){
var x = old[i][0];
var y = old[i][1];
var myLatlng = new google.maps.LatLng(x,y);
var busMarker = new google.maps.Marker({
position: myLatlng,
map: map,
icon: image,
title: old[i][2]
});
}
// 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: 'Your location'
});
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 infowindow = new google.maps.InfoWindow(options);
map.setCenter(options.position);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>
The variable in question is old. I can pass it to the initialize function from within the get location function using initialize(old);. However, as you can see, I'm using a timer, and initialize(old); causes the entire map to reload again and again, whereas I only want the location markers to load again and again.
Solved the problem by moving getLocation() inside initialize(). But what #geocodezip said in the comments also answers my question completely.
Your problem is not with global variables. It is with asynchronous functions. You need to initialize the map, then request data (asynchronous request), make markers on the map, then periodically update them.

Categories

Resources