Repeated tiles when switching from OpenLayers to Leaflet - leaflet

I am trying to change an OpenLayers 2 call to Leaflet, but when I do the map is displayed fine at zoom level 0, but every time I zoom in, the map doubles from the previous number. Any suggestions as to why? Here is a picture to what its doing.
OpenLayers 2 map options
var options = {
projection: new OpenLayers.Projection("EPSG:3857"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
units: "m",
maxResolution: 156543.0339,
maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34,
20037508.34, 20037508.34),
controls: [
new OpenLayers.Control.Navigation(
{dragPanOptions: {enableKinetic: true}}
)
]
};
OpenLayers 2 code
var bathyEsri = new OpenLayers.Layer.XYZ(
' ESRI Ocean'
,'http://services.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/${z}/${y}/${x}.jpg'
,{
sphericalMercator : true
,isBaseLayer : true
,wrapDateLine : true
,opacity : 1
,visibility : true
}
);
Leaflet Options
var options = {
worldCopyJump: true,
maxBounds: L.LatLngBounds([20037508.34,20037508.34],[-20037508.34,-20037508.34]),
crs: L.CRS.EPSG4326,
center: [39.73, -104.99],
zoom: 0
};
Leaflet Code
var bathyEsri = L.tileLayer('http://services.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/${z}/${y}/${x}.jpg');

Your problem is basically a typo.
Your analysis is also misleading: it's not that the map is being "duplicated", but rather every tile being requested is the 0/0/0 tile. If you use the network inspection tools of your browser, you'll see that the tile URL is something like https://services.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer/tile/$3/$4/$5.jpg , but the tile image corresponds to the /0/0/0.jpg tile.
If you look at those URLs a bit more closely, you'll notice some "extra" $ signs. Why are those there? Well, consider that you wrote your tilelayer URL scheme as
var bathyEsri = L.tileLayer('http://...../tile/${z}/${y}/${x}.jpg');
But keep in mind that the Leaflet documentation clearly states:
var bathyEsri = L.tileLayer('http://...../tile/{z}/{y}/{x}.jpg');
Change this, and everything will magically start working.

Related

Leafletjs show a single wrapped map

I want to show a single world map and wrap it around so that each area is shown only once on the screen. Please refer the fiddle http://jsfiddle.net/8m13d6vs/
var osmUrl = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
osm = L.tileLayer(osmUrl, {
noWrap: false,
attribution: "<a href='http://openstreetmap.org'>OpenStreetMap</a>"
});
var map = L.map('map').setView([0, 0], 1).addLayer(osm);
In the above fiddle, wrap is on, but the world map is duplicated. I want a single world map, and on left/right mouse drag, it should wrap around. It should be responsive to the area as well. Is there any way to achieve this? Hope my problem statement is understandable.
There's the Leaflet worldCopyJump option:
var map = L.map('map', {worldCopyJump: true}).setView([0, 0], 1).addLayer(osm);
It defaults to false, but setting this to true will copy the contents of the map over as the user pans beyond the map boundaries.
This sounds like a misunderstanding of the definition of "wrap":
In the context of Leaflet's Tile Layer / Grid Layer option noWrap, it says:
Whether the layer is wrapped around the antimeridian. If true, the GridLayer will only be displayed once at low zoom levels.
So it sounds like simply noWrap: true should achieve your objective.
Updated JSFiddle: http://jsfiddle.net/8m13d6vs/3/
BTW you should consider upgrading Leaflet version to 1+

reproject map extent in openlayers 3

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/

OpenLayers 3 - change base map from ol.layer.Tile (Bing) to ol.layer.Image (static image)

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

OL3: Setting map view center to geolocation.getCurrentPosition doesn't work

When the application starts, I want to center the map view on the users current position. I have tried two different approaches and can't get them work. The first one worked properly in leaflet, but in the development process I have decided to use OL3 instead.
First approach (worked in leaflet):
var myProjectionName = "EPSG:25832";
proj4.defs(myProjectionName,
"+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs");
var centerPosition;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
function (pos) {
centerPosition =
ol.proj.transform(
[position.coords.longitude,
position.coords.latitude],
'EPSG:4326',
myProjectionName);
},
function (err) {centerPosition = [724844,6178000];},
{
enableHighAccuracy: false,
timeout: 5000,
maximumAge: 1000
});
}
My second approach was using the ol.Geolocation class:
var proj1 = ol.proj.get(myProjectionName);
var geolocation = new ol.Geolocation({
projection: proj1
});
var centerPosition= geolocation.getPosition();
The center position is used in creating the view/map object:
var map = new ol.Map({
target: 'map',
logo : false,
layers: [ GSTGroup, OVLGroup, SheatLayer],
view: new ol.View({
projection: myProjectionName,
center: centerPosition,
resolutions : AVLresolutions,
resolution : 2
})
});
I have some suspecions that the cause of the problem is the projection, but on the other hand the projection works properly in transforming layers (WMTS, Vector), source from Geojson in different coordinatesystem and in ol.control.MousePosition.
I am using Firefox 32.0.3 and the geolocator plugin to development/test
Working example in http://jsfiddle.net/AndersFinn/ak4zotn8/
Add after the map declaration the following (tested):
var proj1 = ol.proj.get(myProjectionName);
var geolocation = new ol.Geolocation({
projection: myProjectionName,
tracking: true
});
geolocation.on('change', function(evt) {
console.log(geolocation.getPosition());
map.getView().setCenter(geolocation.getPosition());
});
The most important part is tracking: true in the code: it means you check regularly the position to center.
The second important part is to bind event on geolocation object (an instance of ol.Geolocation)
See in the official examples the geolocation samples and the API docs to make some changes depending of your requirements

Layer order changing when turning layer on/off

I have two geoJson layers being loaded - both layers are the same data for testing purposes, but being drawn from two different json files. When I turn the layers on and off in the layer controller, the draw order of the layers change.
Any ideas why this is happening?
I have put my code into a JSFiddle: http://jsfiddle.net/lprashad/ph5y9/10/ and the JS is below:
//styling for watersheds_copy
var Orange = {
"color": "#ff7800",
"weight": 5,
"opacity": 0.65
};
var Water_Orange = L.geoJson(watersheds_copy, {
style: Orange
});
Water_Orange.addData(watersheds_copy);
//these are blue
var Water_blue = L.geoJson(watersheds, {});
Water_blue.addData(watersheds);
//This sets the inital order - last in layer list being on top. Except minimal - tile layer is always on bottom
var map = L.map('map', {
center: [41.609, -74.028],
zoom: 8,
layers: [minimal, Water_Orange, Water_blue]
});
var baseLayers = {
"Minimal": minimal,
"Night View": midnight
};
//This controls the order in the layer switcher. This does not change draw order
var overlays = {
"Water_Orange": Water_Orange,
"Water_blue": Water_blue
};
L.control.layers(baseLayers, overlays).addTo(map);
LP
While searching I happened upon this site that shows some of the Leaflet code:
http://ruby-doc.org/gems/docs/l/leaflet-js-0.7.0.3/lib/leaflet/src/control/Control_Layers_js.html
In it I found this condition for the application of autoZIndex:
if (this.options.autoZIndex && layer.setZIndex) {
this._lastZIndex++;
layer.setZIndex(this._lastZIndex);
}
TileLayer is the only layer type that has a setZIndex function, so apparently autoZIndex only works there.
I'm not sure which annoys me more. This incredible limitation or the fact that Leafet documentation doesn't point it out.
At least on 0.7.2, I had to use bringToFront in the callback of map.on('overlayadd'). autoZIndex: false did not work in my case neither. A comment on this issue may explain the reason.
It's not specific to L.GeoJson layers. As far as I can tell, it's true of all Leaflet layers with layer control. The last layer turned on is simply on top. I don't think this is a bug either. It's predictable behavior which I use and depend on when I'm designing maps with layer control...