I am currently working on a web application where I'm trying to display a heat map using the library called Leaflet.heat. It works with the Leaflet Javascript library to create an overlay heat map that looks pretty good. I feel like I'm pretty much there but having one last bit of trouble with array format and can't figure out what is wrong. Let me share the code that I have right now.
var mymap;
var marker = [];
var heatMapArr = [];
window.onload = function() {
alert("in initial func");
uponPageLoadDefault();
};
function uponPageLoadDefault()
{
//initial default page load
var branches = new L.LayerGroup();
var items = JSON.parse('${branches}');
var j = 0;
for(var i = 0; i < items.length; i++)
{
var LamMarker = new L.marker([items[i].lat, items[i].lon]);
//GOT RID OF FUNCTION CALL.
var heatMapPoint = {
lat: items[i].lat,
lon: items[i].lon,
intensity: items[i].tranCount
};
heatMapArr.push(heatMapPoint);
LamMarker.bindPopup("<b>" + items[i].branchName + "</b><br>" + items[i].branchAdd + "</br><br>" + items[i].branchCity + "</br><br>" + items[i].branchSt + "</br><br>" + items[i].branchZip + "</br><br>TranCount: " + items[i].tranCount).addTo(branches);
marker.push(LamMarker);
}
mbAttr = 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
mbUrl = 'https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoidGFzdHlicm93bmllcyIsImEiOiJjaXgzZWxkaHowMWZhMnlvd2wzNHllaGwxIn0.0RSZEhtR0OBLMbwjqFfBkg';
var outdoors = L.tileLayer(mbUrl, {id: 'mapbox.outdoors', attribution: mbAttr});
var heatmap = L.heatLayer(heatMapArr, {radius: 6, blur: 8,maxZoom: 8});
var map = L.map('map', {
center: [39.73, -104.99],
zoom: 10,
layers: [outdoors, branches, heatmap]
});
var baseLayers = {
"Outdoors": outdoors
};
var overlays = {
"Branches": branches,
"HeatMap": heatmap
};
L.control.layers(baseLayers, overlays).addTo(map);
So basically I am trying to use the heat map display as a possible overlay that the user can select. The Leaflet-heat library tutorial is located at https://github.com/Leaflet/Leaflet.heat/ and it explains what needs to be done in order for the library to work.
Anyway, I have a list of items with latitude, longitude, and intensity amount, so I'm trying to use that, its called items. I iterate through that, pushing the select information into my heat map array. At this point I should be almost all set besides adding the overlays and creating the map. When I run the program, the map displays but the overlay icon is absent so there is an issue.
In the website tutorial they use a separate Javascript file which has an array of objects to create their heat map. I tried this with my program and then everything worked, which quickly led me to believe there's a problem with my array of objects, probably some minor formatting thing.......I am using another function to create an object with the data I have, so it will be in the same format as the website example.
I tried to use alert and other statements and compare my array to theirs but it hasn't yielded anything useful so I wanted to post my issue here on Stack to get some feedback from others on what could be wrong. I think its something really small that I may not be seeing.
Any feed back is greatly appreciated and certainly let me know if there's any questions.
Thanks!
Related
This question is the "episode 2" of this: Original question
Hi !
I'm still having trouble with my map. In fact, I believed the solution in the link above had solve my problem, but I figured out another problem.
My code and my aim are almost the same as the "episode 1" of this question.
As a reminder, I have a Leaflet map that uses MarkerCluster to show ~36.000 markers. Each marker must have a Popup (that appear onclick) which contains many informations.
As they were too many informations to get at one time (I mean to get all points and all informations at one time), I had the idea to get latitude, longitude and a single ID in order to show the Markers on the map. Next, when click on a Popup, the script make an Ajax request to get infos from a Database, using the single ID contains by each marker.
For now, and with the great help of maximkou, I can make this happen. My problem is, that only the last ID is consider, so it always request on the same ID and always show the same information (which is not what I try to do).
I tried many things (like getting all the markers on the map, trying to put markers on an array, etc.) but I can't figure out how to get this work.
I don't think it's impossible (but maybe it is), I think I simply lack skill on Javascript.
If you have another solution or idea, I will be glad to test it to !
I will now show you an extract of my current code:
function makeMap(pointsToInsert){
if (typeof map != 'undefined') {
map.off();
map.remove();
}
var tiles=L.tileLayer('https://api.mapbox.com/styles/v1/mapbox/streets-v9/tiles/256/{z}/{x}/{y}?access_token=', {
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox',
maxZoom: 20,
}),
latlng = L.latLng(48.8557, 2.3600);
var map = L.map('map', {center: latlng, zoom: 9, zoomControl:false, layers: [tiles]});
var arr = JSON.parse(pointsToInsert); //pointsToInsert come from a PHP script call before
var markers = L.markerClusterGroup();
for (var i = 0; i < arr.length; i++) {
var a = arr[i];
var ID = a[0];
var lat = a[1];
var lon = a[2];
var marker = L.marker(new L.LatLng(lat, lon));
marker.bindPopup(ID);
markers.addLayer(marker);
marker.on('click', function () {
var datas = marker.getPopup().getContent();
var popup = L.popup()
.setLatLng(this.getLatLng())
.setContent("Loading ...")
.openOn(map);
$.ajax({
url: 'getInfos.php',
type : 'POST',
data : "id=" + datas,
dataType: 'html',
success: function (data) {
popup.setContent(data);
},
error : function(resultat, statut, erreur){
alert("Error");
},
});
});
}
map.addLayer(markers);
}
I need some help here, please
If you want me to be more specific or to add others extract just let me know !
Thanks in advance
i hope you can help me with my following problem. since days I´m tinkering on it, but it won´t run...
I´m writing a little web-app based on Google Maps API on wich i can mark my actual position on a map with a modified marker-symbol an so on. Everything works great so far. I receive my geolocation via HTML5-Geolocation function and write the values in to a mysql database. In a separate function (see below) i read out this data an set the marker with my modified symbol on the map.
The next I wan´t to solve is to remove the marker after about 40 minutes automatically from the map. For this I created a separate table on my database which gets filled with the marker-information from the main table. This works so far, I solved it with a php-script and a cron-job. Then the entry from the main table becomes deleted. What makes me insane is to remove the marker after the 40 minutes from the map. I tried several things, from creating arrays with the data of the "to-remove-table", i played around with the setMap-function of Google Maps API, but I´m still on the line.
Here is my code where I read out the data from database and set the marker on the map:
function markPolitesse() {
var infoWindow_spotted = new google.maps.InfoWindow;
downloadUrl("phpsqlajax_genxml2.php", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("politesse_spotted");
for (var i = 0; i < markers.length; i++) {
var number = markers[i].getAttribute("number");
var city = markers[i].getAttribute("city");
var zipcode = markers[i].getAttribute("zipcode");
var street = markers[i].getAttribute("street");
var type = markers[i].getAttribute("street");
var point = new google.maps.LatLng(
parseFloat(markers[i].getAttribute("lat")),
parseFloat(markers[i].getAttribute("lng")));
var html = "<b>" + city + "</b> <br/>" + zipcode + "</b> <br/>" + type + "</b> <br/>";
var marker = new google.maps.Marker({
map: map,
position: point,
title: number,
icon: politessenImage
});
bindInfoWindow(marker, map, infoWindow_spotted, html);
}
});
}
The main- and the "remove-table" contain the following fields:
number, city, zipcode, street, streetnumber, coordinates_lat, coordinates_lng, time, date
I hope you have a impulse for me I would be thankful...
Regards,
Stefan
Store the marker in a global variable/outside the function, then in your function do the following:
marker.setMap(null);
// set up new marker
Then assign your new marker.
I have a basic markerclusterer example which works very well.
var center = new google.maps.LatLng(37.4419, -122.1419);
var options = {
'zoom': 13,
'center': center,
'mapTypeId': google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map"), options);
var markers = [];
for (var i = 0; i < 100; i++) {
var latLng = new google.maps.LatLng(data.photos[i].latitude,
data.photos[i].longitude);
var marker = new google.maps.Marker({'position': latLng});
markers.push(marker);
}
var markerCluster = new MarkerClusterer(map, markers);
What I would like to do is cluster the markers by country and then once you click on it they are still clustered until on3 further click. Currently they are clustered until you are down to one result. I have thousands of markers and would like them visible after one country click and then one more click.
I looked for a solution online and found this http://google-maps-utility-library-v3.googlecode.com/svn/tags/markermanager/1.0/examples/google_northamerica_offices.html
which is produced using this
var officeLayer = [
{
"zoom": [0, 3],
"places": [
{ "name": "US Offices", "icon": ["us", "flag-shadow"], "posn": [40, -97] },
{ "name": "Canadian Offices", "icon": ["ca", "flag-shadow"], "posn": [58, -101] }
]
},
...
};
function setupOfficeMarkers() {
allmarkers.length = 0;
for (var i in officeLayer) {
if (officeLayer.hasOwnProperty(i)) {
var layer = officeLayer[i];
var markers = [];
for (var j in layer["places"]) {
if (layer["places"].hasOwnProperty(j)) {
var place = layer["places"][j];
var icon = getIcon(place["icon"]);
var title = place["name"];
var posn = new google.maps.LatLng(place["posn"][0], place["posn"][1]);
var marker = createMarker(posn, title, getIcon(place["icon"]));
markers.push(marker);
allmarkers.push(marker);
}
}
mgr.addMarkers(markers, layer["zoom"][0], layer["zoom"][1]);
}
}
mgr.refresh();
updateStatus(mgr.getMarkerCount(map.getZoom()));
}
I'm not sure how to implement this into what I've currently got and if i need to include any other scripts/ libraries also.
You are looking at two totally different libraries, there. Your question is about the MarkerClusterer library, but your example solution is about the MarkerManager library.
The MarkerClusterer library automatically clumps markers together based on an algorithm that tries to decide when too markers would be so close together that you can't visibly distinguish one from another. You don't really have a lot of control over when and how it decides to merge markers together this way, so this library is idea when it doesn't matter to you how they get merged, as long as merging happens. Since you want to merge markers together by political boundaries (countries) and not by proximity to each other, this is not the library for you.
The MarkerManager library does not automatically merge markers together at all. What it does do is to selectively hide and reveal markers based on the zoom level of the current map viewport. What you would need to do is do your own merging, and then add to the MarkerManager all of the merged markers, as well as the detail markers, and the zoom levels where you want each marker to be visible. Doing your own merging means you will need an alternate way of determining which country each marker point falls within. Hopefully, you already know (or can get) that information, because it's not automatically provided by any of these libraries.
tl;dr - use the MarkerManager library and not the MarkerClusterer library for grouping by countries, and it's up to you to identify the location for each country and which marker goes with which one.
I am using a mapping app called Leaflet. Some of the code I use is below:
var layer1 =L.tileLayer('http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/7540/256/{z}/{x}/{y}.png', {
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © CloudMade',
maxZoom: 12
}).addTo(map);
// THE ABOVE CODE MERELY PLACES A BASE LAYER INSIDE A DIV TAG. But the key to this is the //addTo method.
I also am getting weather radar data from Aeris and create a layer on leaflet using this:
var radar_img_arr = createVariables();
and the createVariables() looks like this:
function createVariables(){
var radar_images = [];
for (var i = 0; i <= 99; ++i) {
radar_images[i] = L.tileLayer('http://tile2.aerisapi.com/QjvmoFnKc1Wj94aDULEX_8Y7R8eagwQKlUusR5WZk6JTBdz6zlCm3KIP15CLG/radar/{z}/{x}/{y}/'+data.files[i].time +'.png', {opacity: 0.6, format: 'image/png', maxZoom: 12,attribution: "FOSM"}).addTo(map).setZIndex(999);
}
return radar_images;
}
The above adds to the map all data to the map at once just to test.
What I really want is a loop which can remove a old layer from the map and replace it with a new layer.
The 2 important methods are below:
map.removeLayer(radar_img_arr[i]);
map.addLayer(radar_img_arr[i+1]);
I am trying to write a loop to do this and the timing is messed up. other weather sites use Flex or Flash to animate a radar loop but i want to try a Javascript solution.
Does anyone know how to create this loop in JS or jQuery?
Thanks,
Jim
You should use set timeout to iterate over the loop... Something like:
// function for setTimeout
var updateImage = function() {
//gets the current image & update place
var img = radar_img_arr[place++]
// code to update display here.
...
// call the function again in 1 second
setTimeout(updateImage, 1000)
// reset place to 0 if need be
if (step == radar_img_arr.length-1)
place = 0;
}
// variable to store where we are in the array.
var place = 0
// array of images
var radar_img_arr = createVariables()
//start the process in 1 second:
setTimeout(updateImage, 1000)
// or, start it right away:
updateImage()
I don't like to use setInterval, which will automatically call your function over and over however many miliseconds you pass. Reason is, if your function takes longer to run than timer takes, you create a race condition, which in your case would cause the images to update strangely.
I have a pretty well integrated OpenLayers map that I want to add photos from the Panoramio API to. Unfortunately, it seems both API's are under documented on this subject. I found one great tutorial here http://www.gisandchips.org/2010/05/04/openlayers-y-panoramio/ but as I am new to all of this, could be why I cannot complete this on my own. I feel like even using this tutorial I have a lot of blank spaces in my mind and not to mention, the photos are NOT appearing on my map :-/
Here is my portion of the code that demonstrates my use of that tutorial and what I have attempted so far:
var url = "http://www.panoramio.com/map/get_panoramas.php";
var parameters = {
order: 'popularity',
set: 'full',
from: 0,
to: 20,
minx: 84.05,
miny: 31.36,
maxx: 91.89,
maxy: 32.30,
size: 'thumbnail'
} //end parameters
OpenLayers.loadURL(url, parameters, this, displayPhotos);
function displayPhotos(response) {
var json = new OpenLayers.Format.JSON();
var panoramio = json.read(response.responseText);
var features = new Array(panoramio.photos.length);
for (var i = 0; i < panoramio.photos.length; i++) {
var upload_date = panoramio.photos[i].upload_date;
var owner_name = panoramio.photos[i].owner_name;
var photo_id = panoramio.photos[i].photo_id;
var longitude = panoramio.photos[i].longitude;
var latitude = panoramio.photos[i].latitude;
var pheight = panoramio.photos[i].height;
var pwidth = panoramio.photos[i].width;
var photo_title = panoramio.photos[i].photo_title;
var owner_url = panoramio.photos[i].owner_url;
var owner_id = panoramio.photos[i].owner_id;
var photo_file_url = panoramio.photos[i].photo_file_url;
var photo_url = panoramio.photos[i].photo_url;
var fpoint = new OpenLayers.Geometry.Point(longitude, latitude);
var attributes = {
'upload_date': upload_date,
'owner_name': owner_name,
'photo_id': photo_id,
'longitude': longitude,
'latitude': latitude,
'pheight': pheight,
'pwidth': pwidth,
'pheight': pheight,
'photo_title': photo_title,
'owner_url': owner_url,
'owner_id': owner_id,
'photo_file_url': photo_file_url,
'photo_url': photo_url
} //end attributes
features[i] = new OpenLayers.Feature.Vector(fpoint, attributes);
} //end for
var panoramio_style2 = new OpenLayers.StyleMap(OpenLayers.Util.applyDefaults({
pointRadius: 7,
fillColor: "red",
fillOpacity: 1,
strokeColor: "black",
externalGraphic: "panoramio-marker.png"
}, OpenLayers.Feature.Vector.style["default"]));
var vectorPano = new OpenLayers.Layer.Vector("Panoramio Photos", {
styleMap: panoramio_style2
});
vectorPano.addFeatures(features);
map.addLayer(vectorPano);
} //end displayPhotos
In my mind this code should work perfectly. Giving me a result of some Panoramio thumbnails on my slippy map. Unfortunately it seems that the layer is there, but blank..When I look at the response text in Firebug I can see that the JSON is returned with attributes of photos from Panoramio, in the location I have specified (Tibet). I appreciate your help and time to consider my issues.
Thank you,
elshae
I don't know how proficient you are in OpenLayers, but the project is certainly not underdocumented. There is an extensive api documentation and also numerous examples that should help to get you started.
But now back to your problem: likely, this is a projection issue. Panoramio returns WSG-84 (GPS) Coordinates for all the photos it found, and the openstreetmap baselayer of your map is in Spherical Mercator projection ('EPSG:900913').
So you have to convert the coordinates from WSG-84 to Spherical Mercator using something like
var curPic = panoramio.photos[i];
var panLonLat = new OpenLayers.LonLat(curPic.longitude, curPic.latitude);
panLonLat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection('EPSG:900913'));
and then use the converted point for your geometry