我有一个小面积的矩形WMS,并希望限制WMS扩展外的平移,因此地图外部没有可见的白色或黑色区域。
将extent
添加到View
对我不起作用,并且有关此选项的文档已编写
限制中心的程度,换句话说,中心不能 超出这个范围。
但是据我所知,如果中心位于范围区域,但是在角落处,它会在这个范围之外显示白色区域,但我不想看到白色区域。
是否可以通过OL3实现这一目标?
答案 0 :(得分:12)
这是我的解决方案。我刚刚写了它,因此没有经过广泛的测试。例如,如果你开始旋转地图,它可能会破裂,如果缩小太远,它可能会出现故障。
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);
这要求变量map
,view
(具有明显的含义)和extent
(您希望可见的xmin,ymin,xmax,ymax)可用。
答案 1 :(得分:2)
这是一个更强大的实现,在任何情况下都应该可以正常工作。它是用ES6编写的,需要isEqual方法(来自lodash或其他任何东西......)
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);
答案 2 :(得分:1)
这是对@tremby回答的扩展,但是很想发表评论。
首先,他的解决方案对我来说效果很好,但它经常被称为方式。因此,我将其包装在debounce
函数中。
所以
view.on('change:resolution', constrainPan);
view.on('change:center', constrainPan);
变为
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:https://davidwalsh.name/javascript-debounce-function,in underscore.js