leaflet map grey screen for geoJSON Layer - leaflet

Wondering if anyone can help, it's a bit of a strange one. My leaflet map works in isolation, but when added to some existing code the geoJSON (world-map.geojson) appears not to be added to a layer, I just get a grey screen with the leaflet map controls. However, when the leaflet.css is commented out you can see the geoJSON layer has been added... I get no errors and If I comment out references to other JS files it makes no difference.
As this appears to be conflict of sorts i'm not expected a hard and fast answer, but if anyone has come across this before or could suggest any pointers it would be much appreciated.
HTML
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.0.3/dist/leaflet.css">
<script type="text/javascript" src="leaflet.js"></script>
<script type="text/javascript" src="world-map.geojson"></script>
<style type="text/css">
#map {
height: 600px;
width: 100%;
}
</style>
<div id="map"></div>
<script src="map.js"></script>
JS - stripped right back
var geojson,
layer,
map = L.map('map').setView([43.8476, 18.3564],3);
// style each continent
function countriesStyle(feature) {
return {
fillColor: "#FED976",
weight: 1,
opacity: 1,
color: "white",
dashArray: 1,
fillOpacity: 0.7
};
}
// add layer
geojson = L.geoJson(countries, {
style: countriesStyle,
maxZoom: 2,
minZoom: 2
}).addTo(map);
// works. countries var is in the DOM
for(var i = 0; i < countries.features.length; i++) {
console.log(countries.features[i].properties.name)
}

Related

Leaflet polygon precision loss on zoom out

I'm creating multipolygon using geojson data.
While zooming in/out the precision of the polygon fades, the corner points move.
Any suggestion how i can make the polygon more precise when zoomed out?
This is how my current code looks. I went through the documentation and tried multiple things including smoothFactor, but nothing seems to have a effect.
I'm kinda stuck now and need your help.
var map = L.map('map', {
zoomControl: false,
zoomSnap: 0.0,
scrollWheelZoom: true,
keyboard: false,
dragging: false,
boxZoom: false,
doubleClickZoom: false,
tap: false,
touchZoom: false,
maxNativeZoom: 1,
animate: false,
easeLinearity: 0
});
paths =
[[[[6.858829796182704, 46.95251393022377],
[6.858822143959083, 46.95252165923424],
[6.858803353389316, 46.95251293626237],
[6.858811005614312, 46.952505207253175],
[6.858829796182704, 46.95251393022377]]],
[[[6.858817924471068, 46.95249692043298],
[6.858810272248277, 46.95250464944266],
[6.858791481686369, 46.95249592646894],
[6.858799133910535, 46.95248819746051],
[6.858817924471068, 46.95249692043298]]],
[[[6.858837595845731, 46.95250605229153],
[6.8588299436243805, 46.952513781302564],
[6.858811153056015, 46.95250505833199],
[6.858818805278741, 46.95249732932224],
[6.858837595845731, 46.95250605229153]]]]
geojsonLayer = L.polygon(paths, {
smoothFactor: 0.0,
color: "grey",
weight: 1,
opacity: 1,
fillColor: "white",
fillOpacity: 1,
})
geojsonLayer.addTo(map);
geojsonLayer.smoothFactor = 0.0
console.log(geojsonLayer.getBounds())
map.setZoom(24.851706204825632)
console.log(map.getZoom())
var latlng = L.latLng(6.858817924471068, 46.95249692043298);
map.panTo(latlng)
map.zoomSnap
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css">
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<style>
body {
padding: 0;
margin: 0;
}
html, body, #map {
height: 1000px;
width: 1000px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div id="map"></div>
</body>
</html>

Leaflet .png image-map with flipped coordinates?

i have a 4096x4096px .png that represents 15000x15000m. With this code it will be displayed perfectly the way I want it and I could also determine the pixel positions (0/0 top left corner):
<head>
<link rel="stylesheet" href="scripts/leaflet.css"></script>
<style>
#image-map {
width: 1024px;
height: 1024px;
border: 1px solid #ccc;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div id="image-map"></div>
<script src="scripts/leaflet.js"></script>
<script>
// Using leaflet.js to pan and zoom a big image.
// See also: http://kempe.net/blog/2014/06/14/leaflet-pan-zoom-image.html
// create the slippy map
var map = L.map('image-map', {
minZoom: -1,
maxZoom: 2,
center: [0, 0],
zoom: -1,
crs: L.CRS.Simple
});
// dimensions of the image
var w = 4096,
h = 4096,
url = 'images/Bild.png';
// calculate the edges of the image, in coordinate space
var southWest = map.unproject([0, h], map.getMaxZoom()-1);
var northEast = map.unproject([w, 0], map.getMaxZoom()-1);
var bounds = new L.LatLngBounds(southWest, northEast);
// add the image overlay,
// so that it covers the entire map
L.imageOverlay(url, bounds).addTo(map);
// tell leaflet that the map is exactly as big as the image
map.setMaxBounds(bounds);
</script>
</body>
But I don't want the pixel position, i want to get coordinates with a mouse click (0-point in the middle of the graphic). The limits are upper left corner + 7500 / + 7500, lower right corner -7500 / -7500 (and +/- lower left, -/+ upper right) I'm a beginner and I have no idea how to do this. Many of the questions here have similar problems, but I couldn't transfer them to my scenario.
Thanks for your help
EDIT: I have now worked my way towards this code. However, this does not take into account the limits of the overlay and the display is not as good in the example above. You can also read in the XY values outside, cause the picture no longer slides back to the map. The coordinates are ok for that - but they should point in the other direction. How can this be solved? I also think I'm making a mistake with crs: L.CRS.Simple, but when I remove it the graphic is only shown as a narrow strip in the map.
<html>
<head>
<link rel="stylesheet" href="scripts/leaflet.css">
<style>
#map {
width: 1024px;
height: 1024px;
border: 1px solid #ccc;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="scripts/leaflet.js"></script>
<script>
var map = L.map('map', {
minZoom: -3,
maxZoom: 0,
center: [0, 0],
zoom: -3,
crs: L.CRS.Simple
});
url = 'images/Bild.png';
L.imageOverlay(url, [
[4096, -4096],
[-4096, 4096]
]).addTo(map);
var popup = L.popup();
map.on("click", function(e) {
popup
.setLatLng(e.latlng)
.setContent('<p>Lng (x): '+e.latlng.lng+' / Lat (y): '+e.latlng.lat+'</p>')
.openOn(map);
});
</script>
</body>
</html>

How can I create a basic map in LeafLet?

I´m starting to use Leaflet and there´s many things that I would like to know.
During my study I found this interesting video (https://www.youtube.com/watch?v=wnsEYm9hF0o&list=PLGHe6Moaz52PUNP4DtIshALDogSURIlYB)
and I followed the instructions, using sublime text, but my result is different as you can see bellow. My map does not appear.
My code is:
The result (From the video)
My result was:
HTML code:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet.js"></script>
<style>
#map {position: absolute; top: 0; bottom: 0;not left: 0; right: 0;}
</style>
</head>
<body>
<div id= "map"></div>
<script>
var map = L.map('map').setView ([0, 0], 1)
l.tileLayer('https://api.maptiler.com/maps/streets/{z}/{x}/{y}.png?key=mji5GJMMFmiwn83UOmBb', {
attribution:'© MapTiler © OpenStreetMap contributors',
}).adsTo(map);
</script>
</body>
</html>
In order to make your map visible, you have to make sure the map container has a defined height. For example, in CSS, you can do:
#map {
min-height: 80vh;
}
Then, you have to set the map view to your chosen geographical coordinates and a zoom level:
var map = L.map('map').setView([latitude, longitude], zoom level);
Finally when you add the tile layer to the map, you made two typos, you must write:
L.tileLayer instead of l.tileLayer
addTo instead of adsTo.
It should work like that.

Measuring drawn line length with turf.js and mapbox

I'm trying to build out the functionality to measure a line that a user draws over a Mapbox map, using turf.js 'length' feature.
That said, I'm a coding newb - I know just barely enough to be dangerous.
Ultimately I'd like to be able to draw both areas and lines, and have their respective measures returned (area for polygons, lengths for line strings).
Can anyone offer insight as to why this code doesn't work?
https://jsfiddle.net/knxwu342
<html>
<head>
<meta charset=utf-8 />
<title>Line Test</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
.calculation-box-length {
height: 75px;
width: 100px;
position: absolute;
bottom: 40px;
left: 10px;
background-color: rgba(255, 255, 255, .9);
padding: 15px;
text-align: center;
}
</style>
<script src='https://api.tiles.mapbox.com/mapbox.js/plugins/turf/v3.0.11/turf.min.js'>
</script>
<script src='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.0.9/mapbox-gl-draw.js'></script>
<link rel='stylesheet' href='https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-draw/v1.0.9/mapbox-gl-draw.css' type='text/css'/>
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.45.0/mapbox-gl.js'>
</script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.45.0/mapbox-gl.css' rel='stylesheet' />
</head>
<body>
<div id='map'></div>
<div class='calculation-box-length'>
<p>Length:</p>
<div id='calculated-length'></div>
</div>
<nav id="menu"></nav>
<script>mapboxgl.accessToken = 'pk.eyJ1IjoibWJsYWNrbGluIiwiYSI6ImNqaWMxcGk2MzAwd3YzbG1oeW4yOHppdnYifQ.xdb-2slu5LapzpuMCiKzQQ';
//*********-----------------------------------------------------------------------------------------------------------------**********
//Create new map object
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mblacklin/cjii8o7w91g9o2stcktaeixai', // stylesheet location
center: [-117.572737, 51.746916], // starting position [lng, lat]
zoom: 16 // starting zoom
});
//*********-----------------------------------------------------------------------------------------------------------------**********
// Add navigation controls to the map
map.addControl(new mapboxgl.NavigationControl());
//*********-----------------------------------------------------------------------------------------------------------------**********
// Add the ability to draw geometries and display their measurements
//
var draw = new MapboxDraw({
displayControlsDefault: false,
controls: {
line_string: true,
polygon: true,
trash: true
}
});
map.addControl(draw);
map.on('draw.create.', updateLength);
map.on('draw.delete', updateLength);
map.on('draw.update', updateLength);
function updateLength(e) {
var data = draw.getAll();
var answer = document.getElementById('calculated-length');
if (data.features.length > 0) {
var length = turf.length(data);
// restrict to area to 2 decimal points
answer.innerHTML = '<p><strong>' + length + '</strong></p><p> meters</p>';
} else {
answer.innerHTML = '';
if (e.type !== 'draw.delete') alert("Use the draw tools in the upper right to calculate a distance");
}
};
//
//*********-----------------------------------------------------------------------------------------------------------------**********
</script>
</body>
</html>
I see two little problems in your code:
There is a typo in your 'draw.create' listener. Just remove the point after create:
map.on('draw.create', updateLength);
The version of Turf you are using is too old and does not seem to have the length function. Try using the most recent one: https://npmcdn.com/#turf/turf/turf.min.js

Mapbox GL JS: Change a map's style without hiding map layer?

I am using Mapbox GL JS and I would like to allow users to change a map's background style from streets to satellite, while showing a polygon layer above the map background.
I have adapted the Mapbox example, but I can't work out how to stop map.setStyle from setting the new style above (and thus hiding) my polygon layer. I would like it to change without hiding the polygon layer.
Before switching layers:
After switching layers - polygon overlay missing, would like to carry on showing it:
This is my code in full:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title></title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.33.1/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.33.1/mapbox-gl.css' rel='stylesheet' />
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
</style>
</head>
<body>
<style>
#menu {
position: absolute;
background: #fff;
padding: 10px;
font-family: 'Open Sans', sans-serif;
}
</style>
<div id='map'></div>
<div id='menu'>
<input id='basic' type='radio' name='rtoggle' value='basic' checked='checked'>
<label for='basic'>basic</label>
<input id='satellite' type='radio' name='rtoggle' value='satellite'>
<label for='satellite'>satellite</label>
</div>
<script>
mapboxgl.accessToken = 'pk.eyTOKEN';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/basic-v9',
zoom: 5,
center: [-3.0, 54.6]
});
map.on('load', function () {
map.addSource('xxx', {
type: 'vector',
url: 'mapbox://xxx.xxx'
});
map.addLayer({
'id': 'xxx',
'source': 'xxx',
'type': 'fill',
'paint': {
'fill-color': 'red'
},
'source-layer': mylayer
}, 'road'); // Note that I'd like this to display above the OSM 'roads' layer
var layerList = document.getElementById('menu');
var inputs = layerList.getElementsByTagName('input');
function switchLayer(layer) {
var layerId = layer.target.id;
map.setStyle('mapbox://styles/mapbox/' + layerId + '-v9');
}
for (var i = 0; i < inputs.length; i++) {
inputs[i].onclick = switchLayer;
}
});
</script>
</body>
</html>
Mapbox GL JS does not have the concept of a "base layer" and "overlays." All layers of all maps are drawn with the same basic primitives.
If you need to persist one or more custom layers while switching between the provided Mapbox styles, you may choose to
fork the Mapbox style and add your custom layers in Studio
re-add your custom layers after switching styles
download the Mapbox style as JSON in the browser and add your custom layers to the style in the browser