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.
Related
I have a leaflet map with a few layers on it.
Whenever layers are not in the viewport, they are hidden untill panning has completed:
Regular view with layers:
Panning right, to show layers outside viewport:
Panning stopped:
As illustrated above, the layers will first become visible once panning has stopped and mouse(finger) released.
I have tried the following, which didn't work
var map = L.map('map',{ bounceAtZoomLimits: false, removeOutsideVisibleBounds: false}).setView([40, 0], 2);
L.geoJson(mapData).addTo(map);
Seems the solution was right in front of me
Adding the following will render the entire map:
var map = new L.Map('map');
map.getRenderer(map).options.padding = 100;
Solution found here
So I tried to draw grid line on my map and I found a good example on google api documentation here : https://developers.google.com/maps/documentation/javascript/examples/maptype-base
it works , now I have another problem in every area or rectangle which built by grid line, I want them to have a listener on click event and then zoom to area that has been clicked. I have tried like this
google.maps.event.addListener(map, "click", function (e) {
var latLng = e.latLng;
map.setCenter(new google.maps.LatLng(latLng.lat(), latLng.lng()));
map.setZoom(17);
});
it works either, but as you can see the latitude and longitude are the exact location where the cursor / pointer clicked, it's not in the middle of the rectangle or area it means the map after zoomed in is wrong. Could anyone help me with this?
I think the problem is because you are using the overlay(as your grid line), when using the tile overlay Google Maps API breaks up the imagery at each zoom level into a set of square map tiles arranged in a grid. When a map moves to a new location, or to a new zoom level, the Maps API determines which tiles are needed and translates that information into a set of tiles to retrieve.
For example each zoom level increases the magnification by a factor of two. So, at zoom level 1 the map will be rendered as a 2x2 grid of tiles. At zoom level 2, it's a 4x4 grid. At zoom level 3, it's an 8x8 grid, and so on.
So when you zoom in, the coordinates that you click is not always in the middle because tile overlay is not set because of your coordinate.
Check this page for more information about overlay.
You can also check this SO question for more information.
I'm currently using Mapnik to create choropleth tiles of regions in Brazil via node-mapnik by using the g.connector from Wax as in the code below and it works well.
var map = new google.maps.Map(document.getElementById('map-canvas'), {
center: new google.maps.LatLng(-23.1851, -51.0754),
zoom: 8,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL
},
mapTypeId: google.maps.MapTypeId.HYBRID
});
var tiles = {
tilejson: '2.0.0',
tiles: ['url/{z}/{x}/{y}.png']
};
map.overlayMapTypes.insertAt(0, new wax.g.connector(tiles));
But I've noticed, using Chrome developer tools, that Google maps is sending two separate pngs per x, y, z tile back (one a 512x512 vt png with roads and labels and the second a 256x256 kh png of the ground).
Using Wax or other JavaScript tools, is it possible to insert the PNG I'm getting back from Mapnik between the two Google map pngs? My goal is to get the labels to be on top of the images returned by Mapnik. This can certainly be accomplished by changing the opacity of the Mapnik tiles, but the colors don't stand out nearly as well when opacity is reduced. Any help is greatly appreciated.
Looks like it's not currently supported.
If you look at the actual html - the two satellite image layers are in a nested div with a z-index, and the overlay is in a separate div with a different z-index. I believe it's not possible to for a separate div to be nested inside two different z-index's of a different div, aka, this doesn't work:
<div style:"z-index: 5"></div>
<div>
<div style:"z-index: 1"></div>
<div style:"z-index: 10"></div>
</div>
For a single tile, it is possible to detach it from the overlay div, and re-attach it to the map tile div, and assign z-indexes to all three images, but it doesn't seem very practical.
At the moment, there are a number of open requests to add this as a feature to google maps, but nothing exists.
Here's and idea for an alternate approach - enable your google map without the road layer (search for google map style wizard), and render the road layer onto your tiles using mapnik from openStreetMap data.
I have managed to modify a script I found to suite my needs.
my only current issue is that I have to set the center of the map manually in the code and the zoom level.
how can I modify this so the api automatically selects the correct zoom level and center point for the map.
fiddle is here
I need to remove this manual code:
var map = new google.maps.Map(document.getElementById("map"), {
center: new google.maps.LatLng(-30.559, 22.937),
zoom: 4
}),
and configure it to zoom and center automatically based on the routes given (routes array)
you will see in the fiddle that the costa rica route is off the map so zoom needs to go out. if it was a short trip then zoom in to fit all contents into the map
Thanks as always:
You cannot get rid of that code. Option center and zoom are the only required parameters of google.maps.MapOptions object. See docs of MapOptions.
You can get rid of option preserveViewport or set it to false instead of true so your map will be centered and properly zoomed.
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!