I added an image to my map (image overlay). Can I "adjust" the zoom levels due to the image?
At zoomlevel 17, the resolution of the raster map is too low compared to the screen resolution. At zoomlevel 16, the raster map isn't readable anymore.
Is it possible to define something like "zoomlevel 17: 1px of the image = 1px of the screen"?
Please excuse my bumpy English.
Thank you very much!
var map = L.map('image-map', {
minZoom: 16,
maxZoom: 18,
}).setView([46.975768, 7.436308], 17);
var imageUrl = '../Bilder/Karten/Normalansicht.png',
imageBounds = [[46.966635, 7.415942], [46.998849, 7.470108]];
L.imageOverlay(imageUrl, imageBounds).addTo(map);
map.setMaxBounds(imageBounds);
Is it possible to define something like "zoomlevel 17: 1px of the
image = 1px of the screen"?
No.
What you can do, however, is use CRS.Simple. In this coordinate system, 1 map unit = 1px at zoom level 0. You'll have to adjust the image overlay coordinates to achieve the screen resolution/image resolution ratio you want.
Check the tutorial on CRS.Simple at http://leafletjs.com/examples/crs-simple/crs-simple.html
Another option is to use fractional zoom controls (available only in Leaflet 1.0.0-beta, not in the 0.7.x series). By setting the zoomSnap and zoomDelta options, the user will be able to set zoom levels e.g. 16.25, 16.5 and 16.75.
There is no tutorial for this, but you can check some test code at https://github.com/Leaflet/Leaflet/blob/master/debug/map/zoom-delta.html
Related
I have a Leaflet map that points to some offline tiles on a local machine. Initially, tiles that aren't found are shown as a grey image:
If the user then zooms out, the corresponding tiles will be fetched for the current zoom level as usual. However, when the user zooms back in, the old "zoomed out" tiles persist, so you end up with a blurry image outside the bounds of the current tiles:
Is there some way to delete these tiles or just not load tiles for which there is no data in the first place?
Here's what I currently have:
L.tileLayer("offline_map/{z}/{x}/{y}.png",{
maxZoom: 18,
minZoom: 3,
}).addTo(map);
L.TileLayer.include({
_tileOnError: function (done, tile, e) {
map.removeLayer(tile);
}
});
Since you seem to be caching a small rectangular area, you probably want to use the bounds option of L.TileLayer, e.g.:
L.tileLayer("offline_map/{z}/{x}/{y}.png",{
maxZoom: 18,
minZoom: 3,
bounds: L.latLngBounds([[50,10],[60,15]])
}).addTo(map);
Specifying such a bounds option will avoid loading tiles outside of that bounding box (instead of trying and then failing), and will change the way tiles are pruned when changing zoom levels.
In Mapbox, the fitBounds method doesn't seem to play nicely with points that are on both sides of the Atlantic (where the coords jump from 359 to 0).
How is it possible fit the bounds of Alaska or a flight from HK to SF. It might be possible to code a workaround making use of a center point and a custom zoom-level but it feel like a overengineered workaround around a poor handling of the bounds.
If firBounds is no help, is there another method like that would achieve similar results?
Example of fitBounds around Alaska, since Alaska crosses the antimeridian:
map.fitBounds([[172.461667,71.365162],[-129.979511,51.214183]])
Those cases are always a bit of a pain. What may help is wrapping your bounding box coordinates using:
https://www.mapbox.com/mapbox-gl-js/api/#lnglat#wrap
Another solution might be to convert the bounds to a center & zoom value using:
https://github.com/mapbox/geo-viewport
const {width, height} = map.getCanvas().getBoundingClientRect();
const viewport = geoViewport(
[minX, minY, maxX, maxY], // the bounding box (west, south, east north)
[width, height], // map dimensions in pixel
0, // minzoom
22, // maxzoom
512 // tilesize for mapbox-gl-js
);
map.setCenter(viewport.center);
map.setZoom(viewport.zoom)
I'm just getting started creating a Leaflet webapp and I'm failing to draw a rectangle. When I load the page it shows for a split second, barely before the map even loads, and then it disappears (That's in Chrome, in Firefox it doesn't show at all). What am I missing here?
Below is my code:
<script>
var bounds = [[52.42, 4.78], [52.46, 4.88]];
var map = L.map('map', {
maxBounds: bounds,
minZoom: 14
}).setView([52.44, 4.83], 14);
var googleLayer = new L.Google('ROADMAP');
map.addLayer(googleLayer);
$(document).ready(function() {
L.rectangle(bounds, {color: "red", weight: 1}).addTo(map);
});
</script>
I tried drawing the rectangle at the $(document).ready() event but that didn't work.
The rectangle is hidden because the google layer gets drawn on top. Might be a bug, I would expect the layers to be in the z-order in which they get added. Quick fix (check for side effects) is to force the needed order using CSS styles such as these:
.leaflet-google-layer{
z-index: 0 !important;
}
.leaflet-map-pane{
z-index: 100;
}
I am working on leaflet for the very first time and facing the issue with drawing circles and editing (changing location of circle).
The problems I am facing are :-
Editing (moving) circle from one location to another changes its radius.
Note: Pls try to create circle on top of map in given fiddle and then move it to the bottom by clicking edit button.
If I create circle on top section of map it works fine. But If I create circle on bottom of map it only prints a single DOT on map.
I checked few examples and it works fine everywhere.
Here is the working example where circle creation and moving circle is completely fine.
I am not using the geographic map like google maps. I am using and static image as it is my project requirement.
Here is the fiddle of my code.
Just using following code to enable drawing circle :
enabled : this.options.circle,
handler : new L.Draw.Circle(map,this.options.circle),
title : L.drawLocal.draw.toolbar.buttons.circle
What you're seeing is distortion in distance inherent in the mercator projection (and the Google Mercator projection based off it that is inherent to most online maps). Because your map starts at zoom 1, dragging the circle marker north/south will cause a lot of distortion.
So, rather than georeference your image to a global bounding box, try georeferencing it to something much smaller. In your case, your are adding your image overlay relative to the maxZoom, so by increasing maxZoom, your image will be overlayed over a smaller area of the globe, and you will see less (or no) distortions across latitudes.
I changed the maxZoom from 4 to 14, and the result looked like it worked well: fiddle here:
var w = 553, h = 329, url = 'https://kathleenmillar.files.wordpress.com/2012/10/picture2.png';
var map = L.map('map', {
minZoom : 10,
maxZoom : 14,
center : [ w / 2, h / 2 ],
zoom : 11,
crs : L.CRS.Simple
});
// calculate the edges of the image, in coordinate space
var southWest = map.unproject([ 0, h ], map.getMaxZoom() - 3);
var northEast = map.unproject([ w, 0 ], map.getMaxZoom() - 3);
var bounds = new L.LatLngBounds(southWest, northEast);
I have a square image 16384x16384 that has been sliced into tiles using MapTiler to create 6 levels of zoom in Leaflet.
I have set up the image in Leaflet as follows:
var map = L.map('map', {
maxZoom: 6,
minZoom: 0,
}).setView([0, 0],1);
var tilesURL = "_server/tiles/{z}/{x}/{y}.jpg";
L.tileLayer(tilesURL, {
maxZoom: 6,
continuousWorld: 'false',
tms: true
}).addTo(map);
How would I either:
Restrict the view of this large square image to just the middle (landscape rectangle) area?
Produce a non-square rectangular set of tiles?
Additionally, can Leaflet auto-fit the bounded area to the Map container?
Yes. Use the maxBounds option.
No idea, but why do you want to do such a thing?
Yes: the method fitBounds does that.
Couldn't edit #L. Sanna code since the queue is full but I would like to contribute with an example on how to use maxBounds for the first question.
I am using Leaflet 1.7.1 on Angular
Note:
maxBounds() accepts latLngBounds data type as an argument. In my case I used a tuple holding the two coordinates.
maxboundViscosity() accepts a value between 0.0-1.0 that will control how solid the bounds are when dragging the map out of bounds. Value on 1 will prevent any out of bounds areas from showing.
Tip: Adjust you minZoom to have the view not show any out of bound areas.
this.map = L.map('map', {
maxBounds: [[-90, -260],[90, 260]],
maxBoundsViscosity: 1,
center: [39.8282, -98.5795],
zoom: 5,
zoomSnap: 0.15 // enables fractional zooms
});
Happy coding!