Merge pull request #13383 from ahocevar/user-projection
User projection API
This commit is contained in:
@@ -7,7 +7,6 @@ docs: >
|
|||||||
makes it so the map view uses geographic coordinates (even if the view projection is
|
makes it so the map view uses geographic coordinates (even if the view projection is
|
||||||
not geographic).
|
not geographic).
|
||||||
tags: "geographic"
|
tags: "geographic"
|
||||||
experimental: true
|
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
<select id="mode">
|
<select id="mode">
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ docs: >
|
|||||||
makes it so the map view uses geographic coordinates (even if the view projection is
|
makes it so the map view uses geographic coordinates (even if the view projection is
|
||||||
not geographic).
|
not geographic).
|
||||||
tags: "geographic"
|
tags: "geographic"
|
||||||
experimental: true
|
|
||||||
resources:
|
resources:
|
||||||
- https://code.jquery.com/jquery-3.5.1.min.js
|
- https://code.jquery.com/jquery-3.5.1.min.js
|
||||||
- https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css
|
- https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css
|
||||||
|
|||||||
@@ -10,6 +10,5 @@ docs: >
|
|||||||
any geometry on each render frame. The `useGeographic` function is used in this example so that
|
any geometry on each render frame. The `useGeographic` function is used in this example so that
|
||||||
geometries can be in geographic coordinates.
|
geometries can be in geographic coordinates.
|
||||||
tags: "immediate, geographic"
|
tags: "immediate, geographic"
|
||||||
experimental: true
|
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
@@ -11,6 +11,5 @@ tags: "geographic, vector, WFS, tile, strategy, loading, server, maptiler"
|
|||||||
cloak:
|
cloak:
|
||||||
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
- key: get_your_own_D6rA4zTHduk6KOKTXzGB
|
||||||
value: Get your own API key at https://www.maptiler.com/cloud/
|
value: Get your own API key at https://www.maptiler.com/cloud/
|
||||||
experimental: true
|
|
||||||
---
|
---
|
||||||
<div id="map" class="map"></div>
|
<div id="map" class="map"></div>
|
||||||
|
|||||||
+5
-1
@@ -10,6 +10,7 @@ import {DEFAULT_TILE_SIZE} from './tilegrid/common.js';
|
|||||||
import {
|
import {
|
||||||
METERS_PER_UNIT,
|
METERS_PER_UNIT,
|
||||||
createProjection,
|
createProjection,
|
||||||
|
disableCoordinateWarning,
|
||||||
fromUserCoordinate,
|
fromUserCoordinate,
|
||||||
fromUserExtent,
|
fromUserExtent,
|
||||||
getUserProjection,
|
getUserProjection,
|
||||||
@@ -241,7 +242,7 @@ const DEFAULT_MIN_ZOOM = 0;
|
|||||||
* A View has a `projection`. The projection determines the
|
* A View has a `projection`. The projection determines the
|
||||||
* coordinate system of the center, and its units determine the units of the
|
* coordinate system of the center, and its units determine the units of the
|
||||||
* resolution (projection units per pixel). The default projection is
|
* resolution (projection units per pixel). The default projection is
|
||||||
* Spherical Mercator (EPSG:3857).
|
* Web Mercator (EPSG:3857).
|
||||||
*
|
*
|
||||||
* ### The view states
|
* ### The view states
|
||||||
*
|
*
|
||||||
@@ -406,6 +407,9 @@ class View extends BaseObject {
|
|||||||
if (options.extent) {
|
if (options.extent) {
|
||||||
options.extent = fromUserExtent(options.extent, this.projection_);
|
options.extent = fromUserExtent(options.extent, this.projection_);
|
||||||
}
|
}
|
||||||
|
if (options.projection) {
|
||||||
|
disableCoordinateWarning();
|
||||||
|
}
|
||||||
|
|
||||||
this.applyOptions_(options);
|
this.applyOptions_(options);
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-9
@@ -73,8 +73,8 @@ import {
|
|||||||
} from './proj/transforms.js';
|
} from './proj/transforms.js';
|
||||||
import {applyTransform, getWidth} from './extent.js';
|
import {applyTransform, getWidth} from './extent.js';
|
||||||
import {clamp, modulo} from './math.js';
|
import {clamp, modulo} from './math.js';
|
||||||
|
import {equals, getWorldsAway} from './coordinate.js';
|
||||||
import {getDistance} from './sphere.js';
|
import {getDistance} from './sphere.js';
|
||||||
import {getWorldsAway} from './coordinate.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A projection as {@link module:ol/proj/Projection}, SRS identifier
|
* A projection as {@link module:ol/proj/Projection}, SRS identifier
|
||||||
@@ -97,6 +97,16 @@ export {METERS_PER_UNIT};
|
|||||||
|
|
||||||
export {Projection};
|
export {Projection};
|
||||||
|
|
||||||
|
let showCoordinateWarning = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {boolean} [opt_disable = true] Disable console info about `useGeographic()`
|
||||||
|
*/
|
||||||
|
export function disableCoordinateWarning(opt_disable) {
|
||||||
|
const hide = opt_disable === undefined ? true : opt_disable;
|
||||||
|
showCoordinateWarning = !hide;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array<number>} input Input coordinate array.
|
* @param {Array<number>} input Input coordinate array.
|
||||||
* @param {Array<number>} [opt_output] Output array of coordinate values.
|
* @param {Array<number>} [opt_output] Output array of coordinate values.
|
||||||
@@ -386,6 +396,7 @@ export function addCoordinateTransforms(source, destination, forward, inverse) {
|
|||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
export function fromLonLat(coordinate, opt_projection) {
|
export function fromLonLat(coordinate, opt_projection) {
|
||||||
|
disableCoordinateWarning();
|
||||||
return transform(
|
return transform(
|
||||||
coordinate,
|
coordinate,
|
||||||
'EPSG:4326',
|
'EPSG:4326',
|
||||||
@@ -539,18 +550,17 @@ let userProjection = null;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the projection for coordinates supplied from and returned by API methods.
|
* Set the projection for coordinates supplied from and returned by API methods.
|
||||||
* Note that this method is not yet a part of the stable API. Support for user
|
* This includes all API methods except for those interacting with tile grids.
|
||||||
* projections is not yet complete and should be considered experimental.
|
|
||||||
* @param {ProjectionLike} projection The user projection.
|
* @param {ProjectionLike} projection The user projection.
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
export function setUserProjection(projection) {
|
export function setUserProjection(projection) {
|
||||||
userProjection = get(projection);
|
userProjection = get(projection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the user projection if set. Note that this method is not yet a part of
|
* Clear the user projection if set.
|
||||||
* the stable API. Support for user projections is not yet complete and should
|
* @api
|
||||||
* be considered experimental.
|
|
||||||
*/
|
*/
|
||||||
export function clearUserProjection() {
|
export function clearUserProjection() {
|
||||||
userProjection = null;
|
userProjection = null;
|
||||||
@@ -561,15 +571,16 @@ export function clearUserProjection() {
|
|||||||
* Note that this method is not yet a part of the stable API. Support for user
|
* Note that this method is not yet a part of the stable API. Support for user
|
||||||
* projections is not yet complete and should be considered experimental.
|
* projections is not yet complete and should be considered experimental.
|
||||||
* @return {Projection|null} The user projection (or null if not set).
|
* @return {Projection|null} The user projection (or null if not set).
|
||||||
|
* @api
|
||||||
*/
|
*/
|
||||||
export function getUserProjection() {
|
export function getUserProjection() {
|
||||||
return userProjection;
|
return userProjection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use geographic coordinates (WGS-84 datum) in API methods. Note that this
|
* Use geographic coordinates (WGS-84 datum) in API methods. This includes all API
|
||||||
* method is not yet a part of the stable API. Support for user projections is
|
* methods except for those interacting with tile grids.
|
||||||
* not yet complete and should be considered experimental.
|
* @api
|
||||||
*/
|
*/
|
||||||
export function useGeographic() {
|
export function useGeographic() {
|
||||||
setUserProjection('EPSG:4326');
|
setUserProjection('EPSG:4326');
|
||||||
@@ -598,6 +609,20 @@ export function toUserCoordinate(coordinate, sourceProjection) {
|
|||||||
*/
|
*/
|
||||||
export function fromUserCoordinate(coordinate, destProjection) {
|
export function fromUserCoordinate(coordinate, destProjection) {
|
||||||
if (!userProjection) {
|
if (!userProjection) {
|
||||||
|
if (
|
||||||
|
showCoordinateWarning &&
|
||||||
|
!equals(coordinate, [0, 0]) &&
|
||||||
|
coordinate[0] >= -180 &&
|
||||||
|
coordinate[0] <= 180 &&
|
||||||
|
coordinate[1] >= -90 &&
|
||||||
|
coordinate[1] <= 90
|
||||||
|
) {
|
||||||
|
showCoordinateWarning = false;
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.warn(
|
||||||
|
'Call useGeographic() ol/proj once to work with [longitude, latitude] coordinates.'
|
||||||
|
);
|
||||||
|
}
|
||||||
return coordinate;
|
return coordinate;
|
||||||
}
|
}
|
||||||
return transform(coordinate, userProjection, destProjection);
|
return transform(coordinate, userProjection, destProjection);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import Projection from '../../../src/ol/proj/Projection.js';
|
import Projection from '../../../src/ol/proj/Projection.js';
|
||||||
import Units from '../../../src/ol/proj/Units.js';
|
import Units from '../../../src/ol/proj/Units.js';
|
||||||
|
import View from '../../../src/ol/View.js';
|
||||||
import expect from '../expect.js';
|
import expect from '../expect.js';
|
||||||
import proj4 from 'proj4';
|
import proj4 from 'proj4';
|
||||||
import {HALF_SIZE} from '../../../src/ol/proj/epsg3857.js';
|
import {HALF_SIZE} from '../../../src/ol/proj/epsg3857.js';
|
||||||
@@ -8,6 +9,7 @@ import {
|
|||||||
addCommon,
|
addCommon,
|
||||||
clearAllProjections,
|
clearAllProjections,
|
||||||
clearUserProjection,
|
clearUserProjection,
|
||||||
|
disableCoordinateWarning,
|
||||||
equivalent,
|
equivalent,
|
||||||
fromLonLat,
|
fromLonLat,
|
||||||
fromUserCoordinate,
|
fromUserCoordinate,
|
||||||
@@ -890,4 +892,43 @@ describe('ol/proj.js', function () {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Console info about `setUserProjection`', function () {
|
||||||
|
let originalConsole, callCount;
|
||||||
|
beforeEach(function () {
|
||||||
|
disableCoordinateWarning(false);
|
||||||
|
originalConsole = console;
|
||||||
|
callCount = 0;
|
||||||
|
global.console = {
|
||||||
|
...console,
|
||||||
|
warn: () => ++callCount,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
afterEach(function () {
|
||||||
|
global.console = originalConsole;
|
||||||
|
clearUserProjection();
|
||||||
|
});
|
||||||
|
it('is shown once when suspicious coordinates are used', function () {
|
||||||
|
const view = new View({
|
||||||
|
center: [16, 48],
|
||||||
|
});
|
||||||
|
view.setCenter([15, 47]);
|
||||||
|
expect(callCount).to.be(1);
|
||||||
|
});
|
||||||
|
it('is not shown when fromLonLat() is used', function () {
|
||||||
|
const view = new View({
|
||||||
|
center: fromLonLat([16, 48]),
|
||||||
|
});
|
||||||
|
view.setCenter(fromLonLat([15, 47]));
|
||||||
|
expect(callCount).to.be(0);
|
||||||
|
});
|
||||||
|
it('is not shown when useGeographic() is used', function () {
|
||||||
|
useGeographic();
|
||||||
|
const view = new View({
|
||||||
|
center: [16, 48],
|
||||||
|
});
|
||||||
|
view.setCenter([15, 47]);
|
||||||
|
expect(callCount).to.be(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user