Openlayers 3 将平移限制在OpenLayers3中的WMS范围之外

Openlayers 3 将平移限制在OpenLayers3中的WMS范围之外,openlayers-3,Openlayers 3,我有一个小面积的矩形WMS,我想限制WMS扩展外的平移,所以在地图外根本看不到白色或黑色区域。 将范围添加到视图对我不起作用,并且在文档中编写了关于此选项的说明 约束中心的范围,换句话说,中心不能 设置在该范围之外 但正如我所理解的,如果中心在范围内,但在拐角处,它将显示该范围外的白色区域,但我根本不想看到白色区域 使用OL3可以实现这一点吗?这是我的解决方案。我刚刚写的,所以没有经过广泛的测试。例如,如果开始旋转贴图,它可能会断开,如果缩小太远,它可能会出现故障 var constrainPa

我有一个小面积的矩形WMS,我想限制WMS扩展外的平移,所以在地图外根本看不到白色或黑色区域。 将
范围
添加到
视图
对我不起作用,并且在文档中编写了关于此选项的说明

约束中心的范围,换句话说,中心不能 设置在该范围之外

但正如我所理解的,如果中心在范围内,但在拐角处,它将显示该范围外的白色区域,但我根本不想看到白色区域


使用OL3可以实现这一点吗?

这是我的解决方案。我刚刚写的,所以没有经过广泛的测试。例如,如果开始旋转贴图,它可能会断开,如果缩小太远,它可能会出现故障

var constrainPan = function() {
    var visible = view.calculateExtent(map.getSize());
    var centre = view.getCenter();
    var delta;
    var adjust = false;
    if ((delta = extent[0] - visible[0]) > 0) {
        adjust = true;
        centre[0] += delta;
    } else if ((delta = extent[2] - visible[2]) < 0) {
        adjust = true;
        centre[0] += delta;
    }
    if ((delta = extent[1] - visible[1]) > 0) {
        adjust = true;
        centre[1] += delta;
    } else if ((delta = extent[3] - visible[3]) < 0) {
        adjust = true;
        centre[1] += delta;
    }
    if (adjust) {
        view.setCenter(centre);
    }
};
view.on('change:resolution', constrainPan);
view.on('change:center', constrainPan);
var constraintpan=function(){
var visible=view.calculateExtent(map.getSize());
var center=view.getCenter();
var三角洲;
var-adjust=false;
如果((增量=范围[0]-可见[0])>0){
调整=真;
中心[0]+=delta;
}else如果((增量=范围[2]-可见[2])<0){
调整=真;
中心[0]+=delta;
}
如果((增量=范围[1]-可见[1])>0){
调整=真;
中心[1]+=delta;
}否则如果((增量=范围[3]-可见[3])<0){
调整=真;
中心[1]+=delta;
}
如果(调整){
视图。设置中心(中心);
}
};
关于(‘变更:决议’)的意见;
打开视图('更改:中心',平移);

这要求变量
map
view
(具有明显的含义)和
区段
(希望可见的xmin、ymin、xmax、ymax)可用。

这是@tremby answer的一个扩展,但需要一个注释

首先,他的解决方案对我来说非常有效,但它被称为经常使用的方法。因此,我将其包装在一个
debounce
函数中

所以

变成

var dConstrainPan = debounce(constrainPan);
view.on('change:resolution', dConstrainPan);
view.on('change:center', dConstrainPan);
这将导致轻微闪烁,当移动到边界框外时,机器人缩放/移动将毫不延迟地工作

仍然不完美,但从我的角度来看,这是一个有益的改进

去盎司代码:

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

Soruce:,在underline.js中,这里有一个更健壮的实现,在任何情况下都应该运行良好。它是用ES6编写的,需要等质量方法(来自lodash或其他任何东西…)

const-extent=[-357823.236526037008.69391313632.36287230727.3772];
const view=this.olMap.getView();
const modifyValues={};
//禁止在范围外平移的技巧
让pan=(e)=>{
const type=e.type;
const newValue=e.target.get(e.key);
const oldValue=e.oldValue;
if(相等(旧值、新值)){
//当事件未更改值时不执行任何操作
返回;
}
if(isEqual(修改值[类型],新值)){
//打破可能的无限循环
删除修改值[类型];
返回;
}
如果(类型=='change:resolution'&&newValue
这是一个好问题。您想要的还不受支持。不久前,我开始开发一个涵盖您的用例的补丁,但这个补丁尚未合并。看见我会再做一次的。哦,太糟糕了。在我看到的大多数在线地图中,这个白色区域是我真正不喜欢的。现在等待OL3支持它。Erilem的补丁可以工作,你可以自己轻松添加它。到erilem的pull请求的链接在末尾有一个隐藏的额外
,并给出一个404。工作链接:我不喜欢看不到范围外的白色区域。这意味着我永远不能集中在可用区域内的区域。这会导致进一步的问题。效果很好,但在全屏模式下会导致缩放和拖动停止工作。是的,我提到过,如果缩放太远,它可能会中断。当你进入全屏时,可能会出现同样的情况。很高兴它仍然有帮助。如果你有特别的建议,使它更可靠,请建议编辑。我得到了“太多的递归”错误,以更快的平移,我的层正在消失。。。只是为了记录在案是的;对于一般情况,它肯定不是生产就绪的代码(尽管它在我的用例中工作得很好)。欢迎进行任何改进。ES6 lodash导入注意:确保从“lodash”导入{isEqual}。如果忘记了大括号,它不会抛出错误,但是
isEqual()
对于数组总是返回true。
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};
const extent = [-357823.2365, 6037008.6939, 1313632.3628, 7230727.3772];
const view = this.olMap.getView();

const modifyValues = {};

// Trick to forbid panning outside extent
let constrainPan = (e) => {
  const type = e.type;
  const newValue = e.target.get(e.key);
  const oldValue = e.oldValue;

  if (isEqual(oldValue, newValue)) {
    // Do nothing when event doesn't change the value
    return;
  }

  if (isEqual(modifyValues[type], newValue)) {
    // Break possible infinite loop
    delete modifyValues[type];
    return;
  }

  if (type === 'change:resolution' && newValue < oldValue) {
    // Always allow zoom-in.
    return;
  }

  const visibleExtent = view.calculateExtent(this.olMap.getSize());
  const intersection = ol.extent.getIntersection(visibleExtent, extent);
  const modify = !isEqual(intersection, visibleExtent);

  if (modify) {
    if (type === 'change:center') {
      const newCenter = newValue.slice(0);

      if (ol.extent.getWidth(visibleExtent) !== ol.extent.getWidth(intersection)) {
        newCenter[0] = oldValue[0];
      }

      if (ol.extent.getHeight(visibleExtent) !== ol.extent.getHeight(intersection)) {
        newCenter[1] = oldValue[1];
      }

      modifyValues[type] = newCenter;
      view.setCenter(newCenter);
    } else if (type === 'change:resolution') {
      modifyValues[type] = oldValue;
      view.setResolution(oldValue);
    }
  }
};
view.on('change:resolution', constrainPan);
view.on('change:center', constrainPan);