最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Limit Panning OpenLayers 5 - Stack Overflow

programmeradmin6浏览0评论

I'm using OpenLayers 5 for my project and wasn't able to find anything on here for that. In the past, OpenLayers has had restrictExtent, but that seems to have disappeared. Is there a way to limit or restrict the user's ability to pan vertically so that they can't drag it off the screen?

I've tried using the maxExtent on both the layer containing the map and the View, and I've been able to limit what's visible by doing so on the View. I haven't been able to limit the panning, however. Any help with this would be awesome.

map.js

ponentDidMount() {
        BASE_VIEW.setMinZoom(this.getMinZoom());
        this.resize();
        this.map = new Map({
            controls: defaultControls().extend([MOUSE_POSITION_CONTROL]),
            layers: [BASE_LAYER],
            target: 'map',
            view: BASE_VIEW
        });
    }

map-constants.js

const baseView = new View({
    center: fromLonLat(conus, projection),
    projection: projection,
    zoom: 4,
    extent: [Number.NEGATIVE_INFINITY, -43, Number.POSITIVE_INFINITY, 43]
});

I'm using OpenLayers 5 for my project and wasn't able to find anything on here for that. In the past, OpenLayers has had restrictExtent, but that seems to have disappeared. Is there a way to limit or restrict the user's ability to pan vertically so that they can't drag it off the screen?

I've tried using the maxExtent on both the layer containing the map and the View, and I've been able to limit what's visible by doing so on the View. I haven't been able to limit the panning, however. Any help with this would be awesome.

map.js

ponentDidMount() {
        BASE_VIEW.setMinZoom(this.getMinZoom());
        this.resize();
        this.map = new Map({
            controls: defaultControls().extend([MOUSE_POSITION_CONTROL]),
            layers: [BASE_LAYER],
            target: 'map',
            view: BASE_VIEW
        });
    }

map-constants.js

const baseView = new View({
    center: fromLonLat(conus, projection),
    projection: projection,
    zoom: 4,
    extent: [Number.NEGATIVE_INFINITY, -43, Number.POSITIVE_INFINITY, 43]
});
Share Improve this question edited Feb 7, 2019 at 16:51 Andrew asked Feb 6, 2019 at 20:28 AndrewAndrew 892 silver badges11 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 8

The nearest equivalent to OpenLayers 2 restrictedExtent in OL3/4/5 is the misleadingly named extent option of ol.View but that is a center constraint which restricts the map center, and depending on resolution and map size it is possible to pan the edges of the map considerably beyond that.

To replicate restrictedExtent you would need to recalculate the center constraint and reset the view as the resolution changes (ignoring very small changes to avoid performance issues). Assuming you have opened the map at the required maximum extent (using .fit() perhaps) you could then use this code

var extent = map.getView().calculateExtent(); // opening coverage
var resolution = 0;

function resChange() {
    var newResolution = map.getView().getResolution();
    if (resolution == 0 || Math.abs((newResolution-resolution)/resolution) > 0.01) {
        resolution = newResolution;
        var width = map.getSize()[0] * resolution;
        var height = map.getSize()[1] * resolution;
        var view = new ol.View({
            projection: map.getView().getProjection(),
            extent: [extent[0]+(width/2), extent[1]+(height/2), extent[2]-(width/2), extent[3]-(height/2)],
            center: map.getView().getCenter(),
            resolution: resolution,
            maxZoom: map.getView().getMaxZoom(),
            minZoom: map.getView().getMinZoom()
        });
        view.on('change:resolution', resChange);
        map.setView(view);
    }
}
resChange();

Here's a demo. For efficiency I'm only resetting the view at integer zoom levels (resulting in a stretch and snap back effect when zooming out close to the edges), and for the demo to work full page I reset the map when resized.

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([ -2, 50.5, 2, 53], '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./openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" type="text/css">
<script src="https://cdn.rawgit./openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>

UPDATE

In OpenLayers 6 the view extent option does restrict the extent and not the center (useless constrainOnlyCenter is also specified) so no workaround is needed.

发布评论

评论列表(0)

  1. 暂无评论