On this Leaflet application I show all available bus stops in Denmark.
http://drivetime.mapicture.dk/stops
The strange thing is, that if you zoom down to one of the last 4 zoom levels, the layer with these bus stops simply disappears. They reappear when you zoom out again.
The bus stops are made as a single layer retrieved through a WMS request to our Geoserver. The entire javascript code is actually pretty simple, so I have trouble finding out, what causes this behavior.
function CurrentStopsMap(mapNode, zoomSettings) {
var self = this;
self.mapNode = mapNode;
self.zoomSettings = zoomSettings;
self.mapquest = new L.TileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: "©<a href='http://openstreetmap.org/' target='_blank'>OpenStreetMap</a> contributors, Tiles Courtesy of <a href='http://open.mapquest.com' target='_blank'>MapQuest</a>",
subdomains: ['1', '2', '3', '4']
});
self.regions = new L.TileLayer.WMS("http://backend.mapicture.dk:8080/geoserver/mapicture/wms", {
layers: 'mapicture:region',
format: 'image/png',
styles: 'regions',
transparent: false
});
self.stops = new L.TileLayer.WMS("http://backend.mapicture.dk:8080/geoserver/mapicture/wms", {
layers: 'mapicture:stops',
format: 'image/png',
transparent: true
});
self.map = new L.Map(mapNode, {
center: new L.LatLng(zoomSettings.lat, zoomSettings.lon),
zoom: zoomSettings.level,
layers: [self.mapquest, self.stops],
zoomControl: true
});
L.control.layers({
"Kort": self.mapquest,
"Områder": self.regions
}, {
"Stoppesteder": self.stops
}).addTo(self.map);
}
var zoom = {
lat: 56.24,
lon: 10.68,
level: 7
};
var map = new CurrentStopsMap('map', zoom)
This was actually a problem with the Geoserver daemon.
Related
Leaflet has a nice heatmap layer, but which I am finding difficulties to handle when zooming into the map.
I can set the data to have a radius of 0.1 and they look very nice when I have a zoom level of 8.
If a user zooms in to a level of, say 10, the map becomes entirely covered by the heatmap.
Also, if the user zooms out to level 6 the heatmap becomes invisible.
Can anyone, please, let me know how to scale the radius of data points of the heatmap, so as to obtain a similar effect to that of Google Maps Heatmap?
Thank you!
EDITED:
I used the heatmap from Patrick Wield heatmap.js
The code I used is as follows:
<script>
window.onload = function() {
var myData = {
max: 1000,
data: [
{lat: 50.32638, lng: 9.81727, count: 1},
{lat: 50.31009, lng: 9.57019, count: 1},
{lat: 50.31257, lng: 9.44102, count: 1},
]
};
var baseLayer = L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © CloudMade',
maxZoom: 18,
minZoom: 7
}
);
var cfg = {
"radius": .1,
"maxOpacity": 1,
"scaleRadius": true,
"useLocalExtrema": true,
latField: 'lat',
lngField: 'lng',
valueField: 'count'
};
var heatmapLayer = new HeatmapOverlay(cfg);
var map = new L.Map('map', {
center: new L.LatLng(50.339247, 9.902947),
zoom: 8,
layers: [baseLayer, heatmapLayer]
});
heatmapLayer.setData(myData);
layer = heatmapLayer;
};
</script>
I have built a leaflet map with two base layers, and each of these base layers will have their own unique points of interest. The points of interest are being stored as geojson that I loop over to create multiple overlays for different categories. So when viewing the default base layer you would see layers for Show All, Cat1, Cat2 etc.
I need a way to be able to attach overlay layers to a base layer, or remove all overlay layers and then load the relevant ones when the base layer changes.
I tried using the following, which worked to switch categories, with the baselayerchange event, but the overlay layers were still displaying when I switched base layers.
layerControl._layers.forEach(function(layer){
if(layer.overlay){
map.removeLayer(layer.layer)
}
});
I've been searching for a couple of days now for an answer to this without any luck, any help is greatly appreciated.
EDIT
Posting additional code for context. This is not the entirety of the code, there are some plugins that I'm not including code for and have excluded definitions for a several variables, but this should provide better insight into how things are working.
//Initialize the map
var map = new L.Map('map', {
maxZoom: mapMaxZoom,
minZoom: mapMinZoom,
crs: crs1848,
attributionControl: false,
layers: [pano1848]
});
//add controls to the map
var layerControl = L.control.layers(null, null, {position: 'bottomleft'}).addTo(map);
//building category layers from geojson
var types = ['African Americans', 'Art Architecture Culture', 'Education Religion Reform', 'Everyday Life', 'Immigrants', 'Science Inventions', 'Transportation Industry Commerce'];
types.forEach(function(type){
var catType = type.replace(/\s/g,"");
var catPoints = L.geoJson(mapData, {
filter: function(feature, layer){
var cat = feature.properties['category'];
return cat.indexOf(catType) >= 0;
},
onEachFeature: function (feature, layer) {
layer.bindTooltip(feature.properties.name);
(function(layer, properties){
//Create Numeric markers
var numericMarker = L.ExtraMarkers.icon({
icon: 'fa-number',
markerColor: 'yellow',
number: feature.properties['id']
});
layer.setIcon(numericMarker);
layer.on('click', function() {
$.ajax({
url:feature.properties['url'],
dataType:'html',
success: function(result){
$('#detailContainer').html(result);
$('#overlay').fadeIn(300);
}
});
});
})(layer, feature.properties);
}
});
layerControl.addOverlay(catPoints, catType);
});
//Base Layer Change Event
map.on('baselayerchange', function(base){
var layerName;
layerControl._layers.forEach(function(layer){
if(layer.overlay){
map.removeLayer(layer.layer)
}
});
if(base._url.indexOf('1848') >= 0){
map.options.crs = crs1848;
map.fitBounds([
crs1848.unproject(L.point(mapExtent1848[2], mapExtent1848[3])),
crs1848.unproject(L.point(mapExtent1848[0], mapExtent1848[1]))
]);
var southWest = map.unproject([0, 8192], map.getMaxZoom());
var northEast = map.unproject([90112, 0], map.getMaxZoom());
map.setMaxBounds(new L.LatLngBounds(southWest, northEast));
map.addLayer(allPoints);
layerName = '1848 Panorama';
}
else if(base._url.indexOf('2018') >= 0){
map.options.crs = crs2018;
map.fitBounds([
crs2018.unproject(L.point(mapExtent2018[2], mapExtent2018[3])),
crs2018.unproject(L.point(mapExtent2018[0], mapExtent2018[1]))
]);
var southWest = map.unproject([0, 8192], map.getMaxZoom());
var northEast = map.unproject([49152, 0], map.getMaxZoom());
map.setMaxBounds(new L.LatLngBounds(southWest, northEast));
layerName = '2018 Panorama'
}
miniMap.changeLayer(minimapLayers[layerName]);
//map.setView(map.getCenter(), map.getZoom());
});
You may create global variable call "overlays", and remove it like an example below.
Here is the similar example to illustrate your problem jsFiddle
var overlays = {
'Name 1': catPoints,
'Name 2': catType
};
L.control.layers(null, overlays).addTo(map);
// Whenever you want to remove all overlays:
for (var name in overlays) {
map.removeLayer(overlays[name]);
}
In the following code in Ionic Project, sometimes map doesn't fit correctly an center
code:
initMap() {
this.mapInitialised = true;
this.bounds = new google.maps.LatLngBounds();
this.Geolocation.getCurrentPosition().then((position) => {
this.location = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
let mapOptions = {
center: this.location,
zoom: 15,
draggable: true,
backgroundColor: 'white',
fullscreenControl: false,
mapTypeControl: false,
zoomControl: true,
streetViewControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
this.map = new google.maps.Map(this.mapElement.nativeElement, mapOptions);
this.map.fitBounds(this.bounds); //# auto - zoom
this.map.panToBounds(this.bounds);
console.log(this.location);
this.PostMarker(this.Postlatlng);
this.CurrentMarker(this.location);
});
}
CurrentMarker(location){
console.log(location.lat, location.lng);
let image = 'https://maps.gstatic.com/mapfiles/api-3/images/spotlight-poi_hdpi.png';
let marker = new google.maps.Marker({
map: this.map,
animation: google.maps.Animation.DROP,
position: location,
icon: image
});
this.bounds.extend(new google.maps.LatLng(location.lat(), location.lng()));
}
PostMarker(location) {
console.log(location.lat,location.lng);
let image = 'https://maps.gstatic.com/mapfiles/api-3/images/spotlight-poi_hdpi.png';
let marker = new google.maps.Marker({
map: this.map,
animation: google.maps.Animation.DROP,
position: location,
icon: image
});
this.bounds.extend(new google.maps.LatLng(location.lat, location.lng));
}
output:
after zooming out:
update
As you can see in the output map of the screen is pacific ocean while test data point is a place in Tibet and the second point is my current location in Iran. instead of fitting this two point in screen it shows wrong location/area.
This problem mostly happens when two point is so far from each other. In near location Isaw this problem one or two times.
Set the minZoom map option. Otherwise, the screenshot you have posted it how the API (correctly) behaves when you zoom out to 0.
For example:
new google.maps.Map(element,{minZoom:3});
They asked me for a 'toggle button' to switch the clustering on and off Can someone help me to achieve clustering on/off?
Note: loading more than 30,000 points
Create two layers, one with and one without the marker clustering and add them to the leaflet control. For example:
var littleton = L.marker([39.61, -105.02]).bindPopup('This is Littleton, CO.'),
denver = L.marker([39.74, -104.99]).bindPopup('This is Denver, CO.'),
aurora = L.marker([39.73, -104.8]).bindPopup('This is Aurora, CO.'),
golden = L.marker([39.77, -105.23]).bindPopup('This is Golden, CO.');
var cities = L.layerGroup([littleton, denver, aurora, golden]);
var citiesClustered = new L.MarkerClusterGroup();
markers.addLayer(littleton);
markers.addLayer(denver);
markers.addLayer(aurora);
markers.addLayer(golden);
var streets = L.tileLayer(mapboxUrl, {id: 'examples.map-i86knfo3', attribution: mapboxAttribution});
var map = L.map('map', {
center: [39.73, -104.99],
zoom: 10,
layers: [streets, cities]
});
var baseMaps = {
"Streets": streets
};
var overlayMaps = {
"Cities": cities,
"Clustered cities": citiesClustered
};
L.control.layers(baseMaps, overlayMaps).addTo(map);
You can also create a custom control that will de-cluster the markers but this control already exists and it's easy to implement.
I am using mapbox/leaflet to display a picture of a human body rather than a regular map.
I am using leaflet draw and I need to be able to create a circle and move it around while maintaining its radius. However, when I move it towards the bottom of the map/screen, the size increases exponentialy. I want it to stay the same size.
I assume it's something to do with projection or CRS but I'm not sure what to do to stop it.
My code is :
var mapMinZoom = 0;
var mapMaxZoom = 4;
var map = L.map('map', {
maxZoom: mapMaxZoom,
minZoom: mapMinZoom,
crs: L.CRS.Simple,
noWrap: true,
continuousWorld: true
}).setView([0, 0], mapMaxZoom);
var mapBounds = new L.LatLngBounds(
map.unproject([0, 3840], mapMaxZoom),
map.unproject([4096, 0], mapMaxZoom));
map.fitBounds(mapBounds);
L.tileLayer('/tiles/{z}/{x}/{y}.png', {
minZoom: mapMinZoom, maxZoom: mapMaxZoom,
bounds: mapBounds,
attribution: 'Rendered with MapTiler',
noWrap: true,
continuousWorld: true
}).addTo(map);
var touches;
var featureGroup = L.featureGroup().addTo(map);
var drawControl = new L.Control.Draw({
edit: {
featureGroup: featureGroup
}
}).addTo(map);
map.on('draw:created', function (e) {
featureGroup.addLayer(e.layer);
});
Any ideas? I don't need to use leaflet draw, just the L.circle would do, but it has the same issue.
Gif of issue here :
Turns out there are a load of todos in the leaflet 0.7 code... including this little gem :
// TODO Earth hardcoded, move into projection code!
_getLatRadius: function () {
return (this._mRadius / 40075017) * 360;
},
_getLngRadius: function () {
return this._getLatRadius() / Math.cos(L.LatLng.DEG_TO_RAD * this._latlng.lat);
},
Updated to 0.8Dev and it has all been fixed!