I have been reading and researching how to animate overlays. I Haven't found anything related to what I am looking for. Mostly it was related to markers. I have an overlay I apply like this and it works great.
tileNEX = new google.maps.ImageMapType({
getTileUrl: function(tile, zoom) {
return "http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-900913/" + zoom + "/" + tile.x + "/" + tile.y +".png?"+ (new Date()).getTime();
},
tileSize: new google.maps.Size(256, 256),
opacity: 0.60,
name: 'NEXRAD',
isPng: true
});
The source for the data also offers 10 other past images. So I would like to create an animated loop with those feeds. Is this option available in V3 as I have read some conflicts with doing this. I mean it must be possible because I have seen others with it. How would I go about loading the multiple layers then animating them?
-Thanks!
I know this is old but I hope this helps someone else looking for the same thing. This probably isn't the most elegant solution but it got the task done. I simply map over the predefined image urls creating my ImageMapTypes and then pass that into an animation loop which checks to see if there is a layer on the map, clears if it there is and then sets the new layer based on a loop count. Hope this helps.
var map;
// Weather tile url from Iowa Environmental Mesonet (IEM): http://mesonet.agron.iastate.edu/ogc/
var urlTemplate = 'http://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-{timestamp}/{zoom}/{x}/{y}.png';
// The time stamps values for the IEM service for the last 50 minutes broken up into 5 minute increments.
var timestamps = ['900913-m50m', '900913-m45m', '900913-m40m', '900913-m35m', '900913-m30m', '900913-m25m', '900913-m20m', '900913-m15m', '900913-m10m', '900913-m05m', '900913'];
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 38.0781, lng: -97.7030},
zoom: 5
});
let tileSources = timestamps.map((timestamp) => {
return new google.maps.ImageMapType({
getTileUrl: function(tile, zoom) {
const { x, y} = tile;
return `https://mesonet.agron.iastate.edu/cache/tile.py/1.0.0/nexrad-n0q-${timestamp}/${zoom}/${x}/${y}.png?`+ (new Date()).getTime();
},
tileSize: new google.maps.Size(256, 256),
opacity:0.60,
name : 'NEXRAD',
isPng: true
});
});
startAnimation(map, tileSources);
}
function startAnimation(map, layers) {
// create empty overlay entry
map.overlayMapTypes.push(null);
var count = 0;
window.setInterval(() => {
if(map.overlayMapTypes.getLength() > 0)
map.overlayMapTypes.clear();
map.overlayMapTypes.setAt("0",layers[count]);
count = (count + 1) % layers.length;
},800);
}
Related
I have the program below that reads aircraft coordinates from a txt file and places a number of markers on Google Maps. Every 2 sec it reads the txt file again and pushes the markers to the new aircraft locations. This works fine with the original markers "moving" to the new positions. What I would like to do is add a label to the marker to show the height of each aircraft. To do this I need to generate the label after the txt file has been read but when I do it doesn't delete the old markers but adds new markers.
The portion of code below is working fine but without a variable labels. The relevant code is where var eplanezero is created. If I move this line of code anywhere within the setInterval(function (){ the eplanezero.setPosition will not function properly. I have tried dozens of various but nothing seems to work. Any thoughts appreciated. Note that this is only a portion of the code.
moveMarker(map, playerIcon, enemyIcon);
}
function moveMarker(map, playerIcon, enemyIcon)
{
var eplanezero = new google.maps.Marker({map: map, icon: enemyIcon, label: "1"});
setInterval(function ()
{
$.post("MISSION_ADMIN_radar.txt", function(dataenemy, status)
{
var latlnge = JSON.stringify(dataenemy);
latlnge = latlnge.replace(/"/g,"");
latlnge = latlnge.replace(/[\\r\\n]/g,"");
CoordsEnemy = latlnge.split(";");
var army = parseFloat(CoordsEnemy[0].substring(0));
if (army == 2)//Own army = 1, Enemy = 2
{
var commaPos = CoordsEnemy[0].indexOf(',');
var hyphenPos = CoordsEnemy[0].indexOf('+');
var lat0 = parseFloat(CoordsEnemy[0].substring(4, commaPos));
var long0 = parseFloat(CoordsEnemy[0].substring(commaPos + 1, CoordsEnemy[0].length));
}
eplanezero.setPosition(new google.maps.LatLng(lat0, long0));
});
}, 2000);
The altitude is obtained from the same array that holds the lat and long. However, to place the variable Alt into the marker, I have to create variable eplanezero in the setInterval function so that it updates it every 2 secs. When I do this, it will not move the marker but adds a new marker, leaving the original marker in the old position.
The revised code is as follows:
function moveMarker(map, playerIcon, enemyIcon)
{
//var eplanezero = new google.maps.Marker({map: map, icon: enemyIcon, label: "1"});
var eplanezero = new google.maps.Marker({map: map, icon: enemyIcon, label: Alt});
setInterval(function ()
{
$.post("MISSION_ADMIN_radar.txt", function(dataenemy, status)
{
var latlnge = JSON.stringify(dataenemy);
latlnge = latlnge.replace(/"/g,"");
latlnge = latlnge.replace(/[\\r\\n]/g,"");
CoordsEnemy = latlnge.split(";");
var army = parseFloat(CoordsEnemy[0].substring(0));
if (army == 2)//Own army = 1, Enemy = 2
{
var commaPos = CoordsEnemy[0].indexOf(',');
var hyphenPos = CoordsEnemy[0].indexOf('+');
var Alt0 = parseFloat(CoordsEnemy[0].substring(hyphenPos + 1 , CoordsEnemy[0].length));
var lat0 = parseFloat(CoordsEnemy[0].substring(4, commaPos));
var long0 = parseFloat(CoordsEnemy[0].substring(commaPos + 1, CoordsEnemy[0].length));
var eplanezero = new google.maps.Marker({map: map, icon: enemyIcon, label: Alt});
}
eplanezero.setPosition(new google.maps.LatLng(lat0, long0));
});
}, 2000);
.setPosition must be a method that looks in the array and checks for previous coordinates. if the array doesn't contain any coordinates it places a new marker at the new coordinates, If the array does contain coordinates it "moves"the marker to the new location. Establishing the array within the loop deletes any previous array and the coordinates and therefore Google Map correctly places a new marker. Only by creating the array outside the loop will the method work correctly. Unfortunately this means that the label or the icon cannot be changed once the array is created.
I am currently working on a Leaflet Project where I use external geojson files as data input. Since the json contains a lot of objects I would like to use the MarkerCluster plugin which I got from Mappbox:
<script src='https://api.tiles.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/leaflet.markercluster.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/MarkerCluster.css' rel='stylesheet' />
<link href='https://api.tiles.mapbox.com/mapbox.js/plugins/leaflet-markercluster/v0.4.0/MarkerCluster.Default.css' rel='stylesheet' />
Displaying the json-layer without the clustering works just fine, but if i try to assign it to the cluster nothing is displayed.
var markersBar = L.markerClusterGroup();
var barLayer = new L.GeoJSON.AJAX("json/eat_drink/bar.geojson", {
pointToLayer: function(feature, latlng) {
var icon = L.icon({
iconSize: [27, 27],
iconAnchor: [13, 27],
popupAnchor: [1, -24],
iconUrl: 'icon/' + feature.properties.amenity + '.png'
});
return L.marker(latlng, {icon: icon})
},
onEachFeature: function(feature, layer) {
layer.bindPopup(feature.properties.name + ': ' + feature.properties.opening_hours);
}
});
markersBar.addLayer(barLayer);
console.log(markersBar);
map.addLayer(markersBar);
The console.log output lets me assume that there are no objects, but I don't get it why.
Object { options: Object, _featureGroup: Object, _leaflet_id: 24, _nonPointGroup: Object, _inZoomAnimation: 0, _needsClustering: Array[0], _needsRemoving: Array[0], _currentShownBounds: null, _queue: Array[0], _initHooksCalled: true }
What am I doing wrong?
Well it looks like you are using Leaflet-Ajax...so an async request is made to grab your geojson..and your immediate next line is markersBar.addLayer(barLayer);..which would contain nothing since the request is almost certainly not complete yet...
Instead, I believe you can use the loaded event provided in the documentation like
barLayer.on('data:loaded', function () {
markersBar.addLayer(barLayer);
console.log(markersBar);
map.addLayer(markersBar);
});
For anyone looking for a straight forward example for adding a marker cluster with geojson ajax to a map, binding pop-ups and adding to layer control:
// pop-up function
function popUp(f, l) {
var out = [];
if (f.properties) {
for (key in f.properties) {
out.push(key + ": " + f.properties[key]);
}
l.bindPopup(out.join("<br />"));
}
}
// add layer to map and layer control
function add_layer(layr, layr_name) {
map.addLayer(layr);
layerControl.addOverlay(layr, layr_name);
}
// fire ajax request
var points = new L.GeoJSON.AJAX("../data/points.geojson", { onEachFeature: popUp });
// create empty marker cluster group
var markers = L.markerClusterGroup()
// when geojson is loaded, add points to marker cluster group and add to map & layer control
points.on('data:loaded', function () {
markers.addLayer(points);
add_layer(markers, "Point Markers")
});
I am using phonegap, jquerymobile the googlemap API to get my current position and to watch my position.
For this, when I lunch my map page, my position is shown with a marker and the marker move when I move.
Even if it works excpeted when I close my App (onPause).
Here is my code (you can tell me how I can perfect it :o) )
$('#home').live("pagebeforeshow", function() {
if($('#googleAPI').length != 0){
navigator.geolocation.getCurrentPosition(function(position){
//showMap('mapHome',position.coords.latitude, position.coords.longitude);// Canvas, lat, long
var latLng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
// Google Map options
var myOptions = {
zoom: 17,
//zoomControl : 1,
center: latLng,
mapTypeId: google.maps.MapTypeId.ROADMAP////ROADMAP, SATELLITE, HYBRID and TERRAIN
};
// Create the Google Map, set options
Tracking.mapy = new google.maps.Map(document.getElementById('mapHome'), myOptions);
//addMarker(position.coords.latitude,position.coords.longitude);
},
showError,
{
enableHighAccuracy : true,
maximumAge : 2000
//maximumAge:Infinity
});
}
})
$('#home').live("pageshow", function() {
// Place and move the marker regarding to my position and deplacement
if($('#googleAPI').length != 0){
//var track_id = "me";
Tracking.watch_id = navigator.geolocation.watchPosition(
// Success
function(position){
var lat = position.coords.latitude;
var long = position.coords.longitude;
var latLng = new Array();
latLng[0] = lat;
latLng[1] = long;
//Tracking.myCoordinates.push(lat,long);
Tracking.myCoordinates.push(latLng);
addMarker(lat, long);
},
// Error
showError,
{
frequency: 1000
});
console.log('HW : WatchPosition called. Id:' + Tracking.watch_id);
}else{
Alert.show('The map API has not been loaded. Check for connection and try again. (pagebeforeshow)');
}
})
$('#home').live("pagebeforehide", function() {
if($('#googleAPI').length != 0){
//track_id = "me";
// Stop tracking the user
if (Tracking.watch_id != null) {
navigator.geolocation.clearWatch(Tracking.watch_id);
console.log('HW : WatchPosition cancelled Id:' + Tracking.watch_id);
Tracking.watch_id = null;
}
//navigator.geolocation.clearWatch(Tracking.watch_id);
//Tracking.watch_id = null;
Tracking.myCoordinates = new Array();
}else{
Alert.show('The map API has not been loaded. Check for connection and try again. (pagebeforeshide)');
}
});
The problem is when I close my App, because I still need to be alert when I go outside of my geofence. Then, as lomg as I do not stop to watch my position, I need it to be watching even if I close my position or if I lunch another app.
Then I do not know how to do when I called that Phonegap even:
document.addEventListener('pause', onPause, false);
function onPause(){}
Should I simply relunch my watch code with a different watch_id?
Any suggestion?
Many thank and happy new year
I think what you're trying to get at is running a background process using phonegap. The discussion in this link seems to say that it's only possible if you write a plugin to perform that functionality. PhoneGap doesn't have an API to do it out of the box.
Executing javascript in background using phonegap
I have created a site (can be accessed at http://dev.gkr33.com) which is designed for a smartphone and attempts to use the navigator.geolocation api and grab your position via getCurrentPosition. This seems to work initially, however if you try to refresh the page it always brings back the last GPS position. I have added some debug information on the page which grabs the time of the getCurrentPosition return and after the initial positioning it always returns the same time (down to the millisecond).
This only seems to happen in Chrome Mobile. If I browse into the site via the stock Android browser it works fine every time.
The code is shown below;
<script type="text/javascript">
(function ($) {
$(document).ready(function() {
var options = { enableHighAccuracy: true, maximumAge: 0, timeout: 60000 };
var position;
// empty the current html elements, not strictly necessary but
// I'm clutching at straws
$('#debug-latlng').empty();
$('#debug-time').empty();
$('#debug-address').empty();
// Let's try and find out where we are
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(gotPos, gotErr, options );
} else {
gotErr();
}
// We've got our position, let's show map and update user
function gotPos(position) {
var info;
info = position.coords.latitude+','+position.coords.longitude;
$('#debug-latlng').text(info);
$('#debug-time').text(parseTimestamp(position.timestamp));
// the following json call will translate the longitude and
// latitude into an address (a wrapper for google's geocode call)
$.getJSON('http://dev.gkr33.com/api.php', { req: "getLocationInfo", latlng: $('#debug-latlng').text() }, function(json) {
$('#debug-address').text( json['results'][0]['formatted_address'] );
});
var myLatLng = new google.maps.LatLng( position.coords.latitude, position.coords.longitude );
var mapOptions = {
zoom: 12,
center: myLatLng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions);
var marker = new google.maps.Marker({
position: myLatLng,
title: 'You are here',
animation: google.maps.Animation.DROP
});
marker.setMap(map);
} //gotPos
// Trap a GPS error, log it to console and display on site
function gotErr(error) {
var errors = {
1: 'Permission denied',
2: 'Position unavailable',
3: 'Request timeout'
};
console.log("Error: " + errors[error.code]);
$('#debug-latlng').text('GPS position not available');
} //gotErr
// Make timestamp human readable
function parseTimestamp(timestamp) {
var d = new Date(timestamp);
var day = d.getDate();
var month = d.getMonth() + 1;
var year = d.getFullYear();
var hour = d.getHours();
var mins = d.getMinutes();
var secs = d.getSeconds();
var msec = d.getMilliseconds();
return day + "." + month + "." + year + " " + hour + ":" + mins + ":" + secs + "," + msec;
} // parseTimestamp
});
}) (jQuery);
</script>
I have played around with various values for the maximumAge and timeout, but nothing seems to affect the same position.coords and position.time values.
I think there maybe an issue with Chrome Mobile, but I don't wanna assume too much at this point in time and just need clarification that I haven't made a mistake of muppet-like proportions in my code.
Many thanks for any help you can provide.
UPDATE: I suppose I should have said that I have tested this on two Android devices; HTC One X+ and a Samsung Galaxy Tab 7.7 with the same result. On both the stock browser works fine, and on both Chrome doesn't refresh the position. Will test on an Apple Device later :)
I never got to the bottom of this issue, but I got a way around the problem by utilising the watchPosition call, and wrapping this in a 5 second wait before clearing the watchID. Check the code below:
var options = { enableHighAccuracy: true, maximumAge: 100, timeout: 50000 };
if( navigator.geolocation) {
var watchID = navigator.geolocation.watchPosition( gotPos, gotErr, options );
var timeout = setTimeout( function() { navigator.geolocation.clearWatch( watchID ); }, 5000 );
} else {
gotErr();
}
I haven't played around with the "options" values or the timeout delay at the moment, but the above code brings back accurate positioning info on every platform I've tried.
Hope this helps someone with the same issue :)
I finally found a working version for firefox, chrome & default navigator in android (4.2 tested only):
function getGeoLocation() {
var options = null;
if (navigator.geolocation) {
if (browserChrome) //set this var looking for Chrome un user-agent header
options={enableHighAccuracy: false, maximumAge: 15000, timeout: 30000};
else
options={maximumAge:Infinity, timeout:0};
navigator.geolocation.getCurrentPosition(getGeoLocationCallback,
getGeoLocationErrorCallback,
options);
}
}
getCurrentLocation() no longer works on insecure origins in Chrome browsers. Switch to a secure original (HTTPS) to enable.
This is my first time on stackoverflow and working with Openlayers & Google Maps.
I've been browsing different forums & sites, including OpenLayers.org, to solve my issue. I've done searches on a combination of the following: openlayers, google map projections, and spherical mercator... but I have not found a solution.
Problem: The KML data from a web service call (func setDataSource) is shifting as I zoom in and out of the map. My guess is that the projections in my code are wrong or perhaps wrongly placed. I don't have any background on map projections so it is difficult to digest mapping terminology online :-(. Can someone help?
//start here
var options = {
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
units: "m",
numZoomLevels: 18,
maxResolution: 156543.0339,
maxExtent: new OpenLayers.Bounds(-20037508, -20037508,
20037508, 20037508)};
//*map = new OpenLayers.Map('map');
map = new OpenLayers.Map('map', options);
var gphy = new OpenLayers.Layer.Google(
"Google Street",
{'sphericalMercator':true});
// Add the background images via WMS
var bglayer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
"http://labs.metacarta.com/wms/vmap0", {layers: 'basic'}, {'reproject': true});
//map.addLayer(bglayer);
map.addLayers([gphy, bglayer]);
map.addControl(new OpenLayers.Control.LayerSwitcher());
map.zoomToMaxExtent(); //* Zoom all the way out, this command also initalizes the map
OpenLayers.Console.log("initialized");
}
function setDataSource() {
OpenLayers.Console.log("Setting data source to " + OpenLayers.Util.getElement('loc').value);
if (layer != undefined) {map.removeLayer(layer)};
if (selectControl != undefined) {map.removeControl(selectControl)};
// Encode the destination url as a parameter string.
var params = OpenLayers.Util.getParameterString({url:OpenLayers.Util.getElement('loc').value})
// Make the http request to the transformer, with the destination url as a parameter.
layer = new OpenLayers.Layer.GML("KML", transformerURL + params,
{
format: OpenLayers.Format.KML,
formatOptions: {
extractStyles: true,
extractAttributes: true,
maxDepth: 2,
//projection: new OpenLayers.Projection("EPSG:4326"),
}
});
map.addLayer(layer);
Thank you!!!
I figured out the problem. Instead of GML, I tried using Vector instead like this:
layer = new OpenLayers.Layer.Vector("KML", {
projection: map.displayProjection,
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP({
url: transformerURL + params,
format: new OpenLayers.Format.KML({
extractStyles: true,
extractAttributes: true
})
})
});
I found the solution in this sundials example: http://openlayers.org/dev/examples/sundials-spherical-mercator.html :-) Hope this helps anyone w/ the same problem.