0

In openlayers.js (current version 5.3.0) how to restrict the map during the mouse drag? The range of lat shall be [-90,90].

Compared with those two examples hereunder,

https://openlayers.org/en/latest/examples/drag-rotate-and-zoom.html?q=drag

https://docs.mapbox.com/mapbox-gl-js/example/add-image-animated/

If the map is dragged over the lat[-90,90], the map in mapbox restricts the range automatically and the map in OpenLayers will show the blank area.

Here is the same problem, but no prefect answers. https://gis.stackexchange.com/questions/222698/openlayers3-how-to-limits-the-drag-range-of-the-map

The dirty solution I tried is 1. add the map.on('moveend'...) listener 2. detect the map center with zoom 3. if out of range, do map.getView().animate({ center:[...],duration:100})

But the process of animation is, you know, the transition from some blank area to the nominated center.

Are there any options in the Map constructor? Or any position of source code in OpenLayers where some hack code could be done?

Mike
  • 16,042
  • 2
  • 14
  • 30
pvii007
  • 3
  • 6

1 Answers1

0

See Limit Panning OpenLayers 5

Here's the same demo with a global extent:

var view = new ol.View();

var map = new ol.Map({
    layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ],
    target: 'map'
});

function openMap() {

    map.setView(view);
    var extent = ol.proj.transformExtent([ -540, -85, 540, 85], 'EPSG:4326', 'EPSG:3857');

    // fit the extent horizontally or vertically depending on screen size
    // to determine the maximum resolution possible
    var size = map.getSize();
    var width = ol.extent.getWidth(extent);
    var height = ol.extent.getHeight(extent);
    if (size[0]/size[1] > width/height) {
        view.fit([extent[0],(extent[1]+extent[3])/2,extent[2],(extent[1]+extent[3])/2], { constrainResolution: false });
    } else {
        view.fit([(extent[0]+extent[2])/2,extent[1],(extent[0]+extent[2])/2,extent[3]], { constrainResolution: false });
    }
    var maxResolution = view.getResolution();
    var resolution = 0;

    function resChange() {
        var oldView = map.getView();
        if (resolution == 0 || oldView.getZoom()%1 == 0) {
            resolution = oldView.getResolution();
            var width = map.getSize()[0] * resolution;
            var height = map.getSize()[1] * resolution;
            var newView = new ol.View({
                projection: oldView.getProjection(),
                extent: [extent[0]+(width/2), extent[1]+(height/2), extent[2]-(width/2), extent[3]-(height/2)],
                resolution: resolution,
                maxResolution: maxResolution,
                rotation: oldView.getRotation() 
            });
            newView.setCenter(newView.constrainCenter(oldView.getCenter()));
            newView.on('change:resolution', resChange);
            map.setView(newView);
        }
    }
    resChange();

}
map.on('change:size', openMap);
openMap();
<link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" type="text/css">
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>

If you can wait until OpenLayers 6 is released, or don't mind using a beta version, the extent option will constraint the visible extent and unless the multiWorld option is specified the extent defaults to one world https://github.com/openlayers/openlayers/blob/master/changelog/upgrade-notes.md

Mike
  • 16,042
  • 2
  • 14
  • 30
  • Thank you. About the 'change:size', if user's interactions are done such as zoomToExtent,should the 'extent' in code snippet follow the user operation? – pvii007 May 24 '19 at 04:17