My app needs to show a map within a box defined by
const corner1 = L.latLng(5.21244812011719, -96.5979537963867);
const corner2 = L.latLng(34.086555480957, -55.4220504760742);
const map = L.map(el,
{
crs: L.CRS.EPSG4326,
center: [19.6875, -76.201171875],
zoom: 3.5,
maxBounds: new L.latLngBounds(corner1, corner2),
});
L.tileLayer.wms("http://localhost:8080/wms?", {
layers: 'xxx',
tileSize: 700,
transparent: true,
maxBounds: new L.latLngBounds(corner1, corner2),
bounds: new L.latLngBounds(corner1, corner2)
}).addTo(map)
The thing is that the layer is requesting the tiles starting outside the borders defined (for example, this request was made http://localhost:8080/wms?&service=WMS&request=GetMap&layers=Mano%3AT22&styles=&format=image%2Fjpeg&transparent=true&version=1.1.1&maxBounds=%5Bobject%20Object%5D&time=2018-05-02T00%3A00%3A00.000Z&width=700&height=700&srs=EPSG%3A4326&bbox=-87.71484375,28.4765625,-56.953125,59.23828125 the bbox was -87.71484375, 28.4765625, -56.953125, 59.23828125, this contains the corners defined by me but is not optimal as it is requesting a map area that is not going to be seen on my app)
I need that leaflet request tiles that do not exceed the corners defined. How can I archieve that? Thanks in advance
Related
I have an application in which I use mapbox.js to load basemap tiles for a location. Then user can load WMS tiles from a WMS server, of size 256X256 which get loaded on top of the basemap.
I am using mapbox and leaflet to display map as follow:
window.map = L.map('map', { 'minZoom': minZoomLevel(), 'maxZoom': maxZoomLevel(), reuseTiles: true, unloadInvisibleTiles: true }).setView(["35.7804", "-78.6391"], 17)
Then I am using Leaflet, to send requests to my server, and from there send request to WMS server to load tiles using this:
wms = L.tileLayer.wms('/viewers/wms', {
minZoom: 12,
maxZoom: 25,
layers: 'some layer name',
format: 'image/png',
updateWhenIdle: false,
transparent: true,
reuseTiles: true,
showTheRasterReturned: true,
COVERAGE_CQL_FILTER: 'featureId=\'' + featureId + '\''
});
By the time the request reaches my server, a BBOX attribute is added automatically by leaflet which has different co-ordinates (I think it is taking full viewport) i.e.
Started GET
"/viewers/wms?SERVICE=WMS&REQUEST=GetMap&VERSION=1.1.1&LAYERS=some
layer
name&STYLES=&FORMAT=image%2Fpng&TRANSPARENT=true&HEIGHT=256&WIDTH=256&REUSETILES=true&SHOWTHERASTERRETURNED=true&COVERAGE_CQL_FILTER=featureId%3D%279d3a23cba90680cecda337a926f563a6%27&SRS=EPSG%3A3857&**BBOX=-8755402.967897227,4285977.050006404,-8755097.219784087,4286282.798119542**" for 127.0.0.1 at 2018-06-27 16:51:01 -0400
A BBOX attribute is added by leaflet on the fly which are as follows
BBOX=-8755402.967897227,4285977.050006404,-8755097.219784087,4286282.798119542"
although, I want to get tiles only for these co-ordinates:
southWest ={lat: 35.77712238348847, lng: -78.64827990531921}
northEast {lat: 35.783693840245284, lng: -78.62991213798523}
setting up a BBOX option inside L.tileLayer.wms does not help either, as BBOX co-ordinates are added by leaflet.
Leaflet is working as expected.
You just have to remember that while Leaflet uses different Coordinate Reference Systems (CRSs) for the display projection and for L.LatLngs. You specify L.LatLngs (and bounds, etc) in EPSG:4326 (AKA equirectangular), and Leaflet will translate everything into EPSG:3857 (AKA Spherical Mercator).
Note how the URL for the WMS request includes a SRS=EPSG%3A3857 parameter (which means SRS=EPSG:3857 once URI-decoded). This means that Leaflet is providing coordinates in EPSG:3857, and expecting an image projected in EPSG:3857.
If you see no images, that likely means that your WMS server does not support EPSG:3857. Also, I encourage you to read through the Leaflet WMS/TMS tutorial, which highlights how to use different CRSs with WMS raster sources.
although, I want to get tiles only for these co-ordinates
Then use the bounds option of L.TileLayer.WMS. (If you don't see this option in the documentation, remember that L.TileLayer.WMS inherits options from L.TileLayer, which in turn inherits options from L.GridLayer)
Like so:
wms = L.tileLayer.wms('/viewers/wms', {
minZoom: 12,
maxZoom: 25,
layers: 'some layer name',
format: 'image/png',
updateWhenIdle: false,
transparent: true,
reuseTiles: true,
showTheRasterReturned: true,
COVERAGE_CQL_FILTER: 'featureId=\'' + featureId + '\''
bounds: L.latLngBounds([[35.77, -78.65],[35.78, -78.63]])
});
I need to create a circle around a point where a user clicks. How would I do this? Every tutorial shows extracting a circle from a geojson source and not creating one. Need to be able to edit the radius as well.
Did you try something yourself? Following the mapbox examples you should be able to get an idea of how to build something like that.
You would need to do 3 things:
Create a source that holds the data
Create a layer of type "circle" for displaying the data as circles
On every click of the user, extract the "latitude, longitude" and add a point to your data list. Then display all of those points as a circle on the map.
This is an example of how I would have coded that: https://jsfiddle.net/andi_lo/495t0dx2/
Hope that helps you out
mapboxgl.accessToken = '####';
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/light-v9', //stylesheet location
center: [-74.50, 40], // starting position
zoom: 9 // starting zoom
});
map.on('load', () => {
const points = turf.featureCollection([]);
// add data source to hold our data we want to display
map.addSource('circleData', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [],
},
});
// add a layer that displays the data
map.addLayer({
id: 'data',
type: 'circle',
source: 'circleData',
paint: {
'circle-color': '#00b7bf',
'circle-radius': 8,
'circle-stroke-width': 1,
'circle-stroke-color': '#333',
},
});
// on user click, extract the latitude / longitude, update our data source and display it on our map
map.on('click', (clickEvent) => {
const lngLat = new Array(clickEvent.lngLat.lng, clickEvent.lngLat.lat);
points.features.push(turf.point(lngLat));
map.getSource('circleData').setData(points);
});
});
#map {
height: 500px;
}
<div id="map"></div>
As of openlayers 3.11, raster reprojection is introduced. I used OSM as a background layer and it works perfectly on some projection, such as EPSG:25832. Now I need to work on another projection EPSG:2326 but it shows some white gaps between map tiles when zoomed into the map.
I created a jsfiddle for reference, can someone help? Thanks!
var myMap = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
view: new ol.View({
center: [837814, 818872],
projection: 'EPSG:2326',
zoom: 19
})
});
https://jsfiddle.net/86Lu9nd7/
This is a bug in OpenLayers. See https://github.com/openlayers/ol3/issues/4681 for its status.
I want to set an extend on my Openlayers 3.9.0 map.
When the page loads, I want the map to already be centered in that extend, no matter the layers. So I guess I will set an extend to the view, right?
Map contains a single OSM layer like
var layer = new ol.layer.Tile({
source: new ol.source.OSM(
{
attributions: [
new ol.Attribution({
html: 'All maps © ' +
'OpenCycleMap'
})
]
}
),
opacity: 0.8,
brightness: 0.8
});
Then I set the view
var center = ol.proj.transform([21.54967, 38.70250], 'EPSG:4326', 'EPSG:3857');
var view = new ol.View({
center: center,
zoom: 6,
extent: [2297128.5,4618333.0 , 2459120.25,4763120.0]
});
And then the map
var map = new ol.Map({
target: 'map',
layers: [layer],
view: view,
});
I used my extend in an older project, with EPSG 900913. So to convert the extend from 900913 to default Openlayers 3 3857 I went here here and I put
2297128.5, 4618333 that convereted to 2297128.5,4618333.0
and then
2459120.25, 4763120that convereted to 2459120.25,4763120.0
my two problems
1- the converted coords look similar. Did I do something wrong?
2- the map is centered ok, but not zoomed in the extend. The coords define a county in Greece and the map does not zoom there, I see the whole Greece, along with Turkey and Italy.
What I did wrong? Thanks
Thanks everyone. What I did was
Keep the OSM layer as is.
Define the limits of the county. Turns out it was EPSG 900913
var countyLimits= ol.proj.transformExtent([2297128.5, 4618333, 2459120.25, 4763120], 'EPSG:900913', 'EPSG:3857');
View is now
var view = new ol.View({
center: center,
zoom: 6,
extent : countyLimits,
maxZoom:20
});
map is
var map = new ol.Map({
target: 'map',
layers:[layer],
view: view
});
After the map is defined, fit its view in the limits
map.getView().fit(countyLimits, map.getSize());
//get the view of the map and fit it to the limits, according to the map's size
fitExtend is now deprecated, so I used fit. It is experimental , but I guess it will become standard since it replaced fitExtend.
Thanks anyway people
Sources
OL answer
OL3 API
Several issues:
The extent [2297128.5,4618333.0, 2459120.25,4763120.0] seems to be in EPSG 3857 already and there is no need to transform it.
The extent option of ol.View is experimental and does not seem to work well. You can do the following to set the bounding box (after you declare map):
var extent = [2297128.5, 4618333.0, 2459120.25, 4763120.0];
view.fitExtent(extent, map.getSize());
The initial zoom in your example was due to the zoom level set on the view (zoom: 6). Using fitExtent() should override the initial zoom level. You can remove the zoom, center and extent options from your view declaration.
By the way, regarding the http://cs2cs.mygeodata.eu/ site, it seems that you have to specify EPSG:4326 instead of EPSG:900913 for the input coordinate, for the transformation to work correctly.
Note: ol.View.fitExtent() was renamed to ol.View.fit() in OpenLayers v3.7.0
It can be as easy as:
var min = [2297128.5, 4618333.0];
var max = [2459120.25, 4763120.0];
var extent = ol.extent.boundingExtent([min, max]);
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.MapQuest({layer: 'osm'})
})
],
view: new ol.View({
center: ol.proj.fromLonLat([21.54967, 38.70250]),
zoom: 3,
extent: extent
})
});
http://jsfiddle.net/jonataswalker/zc3uL66q/
I need high-res map images for my application (solar power system design). Bing Maps in OL is good for finding the right building, but too low-res for laying out solar panels. So, I want to use a small high-res static map for doing the layout. Here's what I have currently. First load the Bing Maps layer:
var layers = [];
var baseBingMapLayer = new ol.layer.Tile({
source: new ol.source.BingMaps({
key: 'XXXXX',
imagerySet: 'AerialWithLabels',
})
});
layers.push(baseBingMapLayer);
var map = new ol.Map({
layers: layers,
target: 'map',
view: new ol.View({
center: [-13569845.9277,4485666.89612],
zoom: 5,
})
});
Then when I want to load the static map, the strategy is to remove the Bing Maps layer and then add the static image layer. I'm doing the following:
var extent = [0, 0, 1024, 768];
var projection = new ol.proj.Projection({
code: 'xkcd-image',
units: 'pixels',
extent: extent
});
var staticURL =
"https://maps.googleapis.com/maps/api/staticmap"
+ "?center=37.7431569802915,-121.4451930197085&"
+ "zoom=20&size=1024x768&scale=2&zoom=3&"
+ "format=jpg&maptype=satellite"
+ "&key=XXX";
map.removeLayer(baseBingMapLayer);
var imageLayer = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: staticURL,
imageSize: [1024,768],
projection: projection,
imageExtent: extent
})
});
var imageLayerView = new ol.View({
projection: projection,
center: ol.extent.getCenter(extent),
zoom: 2
});
map.addLayer(imageLayer);
map.addView(imageLayerView);
Needless to say, this isn't working. I just get a blank screen with no exceptions thrown.
I actually had some success using jQuery to just empty the entire map div and start over with a new map object. However this seems to cause other problems and didn't seem like the right approach to me.
I'm going to continue working on this problem, but thought I would post since I'm sure I won't be the last person to try this little stunt :-)
Gary