LeafletJS not loading all tiles until moving map - angularjs

I am trying to load a simple leaflet map in my Ionic 2 app. Unfortunately not all tiles are loaded currectly until a moving the map.
this.map = new L.Map('mainmap', {
zoomControl: false,
center: new L.LatLng(40.731253, -73.996139),
zoom: 12,
minZoom: 4,
maxZoom: 19,
layers: [this.mapService.baseMaps.OpenStreetMap],
attributionControl: false
});

There are a couple of solutions for this problem:
1- Add "./node_modules/leaflet/dist/leaflet.css" in the styles array in `angular.json'.
2- Invalidate size when a map is ready:
onMapReady(map: L.Map) {
setTimeout(() => {
map.invalidateSize();
}, 0);
}
Add this to your template:
<div style="height: 300px;"
leaflet
(leafletMapReady)="onMapReady($event)">
</div>
And this will bind onMapReady method which you have in your component.
3- Install Leaflet typings for Typescript:
npm install --save-dev #types/leaflet
Vanilla JavaScript:
1- Validate the size of map:
onMapReady(map: L.Map) {
setTimeout(() => {
map.invalidateSize();
}, 0);
}
2- Add leaflet stylesheet leaflet/dist/leaflet.css in the <head> of your document.

this work for me fine :
this.map = L.map('map');
const self = this;
this.map.on("load",function() { setTimeout(() => {
self.map.invalidateSize();
}, 1); });
this.map.setView([36.3573539, 59.487427], 13);

Just put the creation of the map into the Ionic ionViewDidEnter lifecycle method. Much cleaner than any setTimeout hack ;)
import { Map, tileLayer } from 'leaflet';
...
ionViewDidEnter(): void {
this.map = new Map('map', {
center: [48.1351, 11.5819],
zoom: 3
});
const tiles = tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
minZoom: 3,
attribution: '© OSM'
});
tiles.addTo(this.map);
}

Related

Is there any event listener to check if the wms layer has loaded or not in google maps?

In a react web application, I am overlaying wms tiles on google maps using map's property overlayMapTypes.
if (map && activeLayer) {
let layer = new window.google.maps.ImageMapType({
getTileUrl: activeLayer.type === "wms" ? getTileUrl : getWMTSUrl,
tileSize: new window.google.maps.Size(256, 256),
minZoom: 0,
maxZoom: 24,
opacity: 1.0,
isPng: true,
});
map.overlayMapTypes.setAt(0, layer);
}
Some layers take time to load. So, I want to show a spinner or a message while the layer is
being loaded. Is there an event to get the status of it to check if it is still loading or loading is completed?
There is an event listener tilesloaded, but this is for the google maps base tiles, not for the overlayed map tiles.
useEffect(() => {
if (map) {
map.addListener("tilesloaded", () => {
console.log("Tiles Loaded");
});
}
}, [map]);
tilesloaded event listener is available for ImageMapType as well
let layer = new window.google.maps.ImageMapType({
getTileUrl: activeLayer.type === "wms" ? getTileUrl : getWMTSUrl,
tileSize: new window.google.maps.Size(256, 256),
minZoom: 0,
maxZoom: 24,
opacity: 1.0,
isPng: true,
});
map.overlayMapTypes.setAt(0, layer);
layer.addListener("tilesloaded", () => {
console.log("Overlay tiles loaded");
});

Zoom doesn't change always init value when zoomin. ol 5.3.0 with reactjs

It's a react.js project with OpenLayers 5.3.0
The map is defined in
componentDidUpdate() {
this.map = new Map({
target: this.container,
view: new View({
center: [2.5, 2.5],
projection: projection,
zoom: 2,
minZoom: 0.1,
maxZoom: 7
}),
interactions: defaultInteractions({
// dragPan: false,
keyboard: false,
// mouseWheelZoom: false,
doubleClickZoom :false
}),
layers: [graphic, this.roadLayer, this.robotLayer, this.laserLayer, this.targetLayer, this.restrictLayer, this.specialLayer]
});
view=this.map.getView();
zoom=view.getZoom();
view.on('change:resolution',function(e){
console.log('change:resolution');// dosen't work
});
view.on('change:center',function(e){
console.log('moveing');
});
this.map.on('moveend',function(e){
console.log(view);
zoom = view.getZoom();
// console.log("resolution", view.getResolution()); // Always the same
// console.log('moveend');
console.log("zoom"+zoom); // Always 2
if(view.getZoom()!==zoom)
console.log('zomeend了,change:zoom了');
});
};
The problem is when I zoomin the map, change:resolution won't be triggered and zoom would always be 2 as init value. I also tried put map.on('moveend') at like componentDidMount(), same result.
Why can't I get the current Zoom?
Is it the problem of life circle of React? Any hint would be a huge help.

GeoJSON marker is not showing on my leafletjs map

I'm writing my first larger project in react and I need to set up markers in my map component. I've set everythin up as it is shown in the tutorial however it is not working correctly with my code and the markers are not shown on map.
const dummyGeoJson = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {},
geometry: {
type: "Point",
coordinates: [16.959285736083984, 52.40472293138462]
}
}
]
};
class EventMap extends React.Component {
componentDidMount() {
this.map = L.map("map", {
center: [51.9194, 19.1451],
zoom: 6
});
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 20
}).addTo(this.map);
var geoJsonLayer = L.geoJSON().addTo(this.map);
geoJsonLayer.addData(dummyGeoJson);
}
render() {
return <Wrapper width="100%" height="800px" id="map" />;
}
}
From what i've read in official leaflet tutorial this code should create a new geojson layer and create a marker in a position referenced in geojson but actually the only thing that is shown is my tile layer.
You need to use a pointToLayer function in a GeoJSON options object when creating the GeoJSON layer like this:
componentDidMount() {
const map = L.map("map", {
center: [51.9194, 19.1451],
zoom: 6
});
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 20
}).addTo(map);
L.geoJSON(dummyGeoJson, {
pointToLayer: (feature, latlng) => {
return L.marker(latlng, { icon: customMarker });
}
}).addTo(map);
}
You can then pass a customMarker variable to define some options in order to make your marker be displayed on the UI
Demo
Welcome to SO!
The most probable reason is that you bundle your app (typically with webpack), but the build misses Leaflet default icon images.
So your Marker is there, but you cannot see it because its icon image is missing.
An easy way to debug it is to use another icon instead, as suggested in kboul's answer, or even more simply by using a CircleMarker.
Then to solve the issue of the build engine missing to process the default icon images, see Leaflet #4968:
explicitly import / require the Leaflet default icon images and modify the L.Icon.Default options to use the new imported paths
or use the leaflet-defaulticon-compatibility plugin (I am the author).

Leaflet with two switchable maps

I have two types of map tiles, and I want to be able to switch between them using layers with a custom html control. Both will have the same tilesize and the other options that I have set. The only difference is that one is located in normal map folder and the other in gridmap folder.
This is the code that I use to display one map:
var map = L.map('map', {
maxZoom: mapMaxZoom,
minZoom: mapMinZoom,
zoomControl: false,
crs: L.CRS.MySimple
}).setView([0, 0], 2);
L.tileLayer('normalmap/{z}/{x}/{y}.jpg', {
minZoom: mapMinZoom,
maxZoom: mapMaxZoom,
tileSize: 268,
noWrap: true,
tms: false,
continuousWorld: true
}).addTo(map);
I tried to follow the leaflet example: http://leafletjs.com/examples/layers-control.html
But no luck.
Can someone explain to me how to add 2 maps with a custom control?
Keep a reference to both your tile layers and add/remove them as appropiate:
var map = L.map(...);
var tilelayer1 = L.tileLayer('map1/{z}/{x}/{y}.jpg', { ... });
var tilelayer2 = L.tileLayer('map2/{z}/{x}/{y}.jpg', { ... });
tilelayer1.addTo(map);
document.getElementById('switch-layers').addEventHandler('click', function(ev){
if (map.hasLayer(tilelayer1)) {
map.addLayer(tilelayer2);
map.removeLayer(tilelayer1);
} else {
map.addLayer(tilelayer1);
map.removeLayer(tilelayer2);
}
})
Keep in mind that you can create layers and not add them to the map right away.

openlayers inside qooxdoo JS framework

i´m using the openlayers drawing example inside my mobile JS (qooxdoo) app and all works fine except that the drawing cursor is above the viewport
so I can draw but I don´t see the cursor and I can only see the drawing after I scroll down.
I have used this qooxdoo example as a base. I have also added all the css rules from the openlayers example to my qooxdoo styles.
Seems like a css position issue, but I can´t seem to find it.
Any help would be appreciated.
/**
* Loads JavaScript library which is needed for the map.
*/
_loadMapLibrary: function() {
var self = this;
var req = new qx.bom.request.Script();
var options = {
singleTile: true,
ratio: 1,
isBaseLayer: true,
wrapDateLine: true,
getURL: function() {
var center = self._map.getCenter().transform("EPSG:3857", "EPSG:4326"),
size = self._map.getSize();
return [
this.url, "&center=", center.lat, ",", center.lon, "&zoom=", self._map.getZoom(), "&size=", size.w, "x", size.h].join("");
}
};
req.onload = function() {
var vector = new OpenLayers.Layer.Vector('Vector Layer', {
styleMap: new OpenLayers.StyleMap({
temporary: OpenLayers.Util.applyDefaults({
pointRadius: 16
}, OpenLayers.Feature.Vector.style.temporary)
})
});
// OpenLayers' EditingToolbar internally creates a Navigation control, we
// want a TouchNavigation control here so we create our own editing toolbar
var toolbar = new OpenLayers.Control.Panel({
displayClass: 'olControlEditingToolbar'
});
toolbar.addControls([
// this control is just there to be able to deactivate the drawing
// tools
new OpenLayers.Control({
displayClass: 'olControlNavigation'
}), new OpenLayers.Control.ModifyFeature(vector, {
vertexRenderIntent: 'temporary',
displayClass: 'olControlModifyFeature'
}), new OpenLayers.Control.DrawFeature(vector, OpenLayers.Handler.Point, {
displayClass: 'olControlDrawFeaturePoint'
}), new OpenLayers.Control.DrawFeature(vector, OpenLayers.Handler.Path, {
displayClass: 'olControlDrawFeaturePath'
}), new OpenLayers.Control.DrawFeature(vector, OpenLayers.Handler.Polygon, {
displayClass: 'olControlDrawFeaturePolygon'
})]);
var osm = new OpenLayers.Layer.OSM();
osm.wrapDateLine = false;
map = new OpenLayers.Map({
div: 'googleMap',
projection: 'EPSG:900913',
numZoomLevels: 18,
controls: [
new OpenLayers.Control.TouchNavigation({
dragPanOptions: {
enableKinetic: true
}
}), new OpenLayers.Control.Zoom(), toolbar],
layers: [osm, vector],
center: new OpenLayers.LonLat(0, 0),
zoom: 1,
theme: null
});
// activate the first control to render the "navigation icon"
// as active
toolbar.controls[0].activate();
}
req.open("GET", this._mapUri);
req.send();
},
Please check the z-Index of the cursor's class. The best way is to modify the z-Index through Chrome's debugger console or Firebug.
Is there any live example of your application available?

Resources