I'm using OpenLayers to display a world map on my site. The map wraps to either side, and, in the repeated sections, the coordinates are bonkers.
The pins on the map can be moved. If we move them over to a repeated section, instead of getting the actual coordinates of that spot on the globe, we get an invalid coordinate set which makes that pin disappear from the map altogether.
Here's the code I'm using for the map:
this.maps.vectorSource = new ol.source.Vector({
});
this.maps.vectorLayer = new ol.layer.Vector({
source: self.maps.vectorSource
});
this.maps.rasterLayer = new ol.layer.Tile({
source: new ol.source.OSM({wrapDateLine: false})
});
this.maps.map = new ol.Map({
target: 'map',
interactions: ol.interaction.defaults({mouseWheelZoom:false}),
layers: [self.maps.rasterLayer, self.maps.vectorLayer],
view: new ol.View({
center: ol.proj.transform([-98.583333, 37.833333], 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
});
You can see I've tried setting the wrapDateLine option to false, but this doesn't have any effect best I can tell.
I'd like to solve this either by preventing the map from repeating or by ensuring the repeating sections report proper coordinates. At this point, I don't much care which. Any ideas how I can achieve one of these two results?
Depending on your version of OpenLayers, you may need to use different options to disable the horizonal repeat. Try adding the following options to your OSM source:
wrapX: false,
noWrap: true
I've made a jsFiddle with a slightly modified version of your code to illustrate:
https://jsfiddle.net/fg1oxpu0/
Anthony got me going in the right direction with his answer. We were using OL 3.1.1 which doesn't support wrapX. I updated to 3.2.0 and was able to turn off wrapping. However, this created a both a UX problem (the map now ends on either side and the user needs to manually move back to the other side) and a UI problem (our wide area for map display is now mostly empty).
I tried moving up to the latest version (3.7.0) which, I noticed, began wrapping the vector layer. (Vector wrapping was lost in the move to OL 3 but was restored later.) This allowed me to turn my map wrapping back on, and the pins are drawn on each repeat of the map. It also now reports the correct coordinates even on the repeated maps.
Related
I am a beginner in mapbox, so please be understanding :)
I'm trying to show 3D buildings only from the selected area (in red area). Unfortunately, I did not find any answer in the documentation or on the Internet, so I decided to ask here if there is such a possibility?
I was thinking about copying Tilesets and somehow extracting buildings but I do not know how.
Do you have any ideas?
Link to codepen:
https://codepen.io/Mativve/pen/RzORMo
mapboxgl.accessToken = '--MY-TOKEN--';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mativve/cjxzva0f6042a1cm7710cofya',
center: [21.005950, 52.231034],
zoom: 15,
bearing: 20.80,
pitch: 53.50
});
There's no direct support for area-based filtering, but you could achieve something similar (with some caveats), as follows:
Call map.queryRenderedFeatures() to get all buildings in the current view port.
Use Turf's booleanContains function to create an array of buildings that are within the designated polygon.
Construct a filter that matches only those filters, using some other property, such as a building identifier.
Call map.setFilter() on the buildings layer so that only those buildings are visible.
I am new to leaflet and I want the restrict the panning of a world map horizontally and not vertically (longitude but not latitude) because this map will display pictures when I click on them and I cant see well the image when i restrict the panning horizontally AND vertically. The map by itself it not a picture, it's a real world map. But when I click on certain location, a small picture will appear on the map.
I try to play with maxBounds and setMaxbounds. The normal maxBounds (to view the world map) is :
maxBounds: [[-85, -180.0],[85, 180.0]],
When i try to put the latitude to
[[-150, -180.0],[150, 180.0]]
, the vertical panning is still restricted. Can somebody help please? Thank you.
This sounds similar to a (quite obscure) issue in the Leaflet issue tracker a
while back: see https://github.com/Leaflet/Leaflet/issues/3081
However, that issue was dealing with infinite horizontal bounds, not vertical bounds in a CRS that already has some preset limits.
If you set the map's maxBounds to a value larger than 85 (the value for MAX_LATITUDE of L.Projection.Spherical) and run a debugger, the call stack goes through the map's _panInsideMapBounds(), then panInsideBounds(), then _limitCenter(), then _getBoundsOffset, then project(), then through the map CRS's latLngToPoint, then untimately L.Projection.Spherical's project(). L.Projection.Spherical.project() projects the bounds' limits into pixel coordinates, and clamps the projected point to be inside the projection's limits.
There are a lot of reasons behind this, one of them being to prevent users from putting markers outside the area covered with tiles:
(This is particularly important when a user confuses lat-lng with lng-lat and tries to use a value outside the [-90,90] range for latitude, and the projection code starts returning Infinity values everywhere)
How to get around this? Well, we can always specify the map's CRS, and we can create a CRS with a hacked projection which enforces a different limit. Please be aware that this changes how the pixelOrigin works internally (as explained in the Leaflet tutorial about extending layers), so stuff (particularly plugins) might break.
So something like:
var hackedSphericalMercator = L.Util.extend(L.Projection.SphericalMercator, {
MAX_LATITUDE: 89.999
});
var hackedEPSG3857 = L.Util.extend(L.CRS.EPSG3857, {
projection: hackedSphericalMercator
});
var map = new L.Map('mapcontainer', {
crs: hackedEPSG3857,
});
Of course, then you can set up your own maxBounds:
var map = new L.Map('mapcontainer', {
crs: hackedEPSG3857,
maxBounds: [[-Infinity, -10], [Infinity, 10]]
});
In this case, the bounds' limits would still be clamped to hackedSphericalMercator.MAX_LATITUDE, but you should have enough wiggle room for your application.
As a side note: A radically different approach to this problem would be to use a different map projection. We're used to a spherical cylindrical projection, but that's not the only way to flatten the earth.
In particular, a Transverse Mercator projection (or pretty much any other transverse cylindrical projection, for that matter) works pretty much in the same way, but wraps vertically instead of horizontally, and it's the projected longitudes, not latitudes, the ones which approach infinity asymptotically when approaching the [-180, 180] range. Let me borrow an image from its wikipedia article:
This implies a different set of challenges (namely finding some raster tiles appropriate for your application, including which prime meridian to use, and making proj4leaflet play nice), but it's definitely doable.
I have the follow code:
var area = new Microsoft.Maps.WellKnownText.read(x, { strokeColor: stroke, strokeThickness: 10 });
$scope.map.setView({ center: new Microsoft.Maps.Location(lat, lng), zoom: 17 });
$scope.map.entities.push(area);
Which should map a Well Known Text (wkt) string. This works fine if I have a POINT() but for any other WKT String, it shows nothing. I've looked at the MSDN example, but it only demonstrates POINT(), and no matter what I try, I can't get the other shapes to show up.
Has anyone been able to map shapes through the wkt handler?
Thanks
Docmur
I use the WKT module regularly with all sorts of shapes and haven't had any issues. Here is a larger sample that uses this module to load a large polygon: http://bingmapsv8samples.azurewebsites.net/#North%20Carolina%20Map
Note that your code is incorrectly specifying styles. It should be using a StyleOptions object, also you shouldn't be using the "new" keyword as this is a static function:
var area = Microsoft.Maps.WellKnownText.read(x, { polygonOptions: { strokeColor: stroke, strokeThickness: 10 }});
Documentation can be found here: https://msdn.microsoft.com/en-us/library/mt712880.aspx
Sorry, to be honest, I forgot about this post. We solved this problem a while ago and I can't remember what the issue was. We were having massive problems with CORS errors and 500 error codes from Bing Maps, which have disappeared. Something was wrong with our key, at least that was the best guess they ever came up with.
We currently have the WKT mapping working like a treat.
Thanks
Docmur
I have a mapbox.js map but the parameter zoom doesn't seem to be doing anything
and I can't figure it out in the documentation. whatever I set zoom to the zoom level always defaults to my project zoom level Here is the code:
<script src='https://api.tiles.mapbox.com/mapbox.js/v1.6.1/mapbox.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox.js/v1.6.1/mapbox.css' rel='stylesheet' />
$(document).ready(function() {
var map = L.mapbox.map('map', 'nhaines.hek4pklk', {
zoom: 1
});
// disable drag and zoom handlers
map.dragging.disable();
map.touchZoom.disable();
map.doubleClickZoom.disable();
map.scrollWheelZoom.disable();
// disable tap handler, if present.
if (map.tap) map.tap.disable();
});
It took me a lot of digging around but I figured this out on my own. The dev's didn't respond yet. We were going about this all wrong. Here's what to do:
First, create the MapBox object, but set zoomAnimation to false. This question helped me realize that trying to setZoom while a CSS3 animation was in progress wouldn't ever work because it's tough to break out of. At least that's what I think is going on. Setting zoomAnimation to true allows the map to animate in and bypasses any custom zoom levels, so clearly this is very important.
var map = L.mapbox.map('map', 'username.map_id', {
zoomAnimation: false
});
Next, create a polygon layer and add to map from map's geojson. You find this within your MapBox projects > info tab. (In my case this geojson happens to contain the lat/lng coords of a polygon but your case may be different. featureLayer() should still add the geojson either way.)
var polygonLayer = L.mapbox.featureLayer().loadURL('http://your/maps/geojson').addTo(map);
After polygon layer (or whatever your lat/lng coords are of) has been added to map
polygonLayer.on('ready', function() {
// featureLayer.getBounds() returns the corners of the furthest-out markers,
// and map.fitBounds() makes sure that the map contains these.
map.fitBounds(polygonLayer.getBounds());
map.setView(map.getCenter(), 10);
}
Apparently fitBounds satisfies the map requirements to allow setView to be called on it, since now you can just call the map object directly to get the center lat/lng.
I haven't tested this in simple cases - I adapted this code from mine which checks if an address's lat/lng coords fall within a polygon while iterating over a series of MapBox maps. It should get you going though. Hope it helps!
I've got a problem with osm and openlayers.
first of all, my map object
var wgs84 = new OpenLayers.Projection("EPSG:4326");
var map = new OpenLayers.Map ('map',
{
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: wgs84,
maxExtent: new OpenLayers.Bounds(-180,-20, 180, 90),
controls: [
new OpenLayers.Control.MousePosition(),
new OpenLayers.Control.PanZoomBar(),
]
});
as you can see, my bounding box ends at -20, so the antarctis should be displayed.
but i'm able to zoom out so that i can see the whole world, and the map is smaller than the map-div (which is 900 * 500).
Is there any solution to fix it? you shouldn't be able to get a smaller map than the bounding box allows.
Have you implemented the restrictedExtent parameter?
(from the documentation)
restrictedExtent
{OpenLayers.Bounds} Limit map navigation to this extent where possible. If a non-null restrictedExtent is set, panning will be restricted to the given bounds. In addition, zooming to a resolution that displays more than the restricted extent will center the map on the restricted extent.
See an example here - This stops you panning beyond the bounds but does not restict the zoom levels. This seems to be a heavily reported missing feature that has not had many resolutions.
I believe this SO post has some workarounds for it thoughMin Max Zoom level in OpenLayers
Hope I have been some help.
Take a look at the sample I did at http://beta1234.com.sunflower.arvixe.com/maps/ (the server is a bit slow). It uses restrictedExtent and restricted zoom levels.