Avoid panning off the edge of the world

This commit is contained in:
Tim Schaub
2019-05-14 19:34:03 -06:00
parent 72551ab506
commit 217c6ba764
4 changed files with 59 additions and 10 deletions

View File

@@ -32,9 +32,9 @@ Previously, this options only constrained the view *center*. This behaviour can
As a side effect, the view `rotate` method is gone and has been replaced with `adjustRotation` which takes a delta as input.
##### Zoom is constrained so only one world is visible
##### The view is constrained so only one world is visible
Previously, maps showed multiple worlds at low zoom levels. Now, the view is restricted to show only one world. To get the previous behavior, configure the `ol/View` with `multiWorld: true`.
Previously, maps showed multiple worlds at low zoom levels. In addition, it used to be possible to pan off the north or south edge of the world. Now, the view is restricted to show only one world, and you cannot pan off the edge. To get the previous behavior, configure the `ol/View` with `multiWorld: true`.
##### Removal of deprecated methods

View File

@@ -42,7 +42,8 @@ const layer = new VectorLayer({
const view = new View({
center: [-9.5, 78],
zoom: 2,
projection: 'EPSG:4326'
projection: 'EPSG:4326',
multiWorld: true
});
new Map({
pixelRatio: 1,

View File

@@ -1409,11 +1409,19 @@ function animationCallback(callback, returnValue) {
*/
export function createCenterConstraint(options) {
if (options.extent !== undefined) {
return createExtent(options.extent, options.constrainOnlyCenter,
options.smoothExtentConstraint !== undefined ? options.smoothExtentConstraint : true);
} else {
return centerNone;
const smooth = options.smoothExtentConstraint !== undefined ? options.smoothExtentConstraint : true;
return createExtent(options.extent, options.constrainOnlyCenter, smooth);
}
const projection = createProjection(options.projection, 'EPSG:3857');
if (options.multiWorld !== true && projection.isGlobal()) {
const extent = projection.getExtent().slice();
extent[0] = -Infinity;
extent[2] = Infinity;
return createExtent(extent, false, false);
}
return centerNone;
}

View File

@@ -100,10 +100,50 @@ describe('ol.View', function() {
describe('with no options', function() {
it('gives a correct center constraint function', function() {
const options = {};
const size = [512, 256];
const resolution = 1e5;
const fn = createCenterConstraint(options);
expect(fn([0, 0])).to.eql([0, 0]);
expect(fn(undefined)).to.eql(undefined);
expect(fn([42, -100])).to.eql([42, -100]);
expect(fn([0, 0], resolution, size)).to.eql([0, 0]);
expect(fn([42, -100], resolution, size)).to.eql([42, -100]);
});
});
describe('panning off the edge of the world', function() {
it('disallows going north off the world', function() {
const options = {
projection: 'EPSG:4326'
};
const size = [360, 180];
const resolution = 0.5;
const fn = createCenterConstraint(options);
expect(fn([0, 0], resolution, size)).to.eql([0, 0]);
expect(fn([0, 60], resolution, size)).to.eql([0, 45]);
expect(fn([180, 60], resolution, size)).to.eql([180, 45]);
expect(fn([-180, 60], resolution, size)).to.eql([-180, 45]);
});
it('disallows going south off the world', function() {
const options = {
projection: 'EPSG:4326'
};
const size = [360, 180];
const resolution = 0.5;
const fn = createCenterConstraint(options);
expect(fn([0, 0], resolution, size)).to.eql([0, 0]);
expect(fn([0, -60], resolution, size)).to.eql([0, -45]);
expect(fn([180, -60], resolution, size)).to.eql([180, -45]);
expect(fn([-180, -60], resolution, size)).to.eql([-180, -45]);
});
});
describe('with multiWorld: true', function() {
it('gives a correct center constraint function', function() {
const options = {multiWorld: true};
const size = [512, 256];
const resolution = 1e5;
const fn = createCenterConstraint(options);
expect(fn([0, 0], resolution, size)).to.eql([0, 0]);
expect(fn([42, -100], resolution, size)).to.eql([42, -100]);
});
});