限制OpenLayers 5地图平移

5
我正在使用OpenLayers 5进行项目开发,但在这里没有找到相关信息。过去,OpenLayers有一个restrictExtent函数,但现在似乎已经消失了。是否有一种方法可以限制或禁止用户垂直平移地图,以使其无法将其拖出屏幕?

我尝试在包含地图的图层和视图上使用maxExtent,并且通过在视图上这样做,我已经能够限制可见内容。然而,我还没有能够限制平移。希望您能提供帮助。

map.js

componentDidMount() {
        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]
});
1个回答

8
在OL3/4/5中,与OpenLayers 2的restrictedExtent最接近的相当于是ol.View选项中误导性地命名为extent的选项,但这是一个中心约束,限制了地图中心,并且根据分辨率和地图大小,可以将地图边缘大大超出该范围。
要复制restrictedExtent,您需要在分辨率更改时重新计算中心约束并重置视图(忽略非常小的更改以避免性能问题)。假设您已经按所需的最大范围打开了地图(可能使用.fit()),然后您可以使用以下代码:
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();

这里有一个演示。为了提高效率,我仅在整数缩放级别时重置视图(当接近边缘缩小时会产生拉伸和弹回效果),为了使演示在全屏下工作,当调整大小时我重置了地图。

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.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>

更新

在OpenLayers 6中,视图的extent选项确实会限制范围而不是中心(无用的constrainOnlyCenter也被指定),因此不需要任何解决方法。


这开始让我有点明白了,但你能帮我更好地理解吗?我的视图设置在一个文件中,然后地图在另一个文件中创建。这个函数和随后的函数调用应该放在哪里?编辑:我已经编辑了问题以添加一些代码。 - Andrew
我已经添加了一个可工作的代码片段,希望这能使它更清晰明了。 - Mike
谢谢!这真的很有帮助!我在运行时遇到了一个“TypeError: Cannot read property 'getResolution' of undefined”错误,基于这一行代码:esolution = oldView.getResolution(); - Andrew
1
这是因为函数内部的 this 是局部变量。有多种方法可以覆盖它,例如将 function resChange() { ....} 替换为 resChange = function() { .... }.bind(this); - Mike
好的,我解决了(感谢您一直陪伴着我),问题出在创建newView时调用栈大小超过了最大值。 - Andrew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接