I am trying to add some 2500 icons (2 Kb each) to a leaflet map. Filling the array is no problem. Adding the layer group to the map, however, takes between 2 and 5 seconds. Any suggestion how to improve the performance?
var icongroup = [];
for (id in reclist) {
var recname = reclist[id][0];
var posn = reclist[id][1];
var pose = reclist[id][2];
var mapicon = L.icon({iconUrl: icon, iconSize: [26, 29]});
icongroup.push(L.marker([posn, pose], {icon: mapicon}));
}
L.layerGroup(icongroup).addTo(map);
Adding thousands of markers to the page stresses the browser ressources for sure. There is a high chance this is the reason for your delay.
You should consider replacing your markers by a canvas, or clustering them.
See also: Plotting 140K points in leafletjs
Related
I made a map for my Minetest Game I play.
The project is here : https://github.com/amelaye/aiwMapping I created the map with the Python script gdal2tiles, like this : ./gdal2tiles.py -l -p raster -z 0-10 -w none ../map.png ../tiles
Here is the interesting part of code :
var minZoom = 0
var maxZoom = 9
var img = [
20000, // original width of image
20000 // original height of image
]
// create the map
var map = L.map(mapid, {
minZoom: minZoom,
maxZoom: maxZoom
})
var rc = new L.RasterCoords(map, img)
map.setView(rc.unproject([9000, 10554]), 7)
L.control.layers({
'Spawn': layerGeoGlobal(window.geoInfoSpawn, map, rc, 'red', 'star', 'fa'),
}, {
'Bounds': layerBounds(map, rc, img),
}).addTo(map)
L.tileLayer('./tiles/{z}/{x}/{y}.png', {
noWrap: true,
attribution: ''
}).addTo(map)
It works like a charm, but there is a problem : in Minetest, the coords (lat and lon) go to -10000 to 10000. In my Leaflet map, the coords still positive, then they go from 0 to 20000.
How can I solve this problem ?
CRS SIMPLE does not work.
PS : No relative questions have been posted, please read my message carefully.
When gdal2tiles is not given a georeferenced image (or a world file accompanying the image), it will assume that the (0,0) coordinate is at one of the corners of the image, and that one pixel equals one map unit (both horizontally and vertically).
Since your input image is a .png file, the most straightforward way of working around the issue will be creating an appropriate world file.
If your input image is map.png, create a new plain text file named map.pgw with the following contents...
1
0
0
1
-10000
-10000
...then run gdal2tiles.py again. Note that this worldfile assumes that one pixel equals one map unit, and the image's first corner is at the (-10000,-10000) coordinate.
I create 100 markers on a map.
As each marker may not be visible depending on 5 boolean variables, I want each marker to be embedded in a layer: 1marker = 1 layer.
The 5 conditions are in an L.control with 5 checkboxes.
Initially, all are displayed and depending on the conditions the markers
singlemarker = [];
ListLayers = [];
// loop on the 100 markers from my database
// marker is set by the database
Object.entries(data.themes).forEach(theme => {
var marker = L.marker([Latm, Lngm],{icon: ChxIcon});
singlemarker.push(marker);
ListLayers.push(new L.layerGroup(singlemarker).addTo(map));
singlemarker = [];
})
console.log(ListeLayers.length) //I obtain 100
map.removelayer(ListLayers[0]); //-> not working
Does anyone have a clue to try to solve this problem?
With many thanks
Cordially
Jean Michel
There is an example of the heatmap https://www.mapbox.com/mapbox-gl-js/example/heatmap/ by the number of markers/points on the area. But is there a way to display a heatmap by average pins/markers values? For example if I have 5 pins and their average prop value speed=3 then it will be shown as green cluster/heatmap and if their av. prop val is 6 then it will be red cluster/heatmap.
I found that "clusterAggregates" property can help, but can't find any example of using it.
Thanks
I'll leave my way to do so. Old question, which is sometimes risen, but there are no nice sollution, so... Turf's hexgrid (http://turfjs.org/docs/#hexGrid) can help:
const hexagons = hexGrid(bbox, size);
const collection = // collection of your points;
const hexagonsWithin = collect(hexagons, collection, "propertyToAgretateFrom", "propertyToAggregateIn");
const notEmptyHexagonValues = hexagonsWithin.features.filter(({ properties }) => properties.propertyToAggregateIn.length !== 0);
const notEmptyHexagons = {
"type": "FeatureCollection",
"features": notEmptyHexagonValues,
};
// at this point you're having not empty hexagons as a geojson, which you can add to the map
collect is another method from turf, whatcollection should be you can look up in the docs, because it's changing a lot.
The general idea behind is to "divide" visible part of map (bbox) into hexagons by hexGrid method and and aggregate some properties that you need from every marker inside of every hexagon you'll have into the array, so you can get an average value, for example. And assign a color based on it.
Let's say we have feature.properties.propertyToAgretateFrom as 4 and 5 in two markers. After the aggregation, if these markers were inside one polygon, you'll have it feature.properties.propertyToAggregateIn: [4, 5] - this feature is polygon. From this on you can do pretty much everything you want.
This question has no answer since august.
I've found no question identical.
I hope it's clear enough.
There seems to be few questions on maps but someone must know the answer.
I'm trying to display an offline map using 512x512 tiles. I have the tiles named like 22524#x2.png
if I use the 256x256 tiles the map displays correctly, but the 512 tiles only show a quarter of each tile.
here's my code
//Get the URL template to the map tiles
let baseURL = NSBundle.mainBundle().bundleURL.absoluteString
//let urlTemplate = baseURL.stringByAppendingString("osmm/{z}/{x}/{y}.png/")
let urlTemplate = baseURL.stringByAppendingString("two/{z}/{x}/{y}#2x.png/")
print(urlTemplate)
let carte_indice = MKTileOverlay(URLTemplate:urlTemplate)
carte_indice.geometryFlipped = false
carte_indice.canReplaceMapContent = true
carte_indice.maximumZ = 18
carte_indice.minimumZ = 16
self.mapView.addOverlay(carte_indice)
What do I need to add to get the tiles to display correctly?
Is a map using 256x256 tiles on a retina screen acceptable by apple?
I am not sure what the exact technical term for this question would be so please pardon the noobish question.
I have a leaflet map like this:
var map = L.map("dvMapContainer",
{
}).setView([39.782388193, -86.14135265], 14);
I am adding a marker to this map like this:
var vehicleMarker = new L.Marker([39.782388193, -86.14135265], { id: 'vehicle', icon: cssIcon });
map.addLayer(vehicleMarker);
Every few seconds, I update the position of the vehicleMarker and center the map
vehicleMarker.setLatLng(newLatLng);
map.setView(newLatLng, 18);
This works fine however the effect is not very visually pleasing as the map is constantly moving. I would like to move only the marker until it gets close to the edge of the map and then recenter the map. Is that possible ? Any hints/solutions will be much appreciated.
Each time you check (every few seconds), you can compare your marker location with the map bounds:
var bounds = map.getBounds();
if(vehicleMarker.getLatLng().lng > bounds.getEast()-.001 || vehicleMarker.getLatLng().lng < bounds.getWest()+.001 || vehicleMarker.getLatLng().lat > bounds.getNorth()-.001 || vehicleMarker.getLatLng().lat < bounds.getSouth()+.001)
//change bounds
If your next marker location is close to your current bounds, then change your map's current bounds.
You can change the .001 depending on how far zoomed out you are.
More info on bounds here: http://leafletjs.com/reference.html#latlngbounds