Having issues clearing google maps layer - javascript

I've been working off of this post and this jsfiddle. I'm trying to clear the map layer before I populate new data into it, but it looks like overlays just stack one on top of one another without ever getting cleared.
Here's my code as it currently exists:
// For the heatmap layer
var heatmapData = [];
var heatmap;
// Instantiate counter
var files = 0;
// Looping and loading files with timeout
(function myLoop (i) {
setTimeout(function () {
var xhr = new XMLHttpRequest();
xhr.open('GET', ('js/tweets'+ files + '.json'), true);
xhr.onload = function() {
loadTweets(this.responseText);
};
xhr.send();
// Clear out map styles
heatmap.setMap(null);
if (--i) myLoop(i);
// Stall for 3 seconds
}, 3000)
})(100);
// Parse out the JSON and create markers
function loadTweets(results) {
// Parse out our JSON file
var tweetStructure = $.parseJSON(results);
// Go gets it
for (a in tweetStructure){
var co_arr = tweetStructure[a];
for (coords in co_arr.coordinates){
var d = co_arr.coordinates;
// Stating our lat/longs
var first = d[0];
var second = d[1];
var magnitude = d[2];
// Setting them
var latLng = new google.maps.LatLng(first, second);
// Weighted location to express polarity
var weightedLoc = {
location: latLng,
weight: Math.pow(2, magnitude)
};
heatmapData.push(weightedLoc);
}
}
// Instantiate heat map
heatmap = new google.maps.visualization.HeatmapLayer({
data: heatmapData,
dissipating: false,
map: map
});
}
I'm getting my data from four static JSON files.

With the second for in loop when declaring var d = you don't seem to be iterating though all [coords]. So as a result I guess d[0] will house all key-value pairs from co_arr.coordinates. Might this be part of the problem?

Related

How to plot clients geolocation on a Amcharts map (and deal with the asynchronous provision of the HTML5 geolocation)

I have a world map in my web application, powered by Amcharts4. I want to add a marker on the map, displaying the user's geolocation (using the HTML5 getCurrentPosition function. But the map is already generated while the coordinates are retrieved, how to push a new marker to the map after it has been drawn?
I have working versions of both the Amcharts map, including markers on the map, and of the geolocation function.
Geolocation works asynchronously, the script continues while the location is retrieved, so the map is generated in the meantime.
I'm not a big fan of waiting for the coordinates to be found before continuing, as this might imply a multiple seconds delay.
Essentially I am looking for functionality to push marker data to my Amcharts object after that object is displayed.
This is my js for the map:
// Themes begin
am4core.useTheme(am4themes_animated);
// Create map instance
var chart = am4core.create("chartdiv", am4maps.MapChart);
// Set map definition
chart.geodata = am4geodata_worldLow;
// Set projection
chart.projection = new am4maps.projections.Miller();
// Series for World map
var worldSeries = chart.series.push(new am4maps.MapPolygonSeries());
worldSeries.exclude = ["AQ"];
worldSeries.useGeodata = true;
worldSeries.data = mapdata;
var polygonTemplate = worldSeries.mapPolygons.template;
polygonTemplate.tooltipText = "{text}";
polygonTemplate.adapter.add("tooltipText", function(text, ev) {
if (!ev.dataItem.dataContext.text) {
return "{name}";
}
return text;
})
polygonTemplate.fill = chart.colors.getIndex(0);
polygonTemplate.nonScalingStroke = true;
polygonTemplate.propertyFields.fill = "fill";
polygonTemplate.properties.fill = am4core.color("#dddddd");
chart.zoomControl = new am4maps.ZoomControl();
// Hover state
var hs = polygonTemplate.states.create("hover");
hs.properties.fill = am4core.color("#333");
// Create image series
var imageSeries = chart.series.push(new am4maps.MapImageSeries());
// Create a circle image in image series template so it gets replicated to all new images
var imageSeriesTemplate = imageSeries.mapImages.template;
var circle = imageSeriesTemplate.createChild(am4core.Circle);
circle.radius = 4;
circle.fill = am4core.color("#000");
circle.stroke = am4core.color("#FFFFFF");
circle.strokeWidth = 2;
circle.nonScaling = true;
circle.tooltipText = "{title}";
// Set property fields
imageSeriesTemplate.propertyFields.latitude = "latitude";
imageSeriesTemplate.propertyFields.longitude = "longitude";
// Add data for the three cities
imageSeries.data = [{
"latitude": 51.561678,
"longitude": 5.049685,
"title": "Rural Spark HQ"
}];
if(navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition); }
function showPosition(position) {
clientlocation = ({"latitude": position.coords.latitude, "longitude": position.coords.longitude, "title": "I am here!"});
console.log(clientlocation)
//push this clientlocation data to the map somehow?
}
I can see the client location in the console, but I didn't find any method to get it on the map.
You just can add the new object (clientlocation) to imageSeries.data:
imageSeries.addData(clientlocation);
Or you can just add the data by reassigning the data field:
imageSeries.data = [...imageSeries.data, clientlocation];
Here is a code pen as reference.

Bing Maps v8 API - Zoom Level to show route and pushpin location

I am using the Bing Maps v8 API. I have a map that shows a driving route, and a pushpin of another location. I need to get the map to zoom out to show both the waypoint locations and the pushpin location. Right now, I can get the map to zoom to the waypoints of the pushpin location.
I am not sure how to get both to show on the map zoom. I know that I need to use the LocationRect class.
var searchManager;
var startingPoint = document.getElementById('startPoint').value;
var address = $("#addressLine").val();
var loc;
var patAddLoc;
var waypointLoc;
var pinsLocs = [];
// GET ROUTE BASED ON DIRECTION
function GetMap() {
var map = new Microsoft.Maps.Map(document.getElementById('myMap'), {
//BING API KEY VIA AZURE
credentials: 'X',
zoom: 10,
});
// geocode patient address
geocodeQuery(address);
// look for patient address
function geocodeQuery(query) {
//If search manager is not defined, load the search module.
if (!searchManager) {
//Create an instance of the search manager and call the geocodeQuery function again.
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
searchManager = new Microsoft.Maps.Search.SearchManager(map);
geocodeQuery(query);
});
} else {
var searchRequest = {
where: query,
callback: function (r) {
//Add the first result to the map and zoom into it.
if (r && r.results && r.results.length > 0) {
var pin = new Microsoft.Maps.Pushpin(r.results[0].location);
// get patient address location
patAddLoc = r.results[0].location;
map.entities.push(pin);
// add patient location to pushpin array
pinsLocs.push(patAddLoc);
// view is set with route location
//map.setView({ bounds: r.results[0].bestView });
}
// directions manager
// addWaypoint
Microsoft.Maps.loadModule('Microsoft.Maps.Directions', function addWaypoint() {
var directionsManager = new Microsoft.Maps.Directions.DirectionsManager(map);
// if less than 2 point on the map
if (directionsManager.getAllWaypoints().length < 2) {
directionsManager.clearAll();
var startWaypoint = new Microsoft.Maps.Directions.Waypoint({ address: document.getElementById('startPoint').value });
directionsManager.addWaypoint(startWaypoint);
var endWaypoint = new Microsoft.Maps.Directions.Waypoint({ address: document.getElementById('endPoint').value });
directionsManager.addWaypoint(endWaypoint);
}
// Insert a waypoint
if (document.getElementById('wayPoints').value !== null) {
var addressList = JSON.parse(document.getElementById('wayPoints').value);
var arrayLength = addressList.length;
// insert waypoints from schedule
for (var i = 0; i < arrayLength; i++) {
//alert(addressList[i]);
var hvaddress = addressList[i];
var newWP = new Microsoft.Maps.Directions.Waypoint({ address: hvaddress });
directionsManager.addWaypoint(newWP, 1);
}
}
// Set the element in which the itinerary will be rendered - set autoupdatemapview to false to override autozoom to route
directionsManager.setRenderOptions({ itineraryContainer: document.getElementById('printoutPanel'), autoUpdateMapView: false });
directionsManager.calculateDirections();
var allWaypoints = directionsManager.getAllWaypoints();
// add way point to pinsLocs array
for (var i = 0; i < allWaypoints.length; i++) {
// returns nulls
alert(allWaypoints);
loc = allWaypoints[i].getLocation();
var showMeLoc = loc;
// showMeLoc = undefined.....?
alert(showMeLoc);
pinsLocs.push(loc);
}
// only the address search location is added to the array, waypoint locations are null
alert(pinsLocs);
//Create a LocationRect from array of locations and set the map view.
map.setView({
bounds: Microsoft.Maps.LocationRect.fromLocations(pinsLocs),
padding: 100 //Add a padding to buffer map to account for pushpin pixel dimensions
});
});
},
errorCallback: function (e) {
//If there is an error, alert the user about it.
alert("No results found.");
}
};
//Make the geocode request.
searchManager.geocode(searchRequest);
}
}
}
UPDATE - HERE is the working code for those who have the same question!
var searchManager;
var startingPoint = document.getElementById('startPoint').value;
var address = $("#addressLine").val();
var patAddLoc;
// GET ROUTE BASED ON DIRECTION
function GetMap() {
var map = new Microsoft.Maps.Map(document.getElementById('myMap'), {
//BING API KEY VIA AZURE
credentials: 'XXXXX',
zoom: 10,
});
// geocode patient address
geocodeQuery(address);
// look for patient address
function geocodeQuery(query) {
//If search manager is not defined, load the search module.
if (!searchManager) {
//Create an instance of the search manager and call the geocodeQuery function again.
Microsoft.Maps.loadModule('Microsoft.Maps.Search', function () {
searchManager = new Microsoft.Maps.Search.SearchManager(map);
geocodeQuery(query);
});
} else {
var searchRequest = {
where: query,
callback: function (r) {
//Add the first result to the map and zoom into it.
if (r && r.results && r.results.length > 0) {
locs = [];
var pin = new Microsoft.Maps.Pushpin(r.results[0].location);
// get patient address location
patAddLoc = r.results[0].location;
map.entities.push(pin);
// add patient location to pushpin array
locs.push(r.results[0].location);
// view is set with route location
//map.setView({ bounds: r.results[0].bestView });
}
// directions manager
// addWaypoint
Microsoft.Maps.loadModule('Microsoft.Maps.Directions', function addWaypoint() {
var directionsManager = new Microsoft.Maps.Directions.DirectionsManager(map);
// if less than 2 point on the map
if (directionsManager.getAllWaypoints().length < 2) {
directionsManager.clearAll();
var startWaypoint = new Microsoft.Maps.Directions.Waypoint({ address: document.getElementById('startPoint').value });
directionsManager.addWaypoint(startWaypoint);
var endWaypoint = new Microsoft.Maps.Directions.Waypoint({ address: document.getElementById('endPoint').value });
directionsManager.addWaypoint(endWaypoint);
}
// Insert a waypoint
if (document.getElementById('wayPoints').value !== null) {
var addressList = JSON.parse(document.getElementById('wayPoints').value);
var arrayLength = addressList.length;
// insert waypoints from schedule
for (var i = 0; i < arrayLength; i++) {
//alert(addressList[i]);
var hvaddress = addressList[i];
var newWP = new Microsoft.Maps.Directions.Waypoint({ address: hvaddress });
directionsManager.addWaypoint(newWP, 1);
}
}
// Set the element in which the itinerary will be rendered - set autoupdatemapview to false to override autozoom to route
directionsManager.setRenderOptions({ itineraryContainer: document.getElementById('printoutPanel'), autoUpdateMapView: false });
//Add event handlers to directions manager.
Microsoft.Maps.Events.addHandler(directionsManager, 'directionsError', directionsError);
Microsoft.Maps.Events.addHandler(directionsManager, 'directionsUpdated', directionsUpdated);
// Calculate directions, which displays a route on the map
directionsManager.calculateDirections();
// get route boundaries
function directionsUpdated(e) {
//Get the current route index.
var routeIdx = directionsManager.getRequestOptions().routeIndex;
// get northeast bounding box corner
var bBoxNE = e.routeSummary[routeIdx].northEast;
locs.push(bBoxNE);
// get southwest bounding box corner
var bBoxSW = e.routeSummary[routeIdx].southWest;
locs.push(bBoxSW);
//SET MAP VIEW
//Create a LocationRect from array of locations and set the map view.
map.setView({
bounds: Microsoft.Maps.LocationRect.fromLocations(locs),
padding: 50 //Add a padding to buffer map to account for pushpin pixel dimensions
});
}
function directionsError(e) {
alert('Error: ' + e.message + '\r\nResponse Code: ' + e.responseCode)
}
});
},
errorCallback: function (e) {
//If there is an error, alert the user about it.
alert("No results found.");
}
};
//Make the geocode request.
searchManager.geocode(searchRequest);
}
}
}
If I understand correctly, you want a view that the entirety of the route and the extra location are visible?
How about using directionsManager.getCurrentRoute().routePath to get all the locations on the route, and then using LocationRect.fromLocations(), which can take in an array of locations - in your case all locations of above plus the additional one.
Note that calculateDirections and geocode and asynchronous, so you may want to handle the dependency on patAddLoc (e.g. move the directions code into the geocode callback).
Reference:
https://msdn.microsoft.com/en-us/library/mt750375.aspx
https://msdn.microsoft.com/en-us/library/mt750645.aspx
https://msdn.microsoft.com/en-us/library/mt712644.aspx

Leaflet: layer.getLatLng not working with .eachLayer function

I'm trying to do something very similar to what Chris Essig did here. Because I need to know how much datapoints there are in a radius of 20 meters from where the user has put down the 'trashMarker'.
So far I've got this code:
// Create the FeatureGroup and add it to the map
var jsonGroup = new L.FeatureGroup();
mapOverview.addLayer(jsonGroup)
//Retrieve all data and add to map
$.each(datalistObject['idlist'], function(key, value) {
$.getJSON('http://mydata.com' + value['id'], function(data) {
textbox = value['name'];
var dataid = L.geoJson([data], {
style: function (feature) {
return feature.properties && feature.properties.style;
},
onEachFeature: onEachFeature,
pointToLayer: function (feature, latlng) {
return L.marker(latlng, {
icon: value['icon']
});
}
}).addTo(jsonGroup);
},function(xhr) { console.error(xhr); });
});
//Code to find the markers within a 20 meter radius of trashMarker
function markersInRadius() {
// Lat, long of trash marker on overview map
var trashMarkerLat_long = trashMarkerOverview.getLatLng();
// counter of the amount of markers that are within a 20 meter radius
var counter_markers_in_radius = 0;
console.log(jsonGroup);
// Loop through each point in JSON file
jsonGroup.eachLayer(function (layer) {
// Lat, long of current point
layerLatLong = layer.getLatLng();
// Distance from our circle marker
// To current point in meters
distance_from_layer_circle = layerLatLong.distanceTo(trashMarker_lat_long);
// See if meters is within raduis
// The user has selected
if (distance_from_layer_circle <= 20) {
counter_markers_in_radius += 1;
};
console.log(counter_markers_in_radius);
});
// Close pointsInCircle
};
When I run this code, I get the error saying layer.getLatLng is not a function.
After doing a console.log on the jsonGroup FeatureGroup, I found out that the group has two objects in it's layers tab without any latlng information, but instead a layers tab of its own, containing all the datapoints with
latlng info... Maybe this is where the problem is?
Managed to fix it by running the eachLayer function twice on the jsonGroup variable like so:
function markersInRadius() {
// Lat, long of trash marker on overview map
var trashMarkerLatLng = trashMarkerOverview.getLatLng();
// counter of the amount of markers that are within a 20 meter radius
var pointsInRadius = 0;
console.log(jsonGroup);
// Loop through each point in JSON file
jsonGroup.eachLayer(function (layer) {
layer.eachLayer(function (layer) {
// Lat, long of current point
layerLatLong = layer.getLatLng();
// Distance from trashMarker
// To current point in meters
distanceFromTrashMarker = layerLatLong.distanceTo(trashMarkerLatLng);
// See if meters is within radius
if (distanceFromTrashMarker <= 20) {
pointsInRadius += 1;
};
});
});
console.log(pointsInRadius);
// Close pointsInCircle
};

Changing OpenLayers marker icon

I have a problem with OpenLayers. If I want to change the icon of some marker on the fly (for instance, to paint the marker with another color to indicate a status change), the marker starts behaving buggy, not showing in the proper place and even leaving semi-randomly located copies of itself, noticeable when zooming the map in or out.
I already realized that the problem happens when I reassign the marker.icon attribute, from some pre-loaded icon images which work fine otherwise. I have tried both with and without using icon.clone() to redraw.
Here's a full but simplified example which moves the marker randomly and should modify its icon too. If you comment out the "troublesome code" snippet, it works well, except for the icon change:
<!DOCTYPE HTML>
<HTML>
<HEAD>
<TITLE>Mapa</TITLE>
<SCRIPT language="javascript" type="text/javascript" src="OpenLayers.js"></SCRIPT>
<SCRIPT language="javascript" type="text/javascript">
var vMapa;
var prj0 = new OpenLayers.Projection("EPSG:4326"); // Transform from WGS 1984
var prj1 = new OpenLayers.Projection("EPSG:900913"); // to Spherical Mercator Projection
var vLon = 12.568142;
var vLat = 55.676320;
var vTimer = null;
var vCont = 0;
</SCRIPT>
</HEAD>
<BODY onClose="vTimer = null; vLon = null; vLat = null;">
<DIV id="demoMap" style="height: 700px; width: 1000px;"></DIV><DIV id="Contador">0</DIV>
<SCRIPT>
var options = {
controls: [
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.PanZoomBar(),
]
};
vMapa = new OpenLayers.Map("demoMap", options);
vMapa.addLayer(new OpenLayers.Layer.OSM());
vMapa.setCenter(new OpenLayers.LonLat(vLon, vLat).transform(prj0, prj1), 15, false, false);
var Navigation = new OpenLayers.Control.Navigation( { defaultDblClick: function(event) { return; } } );
vMapa.addControl(Navigation);
var markers = new OpenLayers.Layer.Markers("Markers");
vMapa.addLayer(markers);
var size = new OpenLayers.Size(12, 12);
var offset = new OpenLayers.Pixel(-6, -6);
var iconOff = new OpenLayers.Icon('img/CircOff.png', size, offset);
var iconOn = new OpenLayers.Icon('img/CircOn.png', size, offset);
var marker = new OpenLayers.Marker(new OpenLayers.LonLat(vLon, vLat).transform(prj0, prj1), iconOff.clone());
marker.setOpacity(1.0);
marker.events.register('mousedown', marker, function(evt) { vMapa.panTo(marker.lonlat); OpenLayers.Event.stop(evt); });
marker.pfInfo = 'Vel: 0.0 km/h';
markers.addMarker(marker);
vTimer = setTimeout('TimerEvent()', 1000);
function TimerEvent() {
vLon += ((Math.random() - 0.5) / 500);
vLat += ((Math.random() - 0.5) / 500);
// ------- Troublesome code -------
var ixIcon = Math.round(Math.random());
if (ixIcon == 0) {
marker.icon = iconOff.clone();
} else {
marker.icon = iconOn.clone();
}
// --------------------------------
var newLonLat = new OpenLayers.LonLat(vLon, vLat).transform(prj0, prj1);
var newPx = marker.map.getLayerPxFromViewPortPx(marker.map.getPixelFromLonLat(newLonLat));
marker.moveTo(newPx);
marker.draw();
vCont ++;
document.getElementById('Contador').innerHTML = vCont;
vTimer = setTimeout('TimerEvent()', 1000);
}
</SCRIPT>
</BODY>
</HTML>
Thanks a lot in advance for your suggestions.
I never use Marker to create markers.
I create a Vector layer, and add Point objects. Then style these Points.
This works much better and has more functionality.
You can create a restful web service which can return an SVG as a string. The parameters passed would tell the service what has to change on the icon. The service would read in a template SVG change it appropriately and return it.

OpenLayers => feature is null

This is my GeoJSON result. PasteBin
But when I load it, the result I get in firebug is feature is null. Why's that, are there any errors in my result? The coords in the JSON is written in projection WGS84, and in the code I also have set the externalProjection as WGS84. So why do I get the return "feature is null"?
The code I use to manage my map is :
$(document).ready(function() {
var wgs84 = new OpenLayers.Projection('EPSG:4326');
var layer = null;
var map = new OpenLayers.Map('map',{projection: wgs84});
layer = new OpenLayers.Layer.OSM( "Simple OSM Map");
var baseProjection = layer.projection;
map.addLayer(layer);
map.setCenter(new OpenLayers.LonLat(10,10), 4);
map.events.register("moveend", null, function(){
if(map.zoom == 10)
{
var bounds = map.getExtent();
console.log(bounds);
var ne = new OpenLayers.LonLat(bounds.right,bounds.top).transform(map.getProjectionObject(),wgs84);
var sw = new OpenLayers.LonLat(bounds.left,bounds.bottom).transform(map.getProjectionObject(),wgs84);
var vectorLayer = new OpenLayers.Layer.Vector();
map.addLayer(vectorLayer);
$.getJSON('ajax.php?a=markers&type=json&sw=('+sw.lon+','+sw.lat+')&ne=('+ne.lon+','+ne.lat+')',function(data){
//$.getJSON('test.json',function(data){
var geojson_format = new OpenLayers.Format.GeoJSON({
'externalProjection': wgs84,
'internalProjection': baseProjection
});
vectorLayer.addFeatures(geojson_format.read(data));
});
}
});
});
Your sample OpenLayer code is working correctly, the problem is in your GeoJSON: you misspelled coordinates as "coordninates"

Categories

Resources