I use open layers 4 and I want that Overview Map to show always a whole map in central position, only the red box should move around overview map.
Specifying a overview map view with a single resolution and extent (i.e. center constraint) will work as long as the main map isn't panned so far that the center constraint on the overview is exceeded. e.g. this will give an almost global overview
new ol.control.OverviewMap({
view: new ol.View({
resolutions: [ol.tilegrid.createXYZ().getResolution(0)],
extent: [0, 0, 0, 0]
})
})
If you are using 2180 trying to show a world overview is going to cause reprojection errors! The overview will also need to be in EPSG:2180 with resolution and center constraint appropriate for that
new ol.control.OverviewMap({
view: new ol.View({
projection: 'EPSG:2180'
resolutions: [ ?? ],
extent: [x, y, x, y]
})
})
where ?? needs to be large enough to get all of Poland (and a bit more) in the overview and x, y is somewhere in the center of Poland in EPSG:2180 coordinates.
Related
I tried to draw a polyLine (road lane) with width in meters using the latest stable OpenLayers library, but it didn't have the correct real width (checked on top of Google Maps layer).
This is the code snippet that works for me:
polyLineFeature.setStyle((feature, resolution) => {
const lineString = feature.getGeometry();
const lineStyles = [
new Style({
stroke: new Stroke({
width:
laneWidth /
resolution /
getPointResolution("EPSG:3857", 1, lineString.getCoordinateAt(0.5)),
lineCap: "square",
}),
}),
];
return lineStyles;
});
I use the default projection everywhere (web mercator).
But I don't get the reason why do I have to divide the real width in meters by the current resolution AND another resolution that is relevant within the actual area.
Is this explained anywhere?
WebMercator 3857 is a bad projection with respect to distances. It introduces a huge distortion as you move away from the equator (that's why Greenland looks so big on the map while in reality it is a fairly small piece of land).
By dividing the width by getPointResolution, you are effectively correcting this distortion.
If you were using another projection that preserve distances, such as UTM, you wouldn't have to do this division (or, if you did, the value of getPointResolution would be 1)
I'm creating a feature of removing points from openlayers polygons when drawing. So there is my "configuration":
source = new ol.source.Vector({
wrapX: false,
});
raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
vector = new ol.layer.Vector({
source: source,
style: new ol.style.Style(/* some config */)
});
view = new ol.View({
center: defaultLonLatFormat,
zoom: 12
});
mapx = new ol.Map({
layers: [raster, vector],
target: 'target',
view: view
});
Code used to start drawing:
draw = new ol.interaction.Draw({
source: source,
type: 'Polygon',
});
mapx.addInteraction(draw);
Code used to remove last point:
draw.removeLastPoint();
draw.changed();
Everything works like a charm until polygon is open - until I connect last point with first point. After that removing last point makes nothing. Fortunatelly I can delete points with alt + click - it works until there is 3 points left which makes minimal closed polygon - triangle. Then even alt + click combination doesn't work. I've even tried this on OpenLayers examples - this same behaviour. So I've got three questions:
What happens after closing polygon, so I can't delete points with draw.removeLastPoint()?
Why I'm unable to delete last three points from polygon?
Any ideas how to achieve such functionality?
After the drawing is finished, the sketch is added to the target layer, and also removed from the draw interaction, so if you want to access it, you need to call
source.getFeatures();
any draw interaction functions do no longer have effect on it.
As written here, Polygon is:
Array of linear rings that define the polygon. The first linear ring of the array defines the outer-boundary or surface of the polygon. Each subsequent linear ring defines a hole in the surface of the polygon. A linear ring is an array of vertices' coordinates where the first coordinate and the last are equivalent.
Technically, when the outer boundary is not a linear ring it is not a valid polygon. When you have less than three coordinates, it is more of a line.
You can check the number of points in the polygon geometry and when trying to delete the third point, change the geometry to line (or more preciesly to LineString), and when deleting the second point change it to point.
I am trying to generate a custom non-geographical map with Leaflet using my own tiles.
For the moment I created 10x10 dummy tiles of size 256x256px each with a random solid color using imagemagick.
They are placed in public/map-tiles/1/map_x_y.png where x takes values from 0 to 9 (resp. y).
Since this is a non-geographical map, I paid attention to change crs to L.CRS.Simple (see http://leafletjs.com/examples/crs-simple/crs-simple.html):
var map = L.map('map', {
minZoom: 1,
maxZoom: 1,
center: [0, 0],
crs: L.CRS.Simple
}).setView([0, 0], 1);
L.tileLayer('/map-tiles/{z}/map_{x}_{y}.png', {
bounds: [[0, 0], [2560, 2560]],
tms: true
}).addTo(map);
However this produces tiles slightly shifted and thus misaligned:
Also, tiles with negative y coordinates are fetched, which results in 404d requests, as seen in the console.
What can be the cause of this behavior?
EDIT 1: as IvanSanchez pointed out, the misalignment was caused by the missing leaflet.css stylesheet.
I still have the problem with negative coordinates. As suggested, I added bounds (see updated code above). Observations:
with bounds [[0, 0], [2560, 2560]]: no tiles displayed altogether, blank screen.
with bounds [[-1280, -1280], [1280, 1280]]: all tiles displayed, but negative tiles fetched (eg (5,-1)) resulting in 404s.
EDIT 2: after several tests it looks like the negative tiles are indeed the product of the y-axis handling (http://leafletjs.com/examples/wms/wms.html). The origin is top left, y going downward. I expected the tiles below the origin to be fetched, not above.
What I tried in order to keep my convention with x and y both increasing (that is x increases to the right, y increases downward, tiles with positive coordinate components are fetched from 0 to 9):
setting tms: true for tileLayer. No success, tiles with negative y are still fetched .
changing {y} to {-y} in the tileLayer source path. Results in Error: No value provided for variable {-y}. My script is using Leaflet 1.3.1.
In a map with L.CRS.Simple, all TileLayers have infinite bounds by default.
If you want a TileLayer to request tiles only in a given area, read the Leaflet API documentation, specifically a TileLayer option named bounds (inherited from GridLayer options). Let me quote:
bounds
type LatLngBounds
default undefined
If set, tiles will only be loaded inside the set LatLngBounds.
You also mention:
Weirdly enough, it tries to fetch tiles with negative coordinates [...]
That's not weird, it's behaviour as designed. There is nothing inherently wrong (nor weird) with negative coordinates, and negative tile coordinates are valid and documented in some tile standards
So if you have 10x10 tiles of 256px in size ranging from [0, 0] to [10, 10], you might want something like
L.tileLayer('/map-tiles/map_{x}_{y}.png', {
bounds: [[0, 0], [2560, 2560]]
}).addTo(map);
If the center of your data is the [0, 0] point and your tiles span from [-5, -5] to [5, 5] you might instead want something like
L.tileLayer('/map-tiles/map_{x}_{y}.png', {
bounds: [[-1280, -1280], [1280, 1280]]
}).addTo(map);
The problem boils down to two aspects:
misalignment: the leaflet.css stylesheet was missing and simply needed to be linked to in the HTML of the page.
negative tiles fetched: for Leaflet the y-axis goes downward. I expected tiles to be fetched from left to right, top to bottom with an origin set to the top left corner. Instead, negative y's were fetched. Since my tiles' names are map_x_y.png where x and y take values in {0:9}, this resulted in 404d requests. Setting negative bounds fixed the issue with bounds: [[0,0],[-1230,1230]] (notice the minus sign). 1230 corresponds to the number of tiles at zoom 0 times the size in pixel of one tile.
I wonder how to make a google map not to leave world bounds, like on google maps site itself.
I am using javascript google map api v3, here is my map options:
mapOptions = {
center: new google.maps.LatLng(20, 0),
zoom: 3,
minZoom: 3,
zoomControl: true,
I've restricted map zoom, but user still can drag out of world bounds and even select region there.
How can I prevent this behavior?
You have to make a general check using some conditional statement like if...else and comparing if the current Lat/Lng is falling out of a specified boundary (which is a world bound in your case).
I would recommend you to look at this SO question that may provide you some leads of how to proceed.
Found a nice solution I'd like to share:
if (!allowedBounds.intersects(map.getBounds())) {
map.panToBounds(allowedBounds);
}
it will return to the initial set bounds (minimum way) when the whole screen left the bounds.
Is it possible to have intermediate (2.5, 3.5, 4.5, etc.) zoom levels on a Leaflet map that is using Stamen Toner-lite tiles? This is the code I have so far that calculates the zoom level:
leafletmap.on('zoomstart', function (d){
targetZoom = leafletmap.getZoom(); //Grabs whatever current zoom level is
targetZoom = targetZoom +.5; //Adds .5
leafletmap.setZoom(targetZoom); //Sets new value to zoom level
console.log(targetZoom); //Consoles out new value
});
I tried just adding .5 to the code, but I get a too much recursion error, so I'm guessing it's not that simple. Any help or direction is greatly appreciated!
In version 1.0.0, Leaflet introduced fractional zooming:
https://leafletjs.com/examples/zoom-levels/#fractional-zoom
Before this, the zoom level of the map could be only an integer number
(0, 1, 2, and so on); but now you can use fractional numbers like 1.5
or 1.25.
...
If you set the value of zoomSnap to 0.5, the valid zoom levels of the
map will be 0, 0.5, 1, 1.5, 2, and so on.
If you set a value of 0.1, the valid zoom levels of the map will be 0,
0.1, 0.2, 0.3, 0.4, and so on.
The following example uses a zoomSnap value of 0.25:
var map = L.map('map', {
zoomSnap: 0.25
});
As you can see, Leaflet will only load the tiles for zoom levels 0 or
1, and will scale them as needed.
Leaflet will snap the zoom level to the closest valid one. For
example, if you have zoomSnap: 0.25 and you try to do
map.setZoom(0.8), the zoom will snap back to 0.75. The same happens
with map.fitBounds(bounds), or when ending a pinch-zoom gesture on a
touchscreen.
To be straight to the point: This is not possible. You would need to render your own tile-images, run them of your own server and create your own coordinate reference system (CRS) extension for Leaflet. If you look at how regular tilesets are made you'll understand why.
The URL for requesting tiles for stamen:
http://{s}.tile.stamen.com/toner/{z}/{x}/{y}.png
When requesting tiles, the {z} will be replaced with the map's current zoomlevel. The {x} and {y} are the coordinates for the tile. The {s} will be replaced with a subdomain. So if your at zoomlevel 6 at coordinate 1,1 it would try to load:
http://a.tile.stamen.com/toner/6/1/1.png
Now if you could (but you can't) zoom to level 6.5 it would try to load:
http://a.tile.stamen.com/toner/6.5/1/1.png
Those tiles simple don't exists on the stamen server and thus return a 404 for file not found. You can try for yourself just use these links:
http://a.tile.stamen.com/toner/6/1/1.png
http://a.tile.stamen.com/toner/6.5/1/1.png
http://a.tile.stamen.com/toner/7/1/1.png
So that will never work. You could, as said, run your own tile server, render your own tile images and setup your own L.CRS. You might want to take a look at this question too: Adding an extra zoom levels in Leaflet Maps