merged with upstream and improved key handling
This commit is contained in:
@@ -14,7 +14,7 @@ class AssertionError extends Error {
|
||||
* @param {number} code Error code.
|
||||
*/
|
||||
constructor(code) {
|
||||
const path = VERSION.split('-')[0];
|
||||
const path = VERSION === 'latest' ? VERSION : 'v' + VERSION.split('-')[0];
|
||||
const message = 'Assertion failed. See https://openlayers.org/en/' + path +
|
||||
'/doc/errors/#' + code + ' for details.';
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ const Property = {
|
||||
export class CollectionEvent extends Event {
|
||||
|
||||
/**
|
||||
* @param {import("./CollectionEventType.js").default} type Type.
|
||||
* @param {CollectionEventType} type Type.
|
||||
* @param {*=} opt_element Element.
|
||||
*/
|
||||
constructor(type, opt_element) {
|
||||
@@ -56,6 +56,8 @@ export class CollectionEvent extends Event {
|
||||
* Collection; they trigger events on the appropriate object, not on the
|
||||
* Collection as a whole.
|
||||
*
|
||||
* @fires CollectionEvent
|
||||
*
|
||||
* @template T
|
||||
* @api
|
||||
*/
|
||||
@@ -160,7 +162,7 @@ class Collection extends BaseObject {
|
||||
* @api
|
||||
*/
|
||||
getLength() {
|
||||
return /** @type {number} */ (this.get(Property.LENGTH));
|
||||
return this.get(Property.LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
export default {
|
||||
/**
|
||||
* Triggered when an item is added to the collection.
|
||||
* @event module:ol/Collection~CollectionEvent#add
|
||||
* @event module:ol/Collection.CollectionEvent#add
|
||||
* @api
|
||||
*/
|
||||
ADD: 'add',
|
||||
/**
|
||||
* Triggered when an item is removed from the collection.
|
||||
* @event module:ol/Collection~CollectionEvent#remove
|
||||
* @event module:ol/Collection.CollectionEvent#remove
|
||||
* @api
|
||||
*/
|
||||
REMOVE: 'remove'
|
||||
|
||||
@@ -5,8 +5,14 @@ import {assert} from './asserts.js';
|
||||
import {listen, unlisten, unlistenByKey} from './events.js';
|
||||
import EventType from './events/EventType.js';
|
||||
import BaseObject, {getChangeEventType} from './Object.js';
|
||||
import Geometry from './geom/Geometry.js';
|
||||
import Style from './style/Style.js';
|
||||
|
||||
/**
|
||||
* @typedef {typeof Feature|typeof import("./render/Feature.js").default} FeatureClass
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Feature|import("./render/Feature.js").default} FeatureLike
|
||||
*/
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
@@ -78,7 +84,7 @@ class Feature extends BaseObject {
|
||||
/**
|
||||
* User provided style.
|
||||
* @private
|
||||
* @type {import("./style/Style.js").default|Array<import("./style/Style.js").default>|import("./style/Style.js").StyleFunction}
|
||||
* @type {import("./style/Style.js").StyleLike}
|
||||
*/
|
||||
this.style_ = null;
|
||||
|
||||
@@ -98,11 +104,9 @@ class Feature extends BaseObject {
|
||||
this, getChangeEventType(this.geometryName_),
|
||||
this.handleGeometryChanged_, this);
|
||||
|
||||
if (opt_geometryOrProperties !== undefined) {
|
||||
if (opt_geometryOrProperties instanceof Geometry ||
|
||||
!opt_geometryOrProperties) {
|
||||
/** @type {?Geometry} */
|
||||
const geometry = opt_geometryOrProperties;
|
||||
if (opt_geometryOrProperties) {
|
||||
if (typeof /** @type {?} */ (opt_geometryOrProperties).getSimplifiedGeometry === 'function') {
|
||||
const geometry = /** @type {import("./geom/Geometry.js").default} */ (opt_geometryOrProperties);
|
||||
this.setGeometry(geometry);
|
||||
} else {
|
||||
/** @type {Object<string, *>} */
|
||||
@@ -171,7 +175,7 @@ class Feature extends BaseObject {
|
||||
/**
|
||||
* Get the feature's style. Will return what was provided to the
|
||||
* {@link module:ol/Feature~Feature#setStyle} method.
|
||||
* @return {import("./style/Style.js").default|Array<import("./style/Style.js").default>|import("./style/Style.js").StyleFunction} The feature style.
|
||||
* @return {import("./style/Style.js").StyleLike} The feature style.
|
||||
* @api
|
||||
*/
|
||||
getStyle() {
|
||||
@@ -226,7 +230,7 @@ class Feature extends BaseObject {
|
||||
* Set the style for the feature. This can be a single style object, an array
|
||||
* of styles, or a function that takes a resolution and returns an array of
|
||||
* styles. If it is `null` the feature has no style (a `null` style).
|
||||
* @param {import("./style/Style.js").default|Array<import("./style/Style.js").default>|import("./style/Style.js").StyleFunction} style Style for this feature.
|
||||
* @param {import("./style/Style.js").StyleLike} style Style for this feature.
|
||||
* @api
|
||||
* @fires module:ol/events/Event~Event#event:change
|
||||
*/
|
||||
@@ -272,9 +276,9 @@ class Feature extends BaseObject {
|
||||
|
||||
/**
|
||||
* Convert the provided object into a feature style function. Functions passed
|
||||
* through unchanged. Arrays of import("./style/Style.js").default or single style objects wrapped
|
||||
* through unchanged. Arrays of Style or single style objects wrapped
|
||||
* in a new feature style function.
|
||||
* @param {import("./style/Style.js").StyleFunction|!Array<import("./style/Style.js").default>|!import("./style/Style.js").default} obj
|
||||
* @param {!import("./style/Style.js").StyleFunction|!Array<import("./style/Style.js").default>|!import("./style/Style.js").default} obj
|
||||
* A feature style function, a single style, or an array of styles.
|
||||
* @return {import("./style/Style.js").StyleFunction} A style function.
|
||||
*/
|
||||
@@ -289,9 +293,10 @@ export function createStyleFunction(obj) {
|
||||
if (Array.isArray(obj)) {
|
||||
styles = obj;
|
||||
} else {
|
||||
assert(obj instanceof Style,
|
||||
assert(typeof /** @type {?} */ (obj).getZIndex === 'function',
|
||||
41); // Expected an `import("./style/Style.js").Style` or an array of `import("./style/Style.js").Style`
|
||||
styles = [obj];
|
||||
const style = /** @type {import("./style/Style.js").default} */ (obj);
|
||||
styles = [style];
|
||||
}
|
||||
return function() {
|
||||
return styles;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import GeolocationProperty from './GeolocationProperty.js';
|
||||
import BaseObject, {getChangeEventType} from './Object.js';
|
||||
import {listen} from './events.js';
|
||||
import Event from './events/Event.js';
|
||||
import EventType from './events/EventType.js';
|
||||
import {circular as circularPolygon} from './geom/Polygon.js';
|
||||
import {GEOLOCATION} from './has.js';
|
||||
@@ -11,6 +12,30 @@ import {toRadians} from './math.js';
|
||||
import {get as getProjection, getTransformFromProjections, identityTransform} from './proj.js';
|
||||
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Events emitted on Geolocation error.
|
||||
*/
|
||||
class GeolocationError extends Event {
|
||||
/**
|
||||
* @param {PositionError} error error object.
|
||||
*/
|
||||
constructor(error) {
|
||||
super(EventType.ERROR);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.code = error.code;
|
||||
|
||||
/**
|
||||
* @type {string}
|
||||
*/
|
||||
this.message = error.message;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {boolean} [tracking=false] Start Tracking right after
|
||||
@@ -174,9 +199,8 @@ class Geolocation extends BaseObject {
|
||||
* @param {PositionError} error error object.
|
||||
*/
|
||||
positionError_(error) {
|
||||
error.type = EventType.ERROR;
|
||||
this.setTracking(false);
|
||||
this.dispatchEvent(/** @type {{type: string, target: undefined}} */ (error));
|
||||
this.dispatchEvent(new GeolocationError(error));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ import Text from './style/Text.js';
|
||||
|
||||
|
||||
/**
|
||||
* @type {import("./style/Stroke.js").default}
|
||||
* @type {Stroke}
|
||||
* @private
|
||||
* @const
|
||||
*/
|
||||
@@ -26,7 +26,6 @@ const DEFAULT_STROKE_STYLE = new Stroke({
|
||||
});
|
||||
|
||||
/**
|
||||
* TODO can be configurable
|
||||
* @type {Array<number>}
|
||||
* @private
|
||||
*/
|
||||
@@ -36,7 +35,7 @@ const INTERVALS = [
|
||||
|
||||
/**
|
||||
* @typedef {Object} GraticuleLabelDataType
|
||||
* @property {import("./geom/Point.js").default} geom
|
||||
* @property {Point} geom
|
||||
* @property {string} text
|
||||
*/
|
||||
|
||||
@@ -50,7 +49,7 @@ const INTERVALS = [
|
||||
* appropriate for conformal projections like Spherical Mercator. If you
|
||||
* increase the value, more lines will be drawn and the drawing performance will
|
||||
* decrease.
|
||||
* @property {import("./style/Stroke.js").default} [strokeStyle='rgba(0,0,0,0.2)'] The
|
||||
* @property {Stroke} [strokeStyle='rgba(0,0,0,0.2)'] The
|
||||
* stroke style to use for drawing the graticule. If not provided, a not fully
|
||||
* opaque black will be used.
|
||||
* @property {number} [targetSize=100] The target size of the graticule cells,
|
||||
@@ -71,7 +70,7 @@ const INTERVALS = [
|
||||
* @property {number} [latLabelPosition=1] Latitude label position in fractions
|
||||
* (0..1) of view extent. 0 means at the left of the viewport, 1 means at the
|
||||
* right.
|
||||
* @property {import("./style/Text.js").default} [lonLabelStyle] Longitude label text
|
||||
* @property {Text} [lonLabelStyle] Longitude label text
|
||||
* style. If not provided, the following style will be used:
|
||||
* ```js
|
||||
* new Text({
|
||||
@@ -89,7 +88,7 @@ const INTERVALS = [
|
||||
* Note that the default's `textBaseline` configuration will not work well for
|
||||
* `lonLabelPosition` configurations that position labels close to the top of
|
||||
* the viewport.
|
||||
* @property {import("./style/Text.js").default} [latLabelStyle] Latitude label text style.
|
||||
* @property {Text} [latLabelStyle] Latitude label text style.
|
||||
* If not provided, the following style will be used:
|
||||
* ```js
|
||||
* new Text({
|
||||
@@ -107,6 +106,11 @@ const INTERVALS = [
|
||||
* Note that the default's `textAlign` configuration will not work well for
|
||||
* `latLabelPosition` configurations that position labels close to the left of
|
||||
* the viewport.
|
||||
* @property {Array<number>} [intervals=[90, 45, 30, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.01, 0.005, 0.002, 0.001]]
|
||||
* Intervals (in degrees) for the graticule. Example to limit graticules to 30 and 10 degrees intervals:
|
||||
* ```js
|
||||
* [30, 10]
|
||||
* ```
|
||||
*/
|
||||
|
||||
|
||||
@@ -200,19 +204,19 @@ class Graticule {
|
||||
this.maxLines_ = options.maxLines !== undefined ? options.maxLines : 100;
|
||||
|
||||
/**
|
||||
* @type {Array<import("./geom/LineString.js").default>}
|
||||
* @type {Array<LineString>}
|
||||
* @private
|
||||
*/
|
||||
this.meridians_ = [];
|
||||
|
||||
/**
|
||||
* @type {Array<import("./geom/LineString.js").default>}
|
||||
* @type {Array<LineString>}
|
||||
* @private
|
||||
*/
|
||||
this.parallels_ = [];
|
||||
|
||||
/**
|
||||
* @type {import("./style/Stroke.js").default}
|
||||
* @type {Stroke}
|
||||
* @private
|
||||
*/
|
||||
this.strokeStyle_ = options.strokeStyle !== undefined ? options.strokeStyle : DEFAULT_STROKE_STYLE;
|
||||
@@ -282,7 +286,7 @@ class Graticule {
|
||||
options.latLabelPosition;
|
||||
|
||||
/**
|
||||
* @type {import("./style/Text.js").default}
|
||||
* @type {Text}
|
||||
* @private
|
||||
*/
|
||||
this.lonLabelStyle_ = options.lonLabelStyle !== undefined ? options.lonLabelStyle :
|
||||
@@ -299,7 +303,7 @@ class Graticule {
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {import("./style/Text.js").default}
|
||||
* @type {Text}
|
||||
* @private
|
||||
*/
|
||||
this.latLabelStyle_ = options.latLabelStyle !== undefined ? options.latLabelStyle :
|
||||
@@ -319,6 +323,12 @@ class Graticule {
|
||||
this.parallelsLabels_ = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Array<number>}
|
||||
* @private
|
||||
*/
|
||||
this.intervals_ = options.intervals !== undefined ? options.intervals : INTERVALS;
|
||||
|
||||
this.setMap(options.map !== undefined ? options.map : null);
|
||||
}
|
||||
|
||||
@@ -348,10 +358,10 @@ class Graticule {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./geom/LineString.js").default} lineString Meridian
|
||||
* @param {LineString} lineString Meridian
|
||||
* @param {import("./extent.js").Extent} extent Extent.
|
||||
* @param {number} index Index.
|
||||
* @return {import("./geom/Point.js").default} Meridian point.
|
||||
* @return {Point} Meridian point.
|
||||
* @private
|
||||
*/
|
||||
getMeridianPoint_(lineString, extent, index) {
|
||||
@@ -398,10 +408,10 @@ class Graticule {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./geom/LineString.js").default} lineString Parallels.
|
||||
* @param {LineString} lineString Parallels.
|
||||
* @param {import("./extent.js").Extent} extent Extent.
|
||||
* @param {number} index Index.
|
||||
* @return {import("./geom/Point.js").default} Parallel point.
|
||||
* @return {Point} Parallel point.
|
||||
* @private
|
||||
*/
|
||||
getParallelPoint_(lineString, extent, index) {
|
||||
@@ -530,8 +540,8 @@ class Graticule {
|
||||
const p1 = [];
|
||||
/** @type {Array<number>} **/
|
||||
const p2 = [];
|
||||
for (let i = 0, ii = INTERVALS.length; i < ii; ++i) {
|
||||
const delta = INTERVALS[i] / 2;
|
||||
for (let i = 0, ii = this.intervals_.length; i < ii; ++i) {
|
||||
const delta = this.intervals_[i] / 2;
|
||||
p1[0] = centerLon - delta;
|
||||
p1[1] = centerLat - delta;
|
||||
p2[0] = centerLon + delta;
|
||||
@@ -542,7 +552,7 @@ class Graticule {
|
||||
if (dist <= target) {
|
||||
break;
|
||||
}
|
||||
interval = INTERVALS[i];
|
||||
interval = this.intervals_[i];
|
||||
}
|
||||
return interval;
|
||||
}
|
||||
@@ -561,7 +571,7 @@ class Graticule {
|
||||
* @param {number} minLat Minimal latitude.
|
||||
* @param {number} maxLat Maximal latitude.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {import("./geom/LineString.js").default} The meridian line string.
|
||||
* @return {LineString} The meridian line string.
|
||||
* @param {number} index Index.
|
||||
* @private
|
||||
*/
|
||||
@@ -579,7 +589,7 @@ class Graticule {
|
||||
|
||||
/**
|
||||
* Get the list of meridians. Meridians are lines of equal longitude.
|
||||
* @return {Array<import("./geom/LineString.js").default>} The meridians.
|
||||
* @return {Array<LineString>} The meridians.
|
||||
* @api
|
||||
*/
|
||||
getMeridians() {
|
||||
@@ -591,7 +601,7 @@ class Graticule {
|
||||
* @param {number} minLon Minimal longitude.
|
||||
* @param {number} maxLon Maximal longitude.
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {import("./geom/LineString.js").default} The parallel line string.
|
||||
* @return {LineString} The parallel line string.
|
||||
* @param {number} index Index.
|
||||
* @private
|
||||
*/
|
||||
@@ -609,7 +619,7 @@ class Graticule {
|
||||
|
||||
/**
|
||||
* Get the list of parallels. Parallels are lines of equal latitude.
|
||||
* @return {Array<import("./geom/LineString.js").default>} The parallels.
|
||||
* @return {Array<LineString>} The parallels.
|
||||
* @api
|
||||
*/
|
||||
getParallels() {
|
||||
|
||||
@@ -64,7 +64,7 @@ class ImageWrapper extends ImageBase {
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {import("./ImageState.js").default}
|
||||
* @type {ImageState}
|
||||
*/
|
||||
this.state = ImageState.IDLE;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* @module ol/ImageBase
|
||||
*/
|
||||
import {abstract} from './util.js';
|
||||
import EventTarget from './events/Target.js';
|
||||
import EventType from './events/EventType.js';
|
||||
|
||||
@@ -63,7 +64,9 @@ class ImageBase extends EventTarget {
|
||||
* @abstract
|
||||
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
|
||||
*/
|
||||
getImage() {}
|
||||
getImage() {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} PixelRatio.
|
||||
@@ -90,7 +93,9 @@ class ImageBase extends EventTarget {
|
||||
* Load not yet loaded URI.
|
||||
* @abstract
|
||||
*/
|
||||
load() {}
|
||||
load() {
|
||||
abstract();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import ImageState from './ImageState.js';
|
||||
* If any error occurs during drawing, the "done" callback should be called with
|
||||
* that error.
|
||||
*
|
||||
* @typedef {function(function(Error))} Loader
|
||||
* @typedef {function(function(Error=))} Loader
|
||||
*/
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ class ImageCanvas extends ImageBase {
|
||||
|
||||
/**
|
||||
* Handle async drawing complete.
|
||||
* @param {Error} err Any error during drawing.
|
||||
* @param {Error=} err Any error during drawing.
|
||||
* @private
|
||||
*/
|
||||
handleLoad_(err) {
|
||||
|
||||
@@ -7,17 +7,12 @@ import {createCanvasContext2D} from './dom.js';
|
||||
import {listenOnce, unlistenByKey} from './events.js';
|
||||
import EventType from './events/EventType.js';
|
||||
|
||||
/**
|
||||
* @typedef {function(new: ImageTile, import("./tilecoord.js").TileCoord,
|
||||
* import("./TileState.js").default, string, ?string, import("./Tile.js").LoadFunction)} TileClass
|
||||
* @api
|
||||
*/
|
||||
|
||||
class ImageTile extends Tile {
|
||||
|
||||
/**
|
||||
* @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
|
||||
* @param {import("./TileState.js").default} state State.
|
||||
* @param {TileState} state State.
|
||||
* @param {string} src Image source URI.
|
||||
* @param {?string} crossOrigin Cross origin.
|
||||
* @param {import("./Tile.js").LoadFunction} tileLoadFunction Tile load function.
|
||||
@@ -114,7 +109,8 @@ class ImageTile extends Tile {
|
||||
* @private
|
||||
*/
|
||||
handleImageLoad_() {
|
||||
if (this.image_.naturalWidth && this.image_.naturalHeight) {
|
||||
const image = /** @type {HTMLImageElement} */ (this.image_);
|
||||
if (image.naturalWidth && image.naturalHeight) {
|
||||
this.state = TileState.LOADED;
|
||||
} else {
|
||||
this.state = TileState.EMPTY;
|
||||
|
||||
@@ -27,10 +27,10 @@ class MapBrowserEventHandler extends EventTarget {
|
||||
this.map_ = map;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @type {any}
|
||||
* @private
|
||||
*/
|
||||
this.clickTimeoutId_ = 0;
|
||||
this.clickTimeoutId_;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
@@ -118,17 +118,17 @@ class MapBrowserEventHandler extends EventTarget {
|
||||
let newEvent = new MapBrowserPointerEvent(
|
||||
MapBrowserEventType.CLICK, this.map_, pointerEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
if (this.clickTimeoutId_ !== 0) {
|
||||
if (this.clickTimeoutId_ !== undefined) {
|
||||
// double-click
|
||||
clearTimeout(this.clickTimeoutId_);
|
||||
this.clickTimeoutId_ = 0;
|
||||
this.clickTimeoutId_ = undefined;
|
||||
newEvent = new MapBrowserPointerEvent(
|
||||
MapBrowserEventType.DBLCLICK, this.map_, pointerEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
} else {
|
||||
// click
|
||||
this.clickTimeoutId_ = setTimeout(function() {
|
||||
this.clickTimeoutId_ = 0;
|
||||
this.clickTimeoutId_ = undefined;
|
||||
const newEvent = new MapBrowserPointerEvent(
|
||||
MapBrowserEventType.SINGLECLICK, this.map_, pointerEvent);
|
||||
this.dispatchEvent(newEvent);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
export default {
|
||||
/**
|
||||
* Triggered when a property is changed.
|
||||
* @event module:ol/Object~ObjectEvent#propertychange
|
||||
* @event module:ol/Object.ObjectEvent#propertychange
|
||||
* @api
|
||||
*/
|
||||
PROPERTYCHANGE: 'propertychange'
|
||||
|
||||
@@ -22,7 +22,7 @@ import {containsExtent} from './extent.js';
|
||||
* shifts the overlay down.
|
||||
* @property {import("./coordinate.js").Coordinate} [position] The overlay position
|
||||
* in map projection.
|
||||
* @property {import("./OverlayPositioning.js").default} [positioning='top-left'] Defines how
|
||||
* @property {OverlayPositioning} [positioning='top-left'] Defines how
|
||||
* the overlay is actually positioned with respect to its `position` property.
|
||||
* Possible values are `'bottom-left'`, `'bottom-center'`, `'bottom-right'`,
|
||||
* `'center-left'`, `'center-center'`, `'center-right'`, `'top-left'`,
|
||||
@@ -205,7 +205,7 @@ class Overlay extends BaseObject {
|
||||
this.setOffset(options.offset !== undefined ? options.offset : [0, 0]);
|
||||
|
||||
this.setPositioning(options.positioning !== undefined ?
|
||||
/** @type {import("./OverlayPositioning.js").default} */ (options.positioning) :
|
||||
/** @type {OverlayPositioning} */ (options.positioning) :
|
||||
OverlayPositioning.TOP_LEFT);
|
||||
|
||||
if (options.position !== undefined) {
|
||||
@@ -271,14 +271,14 @@ class Overlay extends BaseObject {
|
||||
|
||||
/**
|
||||
* Get the current positioning of this overlay.
|
||||
* @return {import("./OverlayPositioning.js").default} How the overlay is positioned
|
||||
* @return {OverlayPositioning} How the overlay is positioned
|
||||
* relative to its point on the map.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getPositioning() {
|
||||
return (
|
||||
/** @type {import("./OverlayPositioning.js").default} */ (this.get(Property.POSITIONING))
|
||||
/** @type {OverlayPositioning} */ (this.get(Property.POSITIONING))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -469,7 +469,7 @@ class Overlay extends BaseObject {
|
||||
|
||||
/**
|
||||
* Set the positioning for this overlay.
|
||||
* @param {import("./OverlayPositioning.js").default} positioning how the overlay is
|
||||
* @param {OverlayPositioning} positioning how the overlay is
|
||||
* positioned relative to its point on the map.
|
||||
* @observable
|
||||
* @api
|
||||
|
||||
@@ -42,7 +42,7 @@ import {create as createTransform, apply as applyTransform} from './transform.js
|
||||
* @property {null|import("./extent.js").Extent} extent
|
||||
* @property {import("./coordinate.js").Coordinate} focus
|
||||
* @property {number} index
|
||||
* @property {Object<number, import("./layer/Layer.js").State>} layerStates
|
||||
* @property {Object<string, import("./layer/Layer.js").State>} layerStates
|
||||
* @property {Array<import("./layer/Layer.js").State>} layerStatesArray
|
||||
* @property {import("./transform.js").Transform} pixelToCoordinateTransform
|
||||
* @property {Array<PostRenderFunction>} postRenderFunctions
|
||||
@@ -88,7 +88,7 @@ import {create as createTransform, apply as applyTransform} from './transform.js
|
||||
* @typedef {Object} MapOptions
|
||||
* @property {Collection<import("./control/Control.js").default>|Array<import("./control/Control.js").default>} [controls]
|
||||
* Controls initially added to the map. If not specified,
|
||||
* {@link module:ol/control/util~defaults} is used.
|
||||
* {@link module:ol/control~defaults} is used.
|
||||
* @property {number} [pixelRatio=window.devicePixelRatio] The ratio between
|
||||
* physical pixels and device-independent pixels (dips) on the device.
|
||||
* @property {Collection<import("./interaction/Interaction.js").default>|Array<import("./interaction/Interaction.js").default>} [interactions]
|
||||
@@ -102,7 +102,7 @@ import {create as createTransform, apply as applyTransform} from './transform.js
|
||||
* map target (i.e. the user-provided div for the map). If this is not
|
||||
* `document`, the target element needs to be focused for key events to be
|
||||
* emitted, requiring that the target element has a `tabindex` attribute.
|
||||
* @property {Array<import("./layer/Base.js").default>|Collection<import("./layer/Base.js").default>} [layers]
|
||||
* @property {Array<import("./layer/Base.js").default>|Collection<import("./layer/Base.js").default>|LayerGroup} [layers]
|
||||
* Layers. If this is not defined, a map with no layers will be rendered. Note
|
||||
* that layers are rendered in the order supplied, so if you want, for example,
|
||||
* a vector layer to appear on top of a tile layer, it must come after the tile
|
||||
@@ -464,6 +464,10 @@ class PluggableMap extends BaseObject {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {import("./renderer/Map.js").default} The map renderer
|
||||
*/
|
||||
createRenderer() {
|
||||
throw new Error('Use a map type that has a createRenderer method');
|
||||
}
|
||||
@@ -546,7 +550,7 @@ class PluggableMap extends BaseObject {
|
||||
* callback with each intersecting feature. Layers included in the detection can
|
||||
* be configured through the `layerFilter` option in `opt_options`.
|
||||
* @param {import("./pixel.js").Pixel} pixel Pixel.
|
||||
* @param {function(this: S, (import("./Feature.js").default|import("./render/Feature.js").default),
|
||||
* @param {function(this: S, import("./Feature.js").FeatureLike,
|
||||
* import("./layer/Layer.js").default): T} callback Feature callback. The callback will be
|
||||
* called with two arguments. The first argument is one
|
||||
* {@link module:ol/Feature feature} or
|
||||
@@ -565,7 +569,8 @@ class PluggableMap extends BaseObject {
|
||||
return;
|
||||
}
|
||||
const coordinate = this.getCoordinateFromPixel(pixel);
|
||||
opt_options = opt_options !== undefined ? opt_options : {};
|
||||
opt_options = opt_options !== undefined ? opt_options :
|
||||
/** @type {AtPixelOptions} */ ({});
|
||||
const hitTolerance = opt_options.hitTolerance !== undefined ?
|
||||
opt_options.hitTolerance * this.frameState_.pixelRatio : 0;
|
||||
const layerFilter = opt_options.layerFilter !== undefined ?
|
||||
@@ -579,7 +584,7 @@ class PluggableMap extends BaseObject {
|
||||
* Get all features that intersect a pixel on the viewport.
|
||||
* @param {import("./pixel.js").Pixel} pixel Pixel.
|
||||
* @param {AtPixelOptions=} opt_options Optional options.
|
||||
* @return {Array<import("./Feature.js").default|import("./render/Feature.js").default>} The detected features or
|
||||
* @return {Array<import("./Feature.js").FeatureLike>} The detected features or
|
||||
* `null` if none were found.
|
||||
* @api
|
||||
*/
|
||||
@@ -637,7 +642,8 @@ class PluggableMap extends BaseObject {
|
||||
return false;
|
||||
}
|
||||
const coordinate = this.getCoordinateFromPixel(pixel);
|
||||
opt_options = opt_options !== undefined ? opt_options : {};
|
||||
opt_options = opt_options !== undefined ? opt_options :
|
||||
/** @type {AtPixelOptions} */ ({});
|
||||
const layerFilter = opt_options.layerFilter !== undefined ? opt_options.layerFilter : TRUE;
|
||||
const hitTolerance = opt_options.hitTolerance !== undefined ?
|
||||
opt_options.hitTolerance * this.frameState_.pixelRatio : 0;
|
||||
@@ -657,13 +663,16 @@ class PluggableMap extends BaseObject {
|
||||
|
||||
/**
|
||||
* Returns the map pixel position for a browser event relative to the viewport.
|
||||
* @param {Event} event Event.
|
||||
* @param {Event|TouchEvent} event Event.
|
||||
* @return {import("./pixel.js").Pixel} Pixel.
|
||||
* @api
|
||||
*/
|
||||
getEventPixel(event) {
|
||||
const viewportPosition = this.viewport_.getBoundingClientRect();
|
||||
const eventPosition = event.changedTouches ? event.changedTouches[0] : event;
|
||||
const eventPosition = 'changedTouches' in event ?
|
||||
/** @type {TouchEvent} */ (event).changedTouches[0] :
|
||||
/** @type {MouseEvent} */ (event);
|
||||
|
||||
return [
|
||||
eventPosition.clientX - viewportPosition.left,
|
||||
eventPosition.clientY - viewportPosition.top
|
||||
@@ -963,7 +972,7 @@ class PluggableMap extends BaseObject {
|
||||
tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads);
|
||||
}
|
||||
}
|
||||
if (frameState && this.hasListener(MapEventType.RENDERCOMPLETE) && !frameState.animate &&
|
||||
if (frameState && this.hasListener(RenderEventType.RENDERCOMPLETE) && !frameState.animate &&
|
||||
!this.tileQueue_.getTilesLoading() && !getLoading(this.getLayers().getArray())) {
|
||||
this.renderer_.dispatchRenderEvent(RenderEventType.RENDERCOMPLETE, frameState);
|
||||
}
|
||||
@@ -1295,8 +1304,7 @@ class PluggableMap extends BaseObject {
|
||||
* @param {import("./Feature.js").default} feature Feature.
|
||||
*/
|
||||
skipFeature(feature) {
|
||||
const featureUid = getUid(feature).toString();
|
||||
this.skippedFeatureUids_[featureUid] = true;
|
||||
this.skippedFeatureUids_[getUid(feature)] = true;
|
||||
this.render();
|
||||
}
|
||||
|
||||
@@ -1331,8 +1339,7 @@ class PluggableMap extends BaseObject {
|
||||
* @param {import("./Feature.js").default} feature Feature.
|
||||
*/
|
||||
unskipFeature(feature) {
|
||||
const featureUid = getUid(feature).toString();
|
||||
delete this.skippedFeatureUids_[featureUid];
|
||||
delete this.skippedFeatureUids_[getUid(feature)];
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
@@ -1359,8 +1366,8 @@ function createOptionsInternal(options) {
|
||||
*/
|
||||
const values = {};
|
||||
|
||||
const layerGroup = (options.layers instanceof LayerGroup) ?
|
||||
options.layers : new LayerGroup({layers: options.layers});
|
||||
const layerGroup = options.layers && typeof /** @type {?} */ (options.layers).getLayers === 'function' ?
|
||||
/** @type {LayerGroup} */ (options.layers) : new LayerGroup({layers: /** @type {Collection} */ (options.layers)});
|
||||
values[MapProperty.LAYERGROUP] = layerGroup;
|
||||
|
||||
values[MapProperty.TARGET] = options.target;
|
||||
@@ -1373,9 +1380,9 @@ function createOptionsInternal(options) {
|
||||
if (Array.isArray(options.controls)) {
|
||||
controls = new Collection(options.controls.slice());
|
||||
} else {
|
||||
assert(options.controls instanceof Collection,
|
||||
assert(typeof /** @type {?} */ (options.controls).getArray === 'function',
|
||||
47); // Expected `controls` to be an array or an `import("./Collection.js").Collection`
|
||||
controls = options.controls;
|
||||
controls = /** @type {Collection} */ (options.controls);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1384,9 +1391,9 @@ function createOptionsInternal(options) {
|
||||
if (Array.isArray(options.interactions)) {
|
||||
interactions = new Collection(options.interactions.slice());
|
||||
} else {
|
||||
assert(options.interactions instanceof Collection,
|
||||
assert(typeof /** @type {?} */ (options.interactions).getArray === 'function',
|
||||
48); // Expected `interactions` to be an array or an `import("./Collection.js").Collection`
|
||||
interactions = options.interactions;
|
||||
interactions = /** @type {Collection} */ (options.interactions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1395,7 +1402,7 @@ function createOptionsInternal(options) {
|
||||
if (Array.isArray(options.overlays)) {
|
||||
overlays = new Collection(options.overlays.slice());
|
||||
} else {
|
||||
assert(options.overlays instanceof Collection,
|
||||
assert(typeof /** @type {?} */ (options.overlays).getArray === 'function',
|
||||
49); // Expected `overlays` to be an array or an `import("./Collection.js").Collection`
|
||||
overlays = options.overlays;
|
||||
}
|
||||
@@ -1421,12 +1428,14 @@ export default PluggableMap;
|
||||
function getLoading(layers) {
|
||||
for (let i = 0, ii = layers.length; i < ii; ++i) {
|
||||
const layer = layers[i];
|
||||
if (layer instanceof LayerGroup) {
|
||||
return getLoading(layer.getLayers().getArray());
|
||||
}
|
||||
const source = layers[i].getSource();
|
||||
if (source && source.loading) {
|
||||
return true;
|
||||
if (typeof /** @type {?} */ (layer).getLayers === 'function') {
|
||||
return getLoading(/** @type {LayerGroup} */ (layer).getLayers().getArray());
|
||||
} else {
|
||||
const source = /** @type {import("./layer/Layer.js").default} */ (
|
||||
layer).getSource();
|
||||
if (source && source.loading) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -122,7 +122,7 @@ class Tile extends EventTarget {
|
||||
/**
|
||||
* Lookup of start times for rendering transitions. If the start time is
|
||||
* equal to -1, the transition is complete.
|
||||
* @type {Object<number, number>}
|
||||
* @type {Object<string, number>}
|
||||
*/
|
||||
this.transitionStarts_ = {};
|
||||
|
||||
@@ -180,7 +180,7 @@ class Tile extends EventTarget {
|
||||
}
|
||||
|
||||
let tile = this.interimTile;
|
||||
let prev = this;
|
||||
let prev = /** @type {Tile} */ (this);
|
||||
|
||||
do {
|
||||
if (tile.getState() == TileState.LOADED) {
|
||||
@@ -244,7 +244,7 @@ class Tile extends EventTarget {
|
||||
|
||||
/**
|
||||
* Get the alpha value for rendering.
|
||||
* @param {number} id An id for the renderer.
|
||||
* @param {string} id An id for the renderer.
|
||||
* @param {number} time The render frame time.
|
||||
* @return {number} A number between 0 and 1.
|
||||
*/
|
||||
@@ -272,7 +272,7 @@ class Tile extends EventTarget {
|
||||
* Determine if a tile is in an alpha transition. A tile is considered in
|
||||
* transition if tile.getAlpha() has not yet been called or has been called
|
||||
* and returned 1.
|
||||
* @param {number} id An id for the renderer.
|
||||
* @param {string} id An id for the renderer.
|
||||
* @return {boolean} The tile is in transition.
|
||||
*/
|
||||
inTransition(id) {
|
||||
@@ -284,7 +284,7 @@ class Tile extends EventTarget {
|
||||
|
||||
/**
|
||||
* Mark a transition as complete.
|
||||
* @param {number} id An id for the renderer.
|
||||
* @param {string} id An id for the renderer.
|
||||
*/
|
||||
endTransition(id) {
|
||||
if (this.transition_) {
|
||||
|
||||
@@ -92,30 +92,30 @@ class TileRange {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} Height.
|
||||
*/
|
||||
* @return {number} Height.
|
||||
*/
|
||||
getHeight() {
|
||||
return this.maxY - this.minY + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("./size.js").Size} Size.
|
||||
*/
|
||||
* @return {import("./size.js").Size} Size.
|
||||
*/
|
||||
getSize() {
|
||||
return [this.getWidth(), this.getHeight()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {number} Width.
|
||||
*/
|
||||
* @return {number} Width.
|
||||
*/
|
||||
getWidth() {
|
||||
return this.maxX - this.minX + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TileRange} tileRange Tile range.
|
||||
* @return {boolean} Intersects.
|
||||
*/
|
||||
* @param {TileRange} tileRange Tile range.
|
||||
* @return {boolean} Intersects.
|
||||
*/
|
||||
intersects(tileRange) {
|
||||
return this.minX <= tileRange.maxX &&
|
||||
this.maxX >= tileRange.minX &&
|
||||
|
||||
@@ -12,7 +12,6 @@ export default {
|
||||
/**
|
||||
* Indicates that tile loading failed
|
||||
* @type {number}
|
||||
* @api
|
||||
*/
|
||||
ERROR: 3,
|
||||
EMPTY: 4,
|
||||
|
||||
@@ -25,7 +25,7 @@ class VectorImageTile extends Tile {
|
||||
|
||||
/**
|
||||
* @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
|
||||
* @param {import("./TileState.js").default} state State.
|
||||
* @param {TileState} state State.
|
||||
* @param {number} sourceRevision Source revision.
|
||||
* @param {import("./format/Feature.js").default} format Feature format.
|
||||
* @param {import("./Tile.js").LoadFunction} tileLoadFunction Tile load function.
|
||||
@@ -36,8 +36,7 @@ class VectorImageTile extends Tile {
|
||||
* @param {Object<string, import("./VectorTile.js").default>} sourceTiles Source tiles.
|
||||
* @param {number} pixelRatio Pixel ratio.
|
||||
* @param {import("./proj/Projection.js").default} projection Projection.
|
||||
* @param {function(new: import("./VectorTile.js").default, import("./tilecoord.js").TileCoord, import("./TileState.js").default, string,
|
||||
* import("./format/Feature.js").default, import("./Tile.js").LoadFunction)} tileClass Class to
|
||||
* @param {typeof import("./VectorTile.js").default} tileClass Class to
|
||||
* instantiate for source tiles.
|
||||
* @param {function(this: import("./source/VectorTile.js").default, import("./events/Event.js").default)} handleTileChange
|
||||
* Function to call when a source tile's state changes.
|
||||
@@ -192,7 +191,7 @@ class VectorImageTile extends Tile {
|
||||
* @return {CanvasRenderingContext2D} The rendering context.
|
||||
*/
|
||||
getContext(layer) {
|
||||
const key = getUid(layer).toString();
|
||||
const key = getUid(layer);
|
||||
if (!(key in this.context_)) {
|
||||
this.context_[key] = createCanvasContext2D();
|
||||
}
|
||||
@@ -214,7 +213,7 @@ class VectorImageTile extends Tile {
|
||||
* @return {ReplayState} The replay state.
|
||||
*/
|
||||
getReplayState(layer) {
|
||||
const key = getUid(layer).toString();
|
||||
const key = getUid(layer);
|
||||
if (!(key in this.replayState_)) {
|
||||
this.replayState_[key] = {
|
||||
dirty: false,
|
||||
|
||||
@@ -12,12 +12,6 @@ import TileState from './TileState.js';
|
||||
const DEFAULT_EXTENT = [0, 0, 4096, 4096];
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {function(new: VectorTile, import("./tilecoord.js").TileCoord,
|
||||
* TileState, string, ?string, import("./Tile.js").LoadFunction)} TileClass
|
||||
* @api
|
||||
*/
|
||||
|
||||
class VectorTile extends Tile {
|
||||
|
||||
/**
|
||||
@@ -120,7 +114,7 @@ class VectorTile extends Tile {
|
||||
/**
|
||||
* Get the features for this tile. Geometries will be in the projection returned
|
||||
* by {@link module:ol/VectorTile~VectorTile#getProjection}.
|
||||
* @return {Array<import("./Feature.js").default|import("./render/Feature.js").default>} Features.
|
||||
* @return {Array<import("./Feature.js").FeatureLike>} Features.
|
||||
* @api
|
||||
*/
|
||||
getFeatures() {
|
||||
|
||||
@@ -17,7 +17,6 @@ import {inAndOut} from './easing.js';
|
||||
import {getForViewAndSize, getCenter, getHeight, getWidth, isEmpty} from './extent.js';
|
||||
import GeometryType from './geom/GeometryType.js';
|
||||
import {fromExtent as polygonFromExtent} from './geom/Polygon.js';
|
||||
import SimpleGeometry from './geom/SimpleGeometry.js';
|
||||
import {clamp, modulo} from './math.js';
|
||||
import {assign} from './obj.js';
|
||||
import {createProjection, METERS_PER_UNIT} from './proj.js';
|
||||
@@ -987,9 +986,9 @@ class View extends BaseObject {
|
||||
}
|
||||
/** @type {import("./geom/SimpleGeometry.js").default} */
|
||||
let geometry;
|
||||
if (!(geometryOrExtent instanceof SimpleGeometry)) {
|
||||
assert(Array.isArray(geometryOrExtent),
|
||||
24); // Invalid extent or geometry provided as `geometry`
|
||||
assert(Array.isArray(geometryOrExtent) || typeof /** @type {?} */ (geometryOrExtent).getSimplifiedGeometry === 'function',
|
||||
24); // Invalid extent or geometry provided as `geometry`
|
||||
if (Array.isArray(geometryOrExtent)) {
|
||||
assert(!isEmpty(geometryOrExtent),
|
||||
25); // Cannot fit empty extent provided as `geometry`
|
||||
geometry = polygonFromExtent(geometryOrExtent);
|
||||
@@ -1135,7 +1134,7 @@ class View extends BaseObject {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("./ViewHint.js").default} hint Hint.
|
||||
* @param {ViewHint} hint Hint.
|
||||
* @param {number} delta Delta.
|
||||
* @return {number} New value.
|
||||
*/
|
||||
|
||||
@@ -133,7 +133,7 @@ export function asArray(color) {
|
||||
if (Array.isArray(color)) {
|
||||
return color;
|
||||
} else {
|
||||
return fromString(/** @type {string} */ (color));
|
||||
return fromString(color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,9 +185,7 @@ function fromStringInternal_(s) {
|
||||
} else {
|
||||
assert(false, 14); // Invalid color
|
||||
}
|
||||
return (
|
||||
/** @type {Color} */ (color)
|
||||
);
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,22 +23,9 @@ import {toString} from './color.js';
|
||||
* @api
|
||||
*/
|
||||
export function asColorLike(color) {
|
||||
if (isColorLike(color)) {
|
||||
return /** @type {string|CanvasPattern|CanvasGradient} */ (color);
|
||||
if (Array.isArray(color)) {
|
||||
return toString(color);
|
||||
} else {
|
||||
return toString(/** @type {import("./color.js").Color} */ (color));
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {?} color The value that is potentially an {@link ol/colorlike~ColorLike}.
|
||||
* @return {boolean} The color is an {@link ol/colorlike~ColorLike}.
|
||||
*/
|
||||
export function isColorLike(color) {
|
||||
return (
|
||||
typeof color === 'string' ||
|
||||
color instanceof CanvasPattern ||
|
||||
color instanceof CanvasGradient
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
export {default as Attribution} from './control/Attribution.js';
|
||||
export {default as Control} from './control/Control.js';
|
||||
export {default as FullScreen} from './control/FullScreen.js';
|
||||
export {default as MousePosition} from './control/MousePosition.js';
|
||||
export {default as OverviewMap} from './control/OverviewMap.js';
|
||||
export {default as Rotate} from './control/Rotate.js';
|
||||
export {default as ScaleLine} from './control/ScaleLine.js';
|
||||
|
||||
@@ -16,9 +16,9 @@ import {visibleAtResolution} from '../layer/Layer.js';
|
||||
* @property {HTMLElement|string} [target] Specify a target if you
|
||||
* want the control to be rendered outside of the map's
|
||||
* viewport.
|
||||
* @property {boolean} [collapsible=true] Specify if attributions can
|
||||
* be collapsed. If you use an OSM source, should be set to `false` — see
|
||||
* {@link https://www.openstreetmap.org/copyright OSM Copyright} —
|
||||
* @property {boolean} [collapsible] Specify if attributions can
|
||||
* be collapsed. If not specified, sources control this behavior with their
|
||||
* `attributionsCollapsible` setting.
|
||||
* @property {boolean} [collapsed=true] Specify if attributions should
|
||||
* be collapsed at startup.
|
||||
* @property {string} [tipLabel='Attributions'] Text label to use for the button tip.
|
||||
@@ -70,6 +70,12 @@ class Attribution extends Control {
|
||||
*/
|
||||
this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.overrideCollapsible_ = options.collapsible !== undefined;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
@@ -145,12 +151,12 @@ class Attribution extends Control {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of visible attributions.
|
||||
* Collect a list of visible attributions and set the collapsible state.
|
||||
* @param {import("../PluggableMap.js").FrameState} frameState Frame state.
|
||||
* @return {Array<string>} Attributions.
|
||||
* @private
|
||||
*/
|
||||
getSourceAttributions_(frameState) {
|
||||
collectSourceAttributions_(frameState) {
|
||||
/**
|
||||
* Used to determine if an attribution already exists.
|
||||
* @type {!Object<string, boolean>}
|
||||
@@ -171,7 +177,7 @@ class Attribution extends Control {
|
||||
continue;
|
||||
}
|
||||
|
||||
const source = layerState.layer.getSource();
|
||||
const source = /** @type {import("../layer/Layer.js").default} */ (layerState.layer).getSource();
|
||||
if (!source) {
|
||||
continue;
|
||||
}
|
||||
@@ -186,6 +192,10 @@ class Attribution extends Control {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.overrideCollapsible_ && source.getAttributionsCollapsible() === false) {
|
||||
this.setCollapsible(false);
|
||||
}
|
||||
|
||||
if (Array.isArray(attributions)) {
|
||||
for (let j = 0, jj = attributions.length; j < jj; ++j) {
|
||||
if (!(attributions[j] in lookup)) {
|
||||
@@ -216,7 +226,7 @@ class Attribution extends Control {
|
||||
return;
|
||||
}
|
||||
|
||||
const attributions = this.getSourceAttributions_(frameState);
|
||||
const attributions = this.collectSourceAttributions_(frameState);
|
||||
|
||||
const visible = attributions.length > 0;
|
||||
if (this.renderedVisible_ != visible) {
|
||||
|
||||
@@ -34,9 +34,9 @@ const getChangeType = (function() {
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-full-screen'] CSS class name.
|
||||
* @property {string|HTMLElement} [label='\u2922'] Text label to use for the button.
|
||||
* @property {string|Text} [label='\u2922'] Text label to use for the button.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string|HTMLElement} [labelActive='\u00d7'] Text label to use for the
|
||||
* @property {string|Text} [labelActive='\u00d7'] Text label to use for the
|
||||
* button when full-screen is active.
|
||||
* Instead of text, also an element (e.g. a `span` element) can be used.
|
||||
* @property {string} [tipLabel='Toggle full-screen'] Text label to use for the button tip.
|
||||
@@ -87,7 +87,7 @@ class FullScreen extends Control {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
* @type {Text}
|
||||
*/
|
||||
this.labelNode_ = typeof label === 'string' ?
|
||||
document.createTextNode(label) : label;
|
||||
@@ -96,19 +96,24 @@ class FullScreen extends Control {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
* @type {Text}
|
||||
*/
|
||||
this.labelActiveNode_ = typeof labelActive === 'string' ?
|
||||
document.createTextNode(labelActive) : labelActive;
|
||||
|
||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
|
||||
const button = document.createElement('button');
|
||||
button.className = this.cssClassName_ + '-' + isFullScreen();
|
||||
button.setAttribute('type', 'button');
|
||||
button.title = tipLabel;
|
||||
button.appendChild(this.labelNode_);
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.button_ = document.createElement('button');
|
||||
|
||||
listen(button, EventType.CLICK,
|
||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
|
||||
this.setClassName_(this.button_, isFullScreen());
|
||||
this.button_.setAttribute('type', 'button');
|
||||
this.button_.title = tipLabel;
|
||||
this.button_.appendChild(this.labelNode_);
|
||||
|
||||
listen(this.button_, EventType.CLICK,
|
||||
this.handleClick_, this);
|
||||
|
||||
const cssClasses = this.cssClassName_ + ' ' + CLASS_UNSELECTABLE +
|
||||
@@ -116,7 +121,7 @@ class FullScreen extends Control {
|
||||
(!isFullScreenSupported() ? CLASS_UNSUPPORTED : '');
|
||||
const element = this.element;
|
||||
element.className = cssClasses;
|
||||
element.appendChild(button);
|
||||
element.appendChild(this.button_);
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -176,13 +181,12 @@ class FullScreen extends Control {
|
||||
* @private
|
||||
*/
|
||||
handleFullScreenChange_() {
|
||||
const button = this.element.firstElementChild;
|
||||
const map = this.getMap();
|
||||
if (isFullScreen()) {
|
||||
button.className = this.cssClassName_ + '-true';
|
||||
this.setClassName_(this.button_, true);
|
||||
replaceNode(this.labelActiveNode_, this.labelNode_);
|
||||
} else {
|
||||
button.className = this.cssClassName_ + '-false';
|
||||
this.setClassName_(this.button_, false);
|
||||
replaceNode(this.labelNode_, this.labelActiveNode_);
|
||||
}
|
||||
if (map) {
|
||||
@@ -190,6 +194,20 @@ class FullScreen extends Control {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} element Target element
|
||||
* @param {boolean} fullscreen True if fullscreen class name should be active
|
||||
* @private
|
||||
*/
|
||||
setClassName_(element, fullscreen) {
|
||||
const activeClassName = this.cssClassName_ + '-true';
|
||||
const inactiveClassName = this.cssClassName_ + '-false';
|
||||
const nextClassName = fullscreen ? activeClassName : inactiveClassName;
|
||||
element.classList.remove(activeClassName);
|
||||
element.classList.remove(inactiveClassName);
|
||||
element.classList.add(nextClassName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @api
|
||||
@@ -253,7 +271,7 @@ function requestFullScreenWithKeys(element) {
|
||||
if (element.mozRequestFullScreenWithKeys) {
|
||||
element.mozRequestFullScreenWithKeys();
|
||||
} else if (element.webkitRequestFullscreen) {
|
||||
element.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
|
||||
element.webkitRequestFullscreen();
|
||||
} else {
|
||||
requestFullScreen(element);
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ const COORDINATE_FORMAT = 'coordinateFormat';
|
||||
* @typedef {Object} Options
|
||||
* @property {string} [className='ol-mouse-position'] CSS class name.
|
||||
* @property {import("../coordinate.js").CoordinateFormat} [coordinateFormat] Coordinate format.
|
||||
* @property {import("../proj.js").ProjectionLike} projection Projection.
|
||||
* @property {import("../proj.js").ProjectionLike} [projection] Projection. Default is the view projection.
|
||||
* @property {function(import("../MapEvent.js").default)} [render] Function called when the
|
||||
* control should be re-rendered. This is called in a `requestAnimationFrame`
|
||||
* callback.
|
||||
* @property {Element|string} [target] Specify a target if you want the
|
||||
* @property {HTMLElement|string} [target] Specify a target if you want the
|
||||
* control to be rendered outside of the map's viewport.
|
||||
* @property {string} [undefinedHTML=' '] Markup to show when coordinates are not
|
||||
* available (e.g. when the pointer leaves the map viewport). By default, the last position
|
||||
|
||||
@@ -155,7 +155,7 @@ class OverviewMap extends Control {
|
||||
const ovmap = this.ovmap_;
|
||||
|
||||
if (options.layers) {
|
||||
options.layers.forEach(
|
||||
/** @type {Array<import("../layer/Layer.js").default>} */ (options.layers).forEach(
|
||||
/**
|
||||
* @param {import("../layer/Layer.js").default} layer Layer.
|
||||
*/
|
||||
@@ -204,7 +204,8 @@ class OverviewMap extends Control {
|
||||
};
|
||||
|
||||
const move = function(event) {
|
||||
const coordinates = ovmap.getEventCoordinate(computeDesiredMousePosition(event));
|
||||
const position = /** @type {?} */ (computeDesiredMousePosition(event));
|
||||
const coordinates = ovmap.getEventCoordinate(/** @type {Event} */ (position));
|
||||
|
||||
overlay.setPosition(coordinates);
|
||||
};
|
||||
|
||||
@@ -121,22 +121,19 @@ class ScaleLine extends Control {
|
||||
this, getChangeEventType(UNITS_PROP),
|
||||
this.handleUnitsChanged_, this);
|
||||
|
||||
this.setUnits(/** @type {Units} */ (options.units) ||
|
||||
Units.METRIC);
|
||||
this.setUnits(/** @type {Units} */ (options.units) || Units.METRIC);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the units to use in the scale line.
|
||||
* @return {Units|undefined} The units
|
||||
* @return {Units} The units
|
||||
* to use in the scale line.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getUnits() {
|
||||
return (
|
||||
/** @type {Units|undefined} */ (this.get(UNITS_PROP))
|
||||
);
|
||||
return this.get(UNITS_PROP);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ import ViewHint from '../ViewHint.js';
|
||||
import Control from '../control/Control.js';
|
||||
import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
|
||||
import {easeOut} from '../easing.js';
|
||||
import {listen} from '../events.js';
|
||||
import {listen, unlistenByKey} from '../events.js';
|
||||
import {stopPropagation} from '../events/Event.js';
|
||||
import EventType from '../events/EventType.js';
|
||||
import {clamp} from '../math.js';
|
||||
@@ -57,6 +57,12 @@ class ZoomSlider extends Control {
|
||||
render: options.render || render
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {!Array.<import("../events.js").EventsKey>}
|
||||
* @private
|
||||
*/
|
||||
this.dragListenerKeys_ = [];
|
||||
|
||||
/**
|
||||
* Will hold the current resolution of the view.
|
||||
*
|
||||
@@ -133,7 +139,7 @@ class ZoomSlider extends Control {
|
||||
containerElement.className = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL;
|
||||
containerElement.appendChild(thumbElement);
|
||||
/**
|
||||
* @type {import("../pointer/PointerEventHandler.js").default}
|
||||
* @type {PointerEventHandler}
|
||||
* @private
|
||||
*/
|
||||
this.dragger_ = new PointerEventHandler(containerElement);
|
||||
@@ -231,20 +237,31 @@ class ZoomSlider extends Control {
|
||||
this.previousX_ = event.clientX;
|
||||
this.previousY_ = event.clientY;
|
||||
this.dragging_ = true;
|
||||
|
||||
if (this.dragListenerKeys_.length === 0) {
|
||||
const drag = this.handleDraggerDrag_;
|
||||
const end = this.handleDraggerEnd_;
|
||||
this.dragListenerKeys_.push(
|
||||
listen(document, EventType.MOUSEMOVE, drag, this),
|
||||
listen(document, PointerEventType.POINTERMOVE, drag, this),
|
||||
listen(document, EventType.MOUSEUP, end, this),
|
||||
listen(document, PointerEventType.POINTERUP, end, this)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dragger drag events.
|
||||
*
|
||||
* @param {import("../pointer/PointerEvent.js").default|Event} event The drag event.
|
||||
* @param {import("../pointer/PointerEvent.js").default} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
handleDraggerDrag_(event) {
|
||||
if (this.dragging_) {
|
||||
const element = /** @type {HTMLElement} */ (this.element.firstElementChild);
|
||||
const deltaX = event.clientX - this.previousX_ + parseInt(element.style.left, 10);
|
||||
const deltaY = event.clientY - this.previousY_ + parseInt(element.style.top, 10);
|
||||
const deltaX = event.clientX - this.previousX_ + parseFloat(element.style.left);
|
||||
const deltaY = event.clientY - this.previousY_ + parseFloat(element.style.top);
|
||||
const relativePosition = this.getRelativePosition_(deltaX, deltaY);
|
||||
this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
|
||||
this.getMap().getView().setResolution(this.currentResolution_);
|
||||
@@ -256,7 +273,7 @@ class ZoomSlider extends Control {
|
||||
|
||||
/**
|
||||
* Handle dragger end events.
|
||||
* @param {import("../pointer/PointerEvent.js").default|Event} event The drag event.
|
||||
* @param {import("../pointer/PointerEvent.js").default} event The drag event.
|
||||
* @private
|
||||
*/
|
||||
handleDraggerEnd_(event) {
|
||||
@@ -273,6 +290,8 @@ class ZoomSlider extends Control {
|
||||
this.dragging_ = false;
|
||||
this.previousX_ = undefined;
|
||||
this.previousY_ = undefined;
|
||||
this.dragListenerKeys_.forEach(unlistenByKey);
|
||||
this.dragListenerKeys_.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import Zoom from './Zoom.js';
|
||||
*
|
||||
* @param {DefaultsOptions=} opt_options
|
||||
* Defaults options.
|
||||
* @return {import("../Collection.js").default<import("./Control.js").default>}
|
||||
* @return {Collection<import("./Control.js").default>}
|
||||
* Controls.
|
||||
* @function module:ol/control.defaults
|
||||
* @api
|
||||
|
||||
@@ -22,7 +22,7 @@ import {clear} from './obj.js';
|
||||
* Listener function. This function is called with an event object as argument.
|
||||
* When the function returns `false`, event propagation will stop.
|
||||
*
|
||||
* @typedef {function(import("./events/Event.js").default): (void|boolean)} ListenerFunction
|
||||
* @typedef {function((Event|import("./events/Event.js").default)): (void|boolean)} ListenerFunction
|
||||
* @api
|
||||
*/
|
||||
|
||||
@@ -78,27 +78,36 @@ export function findListener(listeners, listener, opt_this, opt_setDeleteIndex)
|
||||
* @return {Array<EventsKey>|undefined} Listeners.
|
||||
*/
|
||||
export function getListeners(target, type) {
|
||||
const listenerMap = target.ol_lm;
|
||||
const listenerMap = getListenerMap(target);
|
||||
return listenerMap ? listenerMap[type] : undefined;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the lookup of listeners. If one does not exist on the target, it is
|
||||
* created.
|
||||
* @param {import("./events/Target.js").EventTargetLike} target Target.
|
||||
* Get the lookup of listeners.
|
||||
* @param {Object} target Target.
|
||||
* @param {boolean=} opt_create If a map should be created if it doesn't exist.
|
||||
* @return {!Object<string, Array<EventsKey>>} Map of
|
||||
* listeners by event type.
|
||||
*/
|
||||
function getListenerMap(target) {
|
||||
function getListenerMap(target, opt_create) {
|
||||
let listenerMap = target.ol_lm;
|
||||
if (!listenerMap) {
|
||||
if (!listenerMap && opt_create) {
|
||||
listenerMap = target.ol_lm = {};
|
||||
}
|
||||
return listenerMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the listener map from a target.
|
||||
* @param {Object} target Target.
|
||||
*/
|
||||
function removeListenerMap(target) {
|
||||
delete target.ol_lm;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clean up all listener objects of the given type. All properties on the
|
||||
* listener objects will be removed, and if no listeners remain in the listener
|
||||
@@ -110,15 +119,16 @@ function removeListeners(target, type) {
|
||||
const listeners = getListeners(target, type);
|
||||
if (listeners) {
|
||||
for (let i = 0, ii = listeners.length; i < ii; ++i) {
|
||||
target.removeEventListener(type, listeners[i].boundListener);
|
||||
/** @type {import("./events/Target.js").default} */ (target).
|
||||
removeEventListener(type, listeners[i].boundListener);
|
||||
clear(listeners[i]);
|
||||
}
|
||||
listeners.length = 0;
|
||||
const listenerMap = target.ol_lm;
|
||||
const listenerMap = getListenerMap(target);
|
||||
if (listenerMap) {
|
||||
delete listenerMap[type];
|
||||
if (Object.keys(listenerMap).length === 0) {
|
||||
delete target.ol_lm;
|
||||
removeListenerMap(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,7 +151,7 @@ function removeListeners(target, type) {
|
||||
* @return {EventsKey} Unique key for the listener.
|
||||
*/
|
||||
export function listen(target, type, listener, opt_this, opt_once) {
|
||||
const listenerMap = getListenerMap(target);
|
||||
const listenerMap = getListenerMap(target, true);
|
||||
let listeners = listenerMap[type];
|
||||
if (!listeners) {
|
||||
listeners = listenerMap[type] = [];
|
||||
@@ -160,7 +170,8 @@ export function listen(target, type, listener, opt_this, opt_once) {
|
||||
target: target,
|
||||
type: type
|
||||
});
|
||||
target.addEventListener(type, bindListener(listenerObj));
|
||||
/** @type {import("./events/Target.js").default} */ (target).
|
||||
addEventListener(type, bindListener(listenerObj));
|
||||
listeners.push(listenerObj);
|
||||
}
|
||||
|
||||
@@ -228,7 +239,8 @@ export function unlisten(target, type, listener, opt_this) {
|
||||
*/
|
||||
export function unlistenByKey(key) {
|
||||
if (key && key.target) {
|
||||
key.target.removeEventListener(key.type, key.boundListener);
|
||||
/** @type {import("./events/Target.js").default} */ (key.target).
|
||||
removeEventListener(key.type, key.boundListener);
|
||||
const listeners = getListeners(key.target, key.type);
|
||||
if (listeners) {
|
||||
const i = 'deleteIndex' in key ? key.deleteIndex : listeners.indexOf(key);
|
||||
@@ -252,7 +264,9 @@ export function unlistenByKey(key) {
|
||||
*/
|
||||
export function unlistenAll(target) {
|
||||
const listenerMap = getListenerMap(target);
|
||||
for (const type in listenerMap) {
|
||||
removeListeners(target, type);
|
||||
if (listenerMap) {
|
||||
for (const type in listenerMap) {
|
||||
removeListeners(target, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,8 @@ class Target extends Disposable {
|
||||
* Object with a `type` property.
|
||||
*
|
||||
* @param {{type: string,
|
||||
* target: (EventTargetLike|undefined)}|
|
||||
* target: (EventTargetLike|undefined),
|
||||
* propagationStopped: (boolean|undefined)}|
|
||||
* import("./Event.js").default|string} event Event object.
|
||||
* @return {boolean|undefined} `false` if anyone called preventDefault on the
|
||||
* event object or if any of the listeners returned false.
|
||||
|
||||
@@ -24,7 +24,7 @@ import {WEBKIT, MAC} from '../has.js';
|
||||
* @api
|
||||
*/
|
||||
export const altKeyOnly = function(mapBrowserEvent) {
|
||||
const originalEvent = mapBrowserEvent.originalEvent;
|
||||
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent);
|
||||
return (
|
||||
originalEvent.altKey &&
|
||||
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
|
||||
@@ -41,7 +41,7 @@ export const altKeyOnly = function(mapBrowserEvent) {
|
||||
* @api
|
||||
*/
|
||||
export const altShiftKeysOnly = function(mapBrowserEvent) {
|
||||
const originalEvent = mapBrowserEvent.originalEvent;
|
||||
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent);
|
||||
return (
|
||||
originalEvent.altKey &&
|
||||
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
|
||||
@@ -94,7 +94,7 @@ export const click = function(mapBrowserEvent) {
|
||||
* @return {boolean} The result.
|
||||
*/
|
||||
export const mouseActionButton = function(mapBrowserEvent) {
|
||||
const originalEvent = mapBrowserEvent.originalEvent;
|
||||
const originalEvent = /** @type {MouseEvent} */ (mapBrowserEvent.originalEvent);
|
||||
return originalEvent.button == 0 &&
|
||||
!(WEBKIT && MAC && originalEvent.ctrlKey);
|
||||
};
|
||||
@@ -156,7 +156,7 @@ export const doubleClick = function(mapBrowserEvent) {
|
||||
* @api
|
||||
*/
|
||||
export const noModifierKeys = function(mapBrowserEvent) {
|
||||
const originalEvent = mapBrowserEvent.originalEvent;
|
||||
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent);
|
||||
return (
|
||||
!originalEvent.altKey &&
|
||||
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
|
||||
@@ -174,7 +174,7 @@ export const noModifierKeys = function(mapBrowserEvent) {
|
||||
* @api
|
||||
*/
|
||||
export const platformModifierKeyOnly = function(mapBrowserEvent) {
|
||||
const originalEvent = mapBrowserEvent.originalEvent;
|
||||
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent);
|
||||
return !originalEvent.altKey &&
|
||||
(MAC ? originalEvent.metaKey : originalEvent.ctrlKey) &&
|
||||
!originalEvent.shiftKey;
|
||||
@@ -190,7 +190,7 @@ export const platformModifierKeyOnly = function(mapBrowserEvent) {
|
||||
* @api
|
||||
*/
|
||||
export const shiftKeyOnly = function(mapBrowserEvent) {
|
||||
const originalEvent = mapBrowserEvent.originalEvent;
|
||||
const originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent);
|
||||
return (
|
||||
!originalEvent.altKey &&
|
||||
!(originalEvent.metaKey || originalEvent.ctrlKey) &&
|
||||
@@ -208,7 +208,7 @@ export const shiftKeyOnly = function(mapBrowserEvent) {
|
||||
*/
|
||||
export const targetNotEditable = function(mapBrowserEvent) {
|
||||
const target = mapBrowserEvent.originalEvent.target;
|
||||
const tagName = target.tagName;
|
||||
const tagName = /** @type {Element} */ (target).tagName;
|
||||
return (
|
||||
tagName !== 'INPUT' &&
|
||||
tagName !== 'SELECT' &&
|
||||
@@ -224,11 +224,10 @@ export const targetNotEditable = function(mapBrowserEvent) {
|
||||
* @api
|
||||
*/
|
||||
export const mouseOnly = function(mapBrowserEvent) {
|
||||
assert(mapBrowserEvent.pointerEvent, 56); // mapBrowserEvent must originate from a pointer event
|
||||
const pointerEvent = /** @type {import("../MapBrowserPointerEvent").default} */ (mapBrowserEvent).pointerEvent;
|
||||
assert(pointerEvent !== undefined, 56); // mapBrowserEvent must originate from a pointer event
|
||||
// see http://www.w3.org/TR/pointerevents/#widl-PointerEvent-pointerType
|
||||
return (
|
||||
/** @type {import("../MapBrowserEvent.js").default} */ (mapBrowserEvent).pointerEvent.pointerType == 'mouse'
|
||||
);
|
||||
return pointerEvent.pointerType == 'mouse';
|
||||
};
|
||||
|
||||
|
||||
@@ -242,6 +241,7 @@ export const mouseOnly = function(mapBrowserEvent) {
|
||||
* @api
|
||||
*/
|
||||
export const primaryAction = function(mapBrowserEvent) {
|
||||
const pointerEvent = mapBrowserEvent.pointerEvent;
|
||||
const pointerEvent = /** @type {import("../MapBrowserPointerEvent").default} */ (mapBrowserEvent).pointerEvent;
|
||||
assert(pointerEvent !== undefined, 56); // mapBrowserEvent must originate from a pointer event
|
||||
return pointerEvent.isPrimary && pointerEvent.button === 0;
|
||||
};
|
||||
|
||||
@@ -165,7 +165,7 @@ export function containsXY(extent, x, y) {
|
||||
* Get the relationship between a coordinate and extent.
|
||||
* @param {Extent} extent The extent.
|
||||
* @param {import("./coordinate.js").Coordinate} coordinate The coordinate.
|
||||
* @return {import("./extent/Relationship.js").default} The relationship (bitwise compare with
|
||||
* @return {Relationship} The relationship (bitwise compare with
|
||||
* import("./extent/Relationship.js").Relationship).
|
||||
*/
|
||||
export function coordinateRelationship(extent, coordinate) {
|
||||
@@ -478,7 +478,7 @@ export function getCenter(extent) {
|
||||
/**
|
||||
* Get a corner coordinate of an extent.
|
||||
* @param {Extent} extent Extent.
|
||||
* @param {import("./extent/Corner.js").default} corner Corner.
|
||||
* @param {Corner} corner Corner.
|
||||
* @return {import("./coordinate.js").Coordinate} Corner coordinate.
|
||||
*/
|
||||
export function getCorner(extent, corner) {
|
||||
@@ -494,9 +494,7 @@ export function getCorner(extent, corner) {
|
||||
} else {
|
||||
assert(false, 13); // Invalid corner
|
||||
}
|
||||
return (
|
||||
/** @type {!import("./coordinate.js").Coordinate} */ (coordinate)
|
||||
);
|
||||
return coordinate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
import {VOID} from './functions.js';
|
||||
import FormatType from './format/FormatType.js';
|
||||
|
||||
|
||||
/**
|
||||
* {@link module:ol/source/Vector} sources use a function of this type to
|
||||
* load features.
|
||||
@@ -17,7 +16,7 @@ import FormatType from './format/FormatType.js';
|
||||
*
|
||||
* The function is responsible for loading the features and adding them to the
|
||||
* source.
|
||||
* @typedef {function(this:import("./source/Vector.js").default, import("./extent.js").Extent, number,
|
||||
* @typedef {function(this:(import("./source/Vector").default|import("./VectorTile.js").default), import("./extent.js").Extent, number,
|
||||
* import("./proj/Projection.js").default)} FeatureLoader
|
||||
* @api
|
||||
*/
|
||||
@@ -39,10 +38,10 @@ import FormatType from './format/FormatType.js';
|
||||
/**
|
||||
* @param {string|FeatureUrlFunction} url Feature URL service.
|
||||
* @param {import("./format/Feature.js").default} format Feature format.
|
||||
* @param {function(this:import("./VectorTile.js").default, Array<import("./Feature.js").default>, import("./proj/Projection.js").default, import("./extent.js").Extent)|function(this:import("./source/Vector.js").default, Array<import("./Feature.js").default>)} success
|
||||
* @param {function(this:import("./VectorTile.js").default, Array<import("./Feature.js").default>, import("./proj/Projection.js").default, import("./extent.js").Extent)|function(this:import("./source/Vector").default, Array<import("./Feature.js").default>)} success
|
||||
* Function called with the loaded features and optionally with the data
|
||||
* projection. Called with the vector tile or source as `this`.
|
||||
* @param {function(this:import("./VectorTile.js").default)|function(this:import("./source/Vector.js").default)} failure
|
||||
* @param {function(this:import("./VectorTile.js").default)|function(this:import("./source/Vector").default)} failure
|
||||
* Function called when loading failed. Called with the vector tile or
|
||||
* source as `this`.
|
||||
* @return {FeatureLoader} The feature loader.
|
||||
@@ -53,7 +52,7 @@ export function loadFeaturesXhr(url, format, success, failure) {
|
||||
* @param {import("./extent.js").Extent} extent Extent.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {import("./proj/Projection.js").default} projection Projection.
|
||||
* @this {import("./source/Vector.js").default|import("./VectorTile.js").default}
|
||||
* @this {import("./source/Vector").default|import("./VectorTile.js").default}
|
||||
*/
|
||||
function(extent, resolution, projection) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
@@ -121,9 +120,12 @@ export function xhr(url, format) {
|
||||
* @param {Array<import("./Feature.js").default>} features The loaded features.
|
||||
* @param {import("./proj/Projection.js").default} dataProjection Data
|
||||
* projection.
|
||||
* @this {import("./source/Vector.js").default}
|
||||
* @this {import("./source/Vector").default|import("./VectorTile.js").default}
|
||||
*/
|
||||
function(features, dataProjection) {
|
||||
this.addFeatures(features);
|
||||
const sourceOrTile = /** @type {?} */ (this);
|
||||
if (typeof sourceOrTile.addFeatures === 'function') {
|
||||
/** @type {import("./source/Vector").default} */ (sourceOrTile).addFeatures(features);
|
||||
}
|
||||
}, /* FIXME handle error */ VOID);
|
||||
}
|
||||
|
||||
@@ -17,9 +17,31 @@ import Point from '../geom/Point.js';
|
||||
import Polygon from '../geom/Polygon.js';
|
||||
import {deflateCoordinates} from '../geom/flat/deflate.js';
|
||||
import {linearRingIsClockwise} from '../geom/flat/orient.js';
|
||||
import {assign, isEmpty} from '../obj.js';
|
||||
import {isEmpty} from '../obj.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
|
||||
/**
|
||||
* @typedef {import("arcgis-rest-api").Feature} EsriJSONFeature
|
||||
* @typedef {import("arcgis-rest-api").FeatureSet} EsriJSONFeatureSet
|
||||
* @typedef {import("arcgis-rest-api").Geometry} EsriJSONGeometry
|
||||
* @typedef {import("arcgis-rest-api").Point} EsriJSONPoint
|
||||
* @typedef {import("arcgis-rest-api").Polyline} EsriJSONPolyline
|
||||
* @typedef {import("arcgis-rest-api").Polygon} EsriJSONPolygon
|
||||
* @typedef {import("arcgis-rest-api").Multipoint} EsriJSONMultipoint
|
||||
* @typedef {import("arcgis-rest-api").HasZM} EsriJSONHasZM
|
||||
* @typedef {import("arcgis-rest-api").Position} EsriJSONPosition
|
||||
* @typedef {import("arcgis-rest-api").SpatialReferenceWkid} EsriJSONSpatialReferenceWkid
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {Object} EsriJSONMultiPolygon
|
||||
* @property {Array<Array<Array<Array<number>>>>} rings Rings for the MultiPolygon.
|
||||
* @property {boolean} [hasM] If the polygon coordinates have an M value.
|
||||
* @property {boolean} [hasZ] If the polygon coordinates have a Z value.
|
||||
* @property {EsriJSONSpatialReferenceWkid} [spatialReference] The coordinate reference system.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
@@ -104,13 +126,12 @@ class EsriJSON extends JSONFeature {
|
||||
* @inheritDoc
|
||||
*/
|
||||
readFeaturesFromObject(object, opt_options) {
|
||||
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
|
||||
const options = opt_options ? opt_options : {};
|
||||
if (esriJSONObject.features) {
|
||||
const esriJSONFeatureCollection = /** @type {EsriJSONFeatureCollection} */ (object);
|
||||
if (object['features']) {
|
||||
const esriJSONFeatureSet = /** @type {EsriJSONFeatureSet} */ (object);
|
||||
/** @type {Array<import("../Feature.js").default>} */
|
||||
const features = [];
|
||||
const esriJSONFeatures = esriJSONFeatureCollection.features;
|
||||
const esriJSONFeatures = esriJSONFeatureSet.features;
|
||||
options.idField = object.objectIdFieldName;
|
||||
for (let i = 0, ii = esriJSONFeatures.length; i < ii; ++i) {
|
||||
features.push(this.readFeatureFromObject(esriJSONFeatures[i], options));
|
||||
@@ -132,9 +153,9 @@ class EsriJSON extends JSONFeature {
|
||||
* @inheritDoc
|
||||
*/
|
||||
readProjectionFromObject(object) {
|
||||
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
|
||||
if (esriJSONObject.spatialReference && esriJSONObject.spatialReference.wkid) {
|
||||
const crs = esriJSONObject.spatialReference.wkid;
|
||||
if (object['spatialReference'] && object['spatialReference']['wkid'] !== undefined) {
|
||||
const spatialReference = /** @type {EsriJSONSpatialReferenceWkid} */ (object['spatialReference']);
|
||||
const crs = spatialReference.wkid;
|
||||
return getProjection('EPSG:' + crs);
|
||||
} else {
|
||||
return null;
|
||||
@@ -170,8 +191,8 @@ class EsriJSON extends JSONFeature {
|
||||
if (geometry) {
|
||||
object['geometry'] = writeGeometry(geometry, opt_options);
|
||||
if (opt_options && opt_options.featureProjection) {
|
||||
object['geometry']['spatialReference'] = /** @type {EsriJSONCRS} */({
|
||||
wkid: getProjection(opt_options.featureProjection).getCode().split(':').pop()
|
||||
object['geometry']['spatialReference'] = /** @type {EsriJSONSpatialReferenceWkid} */({
|
||||
wkid: Number(getProjection(opt_options.featureProjection).getCode().split(':').pop())
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -200,7 +221,7 @@ class EsriJSON extends JSONFeature {
|
||||
for (let i = 0, ii = features.length; i < ii; ++i) {
|
||||
objects.push(this.writeFeatureObject(features[i], opt_options));
|
||||
}
|
||||
return /** @type {EsriJSONFeatureCollection} */ ({
|
||||
return /** @type {EsriJSONFeatureSet} */ ({
|
||||
'features': objects
|
||||
});
|
||||
}
|
||||
@@ -218,26 +239,27 @@ function readGeometry(object, opt_options) {
|
||||
}
|
||||
/** @type {import("../geom/GeometryType.js").default} */
|
||||
let type;
|
||||
if (typeof object.x === 'number' && typeof object.y === 'number') {
|
||||
if (typeof object['x'] === 'number' && typeof object['y'] === 'number') {
|
||||
type = GeometryType.POINT;
|
||||
} else if (object.points) {
|
||||
} else if (object['points']) {
|
||||
type = GeometryType.MULTI_POINT;
|
||||
} else if (object.paths) {
|
||||
if (object.paths.length === 1) {
|
||||
} else if (object['paths']) {
|
||||
const esriJSONPolyline = /** @type {EsriJSONPolyline} */ (object);
|
||||
if (esriJSONPolyline.paths.length === 1) {
|
||||
type = GeometryType.LINE_STRING;
|
||||
} else {
|
||||
type = GeometryType.MULTI_LINE_STRING;
|
||||
}
|
||||
} else if (object.rings) {
|
||||
const layout = getGeometryLayout(object);
|
||||
const rings = convertRings(object.rings, layout);
|
||||
object = /** @type {EsriJSONGeometry} */(assign({}, object));
|
||||
} else if (object['rings']) {
|
||||
const esriJSONPolygon = /** @type {EsriJSONPolygon} */ (object);
|
||||
const layout = getGeometryLayout(esriJSONPolygon);
|
||||
const rings = convertRings(esriJSONPolygon.rings, layout);
|
||||
if (rings.length === 1) {
|
||||
type = GeometryType.POLYGON;
|
||||
object.rings = rings[0];
|
||||
object['rings'] = rings[0];
|
||||
} else {
|
||||
type = GeometryType.MULTI_POLYGON;
|
||||
object.rings = rings;
|
||||
object['rings'] = rings;
|
||||
}
|
||||
}
|
||||
const geometryReader = GEOMETRY_READERS[type];
|
||||
@@ -254,7 +276,7 @@ function readGeometry(object, opt_options) {
|
||||
* Logic inspired by: https://github.com/Esri/terraformer-arcgis-parser
|
||||
* @param {Array<!Array<!Array<number>>>} rings Rings.
|
||||
* @param {import("../geom/GeometryLayout.js").default} layout Geometry layout.
|
||||
* @return {Array<!Array<!Array<number>>>} Transformed rings.
|
||||
* @return {Array<!Array<!Array<!Array<number>>>>} Transformed rings.
|
||||
*/
|
||||
function convertRings(rings, layout) {
|
||||
const flatRing = [];
|
||||
@@ -301,7 +323,7 @@ function convertRings(rings, layout) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {EsriJSONGeometry} object Object.
|
||||
* @param {EsriJSONPoint} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} Point.
|
||||
*/
|
||||
function readPointGeometry(object) {
|
||||
@@ -323,7 +345,7 @@ function readPointGeometry(object) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {EsriJSONGeometry} object Object.
|
||||
* @param {EsriJSONPolyline} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} LineString.
|
||||
*/
|
||||
function readLineStringGeometry(object) {
|
||||
@@ -333,7 +355,7 @@ function readLineStringGeometry(object) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {EsriJSONGeometry} object Object.
|
||||
* @param {EsriJSONPolyline} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} MultiLineString.
|
||||
*/
|
||||
function readMultiLineStringGeometry(object) {
|
||||
@@ -343,7 +365,7 @@ function readMultiLineStringGeometry(object) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {EsriJSONGeometry} object Object.
|
||||
* @param {EsriJSONHasZM} object Object.
|
||||
* @return {import("../geom/GeometryLayout.js").default} The geometry layout to use.
|
||||
*/
|
||||
function getGeometryLayout(object) {
|
||||
@@ -360,7 +382,7 @@ function getGeometryLayout(object) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {EsriJSONGeometry} object Object.
|
||||
* @param {EsriJSONMultipoint} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} MultiPoint.
|
||||
*/
|
||||
function readMultiPointGeometry(object) {
|
||||
@@ -370,19 +392,17 @@ function readMultiPointGeometry(object) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {EsriJSONGeometry} object Object.
|
||||
* @param {EsriJSONMultiPolygon} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} MultiPolygon.
|
||||
*/
|
||||
function readMultiPolygonGeometry(object) {
|
||||
const layout = getGeometryLayout(object);
|
||||
return new MultiPolygon(
|
||||
/** @type {Array<Array<Array<Array<number>>>>} */(object.rings),
|
||||
layout);
|
||||
return new MultiPolygon(object.rings, layout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {EsriJSONGeometry} object Object.
|
||||
* @param {EsriJSONPolygon} object Object.
|
||||
* @return {import("../geom/Geometry.js").default} Polygon.
|
||||
*/
|
||||
function readPolygonGeometry(object) {
|
||||
@@ -452,13 +472,14 @@ function getHasZM(geometry) {
|
||||
* @return {EsriJSONPolyline} EsriJSON geometry.
|
||||
*/
|
||||
function writeLineStringGeometry(geometry, opt_options) {
|
||||
const hasZM = getHasZM(/** @type {import("../geom/LineString.js").default} */(geometry));
|
||||
const lineString = /** @type {import("../geom/LineString.js").default} */ (geometry);
|
||||
const hasZM = getHasZM(lineString);
|
||||
return (
|
||||
/** @type {EsriJSONPolyline} */ {
|
||||
hasZ: hasZM.hasZ,
|
||||
hasM: hasZM.hasM,
|
||||
paths: [
|
||||
/** @type {import("../geom/LineString.js").default} */ (geometry).getCoordinates()
|
||||
/** @type {Array<EsriJSONPosition>} */ (lineString.getCoordinates())
|
||||
]
|
||||
}
|
||||
);
|
||||
@@ -471,13 +492,14 @@ function writeLineStringGeometry(geometry, opt_options) {
|
||||
* @return {EsriJSONPolygon} EsriJSON geometry.
|
||||
*/
|
||||
function writePolygonGeometry(geometry, opt_options) {
|
||||
const polygon = /** @type {import("../geom/Polygon.js").default} */ (geometry);
|
||||
// Esri geometries use the left-hand rule
|
||||
const hasZM = getHasZM(/** @type {import("../geom/Polygon.js").default} */(geometry));
|
||||
const hasZM = getHasZM(polygon);
|
||||
return (
|
||||
/** @type {EsriJSONPolygon} */ {
|
||||
hasZ: hasZM.hasZ,
|
||||
hasM: hasZM.hasM,
|
||||
rings: /** @type {import("../geom/Polygon.js").default} */ (geometry).getCoordinates(false)
|
||||
rings: /** @type {Array<Array<EsriJSONPosition>>} */ (polygon.getCoordinates(false))
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -489,12 +511,13 @@ function writePolygonGeometry(geometry, opt_options) {
|
||||
* @return {EsriJSONPolyline} EsriJSON geometry.
|
||||
*/
|
||||
function writeMultiLineStringGeometry(geometry, opt_options) {
|
||||
const hasZM = getHasZM(/** @type {import("../geom/MultiLineString.js").default} */(geometry));
|
||||
const multiLineString = /** @type {import("../geom/MultiLineString.js").default} */ (geometry);
|
||||
const hasZM = getHasZM(multiLineString);
|
||||
return (
|
||||
/** @type {EsriJSONPolyline} */ {
|
||||
hasZ: hasZM.hasZ,
|
||||
hasM: hasZM.hasM,
|
||||
paths: /** @type {import("../geom/MultiLineString.js").default} */ (geometry).getCoordinates()
|
||||
paths: /** @type {Array<Array<EsriJSONPosition>>} */ (multiLineString.getCoordinates())
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -506,12 +529,13 @@ function writeMultiLineStringGeometry(geometry, opt_options) {
|
||||
* @return {EsriJSONMultipoint} EsriJSON geometry.
|
||||
*/
|
||||
function writeMultiPointGeometry(geometry, opt_options) {
|
||||
const hasZM = getHasZM(/** @type {import("../geom/MultiPoint.js").default} */(geometry));
|
||||
const multiPoint = /** @type {import("../geom/MultiPoint.js").default} */ (geometry);
|
||||
const hasZM = getHasZM(multiPoint);
|
||||
return (
|
||||
/** @type {EsriJSONMultipoint} */ {
|
||||
hasZ: hasZM.hasZ,
|
||||
hasM: hasZM.hasM,
|
||||
points: /** @type {import("../geom/MultiPoint.js").default} */ (geometry).getCoordinates()
|
||||
points: /** @type {Array<EsriJSONPosition>} */ (multiPoint.getCoordinates())
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @module ol/format/Feature
|
||||
*/
|
||||
import Geometry from '../geom/Geometry.js';
|
||||
import {assign} from '../obj.js';
|
||||
import {abstract} from '../util.js';
|
||||
import {get as getProjection, equivalent as equivalentProjection, transformExtent} from '../proj.js';
|
||||
|
||||
|
||||
@@ -123,7 +123,9 @@ class FeatureFormat {
|
||||
* @abstract
|
||||
* @return {import("./FormatType.js").default} Format.
|
||||
*/
|
||||
getType() {}
|
||||
getType() {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single feature from a source.
|
||||
@@ -131,9 +133,11 @@ class FeatureFormat {
|
||||
* @abstract
|
||||
* @param {Document|Node|Object|string} source Source.
|
||||
* @param {ReadOptions=} opt_options Read options.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
* @return {import("../Feature.js").FeatureLike} Feature.
|
||||
*/
|
||||
readFeature(source, opt_options) {}
|
||||
readFeature(source, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read all features from a source.
|
||||
@@ -141,9 +145,11 @@ class FeatureFormat {
|
||||
* @abstract
|
||||
* @param {Document|Node|ArrayBuffer|Object|string} source Source.
|
||||
* @param {ReadOptions=} opt_options Read options.
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
* @return {Array<import("../Feature.js").FeatureLike>} Features.
|
||||
*/
|
||||
readFeatures(source, opt_options) {}
|
||||
readFeatures(source, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single geometry from a source.
|
||||
@@ -151,9 +157,11 @@ class FeatureFormat {
|
||||
* @abstract
|
||||
* @param {Document|Node|Object|string} source Source.
|
||||
* @param {ReadOptions=} opt_options Read options.
|
||||
* @return {Geometry} Geometry.
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometry(source, opt_options) {}
|
||||
readGeometry(source, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the projection from a source.
|
||||
@@ -162,7 +170,9 @@ class FeatureFormat {
|
||||
* @param {Document|Node|Object|string} source Source.
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
*/
|
||||
readProjection(source) {}
|
||||
readProjection(source) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a feature in this format.
|
||||
@@ -172,7 +182,9 @@ class FeatureFormat {
|
||||
* @param {WriteOptions=} opt_options Write options.
|
||||
* @return {string} Result.
|
||||
*/
|
||||
writeFeature(feature, opt_options) {}
|
||||
writeFeature(feature, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of features in this format.
|
||||
@@ -182,26 +194,30 @@ class FeatureFormat {
|
||||
* @param {WriteOptions=} opt_options Write options.
|
||||
* @return {string} Result.
|
||||
*/
|
||||
writeFeatures(features, opt_options) {}
|
||||
writeFeatures(features, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a single geometry in this format.
|
||||
*
|
||||
* @abstract
|
||||
* @param {Geometry} geometry Geometry.
|
||||
* @param {import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {WriteOptions=} opt_options Write options.
|
||||
* @return {string} Result.
|
||||
*/
|
||||
writeGeometry(geometry, opt_options) {}
|
||||
writeGeometry(geometry, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
}
|
||||
|
||||
export default FeatureFormat;
|
||||
|
||||
/**
|
||||
* @param {Geometry|import("../extent.js").Extent} geometry Geometry.
|
||||
* @param {import("../geom/Geometry.js").default|import("../extent.js").Extent} geometry Geometry.
|
||||
* @param {boolean} write Set to true for writing, false for reading.
|
||||
* @param {(WriteOptions|ReadOptions)=} opt_options Options.
|
||||
* @return {Geometry|import("../extent.js").Extent} Transformed geometry.
|
||||
* @return {import("../geom/Geometry.js").default|import("../extent.js").Extent} Transformed geometry.
|
||||
*/
|
||||
export function transformWithOptions(geometry, write, opt_options) {
|
||||
const featureProjection = opt_options ?
|
||||
@@ -209,28 +225,29 @@ export function transformWithOptions(geometry, write, opt_options) {
|
||||
const dataProjection = opt_options ?
|
||||
getProjection(opt_options.dataProjection) : null;
|
||||
/**
|
||||
* @type {Geometry|import("../extent.js").Extent}
|
||||
* @type {import("../geom/Geometry.js").default|import("../extent.js").Extent}
|
||||
*/
|
||||
let transformed;
|
||||
if (featureProjection && dataProjection &&
|
||||
!equivalentProjection(featureProjection, dataProjection)) {
|
||||
if (geometry instanceof Geometry) {
|
||||
transformed = (write ? geometry.clone() : geometry).transform(
|
||||
write ? featureProjection : dataProjection,
|
||||
write ? dataProjection : featureProjection);
|
||||
} else {
|
||||
if (Array.isArray(geometry)) {
|
||||
// FIXME this is necessary because GML treats extents
|
||||
// as geometries
|
||||
transformed = transformExtent(
|
||||
geometry,
|
||||
dataProjection,
|
||||
featureProjection);
|
||||
} else {
|
||||
transformed = (write ? /** @type {import("../geom/Geometry").default} */ (geometry).clone() : geometry).transform(
|
||||
write ? featureProjection : dataProjection,
|
||||
write ? dataProjection : featureProjection);
|
||||
}
|
||||
} else {
|
||||
transformed = geometry;
|
||||
}
|
||||
if (write && opt_options && opt_options.decimals !== undefined) {
|
||||
const power = Math.pow(10, opt_options.decimals);
|
||||
if (write && opt_options && /** @type {WriteOptions} */ (opt_options).decimals !== undefined &&
|
||||
!Array.isArray(transformed)) {
|
||||
const power = Math.pow(10, /** @type {WriteOptions} */ (opt_options).decimals);
|
||||
// if decimals option on write, round each coordinate appropriately
|
||||
/**
|
||||
* @param {Array<number>} coordinates Coordinates.
|
||||
@@ -243,7 +260,7 @@ export function transformWithOptions(geometry, write, opt_options) {
|
||||
return coordinates;
|
||||
};
|
||||
if (transformed === geometry) {
|
||||
transformed = transformed.clone();
|
||||
transformed = /** @type {import("../geom/Geometry").default} */ (geometry).clone();
|
||||
}
|
||||
transformed.applyTransform(transform);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import {createOrUpdate} from '../extent.js';
|
||||
import {transformWithOptions} from '../format/Feature.js';
|
||||
import GMLBase, {GMLNS} from '../format/GMLBase.js';
|
||||
import {writeStringTextNode} from '../format/xsd.js';
|
||||
import Geometry from '../geom/Geometry.js';
|
||||
import {assign} from '../obj.js';
|
||||
import {get as getProjection, transformExtent} from '../proj.js';
|
||||
import {createElementNS, getAllTextContent, makeArrayPusher, makeChildAppender,
|
||||
@@ -179,7 +178,7 @@ class GML2 extends GMLBase {
|
||||
writeFeatureElement(node, feature, objectStack) {
|
||||
const fid = feature.getId();
|
||||
if (fid) {
|
||||
node.setAttribute('fid', fid);
|
||||
node.setAttribute('fid', /** @type {string} */ (fid));
|
||||
}
|
||||
const context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
const featureNS = context['featureNS'];
|
||||
@@ -196,7 +195,7 @@ class GML2 extends GMLBase {
|
||||
if (value !== null) {
|
||||
keys.push(key);
|
||||
values.push(value);
|
||||
if (key == geometryName || value instanceof Geometry) {
|
||||
if (key == geometryName || typeof /** @type {?} */ (value).getSimplifiedGeometry === 'function') {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] = makeChildAppender(
|
||||
this.writeGeometryElement, this);
|
||||
@@ -285,7 +284,7 @@ class GML2 extends GMLBase {
|
||||
writeGeometryElement(node, geometry, objectStack) {
|
||||
const context = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[objectStack.length - 1]);
|
||||
const item = assign({}, context);
|
||||
item.node = node;
|
||||
item['node'] = node;
|
||||
let value;
|
||||
if (Array.isArray(geometry)) {
|
||||
if (context.dataProjection) {
|
||||
@@ -588,9 +587,9 @@ class GML2 extends GMLBase {
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
GML2.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
|
||||
GML2.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'coordinates': makeReplacer(GML2.prototype.readFlatCoordinates_)
|
||||
}
|
||||
@@ -599,9 +598,9 @@ GML2.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
GML2.prototype.FLAT_LINEAR_RINGS_PARSERS_ = {
|
||||
GML2.prototype.FLAT_LINEAR_RINGS_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'innerBoundaryIs': GML2.prototype.innerBoundaryIsParser_,
|
||||
'outerBoundaryIs': GML2.prototype.outerBoundaryIsParser_
|
||||
@@ -623,9 +622,9 @@ GML2.prototype.BOX_PARSERS_ = {
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
GML2.prototype.GEOMETRY_PARSERS_ = {
|
||||
GML2.prototype.GEOMETRY_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'Point': makeReplacer(GMLBase.prototype.readPoint),
|
||||
'MultiPoint': makeReplacer(
|
||||
|
||||
@@ -6,7 +6,6 @@ import {createOrUpdate} from '../extent.js';
|
||||
import {transformWithOptions} from '../format/Feature.js';
|
||||
import GMLBase, {GMLNS} from '../format/GMLBase.js';
|
||||
import {readNonNegativeIntegerString, writeStringTextNode} from '../format/xsd.js';
|
||||
import Geometry from '../geom/Geometry.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import MultiLineString from '../geom/MultiLineString.js';
|
||||
@@ -183,7 +182,7 @@ class GML3 extends GMLBase {
|
||||
*/
|
||||
readPolygonPatch_(node, objectStack) {
|
||||
return pushParseAndPop([null],
|
||||
this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
|
||||
this.FLAT_LINEAR_RINGS_PARSERS, node, objectStack, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,7 +193,7 @@ class GML3 extends GMLBase {
|
||||
*/
|
||||
readLineStringSegment_(node, objectStack) {
|
||||
return pushParseAndPop([null],
|
||||
this.GEOMETRY_FLAT_COORDINATES_PARSERS_,
|
||||
this.GEOMETRY_FLAT_COORDINATES_PARSERS,
|
||||
node, objectStack, this);
|
||||
}
|
||||
|
||||
@@ -357,9 +356,9 @@ class GML3 extends GMLBase {
|
||||
} else if (node.getAttribute('dimension')) {
|
||||
dim = readNonNegativeIntegerString(
|
||||
node.getAttribute('dimension'));
|
||||
} else if (node.parentNode.getAttribute('srsDimension')) {
|
||||
} else if (/** @type {Element} */ (node.parentNode).getAttribute('srsDimension')) {
|
||||
dim = readNonNegativeIntegerString(
|
||||
node.parentNode.getAttribute('srsDimension'));
|
||||
/** @type {Element} */ (node.parentNode).getAttribute('srsDimension'));
|
||||
} else if (contextDimension) {
|
||||
dim = readNonNegativeIntegerString(contextDimension);
|
||||
}
|
||||
@@ -387,7 +386,7 @@ class GML3 extends GMLBase {
|
||||
writePos_(node, value, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const hasZ = context['hasZ'];
|
||||
const srsDimension = hasZ ? 3 : 2;
|
||||
const srsDimension = hasZ ? '3' : '2';
|
||||
node.setAttribute('srsDimension', srsDimension);
|
||||
const srsName = context['srsName'];
|
||||
let axisOrientation = 'enu';
|
||||
@@ -443,7 +442,7 @@ class GML3 extends GMLBase {
|
||||
writePosList_(node, value, objectStack) {
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
const hasZ = context['hasZ'];
|
||||
const srsDimension = hasZ ? 3 : 2;
|
||||
const srsDimension = hasZ ? '3' : '2';
|
||||
node.setAttribute('srsDimension', srsDimension);
|
||||
const srsName = context['srsName'];
|
||||
// only 2d for simple features profile
|
||||
@@ -731,7 +730,7 @@ class GML3 extends GMLBase {
|
||||
writeGeometryElement(node, geometry, objectStack) {
|
||||
const context = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[objectStack.length - 1]);
|
||||
const item = assign({}, context);
|
||||
item.node = node;
|
||||
item['node'] = node;
|
||||
let value;
|
||||
if (Array.isArray(geometry)) {
|
||||
if (context.dataProjection) {
|
||||
@@ -757,7 +756,7 @@ class GML3 extends GMLBase {
|
||||
writeFeatureElement(node, feature, objectStack) {
|
||||
const fid = feature.getId();
|
||||
if (fid) {
|
||||
node.setAttribute('fid', fid);
|
||||
node.setAttribute('fid', /** @type {string} */ (fid));
|
||||
}
|
||||
const context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
const featureNS = context['featureNS'];
|
||||
@@ -774,7 +773,7 @@ class GML3 extends GMLBase {
|
||||
if (value !== null) {
|
||||
keys.push(key);
|
||||
values.push(value);
|
||||
if (key == geometryName || value instanceof Geometry) {
|
||||
if (key == geometryName || typeof /** @type {?} */ (value).getSimplifiedGeometry === 'function') {
|
||||
if (!(key in context.serializers[featureNS])) {
|
||||
context.serializers[featureNS][key] = makeChildAppender(
|
||||
this.writeGeometryElement, this);
|
||||
@@ -805,6 +804,7 @@ class GML3 extends GMLBase {
|
||||
const context = /** @type {Object} */ (objectStack[objectStack.length - 1]);
|
||||
const featureType = context['featureType'];
|
||||
const featureNS = context['featureNS'];
|
||||
/** @type {Object<string, Object<string, import("../xml.js").Serializer>>} */
|
||||
const serializers = {};
|
||||
serializers[featureNS] = {};
|
||||
serializers[featureNS][featureType] = makeChildAppender(
|
||||
@@ -828,7 +828,7 @@ class GML3 extends GMLBase {
|
||||
*/
|
||||
MULTIGEOMETRY_MEMBER_NODE_FACTORY_(value, objectStack, opt_nodeName) {
|
||||
const parentNode = objectStack[objectStack.length - 1].node;
|
||||
return createElementNS('http://www.opengis.net/gml',
|
||||
return createElementNS(this.namespace,
|
||||
MULTIGEOMETRY_TO_MEMBER_NODENAME[parentNode.nodeName]);
|
||||
}
|
||||
|
||||
@@ -861,7 +861,7 @@ class GML3 extends GMLBase {
|
||||
} else {
|
||||
nodeName = 'Envelope';
|
||||
}
|
||||
return createElementNS('http://www.opengis.net/gml',
|
||||
return createElementNS(this.namespace,
|
||||
nodeName);
|
||||
}
|
||||
|
||||
@@ -876,7 +876,7 @@ class GML3 extends GMLBase {
|
||||
*/
|
||||
writeGeometryNode(geometry, opt_options) {
|
||||
opt_options = this.adaptOptions(opt_options);
|
||||
const geom = createElementNS('http://www.opengis.net/gml', 'geom');
|
||||
const geom = createElementNS(this.namespace, 'geom');
|
||||
const context = {node: geom, hasZ: this.hasZ, srsName: this.srsName,
|
||||
curve: this.curve_, surface: this.surface_,
|
||||
multiSurface: this.multiSurface_, multiCurve: this.multiCurve_};
|
||||
@@ -898,7 +898,7 @@ class GML3 extends GMLBase {
|
||||
*/
|
||||
writeFeaturesNode(features, opt_options) {
|
||||
opt_options = this.adaptOptions(opt_options);
|
||||
const node = createElementNS('http://www.opengis.net/gml', 'featureMembers');
|
||||
const node = createElementNS(this.namespace, 'featureMembers');
|
||||
node.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', this.schemaLocation);
|
||||
const context = {
|
||||
srsName: this.srsName,
|
||||
@@ -921,9 +921,9 @@ class GML3 extends GMLBase {
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
GML3.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
|
||||
GML3.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'pos': makeReplacer(GML3.prototype.readFlatPos_),
|
||||
'posList': makeReplacer(GML3.prototype.readFlatPosList_)
|
||||
@@ -934,9 +934,9 @@ GML3.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS_ = {
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
GML3.prototype.FLAT_LINEAR_RINGS_PARSERS_ = {
|
||||
GML3.prototype.FLAT_LINEAR_RINGS_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'interior': GML3.prototype.interiorParser_,
|
||||
'exterior': GML3.prototype.exteriorParser_
|
||||
@@ -947,9 +947,9 @@ GML3.prototype.FLAT_LINEAR_RINGS_PARSERS_ = {
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
* @protected
|
||||
*/
|
||||
GML3.prototype.GEOMETRY_PARSERS_ = {
|
||||
GML3.prototype.GEOMETRY_PARSERS = {
|
||||
'http://www.opengis.net/gml': {
|
||||
'Point': makeReplacer(GMLBase.prototype.readPoint),
|
||||
'MultiPoint': makeReplacer(
|
||||
|
||||
386
src/ol/format/GML32.js
Normal file
386
src/ol/format/GML32.js
Normal file
@@ -0,0 +1,386 @@
|
||||
/**
|
||||
* @module ol/format/GML32
|
||||
*/
|
||||
import GML3 from './GML3.js';
|
||||
import GMLBase from './GMLBase.js';
|
||||
import {makeArrayPusher, makeReplacer, makeChildAppender} from '../xml.js';
|
||||
import {writeStringTextNode} from '../format/xsd.js';
|
||||
|
||||
/**
|
||||
* @classdesc Feature format for reading and writing data in the GML format
|
||||
* version 3.2.1.
|
||||
* @api
|
||||
*/
|
||||
class GML32 extends GML3 {
|
||||
|
||||
/**
|
||||
* @param {import("./GMLBase.js").Options=} opt_options Optional configuration object.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
const options = /** @type {import("./GMLBase.js").Options} */ (opt_options ? opt_options : {});
|
||||
|
||||
super(options);
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
this.schemaLocation = options.schemaLocation ?
|
||||
options.schemaLocation : this.namespace + ' http://schemas.opengis.net/gml/3.2.1/gml.xsd';
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
GML32.prototype.namespace = 'http://www.opengis.net/gml/3.2';
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @protected
|
||||
*/
|
||||
GML32.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'pos': makeReplacer(GML3.prototype.readFlatPos_),
|
||||
'posList': makeReplacer(GML3.prototype.readFlatPosList_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @protected
|
||||
*/
|
||||
GML32.prototype.FLAT_LINEAR_RINGS_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'interior': GML3.prototype.interiorParser_,
|
||||
'exterior': GML3.prototype.exteriorParser_
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @protected
|
||||
*/
|
||||
GML32.prototype.GEOMETRY_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'Point': makeReplacer(GMLBase.prototype.readPoint),
|
||||
'MultiPoint': makeReplacer(
|
||||
GMLBase.prototype.readMultiPoint),
|
||||
'LineString': makeReplacer(
|
||||
GMLBase.prototype.readLineString),
|
||||
'MultiLineString': makeReplacer(
|
||||
GMLBase.prototype.readMultiLineString),
|
||||
'LinearRing': makeReplacer(
|
||||
GMLBase.prototype.readLinearRing),
|
||||
'Polygon': makeReplacer(GMLBase.prototype.readPolygon),
|
||||
'MultiPolygon': makeReplacer(
|
||||
GMLBase.prototype.readMultiPolygon),
|
||||
'Surface': makeReplacer(GML32.prototype.readSurface_),
|
||||
'MultiSurface': makeReplacer(
|
||||
GML3.prototype.readMultiSurface_),
|
||||
'Curve': makeReplacer(GML32.prototype.readCurve_),
|
||||
'MultiCurve': makeReplacer(
|
||||
GML3.prototype.readMultiCurve_),
|
||||
'Envelope': makeReplacer(GML32.prototype.readEnvelope_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.MULTICURVE_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'curveMember': makeArrayPusher(
|
||||
GML3.prototype.curveMemberParser_),
|
||||
'curveMembers': makeArrayPusher(
|
||||
GML3.prototype.curveMemberParser_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.MULTISURFACE_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'surfaceMember': makeArrayPusher(
|
||||
GML3.prototype.surfaceMemberParser_),
|
||||
'surfaceMembers': makeArrayPusher(
|
||||
GML3.prototype.surfaceMemberParser_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.CURVEMEMBER_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'LineString': makeArrayPusher(
|
||||
GMLBase.prototype.readLineString),
|
||||
'Curve': makeArrayPusher(GML3.prototype.readCurve_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.SURFACEMEMBER_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'Polygon': makeArrayPusher(GMLBase.prototype.readPolygon),
|
||||
'Surface': makeArrayPusher(GML3.prototype.readSurface_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.SURFACE_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'patches': makeReplacer(GML3.prototype.readPatch_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.CURVE_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'segments': makeReplacer(GML3.prototype.readSegment_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.ENVELOPE_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'lowerCorner': makeArrayPusher(
|
||||
GML3.prototype.readFlatPosList_),
|
||||
'upperCorner': makeArrayPusher(
|
||||
GML3.prototype.readFlatPosList_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.PATCHES_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'PolygonPatch': makeReplacer(
|
||||
GML3.prototype.readPolygonPatch_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.SEGMENTS_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'LineStringSegment': makeReplacer(
|
||||
GML3.prototype.readLineStringSegment_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.MULTIPOINT_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'pointMember': makeArrayPusher(
|
||||
GMLBase.prototype.pointMemberParser_),
|
||||
'pointMembers': makeArrayPusher(
|
||||
GMLBase.prototype.pointMemberParser_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.MULTILINESTRING_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'lineStringMember': makeArrayPusher(
|
||||
GMLBase.prototype.lineStringMemberParser_),
|
||||
'lineStringMembers': makeArrayPusher(
|
||||
GMLBase.prototype.lineStringMemberParser_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.MULTIPOLYGON_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'polygonMember': makeArrayPusher(
|
||||
GMLBase.prototype.polygonMemberParser_),
|
||||
'polygonMembers': makeArrayPusher(
|
||||
GMLBase.prototype.polygonMemberParser_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.POINTMEMBER_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'Point': makeArrayPusher(
|
||||
GMLBase.prototype.readFlatCoordinatesFromNode_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.LINESTRINGMEMBER_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'LineString': makeArrayPusher(
|
||||
GMLBase.prototype.readLineString)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.POLYGONMEMBER_PARSERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'Polygon': makeArrayPusher(
|
||||
GMLBase.prototype.readPolygon)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @protected
|
||||
*/
|
||||
GML32.prototype.RING_PARSERS = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'LinearRing': makeReplacer(
|
||||
GMLBase.prototype.readFlatLinearRing_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.RING_SERIALIZERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'exterior': makeChildAppender(GML3.prototype.writeRing_),
|
||||
'interior': makeChildAppender(GML3.prototype.writeRing_)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.ENVELOPE_SERIALIZERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'lowerCorner': makeChildAppender(writeStringTextNode),
|
||||
'upperCorner': makeChildAppender(writeStringTextNode)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.SURFACEORPOLYGONMEMBER_SERIALIZERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'surfaceMember': makeChildAppender(
|
||||
GML3.prototype.writeSurfaceOrPolygonMember_),
|
||||
'polygonMember': makeChildAppender(
|
||||
GML3.prototype.writeSurfaceOrPolygonMember_)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.POINTMEMBER_SERIALIZERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'pointMember': makeChildAppender(
|
||||
GML3.prototype.writePointMember_)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.LINESTRINGORCURVEMEMBER_SERIALIZERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'lineStringMember': makeChildAppender(
|
||||
GML3.prototype.writeLineStringOrCurveMember_),
|
||||
'curveMember': makeChildAppender(
|
||||
GML3.prototype.writeLineStringOrCurveMember_)
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {Object<string, Object<string, import("../xml.js").Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
GML32.prototype.GEOMETRY_SERIALIZERS_ = {
|
||||
'http://www.opengis.net/gml/3.2': {
|
||||
'Curve': makeChildAppender(
|
||||
GML3.prototype.writeCurveOrLineString_),
|
||||
'MultiCurve': makeChildAppender(
|
||||
GML3.prototype.writeMultiCurveOrLineString_),
|
||||
'Point': makeChildAppender(GML32.prototype.writePoint_),
|
||||
'MultiPoint': makeChildAppender(
|
||||
GML3.prototype.writeMultiPoint_),
|
||||
'LineString': makeChildAppender(
|
||||
GML3.prototype.writeCurveOrLineString_),
|
||||
'MultiLineString': makeChildAppender(
|
||||
GML3.prototype.writeMultiCurveOrLineString_),
|
||||
'LinearRing': makeChildAppender(
|
||||
GML3.prototype.writeLinearRing_),
|
||||
'Polygon': makeChildAppender(
|
||||
GML3.prototype.writeSurfaceOrPolygon_),
|
||||
'MultiPolygon': makeChildAppender(
|
||||
GML3.prototype.writeMultiSurfaceOrPolygon_),
|
||||
'Surface': makeChildAppender(
|
||||
GML3.prototype.writeSurfaceOrPolygon_),
|
||||
'MultiSurface': makeChildAppender(
|
||||
GML3.prototype.writeMultiSurfaceOrPolygon_),
|
||||
'Envelope': makeChildAppender(
|
||||
GML3.prototype.writeEnvelope)
|
||||
}
|
||||
};
|
||||
|
||||
export default GML32;
|
||||
@@ -71,6 +71,7 @@ const ONLY_WHITESPACE_RE = /^[\s\xa0]*$/;
|
||||
* gml:MultiPolygon. Since the latter is deprecated in GML 3.
|
||||
* @property {string} [schemaLocation] Optional schemaLocation to use when
|
||||
* writing out the GML, this will override the default provided.
|
||||
* @property {boolean} [hasZ=false] If coordinates have a Z value.
|
||||
*/
|
||||
|
||||
|
||||
@@ -122,11 +123,10 @@ class GMLBase extends XMLFeature {
|
||||
* @type {Object<string, Object<string, Object>>}
|
||||
*/
|
||||
this.FEATURE_COLLECTION_PARSERS = {};
|
||||
this.FEATURE_COLLECTION_PARSERS[GMLNS] = {
|
||||
'featureMember': makeReplacer(this.readFeaturesInternal),
|
||||
this.FEATURE_COLLECTION_PARSERS[this.namespace] = {
|
||||
'featureMember': makeArrayPusher(this.readFeaturesInternal),
|
||||
'featureMembers': makeReplacer(this.readFeaturesInternal)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,15 +138,9 @@ class GMLBase extends XMLFeature {
|
||||
const localName = node.localName;
|
||||
let features = null;
|
||||
if (localName == 'FeatureCollection') {
|
||||
if (node.namespaceURI === 'http://www.opengis.net/wfs') {
|
||||
features = pushParseAndPop([],
|
||||
this.FEATURE_COLLECTION_PARSERS, node,
|
||||
objectStack, this);
|
||||
} else {
|
||||
features = pushParseAndPop(null,
|
||||
this.FEATURE_COLLECTION_PARSERS, node,
|
||||
objectStack, this);
|
||||
}
|
||||
features = pushParseAndPop([],
|
||||
this.FEATURE_COLLECTION_PARSERS, node,
|
||||
objectStack, this);
|
||||
} else if (localName == 'featureMembers' || localName == 'featureMember') {
|
||||
const context = objectStack[0];
|
||||
let featureType = context['featureType'];
|
||||
@@ -189,9 +183,11 @@ class GMLBase extends XMLFeature {
|
||||
featureNS = {};
|
||||
featureNS[defaultPrefix] = ns;
|
||||
}
|
||||
/** @type {Object<string, Object<string, import("../xml.js").Parser>>} */
|
||||
const parsersNS = {};
|
||||
const featureTypes = Array.isArray(featureType) ? featureType : [featureType];
|
||||
for (const p in featureNS) {
|
||||
/** @type {Object<string, import("../xml.js").Parser>} */
|
||||
const parsers = {};
|
||||
for (let i = 0, ii = featureTypes.length; i < ii; ++i) {
|
||||
const featurePrefix = featureTypes[i].indexOf(':') === -1 ?
|
||||
@@ -227,7 +223,7 @@ class GMLBase extends XMLFeature {
|
||||
context['srsName'] = node.firstElementChild.getAttribute('srsName');
|
||||
context['srsDimension'] = node.firstElementChild.getAttribute('srsDimension');
|
||||
/** @type {import("../geom/Geometry.js").default} */
|
||||
const geometry = pushParseAndPop(null, this.GEOMETRY_PARSERS_, node, objectStack, this);
|
||||
const geometry = pushParseAndPop(null, this.GEOMETRY_PARSERS, node, objectStack, this);
|
||||
if (geometry) {
|
||||
return (
|
||||
/** @type {import("../geom/Geometry.js").default} */ (transformWithOptions(geometry, false, context))
|
||||
@@ -240,42 +236,77 @@ class GMLBase extends XMLFeature {
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Feature} Feature.
|
||||
* @param {boolean} asFeature whether result should be wrapped as a feature.
|
||||
* @return {Feature|Object} Feature
|
||||
*/
|
||||
readFeatureElement(node, objectStack) {
|
||||
let n;
|
||||
const fid = node.getAttribute('fid') || getAttributeNS(node, GMLNS, 'id');
|
||||
const values = {};
|
||||
readFeatureElementInternal(node, objectStack, asFeature) {
|
||||
let geometryName;
|
||||
for (n = node.firstElementChild; n; n = n.nextElementSibling) {
|
||||
const values = {};
|
||||
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
|
||||
let value;
|
||||
const localName = n.localName;
|
||||
// Assume attribute elements have one child node and that the child
|
||||
// is a text or CDATA node (to be treated as text).
|
||||
// Otherwise assume it is a geometry node.
|
||||
if (n.childNodes.length === 0 ||
|
||||
(n.childNodes.length === 1 &&
|
||||
(n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))) {
|
||||
let value = getAllTextContent(n, false);
|
||||
// first, check if it is simple attribute
|
||||
if (n.childNodes.length === 0
|
||||
|| (n.childNodes.length === 1 && (n.firstChild.nodeType === 3 || n.firstChild.nodeType === 4))) {
|
||||
value = getAllTextContent(n, false);
|
||||
if (ONLY_WHITESPACE_RE.test(value)) {
|
||||
value = undefined;
|
||||
}
|
||||
values[localName] = value;
|
||||
} else {
|
||||
// boundedBy is an extent and must not be considered as a geometry
|
||||
if (localName !== 'boundedBy') {
|
||||
if (asFeature) {
|
||||
//if feature, try it as a geometry
|
||||
value = this.readGeometryElement(n, objectStack);
|
||||
}
|
||||
if (!value) { //if not a geometry or not a feature, treat it as a complex attribute
|
||||
value = this.readFeatureElementInternal(n, objectStack, false);
|
||||
} else if (localName !== 'boundedBy') {
|
||||
// boundedBy is an extent and must not be considered as a geometry
|
||||
geometryName = localName;
|
||||
}
|
||||
values[localName] = this.readGeometryElement(n, objectStack);
|
||||
}
|
||||
|
||||
if (values[localName]) {
|
||||
if (!(values[localName] instanceof Array)) {
|
||||
values[localName] = [values[localName]];
|
||||
}
|
||||
values[localName].push(value);
|
||||
} else {
|
||||
values[localName] = value;
|
||||
}
|
||||
|
||||
const len = n.attributes.length;
|
||||
if (len > 0) {
|
||||
values[localName] = {_content_: values[localName]};
|
||||
for (let i = 0; i < len; i++) {
|
||||
const attName = n.attributes[i].name;
|
||||
values[localName][attName] = n.attributes[i].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
const feature = new Feature(values);
|
||||
if (geometryName) {
|
||||
feature.setGeometryName(geometryName);
|
||||
if (!asFeature) {
|
||||
return values;
|
||||
} else {
|
||||
const feature = new Feature(values);
|
||||
if (geometryName) {
|
||||
feature.setGeometryName(geometryName);
|
||||
}
|
||||
const fid = node.getAttribute('fid') ||
|
||||
getAttributeNS(node, this.namespace, 'id');
|
||||
if (fid) {
|
||||
feature.setId(fid);
|
||||
}
|
||||
return feature;
|
||||
}
|
||||
if (fid) {
|
||||
feature.setId(fid);
|
||||
}
|
||||
return feature;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {Element} node Node.
|
||||
* @param {Array<*>} objectStack Object stack.
|
||||
* @return {Feature} Feature.
|
||||
*/
|
||||
readFeatureElement(node, objectStack) {
|
||||
return this.readFeatureElementInternal(node, objectStack, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -383,7 +414,7 @@ class GMLBase extends XMLFeature {
|
||||
*/
|
||||
readFlatLinearRing_(node, objectStack) {
|
||||
const ring = pushParseAndPop(null,
|
||||
this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node,
|
||||
this.GEOMETRY_FLAT_COORDINATES_PARSERS, node,
|
||||
objectStack, this);
|
||||
if (ring) {
|
||||
return ring;
|
||||
@@ -412,7 +443,7 @@ class GMLBase extends XMLFeature {
|
||||
readPolygon(node, objectStack) {
|
||||
/** @type {Array<Array<number>>} */
|
||||
const flatLinearRings = pushParseAndPop([null],
|
||||
this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
|
||||
this.FLAT_LINEAR_RINGS_PARSERS, node, objectStack, this);
|
||||
if (flatLinearRings && flatLinearRings[0]) {
|
||||
const flatCoordinates = flatLinearRings[0];
|
||||
const ends = [flatCoordinates.length];
|
||||
@@ -434,7 +465,7 @@ class GMLBase extends XMLFeature {
|
||||
* @return {Array<number>} Flat coordinates.
|
||||
*/
|
||||
readFlatCoordinatesFromNode_(node, objectStack) {
|
||||
return pushParseAndPop(null, this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node, objectStack, this);
|
||||
return pushParseAndPop(null, this.GEOMETRY_FLAT_COORDINATES_PARSERS, node, objectStack, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -469,6 +500,40 @@ class GMLBase extends XMLFeature {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GMLBase.prototype.namespace = GMLNS;
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @protected
|
||||
*/
|
||||
GMLBase.prototype.FLAT_LINEAR_RINGS_PARSERS = {
|
||||
'http://www.opengis.net/gml': {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @protected
|
||||
*/
|
||||
GMLBase.prototype.GEOMETRY_FLAT_COORDINATES_PARSERS = {
|
||||
'http://www.opengis.net/gml': {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
* @protected
|
||||
*/
|
||||
GMLBase.prototype.GEOMETRY_PARSERS = {
|
||||
'http://www.opengis.net/gml': {}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, Object<string, import("../xml.js").Parser>>}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {transformWithOptions} from '../format/Feature.js';
|
||||
import XMLFeature from '../format/XMLFeature.js';
|
||||
import {readString, readDecimal, readNonNegativeInteger, readDateTime, writeStringTextNode, writeNonNegativeIntegerTextNode, writeDecimalTextNode, writeDateTimeTextNode} from '../format/xsd.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import GeometryType from '../geom/GeometryType.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
import MultiLineString from '../geom/MultiLineString.js';
|
||||
import Point from '../geom/Point.js';
|
||||
@@ -738,8 +739,8 @@ function writeWptType(node, coordinate, objectStack) {
|
||||
const namespaceURI = parentNode.namespaceURI;
|
||||
const properties = context['properties'];
|
||||
//FIXME Projection handling
|
||||
node.setAttributeNS(null, 'lat', coordinate[1]);
|
||||
node.setAttributeNS(null, 'lon', coordinate[0]);
|
||||
node.setAttributeNS(null, 'lat', String(coordinate[1]));
|
||||
node.setAttributeNS(null, 'lon', String(coordinate[0]));
|
||||
const geometryLayout = context['geometryLayout'];
|
||||
switch (geometryLayout) {
|
||||
case GeometryLayout.XYZM:
|
||||
@@ -779,12 +780,13 @@ function writeWptType(node, coordinate, objectStack) {
|
||||
function writeRte(node, feature, objectStack) {
|
||||
const options = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[0]);
|
||||
const properties = feature.getProperties();
|
||||
const context = {node: node, 'properties': properties};
|
||||
let geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
geometry = /** @type {LineString} */ (transformWithOptions(geometry, true, options));
|
||||
context['geometryLayout'] = geometry.getLayout();
|
||||
properties['rtept'] = geometry.getCoordinates();
|
||||
const context = {node: node};
|
||||
context['properties'] = properties;
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry.getType() == GeometryType.LINE_STRING) {
|
||||
const lineString = /** @type {LineString} */ (transformWithOptions(geometry, true, options));
|
||||
context['geometryLayout'] = lineString.getLayout();
|
||||
properties['rtept'] = lineString.getCoordinates();
|
||||
}
|
||||
const parentNode = objectStack[objectStack.length - 1].node;
|
||||
const orderedKeys = RTE_SEQUENCE[parentNode.namespaceURI];
|
||||
@@ -804,12 +806,12 @@ function writeTrk(node, feature, objectStack) {
|
||||
const options = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[0]);
|
||||
const properties = feature.getProperties();
|
||||
/** @type {import("../xml.js").NodeStackItem} */
|
||||
const context = {node: node, 'properties': properties};
|
||||
let geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
geometry = /** @type {MultiLineString} */
|
||||
(transformWithOptions(geometry, true, options));
|
||||
properties['trkseg'] = geometry.getLineStrings();
|
||||
const context = {node: node};
|
||||
context['properties'] = properties;
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry.getType() == GeometryType.MULTI_LINE_STRING) {
|
||||
const multiLineString = /** @type {MultiLineString} */ (transformWithOptions(geometry, true, options));
|
||||
properties['trkseg'] = multiLineString.getLineStrings();
|
||||
}
|
||||
const parentNode = objectStack[objectStack.length - 1].node;
|
||||
const orderedKeys = TRK_SEQUENCE[parentNode.namespaceURI];
|
||||
@@ -827,8 +829,9 @@ function writeTrk(node, feature, objectStack) {
|
||||
*/
|
||||
function writeTrkSeg(node, lineString, objectStack) {
|
||||
/** @type {import("../xml.js").NodeStackItem} */
|
||||
const context = {node: node, 'geometryLayout': lineString.getLayout(),
|
||||
'properties': {}};
|
||||
const context = {node: node};
|
||||
context['geometryLayout'] = lineString.getLayout();
|
||||
context['properties'] = {};
|
||||
pushSerializeAndPop(context,
|
||||
TRKSEG_SERIALIZERS, TRKSEG_NODE_FACTORY,
|
||||
lineString.getCoordinates(), objectStack);
|
||||
@@ -844,12 +847,11 @@ function writeWpt(node, feature, objectStack) {
|
||||
const options = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[0]);
|
||||
const context = objectStack[objectStack.length - 1];
|
||||
context['properties'] = feature.getProperties();
|
||||
let geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
geometry = /** @type {Point} */
|
||||
(transformWithOptions(geometry, true, options));
|
||||
context['geometryLayout'] = geometry.getLayout();
|
||||
writeWptType(node, geometry.getCoordinates(), objectStack);
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry.getType() == GeometryType.POINT) {
|
||||
const point = /** @type {Point} */ (transformWithOptions(geometry, true, options));
|
||||
context['geometryLayout'] = point.getLayout();
|
||||
writeWptType(node, point.getCoordinates(), objectStack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -293,14 +293,14 @@ function readGeometry(object, opt_options) {
|
||||
throw new Error('Unsupported GeoJSON type: ' + object.type);
|
||||
}
|
||||
}
|
||||
return transformWithOptions(geometry, false, opt_options);
|
||||
return /** @type {import("../geom/Geometry.js").default} */ (transformWithOptions(geometry, false, opt_options));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {GeoJSONGeometryCollection} object Object.
|
||||
* @param {import("./Feature.js").ReadOptions=} opt_options Read options.
|
||||
* @return {import("../geom/GeometryCollection.js").default} Geometry collection.
|
||||
* @return {GeometryCollection} Geometry collection.
|
||||
*/
|
||||
function readGeometryCollectionGeometry(object, opt_options) {
|
||||
const geometries = object['geometries'].map(
|
||||
@@ -317,7 +317,7 @@ function readGeometryCollectionGeometry(object, opt_options) {
|
||||
|
||||
/**
|
||||
* @param {GeoJSONPoint} object Object.
|
||||
* @return {import("../geom/Point.js").default} Point.
|
||||
* @return {Point} Point.
|
||||
*/
|
||||
function readPointGeometry(object) {
|
||||
return new Point(object['coordinates']);
|
||||
@@ -326,7 +326,7 @@ function readPointGeometry(object) {
|
||||
|
||||
/**
|
||||
* @param {GeoJSONLineString} object Object.
|
||||
* @return {import("../geom/LineString.js").default} LineString.
|
||||
* @return {LineString} LineString.
|
||||
*/
|
||||
function readLineStringGeometry(object) {
|
||||
return new LineString(object['coordinates']);
|
||||
@@ -335,7 +335,7 @@ function readLineStringGeometry(object) {
|
||||
|
||||
/**
|
||||
* @param {GeoJSONMultiLineString} object Object.
|
||||
* @return {import("../geom/MultiLineString.js").default} MultiLineString.
|
||||
* @return {MultiLineString} MultiLineString.
|
||||
*/
|
||||
function readMultiLineStringGeometry(object) {
|
||||
return new MultiLineString(object['coordinates']);
|
||||
@@ -344,7 +344,7 @@ function readMultiLineStringGeometry(object) {
|
||||
|
||||
/**
|
||||
* @param {GeoJSONMultiPoint} object Object.
|
||||
* @return {import("../geom/MultiPoint.js").default} MultiPoint.
|
||||
* @return {MultiPoint} MultiPoint.
|
||||
*/
|
||||
function readMultiPointGeometry(object) {
|
||||
return new MultiPoint(object['coordinates']);
|
||||
@@ -353,7 +353,7 @@ function readMultiPointGeometry(object) {
|
||||
|
||||
/**
|
||||
* @param {GeoJSONMultiPolygon} object Object.
|
||||
* @return {import("../geom/MultiPolygon.js").default} MultiPolygon.
|
||||
* @return {MultiPolygon} MultiPolygon.
|
||||
*/
|
||||
function readMultiPolygonGeometry(object) {
|
||||
return new MultiPolygon(object['coordinates']);
|
||||
@@ -362,7 +362,7 @@ function readMultiPolygonGeometry(object) {
|
||||
|
||||
/**
|
||||
* @param {GeoJSONPolygon} object Object.
|
||||
* @return {import("../geom/Polygon.js").default} Polygon.
|
||||
* @return {Polygon} Polygon.
|
||||
*/
|
||||
function readPolygonGeometry(object) {
|
||||
return new Polygon(object['coordinates']);
|
||||
@@ -375,38 +375,38 @@ function readPolygonGeometry(object) {
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
function writeGeometry(geometry, opt_options) {
|
||||
geometry = transformWithOptions(geometry, true, opt_options);
|
||||
geometry = /** @type {import("../geom/Geometry.js").default} */ (transformWithOptions(geometry, true, opt_options));
|
||||
const type = geometry.getType();
|
||||
|
||||
/** @type {GeoJSONGeometry} */
|
||||
let geoJSON;
|
||||
switch (type) {
|
||||
case GeometryType.POINT: {
|
||||
geoJSON = writePointGeometry(/** @type {import("../geom/Point.js").default} */ (geometry), opt_options);
|
||||
geoJSON = writePointGeometry(/** @type {Point} */ (geometry), opt_options);
|
||||
break;
|
||||
}
|
||||
case GeometryType.LINE_STRING: {
|
||||
geoJSON = writeLineStringGeometry(/** @type {import("../geom/LineString.js").default} */ (geometry), opt_options);
|
||||
geoJSON = writeLineStringGeometry(/** @type {LineString} */ (geometry), opt_options);
|
||||
break;
|
||||
}
|
||||
case GeometryType.POLYGON: {
|
||||
geoJSON = writePolygonGeometry(/** @type {import("../geom/Polygon.js").default} */ (geometry), opt_options);
|
||||
geoJSON = writePolygonGeometry(/** @type {Polygon} */ (geometry), opt_options);
|
||||
break;
|
||||
}
|
||||
case GeometryType.MULTI_POINT: {
|
||||
geoJSON = writeMultiPointGeometry(/** @type {import("../geom/MultiPoint.js").default} */ (geometry), opt_options);
|
||||
geoJSON = writeMultiPointGeometry(/** @type {MultiPoint} */ (geometry), opt_options);
|
||||
break;
|
||||
}
|
||||
case GeometryType.MULTI_LINE_STRING: {
|
||||
geoJSON = writeMultiLineStringGeometry(/** @type {import("../geom/MultiLineString.js").default} */ (geometry), opt_options);
|
||||
geoJSON = writeMultiLineStringGeometry(/** @type {MultiLineString} */ (geometry), opt_options);
|
||||
break;
|
||||
}
|
||||
case GeometryType.MULTI_POLYGON: {
|
||||
geoJSON = writeMultiPolygonGeometry(/** @type {import("../geom/MultiPolygon.js").default} */ (geometry), opt_options);
|
||||
geoJSON = writeMultiPolygonGeometry(/** @type {MultiPolygon} */ (geometry), opt_options);
|
||||
break;
|
||||
}
|
||||
case GeometryType.GEOMETRY_COLLECTION: {
|
||||
geoJSON = writeGeometryCollectionGeometry(/** @type {import("../geom/GeometryCollection.js").default} */ (geometry), opt_options);
|
||||
geoJSON = writeGeometryCollectionGeometry(/** @type {GeometryCollection} */ (geometry), opt_options);
|
||||
break;
|
||||
}
|
||||
case GeometryType.CIRCLE: {
|
||||
@@ -425,7 +425,7 @@ function writeGeometry(geometry, opt_options) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../geom/GeometryCollection.js").default} geometry Geometry.
|
||||
* @param {GeometryCollection} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
|
||||
* @return {GeoJSONGeometryCollection} GeoJSON geometry collection.
|
||||
*/
|
||||
@@ -443,7 +443,7 @@ function writeGeometryCollectionGeometry(geometry, opt_options) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../geom/LineString.js").default} geometry Geometry.
|
||||
* @param {LineString} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
@@ -456,7 +456,7 @@ function writeLineStringGeometry(geometry, opt_options) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../geom/MultiLineString.js").default} geometry Geometry.
|
||||
* @param {MultiLineString} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
@@ -469,7 +469,7 @@ function writeMultiLineStringGeometry(geometry, opt_options) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../geom/MultiPoint.js").default} geometry Geometry.
|
||||
* @param {MultiPoint} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
@@ -482,7 +482,7 @@ function writeMultiPointGeometry(geometry, opt_options) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../geom/MultiPolygon.js").default} geometry Geometry.
|
||||
* @param {MultiPolygon} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
@@ -499,7 +499,7 @@ function writeMultiPolygonGeometry(geometry, opt_options) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../geom/Point.js").default} geometry Geometry.
|
||||
* @param {Point} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
@@ -512,7 +512,7 @@ function writePointGeometry(geometry, opt_options) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../geom/Polygon.js").default} geometry Geometry.
|
||||
* @param {Polygon} geometry Geometry.
|
||||
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
|
||||
* @return {GeoJSONGeometry} GeoJSON geometry.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* @module ol/format/JSONFeature
|
||||
*/
|
||||
import {abstract} from '../util.js';
|
||||
import FeatureFormat from '../format/Feature.js';
|
||||
import FormatType from '../format/FormatType.js';
|
||||
|
||||
@@ -59,7 +60,9 @@ class JSONFeature extends FeatureFormat {
|
||||
* @protected
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromObject(object, opt_options) {}
|
||||
readFeatureFromObject(object, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
@@ -68,7 +71,9 @@ class JSONFeature extends FeatureFormat {
|
||||
* @protected
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
*/
|
||||
readFeaturesFromObject(object, opt_options) {}
|
||||
readFeaturesFromObject(object, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a geometry.
|
||||
@@ -90,7 +95,9 @@ class JSONFeature extends FeatureFormat {
|
||||
* @protected
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometryFromObject(object, opt_options) {}
|
||||
readGeometryFromObject(object, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the projection.
|
||||
@@ -109,7 +116,9 @@ class JSONFeature extends FeatureFormat {
|
||||
* @protected
|
||||
* @return {import("../proj/Projection.js").default} Projection.
|
||||
*/
|
||||
readProjectionFromObject(object) {}
|
||||
readProjectionFromObject(object) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a feature as string.
|
||||
@@ -129,7 +138,9 @@ class JSONFeature extends FeatureFormat {
|
||||
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
writeFeatureObject(feature, opt_options) {}
|
||||
writeFeatureObject(feature, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of features as string.
|
||||
@@ -149,7 +160,9 @@ class JSONFeature extends FeatureFormat {
|
||||
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
writeFeaturesObject(features, opt_options) {}
|
||||
writeFeaturesObject(features, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode a geometry as string.
|
||||
@@ -169,7 +182,9 @@ class JSONFeature extends FeatureFormat {
|
||||
* @param {import("./Feature.js").WriteOptions=} opt_options Write options.
|
||||
* @return {Object} Object.
|
||||
*/
|
||||
writeGeometryObject(geometry, opt_options) {}
|
||||
writeGeometryObject(geometry, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import IconOrigin from '../style/IconOrigin.js';
|
||||
import Stroke from '../style/Stroke.js';
|
||||
import Style from '../style/Style.js';
|
||||
import Text from '../style/Text.js';
|
||||
import {createElementNS, getAllTextContent, isDocument, isNode, makeArrayExtender,
|
||||
import {createElementNS, getAllTextContent, isDocument, makeArrayExtender,
|
||||
makeArrayPusher, makeChildAppender, makeObjectPropertySetter,
|
||||
makeReplacer, makeSequence, makeSimpleNodeFactory, makeStructureNS,
|
||||
OBJECT_PROPERTY_NODE_FACTORY, parse, parseNode, pushParseAndPop,
|
||||
@@ -639,15 +639,15 @@ class KML extends XMLFeature {
|
||||
* @api
|
||||
*/
|
||||
readName(source) {
|
||||
if (isDocument(source)) {
|
||||
return this.readNameFromDocument(/** @type {Document} */ (source));
|
||||
} else if (isNode(source)) {
|
||||
return this.readNameFromNode(/** @type {Element} */ (source));
|
||||
if (!source) {
|
||||
return undefined;
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readNameFromDocument(doc);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readNameFromDocument(/** @type {Document} */ (source));
|
||||
} else {
|
||||
return undefined;
|
||||
return this.readNameFromNode(/** @type {Element} */ (source));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,7 +656,7 @@ class KML extends XMLFeature {
|
||||
* @return {string|undefined} Name.
|
||||
*/
|
||||
readNameFromDocument(doc) {
|
||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||
for (let n = /** @type {Node} */ (doc.firstChild); n; n = n.nextSibling) {
|
||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||
const name = this.readNameFromNode(/** @type {Element} */ (n));
|
||||
if (name) {
|
||||
@@ -703,15 +703,15 @@ class KML extends XMLFeature {
|
||||
*/
|
||||
readNetworkLinks(source) {
|
||||
const networkLinks = [];
|
||||
if (isDocument(source)) {
|
||||
extend(networkLinks, this.readNetworkLinksFromDocument(
|
||||
/** @type {Document} */ (source)));
|
||||
} else if (isNode(source)) {
|
||||
extend(networkLinks, this.readNetworkLinksFromNode(
|
||||
/** @type {Element} */ (source)));
|
||||
} else if (typeof source === 'string') {
|
||||
if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
extend(networkLinks, this.readNetworkLinksFromDocument(doc));
|
||||
} else if (isDocument(source)) {
|
||||
extend(networkLinks, this.readNetworkLinksFromDocument(
|
||||
/** @type {Document} */ (source)));
|
||||
} else {
|
||||
extend(networkLinks, this.readNetworkLinksFromNode(
|
||||
/** @type {Element} */ (source)));
|
||||
}
|
||||
return networkLinks;
|
||||
}
|
||||
@@ -722,7 +722,7 @@ class KML extends XMLFeature {
|
||||
*/
|
||||
readNetworkLinksFromDocument(doc) {
|
||||
const networkLinks = [];
|
||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||
for (let n = /** @type {Node} */ (doc.firstChild); n; n = n.nextSibling) {
|
||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||
extend(networkLinks, this.readNetworkLinksFromNode(/** @type {Element} */ (n)));
|
||||
}
|
||||
@@ -765,15 +765,15 @@ class KML extends XMLFeature {
|
||||
*/
|
||||
readRegion(source) {
|
||||
const regions = [];
|
||||
if (isDocument(source)) {
|
||||
extend(regions, this.readRegionFromDocument(
|
||||
/** @type {Document} */ (source)));
|
||||
} else if (isNode(source)) {
|
||||
extend(regions, this.readRegionFromNode(
|
||||
/** @type {Element} */ (source)));
|
||||
} else if (typeof source === 'string') {
|
||||
if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
extend(regions, this.readRegionFromDocument(doc));
|
||||
} else if (isDocument(source)) {
|
||||
extend(regions, this.readRegionFromDocument(
|
||||
/** @type {Document} */ (source)));
|
||||
} else {
|
||||
extend(regions, this.readRegionFromNode(
|
||||
/** @type {Element} */ (source)));
|
||||
}
|
||||
return regions;
|
||||
}
|
||||
@@ -784,7 +784,7 @@ class KML extends XMLFeature {
|
||||
*/
|
||||
readRegionFromDocument(doc) {
|
||||
const regions = [];
|
||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||
for (let n = /** @type {Node} */ (doc.firstChild); n; n = n.nextSibling) {
|
||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||
extend(regions, this.readRegionFromNode(/** @type {Element} */ (n)));
|
||||
}
|
||||
@@ -838,6 +838,7 @@ class KML extends XMLFeature {
|
||||
kml.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', SCHEMA_LOCATION);
|
||||
|
||||
const /** @type {import("../xml.js").NodeStackItem} */ context = {node: kml};
|
||||
/** @type {!Object<string, (Array<Feature>|Feature|undefined)>} */
|
||||
const properties = {};
|
||||
if (features.length > 1) {
|
||||
properties['Document'] = features;
|
||||
@@ -931,7 +932,7 @@ function createFeatureStyleFunction(style, styleUrl, defaultStyle, sharedStyles,
|
||||
|
||||
if (drawName) {
|
||||
name = /** @type {string} */ (feature.get('name'));
|
||||
drawName = drawName && name;
|
||||
drawName = drawName && !!name;
|
||||
}
|
||||
|
||||
if (style) {
|
||||
@@ -1714,11 +1715,13 @@ function readStyle(node, objectStack) {
|
||||
if (fill !== undefined && !fill) {
|
||||
fillStyle = null;
|
||||
}
|
||||
let imageStyle = /** @type {import("../style/Image.js").default} */
|
||||
('imageStyle' in styleObject ?
|
||||
styleObject['imageStyle'] : DEFAULT_IMAGE_STYLE);
|
||||
if (imageStyle == DEFAULT_NO_IMAGE_STYLE) {
|
||||
imageStyle = undefined;
|
||||
let imageStyle;
|
||||
if ('imageStyle' in styleObject) {
|
||||
if (styleObject['imageStyle'] != DEFAULT_NO_IMAGE_STYLE) {
|
||||
imageStyle = styleObject['imageStyle'];
|
||||
}
|
||||
} else {
|
||||
imageStyle = DEFAULT_IMAGE_STYLE;
|
||||
}
|
||||
const textStyle = /** @type {Text} */
|
||||
('textStyle' in styleObject ?
|
||||
@@ -2073,9 +2076,10 @@ function whenParser(node, objectStack) {
|
||||
function writeColorTextNode(node, color) {
|
||||
const rgba = asArray(color);
|
||||
const opacity = (rgba.length == 4) ? rgba[3] : 1;
|
||||
/** @type {Array<string|number>} */
|
||||
const abgr = [opacity * 255, rgba[2], rgba[1], rgba[0]];
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
const hex = parseInt(abgr[i], 10).toString(16);
|
||||
const hex = Math.floor(/** @type {number} */ (abgr[i])).toString(16);
|
||||
abgr[i] = (hex.length == 1) ? '0' + hex : hex;
|
||||
}
|
||||
writeStringTextNode(node, abgr.join(''));
|
||||
@@ -2666,7 +2670,7 @@ function writePlacemark(node, feature, objectStack) {
|
||||
|
||||
// set id
|
||||
if (feature.getId()) {
|
||||
node.setAttribute('id', feature.getId());
|
||||
node.setAttribute('id', /** @type {string} */ (feature.getId()));
|
||||
}
|
||||
|
||||
// serialize properties (properties unknown to KML are not serialized)
|
||||
@@ -2713,7 +2717,7 @@ function writePlacemark(node, feature, objectStack) {
|
||||
const options = /** @type {import("./Feature.js").WriteOptions} */ (objectStack[0]);
|
||||
let geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
geometry = transformWithOptions(geometry, true, options);
|
||||
geometry = /** @type {import("../geom/Geometry.js").default} */ (transformWithOptions(geometry, true, options));
|
||||
}
|
||||
pushSerializeAndPop(context, PLACEMARK_SERIALIZERS,
|
||||
GEOMETRY_NODE_FACTORY, [geometry], objectStack);
|
||||
@@ -2893,7 +2897,7 @@ function writeStyle(node, style, objectStack) {
|
||||
const strokeStyle = style.getStroke();
|
||||
const imageStyle = style.getImage();
|
||||
const textStyle = style.getText();
|
||||
if (imageStyle instanceof Icon) {
|
||||
if (imageStyle && typeof /** @type {?} */ (imageStyle).getSrc === 'function') {
|
||||
properties['IconStyle'] = imageStyle;
|
||||
}
|
||||
if (textStyle) {
|
||||
@@ -2918,8 +2922,8 @@ function writeStyle(node, style, objectStack) {
|
||||
* @param {Vec2} vec2 Vec2.
|
||||
*/
|
||||
function writeVec2(node, vec2) {
|
||||
node.setAttribute('x', vec2.x);
|
||||
node.setAttribute('y', vec2.y);
|
||||
node.setAttribute('x', String(vec2.x));
|
||||
node.setAttribute('y', String(vec2.y));
|
||||
node.setAttribute('xunits', vec2.xunits);
|
||||
node.setAttribute('yunits', vec2.yunits);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
import {assert} from '../asserts.js';
|
||||
import PBF from 'pbf';
|
||||
import FeatureFormat, {transformWithOptions} from '../format/Feature.js';
|
||||
import FormatType from '../format/FormatType.js';
|
||||
import FeatureFormat, {transformWithOptions} from './Feature.js';
|
||||
import FormatType from './FormatType.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
import GeometryType from '../geom/GeometryType.js';
|
||||
import LineString from '../geom/LineString.js';
|
||||
@@ -23,17 +23,14 @@ import RenderFeature from '../render/Feature.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {function((import("../geom/Geometry.js").default|Object<string,*>)=)|function(GeometryType,Array<number>,(Array<number>|Array<Array<number>>),Object<string,*>,number)} [featureClass]
|
||||
* Class for features returned by {@link module:ol/format/MVT#readFeatures}. Set to
|
||||
* {@link module:ol/Feature~Feature} to get full editing and geometry support at the cost of
|
||||
* decreased rendering performance. The default is {@link module:ol/render/Feature~RenderFeature},
|
||||
* which is optimized for rendering and hit detection.
|
||||
* @property {string} [geometryName='geometry'] Geometry name to use when creating
|
||||
* features.
|
||||
* @property {string} [layerName='layer'] Name of the feature attribute that
|
||||
* holds the layer name.
|
||||
* @property {Array<string>} [layers] Layers to read features from. If not
|
||||
* provided, features will be read from all layers.
|
||||
* @property {import("../Feature.js").FeatureClass} [featureClass] Class for features returned by
|
||||
* {@link module:ol/format/MVT#readFeatures}. Set to {@link module:ol/Feature~Feature} to get full editing and geometry
|
||||
* support at the cost of decreased rendering performance. The default is
|
||||
* {@link module:ol/render/Feature~RenderFeature}, which is optimized for rendering and hit detection.
|
||||
* @property {string} [geometryName='geometry'] Geometry name to use when creating features.
|
||||
* @property {string} [layerName='layer'] Name of the feature attribute that holds the layer name.
|
||||
* @property {Array<string>} [layers] Layers to read features from. If not provided, features will be read from all
|
||||
* layers.
|
||||
*/
|
||||
|
||||
|
||||
@@ -64,12 +61,9 @@ class MVT extends FeatureFormat {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {function((import("../geom/Geometry.js").default|Object<string,*>)=)|
|
||||
* function(GeometryType,Array<number>,
|
||||
* (Array<number>|Array<Array<number>>),Object<string,*>,number)}
|
||||
* @type {import("../Feature.js").FeatureClass}
|
||||
*/
|
||||
this.featureClass_ = options.featureClass ?
|
||||
options.featureClass : RenderFeature;
|
||||
this.featureClass_ = options.featureClass ? options.featureClass : RenderFeature;
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -167,7 +161,7 @@ class MVT extends FeatureFormat {
|
||||
* @param {Object} pbf PBF
|
||||
* @param {Object} rawFeature Raw Mapbox feature.
|
||||
* @param {import("./Feature.js").ReadOptions=} opt_options Read options.
|
||||
* @return {import("../Feature.js").default|RenderFeature} Feature.
|
||||
* @return {import("../Feature.js").FeatureLike} Feature.
|
||||
*/
|
||||
createFeature_(pbf, rawFeature, opt_options) {
|
||||
const type = rawFeature.type;
|
||||
@@ -215,11 +209,13 @@ class MVT extends FeatureFormat {
|
||||
geometryType === GeometryType.MULTI_LINE_STRING ? new MultiLineString(flatCoordinates, GeometryLayout.XY, ends) :
|
||||
null;
|
||||
}
|
||||
feature = new this.featureClass_();
|
||||
const ctor = /** @type {typeof import("../Feature.js").default} */ (this.featureClass_);
|
||||
feature = new ctor();
|
||||
if (this.geometryName_) {
|
||||
feature.setGeometryName(this.geometryName_);
|
||||
}
|
||||
const geometry = transformWithOptions(geom, false, this.adaptOptions(opt_options));
|
||||
const geometry = /** @type {import("../geom/Geometry.js").default} */ (transformWithOptions(geom, false,
|
||||
this.adaptOptions(opt_options)));
|
||||
feature.setGeometry(geometry);
|
||||
feature.setId(id);
|
||||
feature.setProperties(values);
|
||||
@@ -252,7 +248,7 @@ class MVT extends FeatureFormat {
|
||||
|
||||
const pbf = new PBF(/** @type {ArrayBuffer} */ (source));
|
||||
const pbfLayers = pbf.readFields(layersPBFReader, {});
|
||||
/** @type {Array<import("../Feature.js").default|RenderFeature>} */
|
||||
/** @type {Array<import("../Feature.js").FeatureLike>} */
|
||||
const features = [];
|
||||
for (const name in pbfLayers) {
|
||||
if (layers && layers.indexOf(name) == -1) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* @module ol/format/TextFeature
|
||||
*/
|
||||
import {abstract} from '../util.js';
|
||||
import FeatureFormat from '../format/Feature.js';
|
||||
import FormatType from '../format/FormatType.js';
|
||||
|
||||
@@ -43,7 +44,9 @@ class TextFeature extends FeatureFormat {
|
||||
* @protected
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
readFeatureFromText(text, opt_options) {}
|
||||
readFeatureFromText(text, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the features from the source.
|
||||
@@ -64,7 +67,9 @@ class TextFeature extends FeatureFormat {
|
||||
* @protected
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
*/
|
||||
readFeaturesFromText(text, opt_options) {}
|
||||
readFeaturesFromText(text, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the geometry from the source.
|
||||
@@ -85,7 +90,9 @@ class TextFeature extends FeatureFormat {
|
||||
* @protected
|
||||
* @return {import("../geom/Geometry.js").default} Geometry.
|
||||
*/
|
||||
readGeometryFromText(text, opt_options) {}
|
||||
readGeometryFromText(text, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the projection from the source.
|
||||
@@ -126,7 +133,9 @@ class TextFeature extends FeatureFormat {
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeFeatureText(feature, opt_options) {}
|
||||
writeFeatureText(feature, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode an array of features as string.
|
||||
@@ -147,7 +156,9 @@ class TextFeature extends FeatureFormat {
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeFeaturesText(features, opt_options) {}
|
||||
writeFeaturesText(features, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a single geometry.
|
||||
@@ -168,7 +179,9 @@ class TextFeature extends FeatureFormat {
|
||||
* @protected
|
||||
* @return {string} Text.
|
||||
*/
|
||||
writeGeometryText(geometry, opt_options) {}
|
||||
writeGeometryText(geometry, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ class TopoJSON extends JSONFeature {
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object<string, function(TopoJSONGeometry, Array, ...Array): import("../geom/Geometry.js").default>}
|
||||
* @type {Object<string, function(TopoJSONGeometry, Array, ...Array=): import("../geom/Geometry.js").default>}
|
||||
*/
|
||||
const GEOMETRY_READERS = {
|
||||
'Point': readPointGeometry,
|
||||
|
||||
@@ -8,10 +8,9 @@ import GMLBase, {GMLNS} from '../format/GMLBase.js';
|
||||
import {and as andFilter, bbox as bboxFilter} from '../format/filter.js';
|
||||
import XMLFeature from '../format/XMLFeature.js';
|
||||
import {readNonNegativeIntegerString, readNonNegativeInteger, writeStringTextNode} from '../format/xsd.js';
|
||||
import Geometry from '../geom/Geometry.js';
|
||||
import {assign} from '../obj.js';
|
||||
import {get as getProjection} from '../proj.js';
|
||||
import {createElementNS, isDocument, isNode, makeArrayPusher, makeChildAppender,
|
||||
import {createElementNS, isDocument, makeArrayPusher, makeChildAppender,
|
||||
makeObjectPropertySetter, makeSimpleNodeFactory, parse, parseNode,
|
||||
pushParseAndPop, pushSerializeAndPop, XML_SCHEMA_INSTANCE_URI} from '../xml.js';
|
||||
|
||||
@@ -257,10 +256,15 @@ class WFS extends XMLFeature {
|
||||
* @inheritDoc
|
||||
*/
|
||||
readFeaturesFromNode(node, opt_options) {
|
||||
const context = /** @type {import("../xml.js").NodeStackItem} */ ({
|
||||
/** @type {import("../xml.js").NodeStackItem} */
|
||||
const context = {
|
||||
node: node
|
||||
};
|
||||
assign(context, {
|
||||
'featureType': this.featureType_,
|
||||
'featureNS': this.featureNS_
|
||||
});
|
||||
|
||||
assign(context, this.getReadOptions(node, opt_options ? opt_options : {}));
|
||||
const objectStack = [context];
|
||||
this.gmlFormat_.FEATURE_COLLECTION_PARSERS[GMLNS][
|
||||
@@ -283,16 +287,16 @@ class WFS extends XMLFeature {
|
||||
* @api
|
||||
*/
|
||||
readTransactionResponse(source) {
|
||||
if (isDocument(source)) {
|
||||
return this.readTransactionResponseFromDocument(
|
||||
/** @type {Document} */ (source));
|
||||
} else if (isNode(source)) {
|
||||
return this.readTransactionResponseFromNode(/** @type {Element} */ (source));
|
||||
if (!source) {
|
||||
return undefined;
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readTransactionResponseFromDocument(doc);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readTransactionResponseFromDocument(
|
||||
/** @type {Document} */ (source));
|
||||
} else {
|
||||
return undefined;
|
||||
return this.readTransactionResponseFromNode(/** @type {Element} */ (source));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,17 +309,17 @@ class WFS extends XMLFeature {
|
||||
* @api
|
||||
*/
|
||||
readFeatureCollectionMetadata(source) {
|
||||
if (isDocument(source)) {
|
||||
return this.readFeatureCollectionMetadataFromDocument(
|
||||
/** @type {Document} */ (source));
|
||||
} else if (isNode(source)) {
|
||||
return this.readFeatureCollectionMetadataFromNode(
|
||||
/** @type {Element} */ (source));
|
||||
if (!source) {
|
||||
return undefined;
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readFeatureCollectionMetadataFromDocument(doc);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readFeatureCollectionMetadataFromDocument(
|
||||
/** @type {Document} */ (source));
|
||||
} else {
|
||||
return undefined;
|
||||
return this.readFeatureCollectionMetadataFromNode(
|
||||
/** @type {Element} */ (source));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,7 +329,7 @@ class WFS extends XMLFeature {
|
||||
* FeatureCollection metadata.
|
||||
*/
|
||||
readFeatureCollectionMetadataFromDocument(doc) {
|
||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||
for (let n = /** @type {Node} */ (doc.firstChild); n; n = n.nextSibling) {
|
||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||
return this.readFeatureCollectionMetadataFromNode(/** @type {Element} */ (n));
|
||||
}
|
||||
@@ -353,7 +357,7 @@ class WFS extends XMLFeature {
|
||||
* @return {TransactionResponse|undefined} Transaction response.
|
||||
*/
|
||||
readTransactionResponseFromDocument(doc) {
|
||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||
for (let n = /** @type {Node} */ (doc.firstChild); n; n = n.nextSibling) {
|
||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||
return this.readTransactionResponseFromNode(/** @type {Element} */ (n));
|
||||
}
|
||||
@@ -391,16 +395,16 @@ class WFS extends XMLFeature {
|
||||
node.setAttribute('outputFormat', options.outputFormat);
|
||||
}
|
||||
if (options.maxFeatures !== undefined) {
|
||||
node.setAttribute('maxFeatures', options.maxFeatures);
|
||||
node.setAttribute('maxFeatures', String(options.maxFeatures));
|
||||
}
|
||||
if (options.resultType) {
|
||||
node.setAttribute('resultType', options.resultType);
|
||||
}
|
||||
if (options.startIndex !== undefined) {
|
||||
node.setAttribute('startIndex', options.startIndex);
|
||||
node.setAttribute('startIndex', String(options.startIndex));
|
||||
}
|
||||
if (options.count !== undefined) {
|
||||
node.setAttribute('count', options.count);
|
||||
node.setAttribute('count', String(options.count));
|
||||
}
|
||||
filter = options.filter;
|
||||
if (options.bbox) {
|
||||
@@ -419,14 +423,17 @@ class WFS extends XMLFeature {
|
||||
node.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', this.schemaLocation_);
|
||||
/** @type {import("../xml.js").NodeStackItem} */
|
||||
const context = {
|
||||
node: node,
|
||||
node: node
|
||||
};
|
||||
assign(context, {
|
||||
'srsName': options.srsName,
|
||||
'featureNS': options.featureNS ? options.featureNS : this.featureNS_,
|
||||
'featurePrefix': options.featurePrefix,
|
||||
'geometryName': options.geometryName,
|
||||
'filter': filter,
|
||||
'propertyNames': options.propertyNames ? options.propertyNames : []
|
||||
};
|
||||
});
|
||||
|
||||
assert(Array.isArray(options.featureTypes),
|
||||
11); // `options.featureTypes` should be an Array
|
||||
writeGetFeature(node, /** @type {!Array<string>} */ (options.featureTypes), [context]);
|
||||
@@ -463,9 +470,9 @@ class WFS extends XMLFeature {
|
||||
node.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', schemaLocation);
|
||||
const featurePrefix = options.featurePrefix ? options.featurePrefix : FEATURE_PREFIX;
|
||||
if (inserts) {
|
||||
obj = {node: node, 'featureNS': options.featureNS,
|
||||
obj = assign({node: node}, {'featureNS': options.featureNS,
|
||||
'featureType': options.featureType, 'featurePrefix': featurePrefix,
|
||||
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
|
||||
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName});
|
||||
assign(obj, baseObj);
|
||||
pushSerializeAndPop(obj,
|
||||
TRANSACTION_SERIALIZERS,
|
||||
@@ -473,9 +480,9 @@ class WFS extends XMLFeature {
|
||||
objectStack);
|
||||
}
|
||||
if (updates) {
|
||||
obj = {node: node, 'featureNS': options.featureNS,
|
||||
obj = assign({node: node}, {'featureNS': options.featureNS,
|
||||
'featureType': options.featureType, 'featurePrefix': featurePrefix,
|
||||
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
|
||||
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName});
|
||||
assign(obj, baseObj);
|
||||
pushSerializeAndPop(obj,
|
||||
TRANSACTION_SERIALIZERS,
|
||||
@@ -505,7 +512,7 @@ class WFS extends XMLFeature {
|
||||
* @inheritDoc
|
||||
*/
|
||||
readProjectionFromDocument(doc) {
|
||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||
for (let n = /** @type {Node} */ (doc.firstChild); n; n = n.nextSibling) {
|
||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||
return this.readProjectionFromNode(n);
|
||||
}
|
||||
@@ -620,7 +627,7 @@ function writeOgcFidFilter(node, fid, objectStack) {
|
||||
const filter = createElementNS(OGCNS, 'Filter');
|
||||
const child = createElementNS(OGCNS, 'FeatureId');
|
||||
filter.appendChild(child);
|
||||
child.setAttribute('fid', fid);
|
||||
child.setAttribute('fid', /** @type {string} */ (fid));
|
||||
node.appendChild(filter);
|
||||
}
|
||||
|
||||
@@ -686,7 +693,7 @@ function writeUpdate(node, feature, objectStack) {
|
||||
const value = feature.get(keys[i]);
|
||||
if (value !== undefined) {
|
||||
let name = keys[i];
|
||||
if (value instanceof Geometry) {
|
||||
if (value && typeof /** @type {?} */ (value).getSimplifiedGeometry === 'function') {
|
||||
name = geometryName;
|
||||
}
|
||||
values.push({name: name, value: value});
|
||||
@@ -717,7 +724,7 @@ function writeProperty(node, pair, objectStack) {
|
||||
if (pair.value !== undefined && pair.value !== null) {
|
||||
const value = createElementNS(WFSNS, 'Value');
|
||||
node.appendChild(value);
|
||||
if (pair.value instanceof Geometry) {
|
||||
if (pair.value && typeof /** @type {?} */ (pair.value).getSimplifiedGeometry === 'function') {
|
||||
if (gmlVersion === 2) {
|
||||
GML2.prototype.writeGeometryElement(value,
|
||||
pair.value, objectStack);
|
||||
@@ -742,7 +749,7 @@ function writeNative(node, nativeElement, objectStack) {
|
||||
node.setAttribute('vendorId', nativeElement.vendorId);
|
||||
}
|
||||
if (nativeElement.safeToIgnore !== undefined) {
|
||||
node.setAttribute('safeToIgnore', nativeElement.safeToIgnore);
|
||||
node.setAttribute('safeToIgnore', String(nativeElement.safeToIgnore));
|
||||
}
|
||||
if (nativeElement.value !== undefined) {
|
||||
writeStringTextNode(node, nativeElement.value);
|
||||
|
||||
@@ -13,10 +13,10 @@ import MultiPoint from '../geom/MultiPoint.js';
|
||||
import MultiPolygon from '../geom/MultiPolygon.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import Polygon from '../geom/Polygon.js';
|
||||
import SimpleGeometry from '../geom/SimpleGeometry.js';
|
||||
|
||||
|
||||
/**
|
||||
* Geometry constructors
|
||||
* @enum {function (new:import("../geom/Geometry.js").default, Array, GeometryLayout)}
|
||||
*/
|
||||
const GeometryConstructor = {
|
||||
@@ -159,29 +159,32 @@ class Lexer {
|
||||
*/
|
||||
nextToken() {
|
||||
const c = this.nextChar_();
|
||||
const token = {position: this.index_, value: c};
|
||||
const position = this.index_;
|
||||
/** @type {number|string} */
|
||||
let value = c;
|
||||
let type;
|
||||
|
||||
if (c == '(') {
|
||||
token.type = TokenType.LEFT_PAREN;
|
||||
type = TokenType.LEFT_PAREN;
|
||||
} else if (c == ',') {
|
||||
token.type = TokenType.COMMA;
|
||||
type = TokenType.COMMA;
|
||||
} else if (c == ')') {
|
||||
token.type = TokenType.RIGHT_PAREN;
|
||||
type = TokenType.RIGHT_PAREN;
|
||||
} else if (this.isNumeric_(c) || c == '-') {
|
||||
token.type = TokenType.NUMBER;
|
||||
token.value = this.readNumber_();
|
||||
type = TokenType.NUMBER;
|
||||
value = this.readNumber_();
|
||||
} else if (this.isAlpha_(c)) {
|
||||
token.type = TokenType.TEXT;
|
||||
token.value = this.readText_();
|
||||
type = TokenType.TEXT;
|
||||
value = this.readText_();
|
||||
} else if (this.isWhiteSpace_(c)) {
|
||||
return this.nextToken();
|
||||
} else if (c === '') {
|
||||
token.type = TokenType.EOF;
|
||||
type = TokenType.EOF;
|
||||
} else {
|
||||
throw new Error('Unexpected character: ' + c);
|
||||
}
|
||||
|
||||
return token;
|
||||
return {position: position, value: value, type: type};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -372,7 +375,7 @@ class Parser {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!Array<!Array<number>>} All points in a polygon.
|
||||
* @return {!Array<!Array<!Array<number>>>} All points in a polygon.
|
||||
* @private
|
||||
*/
|
||||
parsePolygonText_() {
|
||||
@@ -409,8 +412,8 @@ class Parser {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!Array<!Array<number>>} All linestring points
|
||||
* in a multilinestring.
|
||||
* @return {!Array<!Array<!Array<number>>>} All linestring points
|
||||
* in a multilinestring.
|
||||
* @private
|
||||
*/
|
||||
parseMultiLineStringText_() {
|
||||
@@ -426,7 +429,7 @@ class Parser {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!Array<!Array<number>>} All polygon points in a multipolygon.
|
||||
* @return {!Array<!Array<!Array<!Array<number>>>>} All polygon points in a multipolygon.
|
||||
* @private
|
||||
*/
|
||||
parseMultiPolygonText_() {
|
||||
@@ -451,7 +454,7 @@ class Parser {
|
||||
for (let i = 0; i < dimensions; ++i) {
|
||||
const token = this.token_;
|
||||
if (this.match(TokenType.NUMBER)) {
|
||||
coordinates.push(token.value);
|
||||
coordinates.push(/** @type {number} */ (token.value));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@@ -487,7 +490,7 @@ class Parser {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!Array<!Array<number>>} An array of points.
|
||||
* @return {!Array<!Array<!Array<number>>>} An array of points.
|
||||
* @private
|
||||
*/
|
||||
parseLineStringTextList_() {
|
||||
@@ -499,7 +502,7 @@ class Parser {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!Array<!Array<number>>} An array of points.
|
||||
* @return {!Array<!Array<!Array<!Array<number>>>>} An array of points.
|
||||
* @private
|
||||
*/
|
||||
parsePolygonTextList_() {
|
||||
@@ -820,7 +823,7 @@ function encodeMultiPolygonGeometry(geom) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {SimpleGeometry} geom SimpleGeometry geometry.
|
||||
* @param {import("../geom/SimpleGeometry.js").default} geom SimpleGeometry geometry.
|
||||
* @return {string} Potential dimensional information for WKT type.
|
||||
*/
|
||||
function encodeGeometryLayout(geom) {
|
||||
@@ -853,7 +856,7 @@ const GeometryEncoder = {
|
||||
|
||||
/**
|
||||
* Encode a geometry as WKT.
|
||||
* @param {import("../geom/Geometry.js").default} geom The geometry to encode.
|
||||
* @param {!import("../geom/Geometry.js").default} geom The geometry to encode.
|
||||
* @return {string} WKT string for the geometry.
|
||||
*/
|
||||
function encode(geom) {
|
||||
@@ -861,8 +864,8 @@ function encode(geom) {
|
||||
const geometryEncoder = GeometryEncoder[type];
|
||||
const enc = geometryEncoder(geom);
|
||||
type = type.toUpperCase();
|
||||
if (geom instanceof SimpleGeometry) {
|
||||
const dimInfo = encodeGeometryLayout(geom);
|
||||
if (typeof /** @type {?} */ (geom).getFlatCoordinates === 'function') {
|
||||
const dimInfo = encodeGeometryLayout(/** @type {import("../geom/SimpleGeometry.js").default} */ (geom));
|
||||
if (dimInfo.length > 0) {
|
||||
type += ' ' + dimInfo;
|
||||
}
|
||||
|
||||
@@ -100,10 +100,12 @@ class WMSGetFeatureInfo extends XMLFeature {
|
||||
if (layer.nodeType !== Node.ELEMENT_NODE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const layerElement = /** @type {Element} */ (layer);
|
||||
const context = objectStack[0];
|
||||
|
||||
const toRemove = layerIdentifier;
|
||||
const layerName = layer.localName.replace(toRemove, '');
|
||||
const layerName = layerElement.localName.replace(toRemove, '');
|
||||
|
||||
if (this.layers_ && !includes(this.layers_, layerName)) {
|
||||
continue;
|
||||
@@ -115,14 +117,15 @@ class WMSGetFeatureInfo extends XMLFeature {
|
||||
context['featureType'] = featureType;
|
||||
context['featureNS'] = this.featureNS_;
|
||||
|
||||
/** @type {Object<string, import("../xml.js").Parser>} */
|
||||
const parsers = {};
|
||||
parsers[featureType] = makeArrayPusher(
|
||||
this.gmlFormat_.readFeatureElement, this.gmlFormat_);
|
||||
const parsersNS = makeStructureNS(
|
||||
[context['featureNS'], null], parsers);
|
||||
layer.setAttribute('namespaceURI', this.featureNS_);
|
||||
layerElement.setAttribute('namespaceURI', this.featureNS_);
|
||||
const layerFeatures = pushParseAndPop(
|
||||
[], parsersNS, layer, objectStack, this.gmlFormat_);
|
||||
[], parsersNS, layerElement, objectStack, this.gmlFormat_);
|
||||
if (layerFeatures) {
|
||||
extend(features, layerFeatures);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ const PARSERS = makeStructureNS(
|
||||
* @classdesc
|
||||
* Format for reading WMTS capabilities data.
|
||||
*
|
||||
* @api
|
||||
* @api
|
||||
*/
|
||||
class WMTSCapabilities extends XML {
|
||||
constructor() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @module ol/format/XML
|
||||
*/
|
||||
import {isDocument, isNode, parse} from '../xml.js';
|
||||
import {isDocument, parse} from '../xml.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
@@ -18,15 +18,15 @@ class XML {
|
||||
* @api
|
||||
*/
|
||||
read(source) {
|
||||
if (isDocument(source)) {
|
||||
return this.readFromDocument(/** @type {Document} */ (source));
|
||||
} else if (isNode(source)) {
|
||||
return this.readFromNode(/** @type {Element} */ (source));
|
||||
if (!source) {
|
||||
return null;
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readFromDocument(doc);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readFromDocument(/** @type {Document} */ (source));
|
||||
} else {
|
||||
return null;
|
||||
return this.readFromNode(/** @type {Element} */ (source));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/**
|
||||
* @module ol/format/XMLFeature
|
||||
*/
|
||||
import {abstract} from '../util.js';
|
||||
import {extend} from '../array.js';
|
||||
import FeatureFormat from '../format/Feature.js';
|
||||
import FormatType from '../format/FormatType.js';
|
||||
import {isDocument, isNode, parse} from '../xml.js';
|
||||
import {isDocument, parse} from '../xml.js';
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
@@ -41,15 +42,15 @@ class XMLFeature extends FeatureFormat {
|
||||
* @api
|
||||
*/
|
||||
readFeature(source, opt_options) {
|
||||
if (isDocument(source)) {
|
||||
return this.readFeatureFromDocument(/** @type {Document} */ (source), opt_options);
|
||||
} else if (isNode(source)) {
|
||||
return this.readFeatureFromNode(/** @type {Node} */ (source), opt_options);
|
||||
if (!source) {
|
||||
return null;
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readFeatureFromDocument(doc, opt_options);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readFeatureFromDocument(/** @type {Document} */ (source), opt_options);
|
||||
} else {
|
||||
return null;
|
||||
return this.readFeatureFromNode(/** @type {Node} */ (source), opt_options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,16 +86,16 @@ class XMLFeature extends FeatureFormat {
|
||||
* @api
|
||||
*/
|
||||
readFeatures(source, opt_options) {
|
||||
if (isDocument(source)) {
|
||||
return this.readFeaturesFromDocument(
|
||||
/** @type {Document} */ (source), opt_options);
|
||||
} else if (isNode(source)) {
|
||||
return this.readFeaturesFromNode(/** @type {Node} */ (source), opt_options);
|
||||
if (!source) {
|
||||
return [];
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readFeaturesFromDocument(doc, opt_options);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readFeaturesFromDocument(
|
||||
/** @type {Document} */ (source), opt_options);
|
||||
} else {
|
||||
return [];
|
||||
return this.readFeaturesFromNode(/** @type {Node} */ (source), opt_options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +108,7 @@ class XMLFeature extends FeatureFormat {
|
||||
readFeaturesFromDocument(doc, opt_options) {
|
||||
/** @type {Array<import("../Feature.js").default>} */
|
||||
const features = [];
|
||||
for (let n = doc.firstChild; n; n = n.nextSibling) {
|
||||
for (let n = /** @type {Node} */ (doc.firstChild); n; n = n.nextSibling) {
|
||||
if (n.nodeType == Node.ELEMENT_NODE) {
|
||||
extend(features, this.readFeaturesFromNode(n, opt_options));
|
||||
}
|
||||
@@ -122,22 +123,24 @@ class XMLFeature extends FeatureFormat {
|
||||
* @protected
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
*/
|
||||
readFeaturesFromNode(node, opt_options) {}
|
||||
readFeaturesFromNode(node, opt_options) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
readGeometry(source, opt_options) {
|
||||
if (isDocument(source)) {
|
||||
return this.readGeometryFromDocument(
|
||||
/** @type {Document} */ (source), opt_options);
|
||||
} else if (isNode(source)) {
|
||||
return this.readGeometryFromNode(/** @type {Node} */ (source), opt_options);
|
||||
if (!source) {
|
||||
return null;
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readGeometryFromDocument(doc, opt_options);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readGeometryFromDocument(
|
||||
/** @type {Document} */ (source), opt_options);
|
||||
} else {
|
||||
return null;
|
||||
return this.readGeometryFromNode(/** @type {Node} */ (source), opt_options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,15 +172,15 @@ class XMLFeature extends FeatureFormat {
|
||||
* @api
|
||||
*/
|
||||
readProjection(source) {
|
||||
if (isDocument(source)) {
|
||||
return this.readProjectionFromDocument(/** @type {Document} */ (source));
|
||||
} else if (isNode(source)) {
|
||||
return this.readProjectionFromNode(/** @type {Node} */ (source));
|
||||
if (!source) {
|
||||
return null;
|
||||
} else if (typeof source === 'string') {
|
||||
const doc = parse(source);
|
||||
return this.readProjectionFromDocument(doc);
|
||||
} else if (isDocument(source)) {
|
||||
return this.readProjectionFromDocument(/** @type {Document} */ (source));
|
||||
} else {
|
||||
return null;
|
||||
return this.readProjectionFromNode(/** @type {Node} */ (source));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import Within from '../format/filter/Within.js';
|
||||
* Create a logical `<And>` operator between two or more filter conditions.
|
||||
*
|
||||
* @param {...import("./filter/Filter.js").default} conditions Filter conditions.
|
||||
* @returns {!import("./filter/And.js").default} `<And>` operator.
|
||||
* @returns {!And} `<And>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function and(conditions) {
|
||||
@@ -37,7 +37,7 @@ export function and(conditions) {
|
||||
* Create a logical `<Or>` operator between two or more filter conditions.
|
||||
*
|
||||
* @param {...import("./filter/Filter.js").default} conditions Filter conditions.
|
||||
* @returns {!import("./filter/Or.js").default} `<Or>` operator.
|
||||
* @returns {!Or} `<Or>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function or(conditions) {
|
||||
@@ -50,7 +50,7 @@ export function or(conditions) {
|
||||
* Represents a logical `<Not>` operator for a filter condition.
|
||||
*
|
||||
* @param {!import("./filter/Filter.js").default} condition Filter condition.
|
||||
* @returns {!import("./filter/Not.js").default} `<Not>` operator.
|
||||
* @returns {!Not} `<Not>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function not(condition) {
|
||||
@@ -66,7 +66,7 @@ export function not(condition) {
|
||||
* @param {!import("../extent.js").Extent} extent Extent.
|
||||
* @param {string=} opt_srsName SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
* @returns {!import("./filter/Bbox.js").default} `<BBOX>` operator.
|
||||
* @returns {!Bbox} `<BBOX>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function bbox(geometryName, extent, opt_srsName) {
|
||||
@@ -81,7 +81,7 @@ export function bbox(geometryName, extent, opt_srsName) {
|
||||
* @param {!import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {string=} opt_srsName SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
* @returns {!import("./filter/Contains.js").default} `<Contains>` operator.
|
||||
* @returns {!Contains} `<Contains>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function contains(geometryName, geometry, opt_srsName) {
|
||||
@@ -96,7 +96,7 @@ export function contains(geometryName, geometry, opt_srsName) {
|
||||
* @param {!import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {string=} opt_srsName SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
* @returns {!import("./filter/Intersects.js").default} `<Intersects>` operator.
|
||||
* @returns {!Intersects} `<Intersects>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function intersects(geometryName, geometry, opt_srsName) {
|
||||
@@ -111,7 +111,7 @@ export function intersects(geometryName, geometry, opt_srsName) {
|
||||
* @param {!import("../geom/Geometry.js").default} geometry Geometry.
|
||||
* @param {string=} opt_srsName SRS name. No srsName attribute will be
|
||||
* set on geometries when this is not provided.
|
||||
* @returns {!import("./filter/Within.js").default} `<Within>` operator.
|
||||
* @returns {!Within} `<Within>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function within(geometryName, geometry, opt_srsName) {
|
||||
@@ -125,7 +125,7 @@ export function within(geometryName, geometry, opt_srsName) {
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!(string|number)} expression The value to compare.
|
||||
* @param {boolean=} opt_matchCase Case-sensitive?
|
||||
* @returns {!import("./filter/EqualTo.js").default} `<PropertyIsEqualTo>` operator.
|
||||
* @returns {!EqualTo} `<PropertyIsEqualTo>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function equalTo(propertyName, expression, opt_matchCase) {
|
||||
@@ -139,7 +139,7 @@ export function equalTo(propertyName, expression, opt_matchCase) {
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!(string|number)} expression The value to compare.
|
||||
* @param {boolean=} opt_matchCase Case-sensitive?
|
||||
* @returns {!import("./filter/NotEqualTo.js").default} `<PropertyIsNotEqualTo>` operator.
|
||||
* @returns {!NotEqualTo} `<PropertyIsNotEqualTo>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function notEqualTo(propertyName, expression, opt_matchCase) {
|
||||
@@ -152,7 +152,7 @@ export function notEqualTo(propertyName, expression, opt_matchCase) {
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!number} expression The value to compare.
|
||||
* @returns {!import("./filter/LessThan.js").default} `<PropertyIsLessThan>` operator.
|
||||
* @returns {!LessThan} `<PropertyIsLessThan>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function lessThan(propertyName, expression) {
|
||||
@@ -165,7 +165,7 @@ export function lessThan(propertyName, expression) {
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!number} expression The value to compare.
|
||||
* @returns {!import("./filter/LessThanOrEqualTo.js").default} `<PropertyIsLessThanOrEqualTo>` operator.
|
||||
* @returns {!LessThanOrEqualTo} `<PropertyIsLessThanOrEqualTo>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function lessThanOrEqualTo(propertyName, expression) {
|
||||
@@ -178,7 +178,7 @@ export function lessThanOrEqualTo(propertyName, expression) {
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!number} expression The value to compare.
|
||||
* @returns {!import("./filter/GreaterThan.js").default} `<PropertyIsGreaterThan>` operator.
|
||||
* @returns {!GreaterThan} `<PropertyIsGreaterThan>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function greaterThan(propertyName, expression) {
|
||||
@@ -191,7 +191,7 @@ export function greaterThan(propertyName, expression) {
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!number} expression The value to compare.
|
||||
* @returns {!import("./filter/GreaterThanOrEqualTo.js").default} `<PropertyIsGreaterThanOrEqualTo>` operator.
|
||||
* @returns {!GreaterThanOrEqualTo} `<PropertyIsGreaterThanOrEqualTo>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function greaterThanOrEqualTo(propertyName, expression) {
|
||||
@@ -204,7 +204,7 @@ export function greaterThanOrEqualTo(propertyName, expression) {
|
||||
* is null.
|
||||
*
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @returns {!import("./filter/IsNull.js").default} `<PropertyIsNull>` operator.
|
||||
* @returns {!IsNull} `<PropertyIsNull>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function isNull(propertyName) {
|
||||
@@ -219,7 +219,7 @@ export function isNull(propertyName) {
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!number} lowerBoundary The lower bound of the range.
|
||||
* @param {!number} upperBoundary The upper bound of the range.
|
||||
* @returns {!import("./filter/IsBetween.js").default} `<PropertyIsBetween>` operator.
|
||||
* @returns {!IsBetween} `<PropertyIsBetween>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function between(propertyName, lowerBoundary, upperBoundary) {
|
||||
@@ -240,7 +240,7 @@ export function between(propertyName, lowerBoundary, upperBoundary) {
|
||||
* @param {string=} opt_escapeChar Escape character which can be used to escape
|
||||
* the pattern characters. Default is '!'.
|
||||
* @param {boolean=} opt_matchCase Case-sensitive?
|
||||
* @returns {!import("./filter/IsLike.js").default} `<PropertyIsLike>` operator.
|
||||
* @returns {!IsLike} `<PropertyIsLike>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function like(propertyName, pattern,
|
||||
@@ -256,7 +256,7 @@ export function like(propertyName, pattern,
|
||||
* @param {!string} propertyName Name of the context property to compare.
|
||||
* @param {!string} begin The begin date in ISO-8601 format.
|
||||
* @param {!string} end The end date in ISO-8601 format.
|
||||
* @returns {!import("./filter/During.js").default} `<During>` operator.
|
||||
* @returns {!During} `<During>` operator.
|
||||
* @api
|
||||
*/
|
||||
export function during(propertyName, begin, end) {
|
||||
|
||||
@@ -15,8 +15,7 @@ class And extends LogicalNary {
|
||||
* @param {...import("./Filter.js").default} conditions Conditions.
|
||||
*/
|
||||
constructor(conditions) {
|
||||
const params = ['And'].concat(Array.prototype.slice.call(arguments));
|
||||
super(...params);
|
||||
super('And', Array.prototype.slice.call(arguments));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ class LogicalNary extends Filter {
|
||||
|
||||
/**
|
||||
* @param {!string} tagName The XML tag name for this filter.
|
||||
* @param {...import("./Filter.js").default} conditions Conditions.
|
||||
* @param {Array<import("./Filter.js").default>} conditions Conditions.
|
||||
*/
|
||||
constructor(tagName, conditions) {
|
||||
|
||||
@@ -24,7 +24,7 @@ class LogicalNary extends Filter {
|
||||
/**
|
||||
* @type {Array<import("./Filter.js").default>}
|
||||
*/
|
||||
this.conditions = Array.prototype.slice.call(arguments, 1);
|
||||
this.conditions = conditions;
|
||||
assert(this.conditions.length >= 2, 57); // At least 2 conditions are required.
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,7 @@ class Or extends LogicalNary {
|
||||
* @param {...import("./Filter.js").default} conditions Conditions.
|
||||
*/
|
||||
constructor(conditions) {
|
||||
const params = ['Or'].concat(Array.prototype.slice.call(arguments));
|
||||
super(...params);
|
||||
super('Or', Array.prototype.slice.call(arguments));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -194,7 +194,9 @@ class Circle extends SimpleGeometry {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getCoordinates() {}
|
||||
getCoordinates() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* @module ol/geom/Geometry
|
||||
*/
|
||||
import {abstract} from '../util.js';
|
||||
import BaseObject from '../Object.js';
|
||||
import {createEmpty, getHeight, returnOrUpdate} from '../extent.js';
|
||||
import {FALSE} from '../functions.js';
|
||||
import {transform2D} from '../geom/flat/transform.js';
|
||||
import {get as getProjection, getTransform} from '../proj.js';
|
||||
import Units from '../proj/Units.js';
|
||||
@@ -70,7 +70,9 @@ class Geometry extends BaseObject {
|
||||
* @abstract
|
||||
* @return {!Geometry} Clone.
|
||||
*/
|
||||
clone() {}
|
||||
clone() {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
@@ -80,7 +82,18 @@ class Geometry extends BaseObject {
|
||||
* @param {number} minSquaredDistance Minimum squared distance.
|
||||
* @return {number} Minimum squared distance.
|
||||
*/
|
||||
closestPointXY(x, y, closestPoint, minSquaredDistance) {}
|
||||
closestPointXY(x, y, closestPoint, minSquaredDistance) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @return {boolean} Contains (x, y).
|
||||
*/
|
||||
containsXY(x, y) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the closest point of the geometry to the passed point as
|
||||
@@ -113,7 +126,9 @@ class Geometry extends BaseObject {
|
||||
* @protected
|
||||
* @return {import("../extent.js").Extent} extent Extent.
|
||||
*/
|
||||
computeExtent(extent) {}
|
||||
computeExtent(extent) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extent of the geometry.
|
||||
@@ -137,7 +152,9 @@ class Geometry extends BaseObject {
|
||||
* @param {import("../coordinate.js").Coordinate} anchor The rotation center.
|
||||
* @api
|
||||
*/
|
||||
rotate(angle, anchor) {}
|
||||
rotate(angle, anchor) {
|
||||
abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale the geometry (with an optional origin). This modifies the geometry
|
||||
@@ -150,7 +167,9 @@ class Geometry extends BaseObject {
|
||||
* of the geometry extent).
|
||||
* @api
|
||||
*/
|
||||
scale(sx, opt_sy, opt_anchor) {}
|
||||
scale(sx, opt_sy, opt_anchor) {
|
||||
abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a simplified version of this geometry. For linestrings, this uses
|
||||
@@ -174,14 +193,18 @@ class Geometry extends BaseObject {
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {Geometry} Simplified geometry.
|
||||
*/
|
||||
getSimplifiedGeometry(squaredTolerance) {}
|
||||
getSimplifiedGeometry(squaredTolerance) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of this geometry.
|
||||
* @abstract
|
||||
* @return {import("./GeometryType.js").default} Geometry type.
|
||||
*/
|
||||
getType() {}
|
||||
getType() {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a transform function to each coordinate of the geometry.
|
||||
@@ -191,7 +214,9 @@ class Geometry extends BaseObject {
|
||||
* @abstract
|
||||
* @param {import("../proj.js").TransformFunction} transformFn Transform.
|
||||
*/
|
||||
applyTransform(transformFn) {}
|
||||
applyTransform(transformFn) {
|
||||
abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the geometry and the passed extent intersect.
|
||||
@@ -199,7 +224,9 @@ class Geometry extends BaseObject {
|
||||
* @param {import("../extent.js").Extent} extent Extent.
|
||||
* @return {boolean} `true` if the geometry and the extent intersect.
|
||||
*/
|
||||
intersectsExtent(extent) {}
|
||||
intersectsExtent(extent) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the geometry. This modifies the geometry coordinates in place. If
|
||||
@@ -209,7 +236,9 @@ class Geometry extends BaseObject {
|
||||
* @param {number} deltaY Delta Y.
|
||||
* @api
|
||||
*/
|
||||
translate(deltaX, deltaY) {}
|
||||
translate(deltaX, deltaY) {
|
||||
abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform each coordinate of the geometry from one coordinate reference
|
||||
@@ -227,11 +256,12 @@ class Geometry extends BaseObject {
|
||||
* @api
|
||||
*/
|
||||
transform(source, destination) {
|
||||
source = getProjection(source);
|
||||
const transformFn = source.getUnits() == Units.TILE_PIXELS ?
|
||||
/** @type {import("../proj/Projection.js").default} */
|
||||
const sourceProj = getProjection(source);
|
||||
const transformFn = sourceProj.getUnits() == Units.TILE_PIXELS ?
|
||||
function(inCoordinates, outCoordinates, stride) {
|
||||
const pixelExtent = source.getExtent();
|
||||
const projectedExtent = source.getWorldExtent();
|
||||
const pixelExtent = sourceProj.getExtent();
|
||||
const projectedExtent = sourceProj.getWorldExtent();
|
||||
const scale = getHeight(projectedExtent) / getHeight(pixelExtent);
|
||||
composeTransform(tmpTransform,
|
||||
projectedExtent[0], projectedExtent[3],
|
||||
@@ -239,21 +269,14 @@ class Geometry extends BaseObject {
|
||||
0, 0);
|
||||
transform2D(inCoordinates, 0, inCoordinates.length, stride,
|
||||
tmpTransform, outCoordinates);
|
||||
return getTransform(source, destination)(inCoordinates, outCoordinates, stride);
|
||||
return getTransform(sourceProj, destination)(inCoordinates, outCoordinates, stride);
|
||||
} :
|
||||
getTransform(source, destination);
|
||||
getTransform(sourceProj, destination);
|
||||
this.applyTransform(transformFn);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {number} x X.
|
||||
* @param {number} y Y.
|
||||
* @return {boolean} Contains (x, y).
|
||||
*/
|
||||
Geometry.prototype.containsXY = FALSE;
|
||||
|
||||
|
||||
export default Geometry;
|
||||
|
||||
@@ -57,9 +57,9 @@ class LineString extends SimpleGeometry {
|
||||
this.maxDeltaRevision_ = -1;
|
||||
|
||||
if (opt_layout !== undefined && !Array.isArray(coordinates[0])) {
|
||||
this.setFlatCoordinates(opt_layout, coordinates);
|
||||
this.setFlatCoordinates(opt_layout, /** @type {Array<number>} */ (coordinates));
|
||||
} else {
|
||||
this.setCoordinates(coordinates, opt_layout);
|
||||
this.setCoordinates(/** @type {Array<import("../coordinate.js").Coordinate>} */ (coordinates), opt_layout);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,9 +42,9 @@ class LinearRing extends SimpleGeometry {
|
||||
this.maxDeltaRevision_ = -1;
|
||||
|
||||
if (opt_layout !== undefined && !Array.isArray(coordinates[0])) {
|
||||
this.setFlatCoordinates(opt_layout, coordinates);
|
||||
this.setFlatCoordinates(opt_layout, /** @type {Array<number>} */ (coordinates));
|
||||
} else {
|
||||
this.setCoordinates(coordinates, opt_layout);
|
||||
this.setCoordinates(/** @type {Array<import("../coordinate.js").Coordinate>} */ (coordinates), opt_layout);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -118,7 +118,9 @@ class LinearRing extends SimpleGeometry {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
intersectsExtent(extent) {}
|
||||
intersectsExtent(extent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the coordinates of the linear ring.
|
||||
|
||||
@@ -23,7 +23,7 @@ import {douglasPeuckerArray} from '../geom/flat/simplify.js';
|
||||
class MultiLineString extends SimpleGeometry {
|
||||
|
||||
/**
|
||||
* @param {Array<Array<import("../coordinate.js").Coordinate>|import("../geom.js").MultiLineString>|Array<number>} coordinates
|
||||
* @param {Array<Array<import("../coordinate.js").Coordinate>|LineString>|Array<number>} coordinates
|
||||
* Coordinates or LineString geometries. (For internal use, flat coordinates in
|
||||
* combination with `opt_layout` and `opt_ends` are also accepted.)
|
||||
* @param {GeometryLayout=} opt_layout Layout.
|
||||
@@ -52,16 +52,17 @@ class MultiLineString extends SimpleGeometry {
|
||||
this.maxDeltaRevision_ = -1;
|
||||
|
||||
if (Array.isArray(coordinates[0])) {
|
||||
this.setCoordinates(coordinates, opt_layout);
|
||||
this.setCoordinates(/** @type {Array<Array<import("../coordinate.js").Coordinate>>} */ (coordinates), opt_layout);
|
||||
} else if (opt_layout !== undefined && opt_ends) {
|
||||
this.setFlatCoordinates(opt_layout, coordinates);
|
||||
this.setFlatCoordinates(opt_layout, /** @type {Array<number>} */ (coordinates));
|
||||
this.ends_ = opt_ends;
|
||||
} else {
|
||||
let layout = this.getLayout();
|
||||
const lineStrings = /** @type {Array<LineString>} */ (coordinates);
|
||||
const flatCoordinates = [];
|
||||
const ends = [];
|
||||
for (let i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
const lineString = coordinates[i];
|
||||
for (let i = 0, ii = lineStrings.length; i < ii; ++i) {
|
||||
const lineString = lineStrings[i];
|
||||
if (i === 0) {
|
||||
layout = lineString.getLayout();
|
||||
}
|
||||
|
||||
@@ -28,10 +28,10 @@ import {quantizeMultiArray} from '../geom/flat/simplify.js';
|
||||
class MultiPolygon extends SimpleGeometry {
|
||||
|
||||
/**
|
||||
* @param {Array<Array<Array<import("../coordinate.js").Coordinate>>>|Array<number>} coordinates Coordinates.
|
||||
* For internal use, flat coordinats in combination with `opt_layout` and `opt_endss` are also accepted.
|
||||
* @param {Array<Array<Array<import("../coordinate.js").Coordinate>>|Polygon>|Array<number>} coordinates Coordinates.
|
||||
* For internal use, flat coordinates in combination with `opt_layout` and `opt_endss` are also accepted.
|
||||
* @param {GeometryLayout=} opt_layout Layout.
|
||||
* @param {Array<number>=} opt_endss Array of ends for internal use with flat coordinates.
|
||||
* @param {Array<Array<number>>=} opt_endss Array of ends for internal use with flat coordinates.
|
||||
*/
|
||||
constructor(coordinates, opt_layout, opt_endss) {
|
||||
|
||||
@@ -81,10 +81,11 @@ class MultiPolygon extends SimpleGeometry {
|
||||
|
||||
if (!opt_endss && !Array.isArray(coordinates[0])) {
|
||||
let layout = this.getLayout();
|
||||
const polygons = /** @type {Array<Polygon>} */ (coordinates);
|
||||
const flatCoordinates = [];
|
||||
const endss = [];
|
||||
for (let i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
const polygon = coordinates[i];
|
||||
for (let i = 0, ii = polygons.length; i < ii; ++i) {
|
||||
const polygon = polygons[i];
|
||||
if (i === 0) {
|
||||
layout = polygon.getLayout();
|
||||
}
|
||||
@@ -101,10 +102,11 @@ class MultiPolygon extends SimpleGeometry {
|
||||
opt_endss = endss;
|
||||
}
|
||||
if (opt_layout !== undefined && opt_endss) {
|
||||
this.setFlatCoordinates(opt_layout, coordinates);
|
||||
this.setFlatCoordinates(opt_layout, /** @type {Array<number>} */ (coordinates));
|
||||
this.endss_ = opt_endss;
|
||||
} else {
|
||||
this.setCoordinates(coordinates, opt_layout);
|
||||
this.setCoordinates(/** @type {Array<Array<Array<import("../coordinate.js").Coordinate>>>} */ (coordinates),
|
||||
opt_layout);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,10 +86,10 @@ class Polygon extends SimpleGeometry {
|
||||
this.orientedFlatCoordinates_ = null;
|
||||
|
||||
if (opt_layout !== undefined && opt_ends) {
|
||||
this.setFlatCoordinates(opt_layout, coordinates);
|
||||
this.setFlatCoordinates(opt_layout, /** @type {Array<number>} */ (coordinates));
|
||||
this.ends_ = opt_ends;
|
||||
} else {
|
||||
this.setCoordinates(coordinates, opt_layout);
|
||||
this.setCoordinates(/** @type {Array<Array<import("../coordinate.js").Coordinate>>} */ (coordinates), opt_layout);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @module ol/geom/SimpleGeometry
|
||||
*/
|
||||
import {FALSE} from '../functions.js';
|
||||
import {abstract} from '../util.js';
|
||||
import {createOrUpdateFromFlatCoordinates, getCenter} from '../extent.js';
|
||||
import Geometry from '../geom/Geometry.js';
|
||||
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||
@@ -53,7 +53,9 @@ class SimpleGeometry extends Geometry {
|
||||
* @abstract
|
||||
* @return {Array} Coordinates.
|
||||
*/
|
||||
getCoordinates() {}
|
||||
getCoordinates() {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first coordinate of the geometry.
|
||||
@@ -81,7 +83,7 @@ class SimpleGeometry extends Geometry {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link module:ol/geom/GeometryLayout~GeometryLayout layout} of the geometry.
|
||||
* Return the {@link module:ol/geom/GeometryLayout layout} of the geometry.
|
||||
* @return {GeometryLayout} Layout.
|
||||
* @api
|
||||
*/
|
||||
@@ -147,7 +149,7 @@ class SimpleGeometry extends Geometry {
|
||||
/**
|
||||
* @param {GeometryLayout} layout Layout.
|
||||
* @param {Array<number>} flatCoordinates Flat coordinates.
|
||||
*/
|
||||
*/
|
||||
setFlatCoordinates(layout, flatCoordinates) {
|
||||
this.stride = getStrideForLayout(layout);
|
||||
this.layout = layout;
|
||||
@@ -159,7 +161,9 @@ class SimpleGeometry extends Geometry {
|
||||
* @param {!Array} coordinates Coordinates.
|
||||
* @param {GeometryLayout=} opt_layout Layout.
|
||||
*/
|
||||
setCoordinates(coordinates, opt_layout) {}
|
||||
setCoordinates(coordinates, opt_layout) {
|
||||
abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {GeometryLayout|undefined} layout Layout.
|
||||
@@ -291,12 +295,6 @@ export function getStrideForLayout(layout) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
SimpleGeometry.prototype.containsXY = FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {SimpleGeometry} simpleGeometry Simple geometry.
|
||||
* @param {import("../transform.js").Transform} transform Transform.
|
||||
|
||||
@@ -111,7 +111,9 @@ export function intersectsLinearRingArray(flatCoordinates, offset, ends, stride,
|
||||
}
|
||||
for (let i = 1, ii = ends.length; i < ii; ++i) {
|
||||
if (linearRingContainsExtent(flatCoordinates, ends[i - 1], ends[i], stride, extent)) {
|
||||
return false;
|
||||
if (!intersectsLineString(flatCoordinates, ends[i - 1], ends[i], stride, extent)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -13,14 +13,14 @@ import {get as getProjection} from '../proj.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {Array<function(new: import("../format/Feature.js").default)>} [formatConstructors] Format constructors.
|
||||
* @property {Array<typeof import("../format/Feature.js").default>} [formatConstructors] Format constructors.
|
||||
* @property {import("../source/Vector.js").default} [source] Optional vector source where features will be added. If a source is provided
|
||||
* all existing features will be removed and new features will be added when
|
||||
* they are dropped on the target. If you want to add features to a vector
|
||||
* source without removing the existing features (append only), instead of
|
||||
* providing the source option listen for the "addfeatures" event.
|
||||
* @property {import("../proj.js").ProjectionLike} [projection] Target projection. By default, the map's view's projection is used.
|
||||
* @property {Element} [target] The element that is used as the drop target, default is the viewport element.
|
||||
* @property {HTMLElement} [target] The element that is used as the drop target, default is the viewport element.
|
||||
*/
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class DragAndDropEvent extends Event {
|
||||
|
||||
/**
|
||||
* The features parsed from dropped data.
|
||||
* @type {Array<import("../Feature.js").default>|undefined}
|
||||
* @type {Array<import("../Feature.js").FeatureLike>|undefined}
|
||||
* @api
|
||||
*/
|
||||
this.features = opt_features;
|
||||
@@ -101,7 +101,7 @@ class DragAndDrop extends Interaction {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Array<function(new: import("../format/Feature.js").default)>}
|
||||
* @type {Array<typeof import("../format/Feature.js").default>}
|
||||
*/
|
||||
this.formatConstructors_ = options.formatConstructors ?
|
||||
options.formatConstructors : [];
|
||||
@@ -127,7 +127,7 @@ class DragAndDrop extends Interaction {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {Element}
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.target = options.target ? options.target : null;
|
||||
|
||||
@@ -150,15 +150,7 @@ class DragAndDrop extends Interaction {
|
||||
const formatConstructors = this.formatConstructors_;
|
||||
let features = [];
|
||||
for (let i = 0, ii = formatConstructors.length; i < ii; ++i) {
|
||||
/**
|
||||
* Avoid "cannot instantiate abstract class" error.
|
||||
* @type {Function}
|
||||
*/
|
||||
const formatConstructor = formatConstructors[i];
|
||||
/**
|
||||
* @type {import("../format/Feature.js").default}
|
||||
*/
|
||||
const format = new formatConstructor();
|
||||
const format = new formatConstructors[i]();
|
||||
features = this.tryReadFeatures_(format, result, {
|
||||
featureProjection: projection
|
||||
});
|
||||
@@ -220,7 +212,7 @@ class DragAndDrop extends Interaction {
|
||||
* @param {string} text Text.
|
||||
* @param {import("../format/Feature.js").ReadOptions} options Read options.
|
||||
* @private
|
||||
* @return {Array<import("../Feature.js").default>} Features.
|
||||
* @return {Array<import("../Feature.js").FeatureLike>} Features.
|
||||
*/
|
||||
tryReadFeatures_(format, text, options) {
|
||||
try {
|
||||
|
||||
@@ -115,11 +115,7 @@ class DragBox extends PointerInteraction {
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
|
||||
super({
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleDragEvent: handleDragEvent,
|
||||
handleUpEvent: handleUpEvent
|
||||
});
|
||||
super();
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
@@ -159,7 +155,22 @@ class DragBox extends PointerInteraction {
|
||||
* @type {EndCondition}
|
||||
*/
|
||||
this.boxEndCondition_ = options.boxEndCondition ?
|
||||
options.boxEndCondition : defaultBoxEndCondition;
|
||||
options.boxEndCondition : this.defaultBoxEndCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default condition for determining whether the boxend event
|
||||
* should fire.
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent The originating MapBrowserEvent
|
||||
* leading to the box end.
|
||||
* @param {import("../pixel.js").Pixel} startPixel The starting pixel of the box.
|
||||
* @param {import("../pixel.js").Pixel} endPixel The end pixel of the box.
|
||||
* @return {boolean} Whether or not the boxend condition should be fired.
|
||||
*/
|
||||
defaultBoxEndCondition(mapBrowserEvent, startPixel, endPixel) {
|
||||
const width = endPixel[0] - startPixel[0];
|
||||
const height = endPixel[1] - startPixel[1];
|
||||
return width * width + height * height >= this.minArea_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,83 +181,58 @@ class DragBox extends PointerInteraction {
|
||||
getGeometry() {
|
||||
return this.box_.getGeometry();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDragEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default condition for determining whether the boxend event
|
||||
* should fire.
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent The originating MapBrowserEvent
|
||||
* leading to the box end.
|
||||
* @param {import("../pixel.js").Pixel} startPixel The starting pixel of the box.
|
||||
* @param {import("../pixel.js").Pixel} endPixel The end pixel of the box.
|
||||
* @return {boolean} Whether or not the boxend condition should be fired.
|
||||
* @this {DragBox}
|
||||
*/
|
||||
function defaultBoxEndCondition(mapBrowserEvent, startPixel, endPixel) {
|
||||
const width = endPixel[0] - startPixel[0];
|
||||
const height = endPixel[1] - startPixel[1];
|
||||
return width * width + height * height >= this.minArea_;
|
||||
}
|
||||
this.box_.setPixels(this.startPixel_, mapBrowserEvent.pixel);
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @this {DragBox}
|
||||
*/
|
||||
function handleDragEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.box_.setPixels(this.startPixel_, mapBrowserEvent.pixel);
|
||||
|
||||
this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXDRAG,
|
||||
mapBrowserEvent.coordinate, mapBrowserEvent));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {DragBox}
|
||||
*/
|
||||
function handleUpEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.box_.setMap(null);
|
||||
|
||||
if (this.boxEndCondition_(mapBrowserEvent, this.startPixel_, mapBrowserEvent.pixel)) {
|
||||
this.onBoxEnd_(mapBrowserEvent);
|
||||
this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXEND,
|
||||
this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXDRAG,
|
||||
mapBrowserEvent.coordinate, mapBrowserEvent));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Start drag sequence?
|
||||
* @this {DragBox}
|
||||
*/
|
||||
function handleDownEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
this.box_.setMap(null);
|
||||
|
||||
if (this.boxEndCondition_(mapBrowserEvent, this.startPixel_, mapBrowserEvent.pixel)) {
|
||||
this.onBoxEnd_(mapBrowserEvent);
|
||||
this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXEND,
|
||||
mapBrowserEvent.coordinate, mapBrowserEvent));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mouseActionButton(mapBrowserEvent) &&
|
||||
this.condition_(mapBrowserEvent)) {
|
||||
this.startPixel_ = mapBrowserEvent.pixel;
|
||||
this.box_.setMap(mapBrowserEvent.map);
|
||||
this.box_.setPixels(this.startPixel_, this.startPixel_);
|
||||
this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXSTART,
|
||||
mapBrowserEvent.coordinate, mapBrowserEvent));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDownEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mouseActionButton(mapBrowserEvent) &&
|
||||
this.condition_(mapBrowserEvent)) {
|
||||
this.startPixel_ = mapBrowserEvent.pixel;
|
||||
this.box_.setMap(mapBrowserEvent.map);
|
||||
this.box_.setPixels(this.startPixel_, this.startPixel_);
|
||||
this.dispatchEvent(new DragBoxEvent(DragBoxEventType.BOXSTART,
|
||||
mapBrowserEvent.coordinate, mapBrowserEvent));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,6 @@ class DragPan extends PointerInteraction {
|
||||
constructor(opt_options) {
|
||||
|
||||
super({
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleDragEvent: handleDragEvent,
|
||||
handleUpEvent: handleUpEvent,
|
||||
stopDown: FALSE
|
||||
});
|
||||
|
||||
@@ -73,112 +70,102 @@ class DragPan extends PointerInteraction {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @this {DragPan}
|
||||
*/
|
||||
function handleDragEvent(mapBrowserEvent) {
|
||||
if (!this.panning_) {
|
||||
this.panning_ = true;
|
||||
this.getMap().getView().setHint(ViewHint.INTERACTING, 1);
|
||||
}
|
||||
const targetPointers = this.targetPointers;
|
||||
const centroid = centroidFromPointers(targetPointers);
|
||||
if (targetPointers.length == this.lastPointersCount_) {
|
||||
if (this.kinetic_) {
|
||||
this.kinetic_.update(centroid[0], centroid[1]);
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDragEvent(mapBrowserEvent) {
|
||||
if (!this.panning_) {
|
||||
this.panning_ = true;
|
||||
this.getMap().getView().setHint(ViewHint.INTERACTING, 1);
|
||||
}
|
||||
if (this.lastCentroid) {
|
||||
const deltaX = this.lastCentroid[0] - centroid[0];
|
||||
const deltaY = centroid[1] - this.lastCentroid[1];
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
let center = [deltaX, deltaY];
|
||||
scaleCoordinate(center, view.getResolution());
|
||||
rotateCoordinate(center, view.getRotation());
|
||||
addCoordinate(center, view.getCenter());
|
||||
center = view.constrainCenter(center);
|
||||
view.setCenter(center);
|
||||
}
|
||||
} else if (this.kinetic_) {
|
||||
// reset so we don't overestimate the kinetic energy after
|
||||
// after one finger down, tiny drag, second finger down
|
||||
this.kinetic_.begin();
|
||||
}
|
||||
this.lastCentroid = centroid;
|
||||
this.lastPointersCount_ = targetPointers.length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {DragPan}
|
||||
*/
|
||||
function handleUpEvent(mapBrowserEvent) {
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
if (this.targetPointers.length === 0) {
|
||||
if (!this.noKinetic_ && this.kinetic_ && this.kinetic_.end()) {
|
||||
const distance = this.kinetic_.getDistance();
|
||||
const angle = this.kinetic_.getAngle();
|
||||
const center = /** @type {!import("../coordinate.js").Coordinate} */ (view.getCenter());
|
||||
const centerpx = map.getPixelFromCoordinate(center);
|
||||
const dest = map.getCoordinateFromPixel([
|
||||
centerpx[0] - distance * Math.cos(angle),
|
||||
centerpx[1] - distance * Math.sin(angle)
|
||||
]);
|
||||
view.animate({
|
||||
center: view.constrainCenter(dest),
|
||||
duration: 500,
|
||||
easing: easeOut
|
||||
});
|
||||
}
|
||||
if (this.panning_) {
|
||||
this.panning_ = false;
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
if (this.kinetic_) {
|
||||
const targetPointers = this.targetPointers;
|
||||
const centroid = centroidFromPointers(targetPointers);
|
||||
if (targetPointers.length == this.lastPointersCount_) {
|
||||
if (this.kinetic_) {
|
||||
this.kinetic_.update(centroid[0], centroid[1]);
|
||||
}
|
||||
if (this.lastCentroid) {
|
||||
const deltaX = this.lastCentroid[0] - centroid[0];
|
||||
const deltaY = centroid[1] - this.lastCentroid[1];
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
let center = [deltaX, deltaY];
|
||||
scaleCoordinate(center, view.getResolution());
|
||||
rotateCoordinate(center, view.getRotation());
|
||||
addCoordinate(center, view.getCenter());
|
||||
center = view.constrainCenter(center);
|
||||
view.setCenter(center);
|
||||
}
|
||||
} else if (this.kinetic_) {
|
||||
// reset so we don't overestimate the kinetic energy after
|
||||
// after one finger up, tiny drag, second finger up
|
||||
// after one finger down, tiny drag, second finger down
|
||||
this.kinetic_.begin();
|
||||
}
|
||||
this.lastCentroid = null;
|
||||
return true;
|
||||
this.lastCentroid = centroid;
|
||||
this.lastPointersCount_ = targetPointers.length;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Start drag sequence?
|
||||
* @this {DragPan}
|
||||
*/
|
||||
function handleDownEvent(mapBrowserEvent) {
|
||||
if (this.targetPointers.length > 0 && this.condition_(mapBrowserEvent)) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(mapBrowserEvent) {
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
this.lastCentroid = null;
|
||||
// stop any current animation
|
||||
if (view.getAnimating()) {
|
||||
view.setCenter(mapBrowserEvent.frameState.viewState.center);
|
||||
if (this.targetPointers.length === 0) {
|
||||
if (!this.noKinetic_ && this.kinetic_ && this.kinetic_.end()) {
|
||||
const distance = this.kinetic_.getDistance();
|
||||
const angle = this.kinetic_.getAngle();
|
||||
const center = /** @type {!import("../coordinate.js").Coordinate} */ (view.getCenter());
|
||||
const centerpx = map.getPixelFromCoordinate(center);
|
||||
const dest = map.getCoordinateFromPixel([
|
||||
centerpx[0] - distance * Math.cos(angle),
|
||||
centerpx[1] - distance * Math.sin(angle)
|
||||
]);
|
||||
view.animate({
|
||||
center: view.constrainCenter(dest),
|
||||
duration: 500,
|
||||
easing: easeOut
|
||||
});
|
||||
}
|
||||
if (this.panning_) {
|
||||
this.panning_ = false;
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
if (this.kinetic_) {
|
||||
// reset so we don't overestimate the kinetic energy after
|
||||
// after one finger up, tiny drag, second finger up
|
||||
this.kinetic_.begin();
|
||||
}
|
||||
this.lastCentroid = null;
|
||||
return true;
|
||||
}
|
||||
if (this.kinetic_) {
|
||||
this.kinetic_.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDownEvent(mapBrowserEvent) {
|
||||
if (this.targetPointers.length > 0 && this.condition_(mapBrowserEvent)) {
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
this.lastCentroid = null;
|
||||
// stop any current animation
|
||||
if (view.getAnimating()) {
|
||||
view.setCenter(mapBrowserEvent.frameState.viewState.center);
|
||||
}
|
||||
if (this.kinetic_) {
|
||||
this.kinetic_.begin();
|
||||
}
|
||||
// No kinetic as soon as more than one pointer on the screen is
|
||||
// detected. This is to prevent nasty pans after pinch.
|
||||
this.noKinetic_ = this.targetPointers.length > 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
// No kinetic as soon as more than one pointer on the screen is
|
||||
// detected. This is to prevent nasty pans after pinch.
|
||||
this.noKinetic_ = this.targetPointers.length > 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default DragPan;
|
||||
|
||||
@@ -38,9 +38,6 @@ class DragRotate extends PointerInteraction {
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super({
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleDragEvent: handleDragEvent,
|
||||
handleUpEvent: handleUpEvent,
|
||||
stopDown: FALSE
|
||||
});
|
||||
|
||||
@@ -64,73 +61,66 @@ class DragRotate extends PointerInteraction {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDragEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @this {DragRotate}
|
||||
*/
|
||||
function handleDragEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
if (view.getConstraints().rotation === disable) {
|
||||
return;
|
||||
}
|
||||
const size = map.getSize();
|
||||
const offset = mapBrowserEvent.pixel;
|
||||
const theta =
|
||||
Math.atan2(size[1] / 2 - offset[1], offset[0] - size[0] / 2);
|
||||
if (this.lastAngle_ !== undefined) {
|
||||
const delta = theta - this.lastAngle_;
|
||||
const rotation = view.getRotation();
|
||||
rotateWithoutConstraints(view, rotation - delta);
|
||||
}
|
||||
this.lastAngle_ = theta;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {DragRotate}
|
||||
*/
|
||||
function handleUpEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
const rotation = view.getRotation();
|
||||
rotate(view, rotation, undefined, this.duration_);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Start drag sequence?
|
||||
* @this {DragRotate}
|
||||
*/
|
||||
function handleDownEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mouseActionButton(mapBrowserEvent) && this.condition_(mapBrowserEvent)) {
|
||||
const map = mapBrowserEvent.map;
|
||||
map.getView().setHint(ViewHint.INTERACTING, 1);
|
||||
this.lastAngle_ = undefined;
|
||||
return true;
|
||||
} else {
|
||||
const view = map.getView();
|
||||
if (view.getConstraints().rotation === disable) {
|
||||
return;
|
||||
}
|
||||
const size = map.getSize();
|
||||
const offset = mapBrowserEvent.pixel;
|
||||
const theta =
|
||||
Math.atan2(size[1] / 2 - offset[1], offset[0] - size[0] / 2);
|
||||
if (this.lastAngle_ !== undefined) {
|
||||
const delta = theta - this.lastAngle_;
|
||||
const rotation = view.getRotation();
|
||||
rotateWithoutConstraints(view, rotation - delta);
|
||||
}
|
||||
this.lastAngle_ = theta;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
const rotation = view.getRotation();
|
||||
rotate(view, rotation, undefined, this.duration_);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDownEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mouseActionButton(mapBrowserEvent) && this.condition_(mapBrowserEvent)) {
|
||||
const map = mapBrowserEvent.map;
|
||||
map.getView().setHint(ViewHint.INTERACTING, 1);
|
||||
this.lastAngle_ = undefined;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default DragRotate;
|
||||
|
||||
@@ -38,11 +38,7 @@ class DragRotateAndZoom extends PointerInteraction {
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super({
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleDragEvent: handleDragEvent,
|
||||
handleUpEvent: handleUpEvent
|
||||
});
|
||||
super(/** @type {import("./Pointer.js").Options} */ (options));
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -76,80 +72,71 @@ class DragRotateAndZoom extends PointerInteraction {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDragEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @this {DragRotateAndZoom}
|
||||
*/
|
||||
function handleDragEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return;
|
||||
const map = mapBrowserEvent.map;
|
||||
const size = map.getSize();
|
||||
const offset = mapBrowserEvent.pixel;
|
||||
const deltaX = offset[0] - size[0] / 2;
|
||||
const deltaY = size[1] / 2 - offset[1];
|
||||
const theta = Math.atan2(deltaY, deltaX);
|
||||
const magnitude = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
const view = map.getView();
|
||||
if (view.getConstraints().rotation !== disable && this.lastAngle_ !== undefined) {
|
||||
const angleDelta = theta - this.lastAngle_;
|
||||
rotateWithoutConstraints(view, view.getRotation() - angleDelta);
|
||||
}
|
||||
this.lastAngle_ = theta;
|
||||
if (this.lastMagnitude_ !== undefined) {
|
||||
const resolution = this.lastMagnitude_ * (view.getResolution() / magnitude);
|
||||
zoomWithoutConstraints(view, resolution);
|
||||
}
|
||||
if (this.lastMagnitude_ !== undefined) {
|
||||
this.lastScaleDelta_ = this.lastMagnitude_ / magnitude;
|
||||
}
|
||||
this.lastMagnitude_ = magnitude;
|
||||
}
|
||||
|
||||
const map = mapBrowserEvent.map;
|
||||
const size = map.getSize();
|
||||
const offset = mapBrowserEvent.pixel;
|
||||
const deltaX = offset[0] - size[0] / 2;
|
||||
const deltaY = size[1] / 2 - offset[1];
|
||||
const theta = Math.atan2(deltaY, deltaX);
|
||||
const magnitude = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||
const view = map.getView();
|
||||
if (view.getConstraints().rotation !== disable && this.lastAngle_ !== undefined) {
|
||||
const angleDelta = theta - this.lastAngle_;
|
||||
rotateWithoutConstraints(view, view.getRotation() - angleDelta);
|
||||
}
|
||||
this.lastAngle_ = theta;
|
||||
if (this.lastMagnitude_ !== undefined) {
|
||||
const resolution = this.lastMagnitude_ * (view.getResolution() / magnitude);
|
||||
zoomWithoutConstraints(view, resolution);
|
||||
}
|
||||
if (this.lastMagnitude_ !== undefined) {
|
||||
this.lastScaleDelta_ = this.lastMagnitude_ / magnitude;
|
||||
}
|
||||
this.lastMagnitude_ = magnitude;
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {DragRotateAndZoom}
|
||||
*/
|
||||
function handleUpEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
const direction = this.lastScaleDelta_ - 1;
|
||||
rotate(view, view.getRotation());
|
||||
zoom(view, view.getResolution(), undefined, this.duration_, direction);
|
||||
this.lastScaleDelta_ = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Start drag sequence?
|
||||
* @this {DragRotateAndZoom}
|
||||
*/
|
||||
function handleDownEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
const direction = this.lastScaleDelta_ - 1;
|
||||
rotate(view, view.getRotation());
|
||||
zoom(view, view.getResolution(), undefined, this.duration_, direction);
|
||||
this.lastScaleDelta_ = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.condition_(mapBrowserEvent)) {
|
||||
mapBrowserEvent.map.getView().setHint(ViewHint.INTERACTING, 1);
|
||||
this.lastAngle_ = undefined;
|
||||
this.lastMagnitude_ = undefined;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDownEvent(mapBrowserEvent) {
|
||||
if (!mouseOnly(mapBrowserEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.condition_(mapBrowserEvent)) {
|
||||
mapBrowserEvent.map.getView().setHint(ViewHint.INTERACTING, 1);
|
||||
this.lastAngle_ = undefined;
|
||||
this.lastMagnitude_ = undefined;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import MultiPolygon from '../geom/MultiPolygon.js';
|
||||
import {POINTER_TYPE} from '../pointer/MouseSource.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import Polygon, {fromCircle, makeRegular} from '../geom/Polygon.js';
|
||||
import PointerInteraction, {handleEvent as handlePointerEvent} from '../interaction/Pointer.js';
|
||||
import PointerInteraction from '../interaction/Pointer.js';
|
||||
import InteractionProperty from '../interaction/Property.js';
|
||||
import VectorLayer from '../layer/Vector.js';
|
||||
import VectorSource from '../source/Vector.js';
|
||||
@@ -56,7 +56,7 @@ import {createEditingStyle} from '../style/Style.js';
|
||||
* @property {import("../events/condition.js").Condition} [finishCondition] A function
|
||||
* that takes an {@link module:ol/MapBrowserEvent~MapBrowserEvent} and returns a
|
||||
* boolean to indicate whether the drawing can be finished.
|
||||
* @property {import("../style/Style.js").default|Array<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction} [style]
|
||||
* @property {import("../style/Style.js").StyleLike} [style]
|
||||
* Style for sketch features.
|
||||
* @property {GeometryFunction} [geometryFunction]
|
||||
* Function that is called when a geometry's coordinates are updated.
|
||||
@@ -81,12 +81,36 @@ import {createEditingStyle} from '../style/Style.js';
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Coordinate type when drawing points.
|
||||
* @typedef {import("../coordinate.js").Coordinate} PointCoordType
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Coordinate type when drawing lines.
|
||||
* @typedef {Array<import("../coordinate.js").Coordinate>} LineCoordType
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Coordinate type when drawing polygons.
|
||||
* @typedef {Array<Array<import("../coordinate.js").Coordinate>>} PolyCoordType
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Types used for drawing coordinates.
|
||||
* @typedef {PointCoordType|LineCoordType|PolyCoordType} SketchCoordType
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Function that takes an array of coordinates and an optional existing geometry as
|
||||
* arguments, and returns a geometry. The optional existing geometry is the
|
||||
* geometry that is returned when the function is called without a second
|
||||
* argument.
|
||||
* @typedef {function(!Array<import("../coordinate.js").Coordinate>, import("../geom/SimpleGeometry.js").default=):
|
||||
* @typedef {function(!SketchCoordType, import("../geom/SimpleGeometry.js").default=):
|
||||
* import("../geom/SimpleGeometry.js").default} GeometryFunction
|
||||
*/
|
||||
|
||||
@@ -162,12 +186,12 @@ class Draw extends PointerInteraction {
|
||||
*/
|
||||
constructor(options) {
|
||||
|
||||
super({
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleEvent: handleEvent,
|
||||
handleUpEvent: handleUpEvent,
|
||||
stopDown: FALSE
|
||||
});
|
||||
const pointerOptions = /** @type {import("./Pointer.js").Options} */ (options);
|
||||
if (!pointerOptions.stopDown) {
|
||||
pointerOptions.stopDown = FALSE;
|
||||
}
|
||||
|
||||
super(pointerOptions);
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
@@ -182,7 +206,7 @@ class Draw extends PointerInteraction {
|
||||
this.downPx_ = null;
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @type {?}
|
||||
* @private
|
||||
*/
|
||||
this.downTimeout_;
|
||||
@@ -272,8 +296,7 @@ class Draw extends PointerInteraction {
|
||||
if (!geometryFunction) {
|
||||
if (this.type_ === GeometryType.CIRCLE) {
|
||||
/**
|
||||
* @param {!Array<import("../coordinate.js").Coordinate>} coordinates
|
||||
* The coordinates.
|
||||
* @param {!LineCoordType} coordinates The coordinates.
|
||||
* @param {import("../geom/SimpleGeometry.js").default=} opt_geometry Optional geometry.
|
||||
* @return {import("../geom/SimpleGeometry.js").default} A geometry.
|
||||
*/
|
||||
@@ -296,8 +319,7 @@ class Draw extends PointerInteraction {
|
||||
Constructor = Polygon;
|
||||
}
|
||||
/**
|
||||
* @param {!Array<import("../coordinate.js").Coordinate>} coordinates
|
||||
* The coordinates.
|
||||
* @param {!LineCoordType} coordinates The coordinates.
|
||||
* @param {import("../geom/SimpleGeometry.js").default=} opt_geometry Optional geometry.
|
||||
* @return {import("../geom/SimpleGeometry.js").default} A geometry.
|
||||
*/
|
||||
@@ -358,7 +380,7 @@ class Draw extends PointerInteraction {
|
||||
|
||||
/**
|
||||
* Sketch coordinates. Used when drawing a line or polygon.
|
||||
* @type {import("../coordinate.js").Coordinate|Array<import("../coordinate.js").Coordinate>|Array<Array<import("../coordinate.js").Coordinate>>}
|
||||
* @type {SketchCoordType}
|
||||
* @private
|
||||
*/
|
||||
this.sketchCoords_ = null;
|
||||
@@ -372,7 +394,7 @@ class Draw extends PointerInteraction {
|
||||
|
||||
/**
|
||||
* Sketch line coordinates. Used when drawing a polygon or circle.
|
||||
* @type {Array<import("../coordinate.js").Coordinate>}
|
||||
* @type {LineCoordType}
|
||||
* @private
|
||||
*/
|
||||
this.sketchLineCoords_ = null;
|
||||
@@ -450,6 +472,123 @@ class Draw extends PointerInteraction {
|
||||
return this.overlay_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the {@link module:ol/MapBrowserEvent map browser event} and may actually draw or finish the drawing.
|
||||
* @override
|
||||
* @api
|
||||
*/
|
||||
handleEvent(event) {
|
||||
if (event.originalEvent.type === EventType.CONTEXTMENU) {
|
||||
// Avoid context menu for long taps when drawing on mobile
|
||||
event.preventDefault();
|
||||
}
|
||||
this.freehand_ = this.mode_ !== Mode.POINT && this.freehandCondition_(event);
|
||||
let move = event.type === MapBrowserEventType.POINTERMOVE;
|
||||
let pass = true;
|
||||
if (!this.freehand_ && this.lastDragTime_ && event.type === MapBrowserEventType.POINTERDRAG) {
|
||||
const now = Date.now();
|
||||
if (now - this.lastDragTime_ >= this.dragVertexDelay_) {
|
||||
this.downPx_ = event.pixel;
|
||||
this.shouldHandle_ = !this.freehand_;
|
||||
move = true;
|
||||
} else {
|
||||
this.lastDragTime_ = undefined;
|
||||
}
|
||||
if (this.shouldHandle_ && this.downTimeout_ !== undefined) {
|
||||
clearTimeout(this.downTimeout_);
|
||||
this.downTimeout_ = undefined;
|
||||
}
|
||||
}
|
||||
if (this.freehand_ &&
|
||||
event.type === MapBrowserEventType.POINTERDRAG &&
|
||||
this.sketchFeature_ !== null) {
|
||||
this.addToDrawing_(event);
|
||||
pass = false;
|
||||
} else if (this.freehand_ &&
|
||||
event.type === MapBrowserEventType.POINTERDOWN) {
|
||||
pass = false;
|
||||
} else if (move) {
|
||||
pass = event.type === MapBrowserEventType.POINTERMOVE;
|
||||
if (pass && this.freehand_) {
|
||||
pass = this.handlePointerMove_(event);
|
||||
} else if (/** @type {MapBrowserPointerEvent} */ (event).pointerEvent.pointerType == POINTER_TYPE ||
|
||||
(event.type === MapBrowserEventType.POINTERDRAG && this.downTimeout_ === undefined)) {
|
||||
this.handlePointerMove_(event);
|
||||
}
|
||||
} else if (event.type === MapBrowserEventType.DBLCLICK) {
|
||||
pass = false;
|
||||
}
|
||||
|
||||
return super.handleEvent(event) && pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDownEvent(event) {
|
||||
this.shouldHandle_ = !this.freehand_;
|
||||
|
||||
if (this.freehand_) {
|
||||
this.downPx_ = event.pixel;
|
||||
if (!this.finishCoordinate_) {
|
||||
this.startDrawing_(event);
|
||||
}
|
||||
return true;
|
||||
} else if (this.condition_(event)) {
|
||||
this.lastDragTime_ = Date.now();
|
||||
this.downTimeout_ = setTimeout(function() {
|
||||
this.handlePointerMove_(new MapBrowserPointerEvent(
|
||||
MapBrowserEventType.POINTERMOVE, event.map, event.pointerEvent, false, event.frameState));
|
||||
}.bind(this), this.dragVertexDelay_);
|
||||
this.downPx_ = event.pixel;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(event) {
|
||||
let pass = true;
|
||||
|
||||
if (this.downTimeout_) {
|
||||
clearTimeout(this.downTimeout_);
|
||||
this.downTimeout_ = undefined;
|
||||
}
|
||||
|
||||
this.handlePointerMove_(event);
|
||||
|
||||
const circleMode = this.mode_ === Mode.CIRCLE;
|
||||
|
||||
if (this.shouldHandle_) {
|
||||
if (!this.finishCoordinate_) {
|
||||
this.startDrawing_(event);
|
||||
if (this.mode_ === Mode.POINT) {
|
||||
this.finishDrawing();
|
||||
}
|
||||
} else if (this.freehand_ || circleMode) {
|
||||
this.finishDrawing();
|
||||
} else if (this.atFinish_(event)) {
|
||||
if (this.finishCondition_(event)) {
|
||||
this.finishDrawing();
|
||||
}
|
||||
} else {
|
||||
this.addToDrawing_(event);
|
||||
}
|
||||
pass = false;
|
||||
} else if (this.freehand_) {
|
||||
this.finishCoordinate_ = null;
|
||||
this.abortDrawing_();
|
||||
}
|
||||
if (!pass && this.stopClick_) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle move events.
|
||||
* @param {import("../MapBrowserEvent.js").default} event A move event.
|
||||
@@ -495,10 +634,9 @@ class Draw extends PointerInteraction {
|
||||
if (this.mode_ === Mode.LINE_STRING) {
|
||||
potentiallyDone = this.sketchCoords_.length > this.minPoints_;
|
||||
} else if (this.mode_ === Mode.POLYGON) {
|
||||
potentiallyDone = this.sketchCoords_[0].length >
|
||||
this.minPoints_;
|
||||
potentiallyFinishCoordinates = [this.sketchCoords_[0][0],
|
||||
this.sketchCoords_[0][this.sketchCoords_[0].length - 2]];
|
||||
const sketchCoords = /** @type {PolyCoordType} */ (this.sketchCoords_);
|
||||
potentiallyDone = sketchCoords[0].length > this.minPoints_;
|
||||
potentiallyFinishCoordinates = [sketchCoords[0][0], sketchCoords[0][sketchCoords[0].length - 2]];
|
||||
}
|
||||
if (potentiallyDone) {
|
||||
const map = event.map;
|
||||
@@ -577,7 +715,7 @@ class Draw extends PointerInteraction {
|
||||
if (this.mode_ === Mode.POINT) {
|
||||
last = this.sketchCoords_;
|
||||
} else if (this.mode_ === Mode.POLYGON) {
|
||||
coordinates = this.sketchCoords_[0];
|
||||
coordinates = /** @type {PolyCoordType} */ (this.sketchCoords_)[0];
|
||||
last = coordinates[coordinates.length - 1];
|
||||
if (this.atFinish_(event)) {
|
||||
// snap to finish
|
||||
@@ -589,18 +727,19 @@ class Draw extends PointerInteraction {
|
||||
}
|
||||
last[0] = coordinate[0];
|
||||
last[1] = coordinate[1];
|
||||
this.geometryFunction_(/** @type {!Array<import("../coordinate.js").Coordinate>} */ (this.sketchCoords_), geometry);
|
||||
this.geometryFunction_(/** @type {!LineCoordType} */ (this.sketchCoords_), geometry);
|
||||
if (this.sketchPoint_) {
|
||||
const sketchPointGeom = /** @type {Point} */ (this.sketchPoint_.getGeometry());
|
||||
sketchPointGeom.setCoordinates(coordinate);
|
||||
}
|
||||
/** @type {LineString} */
|
||||
let sketchLineGeom;
|
||||
if (geometry instanceof Polygon &&
|
||||
if (geometry.getType() == GeometryType.POLYGON &&
|
||||
this.mode_ !== Mode.POLYGON) {
|
||||
if (!this.sketchLine_) {
|
||||
this.sketchLine_ = new Feature();
|
||||
}
|
||||
const ring = geometry.getLinearRing(0);
|
||||
const ring = /** @type {Polygon} */ (geometry).getLinearRing(0);
|
||||
sketchLineGeom = /** @type {LineString} */ (this.sketchLine_.getGeometry());
|
||||
if (!sketchLineGeom) {
|
||||
sketchLineGeom = new LineString(ring.getFlatCoordinates(), ring.getLayout());
|
||||
@@ -629,7 +768,7 @@ class Draw extends PointerInteraction {
|
||||
let coordinates;
|
||||
if (this.mode_ === Mode.LINE_STRING) {
|
||||
this.finishCoordinate_ = coordinate.slice();
|
||||
coordinates = this.sketchCoords_;
|
||||
coordinates = /** @type {LineCoordType} */ (this.sketchCoords_);
|
||||
if (coordinates.length >= this.maxPoints_) {
|
||||
if (this.freehand_) {
|
||||
coordinates.pop();
|
||||
@@ -640,7 +779,7 @@ class Draw extends PointerInteraction {
|
||||
coordinates.push(coordinate.slice());
|
||||
this.geometryFunction_(coordinates, geometry);
|
||||
} else if (this.mode_ === Mode.POLYGON) {
|
||||
coordinates = this.sketchCoords_[0];
|
||||
coordinates = /** @type {PolyCoordType} */ (this.sketchCoords_)[0];
|
||||
if (coordinates.length >= this.maxPoints_) {
|
||||
if (this.freehand_) {
|
||||
coordinates.pop();
|
||||
@@ -669,16 +808,18 @@ class Draw extends PointerInteraction {
|
||||
return;
|
||||
}
|
||||
const geometry = /** @type {import("../geom/SimpleGeometry.js").default} */ (this.sketchFeature_.getGeometry());
|
||||
let coordinates, sketchLineGeom;
|
||||
let coordinates;
|
||||
/** @type {LineString} */
|
||||
let sketchLineGeom;
|
||||
if (this.mode_ === Mode.LINE_STRING) {
|
||||
coordinates = this.sketchCoords_;
|
||||
coordinates = /** @type {LineCoordType} */ (this.sketchCoords_);
|
||||
coordinates.splice(-2, 1);
|
||||
this.geometryFunction_(coordinates, geometry);
|
||||
if (coordinates.length >= 2) {
|
||||
this.finishCoordinate_ = coordinates[coordinates.length - 2].slice();
|
||||
}
|
||||
} else if (this.mode_ === Mode.POLYGON) {
|
||||
coordinates = this.sketchCoords_[0];
|
||||
coordinates = /** @type {PolyCoordType} */ (this.sketchCoords_)[0];
|
||||
coordinates.splice(-2, 1);
|
||||
sketchLineGeom = /** @type {LineString} */ (this.sketchLine_.getGeometry());
|
||||
sketchLineGeom.setCoordinates(coordinates);
|
||||
@@ -711,18 +852,18 @@ class Draw extends PointerInteraction {
|
||||
this.geometryFunction_(coordinates, geometry);
|
||||
} else if (this.mode_ === Mode.POLYGON) {
|
||||
// remove the redundant last point in ring
|
||||
coordinates[0].pop();
|
||||
/** @type {PolyCoordType} */ (coordinates)[0].pop();
|
||||
this.geometryFunction_(coordinates, geometry);
|
||||
coordinates = geometry.getCoordinates();
|
||||
}
|
||||
|
||||
// cast multi-part geometries
|
||||
if (this.type_ === GeometryType.MULTI_POINT) {
|
||||
sketchFeature.setGeometry(new MultiPoint([coordinates]));
|
||||
sketchFeature.setGeometry(new MultiPoint([/** @type {PointCoordType} */(coordinates)]));
|
||||
} else if (this.type_ === GeometryType.MULTI_LINE_STRING) {
|
||||
sketchFeature.setGeometry(new MultiLineString([coordinates]));
|
||||
sketchFeature.setGeometry(new MultiLineString([/** @type {LineCoordType} */(coordinates)]));
|
||||
} else if (this.type_ === GeometryType.MULTI_POLYGON) {
|
||||
sketchFeature.setGeometry(new MultiPolygon([coordinates]));
|
||||
sketchFeature.setGeometry(new MultiPolygon([/** @type {PolyCoordType} */(coordinates)]));
|
||||
}
|
||||
|
||||
// First dispatch event to allow full set up of feature
|
||||
@@ -749,7 +890,7 @@ class Draw extends PointerInteraction {
|
||||
this.sketchFeature_ = null;
|
||||
this.sketchPoint_ = null;
|
||||
this.sketchLine_ = null;
|
||||
this.overlay_.getSource().clear(true);
|
||||
/** @type {VectorSource} */ (this.overlay_.getSource()).clear(true);
|
||||
}
|
||||
return sketchFeature;
|
||||
}
|
||||
@@ -788,7 +929,7 @@ class Draw extends PointerInteraction {
|
||||
if (this.sketchPoint_) {
|
||||
sketchFeatures.push(this.sketchPoint_);
|
||||
}
|
||||
const overlaySource = this.overlay_.getSource();
|
||||
const overlaySource = /** @type {VectorSource} */ (this.overlay_.getSource());
|
||||
overlaySource.clear(true);
|
||||
overlaySource.addFeatures(sketchFeatures);
|
||||
}
|
||||
@@ -818,132 +959,6 @@ function getDefaultStyleFunction() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles the {@link module:ol/MapBrowserEvent map browser event} and may actually
|
||||
* draw or finish the drawing.
|
||||
* @param {import("../MapBrowserEvent.js").default} event Map browser event.
|
||||
* @return {boolean} `false` to stop event propagation.
|
||||
* @this {Draw}
|
||||
* @api
|
||||
*/
|
||||
export function handleEvent(event) {
|
||||
if (event.originalEvent.type === EventType.CONTEXTMENU) {
|
||||
// Avoid context menu for long taps when drawing on mobile
|
||||
event.preventDefault();
|
||||
}
|
||||
this.freehand_ = this.mode_ !== Mode.POINT && this.freehandCondition_(event);
|
||||
let move = event.type === MapBrowserEventType.POINTERMOVE;
|
||||
let pass = true;
|
||||
if (!this.freehand_ && this.lastDragTime_ && event.type === MapBrowserEventType.POINTERDRAG) {
|
||||
const now = Date.now();
|
||||
if (now - this.lastDragTime_ >= this.dragVertexDelay_) {
|
||||
this.downPx_ = event.pixel;
|
||||
this.shouldHandle_ = !this.freehand_;
|
||||
move = true;
|
||||
} else {
|
||||
this.lastDragTime_ = undefined;
|
||||
}
|
||||
if (this.shouldHandle_ && this.downTimeout_) {
|
||||
clearTimeout(this.downTimeout_);
|
||||
this.downTimeout_ = undefined;
|
||||
}
|
||||
}
|
||||
if (this.freehand_ &&
|
||||
event.type === MapBrowserEventType.POINTERDRAG &&
|
||||
this.sketchFeature_ !== null) {
|
||||
this.addToDrawing_(event);
|
||||
pass = false;
|
||||
} else if (this.freehand_ &&
|
||||
event.type === MapBrowserEventType.POINTERDOWN) {
|
||||
pass = false;
|
||||
} else if (move) {
|
||||
pass = event.type === MapBrowserEventType.POINTERMOVE;
|
||||
if (pass && this.freehand_) {
|
||||
pass = this.handlePointerMove_(event);
|
||||
} else if (event.pointerEvent.pointerType == POINTER_TYPE ||
|
||||
(event.type === MapBrowserEventType.POINTERDRAG && !this.downTimeout_)) {
|
||||
this.handlePointerMove_(event);
|
||||
}
|
||||
} else if (event.type === MapBrowserEventType.DBLCLICK) {
|
||||
pass = false;
|
||||
}
|
||||
|
||||
return handlePointerEvent.call(this, event) && pass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} event Event.
|
||||
* @return {boolean} Start drag sequence?
|
||||
* @this {Draw}
|
||||
*/
|
||||
function handleDownEvent(event) {
|
||||
this.shouldHandle_ = !this.freehand_;
|
||||
|
||||
if (this.freehand_) {
|
||||
this.downPx_ = event.pixel;
|
||||
if (!this.finishCoordinate_) {
|
||||
this.startDrawing_(event);
|
||||
}
|
||||
return true;
|
||||
} else if (this.condition_(event)) {
|
||||
this.lastDragTime_ = Date.now();
|
||||
this.downTimeout_ = setTimeout(function() {
|
||||
this.handlePointerMove_(new MapBrowserPointerEvent(
|
||||
MapBrowserEventType.POINTERMOVE, event.map, event.pointerEvent, event.frameState));
|
||||
}.bind(this), this.dragVertexDelay_);
|
||||
this.downPx_ = event.pixel;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} event Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {Draw}
|
||||
*/
|
||||
function handleUpEvent(event) {
|
||||
let pass = true;
|
||||
|
||||
if (this.downTimeout_) {
|
||||
clearTimeout(this.downTimeout_);
|
||||
this.downTimeout_ = undefined;
|
||||
}
|
||||
|
||||
this.handlePointerMove_(event);
|
||||
|
||||
const circleMode = this.mode_ === Mode.CIRCLE;
|
||||
|
||||
if (this.shouldHandle_) {
|
||||
if (!this.finishCoordinate_) {
|
||||
this.startDrawing_(event);
|
||||
if (this.mode_ === Mode.POINT) {
|
||||
this.finishDrawing();
|
||||
}
|
||||
} else if (this.freehand_ || circleMode) {
|
||||
this.finishDrawing();
|
||||
} else if (this.atFinish_(event)) {
|
||||
if (this.finishCondition_(event)) {
|
||||
this.finishDrawing();
|
||||
}
|
||||
} else {
|
||||
this.addToDrawing_(event);
|
||||
}
|
||||
pass = false;
|
||||
} else if (this.freehand_) {
|
||||
this.finishCoordinate_ = null;
|
||||
this.abortDrawing_();
|
||||
}
|
||||
if (!pass && this.stopClick_) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a `geometryFunction` for `type: 'Circle'` that will create a regular
|
||||
* polygon with a user specified number of sides and start angle instead of an
|
||||
@@ -959,8 +974,8 @@ function handleUpEvent(event) {
|
||||
*/
|
||||
export function createRegularPolygon(opt_sides, opt_angle) {
|
||||
return function(coordinates, opt_geometry) {
|
||||
const center = coordinates[0];
|
||||
const end = coordinates[1];
|
||||
const center = /** @type {LineCoordType} */ (coordinates)[0];
|
||||
const end = /** @type {LineCoordType} */ (coordinates)[1];
|
||||
const radius = Math.sqrt(
|
||||
squaredCoordinateDistance(center, end));
|
||||
const geometry = opt_geometry ? /** @type {Polygon} */ (opt_geometry) :
|
||||
@@ -987,7 +1002,7 @@ export function createRegularPolygon(opt_sides, opt_angle) {
|
||||
export function createBox() {
|
||||
return (
|
||||
function(coordinates, opt_geometry) {
|
||||
const extent = boundingExtent(coordinates);
|
||||
const extent = boundingExtent(/** @type {LineCoordType} */ (coordinates));
|
||||
const boxCoordinates = [[
|
||||
getBottomLeft(extent),
|
||||
getBottomRight(extent),
|
||||
|
||||
@@ -3,14 +3,13 @@
|
||||
*/
|
||||
import Feature from '../Feature.js';
|
||||
import MapBrowserEventType from '../MapBrowserEventType.js';
|
||||
import MapBrowserPointerEvent from '../MapBrowserPointerEvent.js';
|
||||
import {squaredDistanceToSegment, closestOnSegment, distance as coordinateDistance, squaredDistance as squaredCoordinateDistance} from '../coordinate.js';
|
||||
import Event from '../events/Event.js';
|
||||
import {boundingExtent, getArea} from '../extent.js';
|
||||
import GeometryType from '../geom/GeometryType.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import {fromExtent as polygonFromExtent} from '../geom/Polygon.js';
|
||||
import PointerInteraction, {handleEvent as handlePointerEvent} from '../interaction/Pointer.js';
|
||||
import PointerInteraction from '../interaction/Pointer.js';
|
||||
import VectorLayer from '../layer/Vector.js';
|
||||
import VectorSource from '../source/Vector.js';
|
||||
import {createEditingStyle} from '../style/Style.js';
|
||||
@@ -20,12 +19,12 @@ import {createEditingStyle} from '../style/Style.js';
|
||||
* @typedef {Object} Options
|
||||
* @property {import("../extent.js").Extent} [extent] Initial extent. Defaults to no
|
||||
* initial extent.
|
||||
* @property {import("../style/Style.js").default|Array<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction} [boxStyle]
|
||||
* @property {import("../style/Style.js").StyleLike} [boxStyle]
|
||||
* Style for the drawn extent box. Defaults to
|
||||
* {@link module:ol/style/Style~createEditing()['Polygon']}
|
||||
* @property {number} [pixelTolerance=10] Pixel tolerance for considering the
|
||||
* pointer close enough to a segment or vertex for editing.
|
||||
* @property {import("../style/Style.js").default|Array<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction} [pointerStyle]
|
||||
* @property {import("../style/Style.js").StyleLike} [pointerStyle]
|
||||
* Style for the cursor used to draw the extent. Defaults to
|
||||
* {@link module:ol/style/Style~createEditing()['Point']}
|
||||
* @property {boolean} [wrapX=false] Wrap the drawn extent across multiple maps
|
||||
@@ -85,15 +84,10 @@ class ExtentInteraction extends PointerInteraction {
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
|
||||
super({
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleDragEvent: handleDragEvent,
|
||||
handleEvent: handleEvent,
|
||||
handleUpEvent: handleUpEvent
|
||||
});
|
||||
|
||||
const options = opt_options || {};
|
||||
|
||||
super(/** @type {import("./Pointer.js").Options} */ (options));
|
||||
|
||||
/**
|
||||
* Extent of the drawn box
|
||||
* @type {import("../extent.js").Extent}
|
||||
@@ -248,7 +242,7 @@ class ExtentInteraction extends PointerInteraction {
|
||||
extentFeature = new Feature(polygonFromExtent(extent));
|
||||
}
|
||||
this.extentFeature_ = extentFeature;
|
||||
this.extentOverlay_.getSource().addFeature(extentFeature);
|
||||
/** @type {VectorSource} */ (this.extentOverlay_.getSource()).addFeature(extentFeature);
|
||||
} else {
|
||||
if (!extent) {
|
||||
extentFeature.setGeometry(undefined);
|
||||
@@ -269,7 +263,7 @@ class ExtentInteraction extends PointerInteraction {
|
||||
if (!vertexFeature) {
|
||||
vertexFeature = new Feature(new Point(vertex));
|
||||
this.vertexFeature_ = vertexFeature;
|
||||
this.vertexOverlay_.getSource().addFeature(vertexFeature);
|
||||
/** @type {VectorSource} */ (this.vertexOverlay_.getSource()).addFeature(vertexFeature);
|
||||
} else {
|
||||
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
|
||||
geometry.setCoordinates(vertex);
|
||||
@@ -277,6 +271,105 @@ class ExtentInteraction extends PointerInteraction {
|
||||
return vertexFeature;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleEvent(mapBrowserEvent) {
|
||||
if (!(/** @type {import("../MapBrowserPointerEvent.js").default} */ (mapBrowserEvent).pointerEvent)) {
|
||||
return true;
|
||||
}
|
||||
//display pointer (if not dragging)
|
||||
if (mapBrowserEvent.type == MapBrowserEventType.POINTERMOVE && !this.handlingDownUpSequence) {
|
||||
this.handlePointerMove_(mapBrowserEvent);
|
||||
}
|
||||
//call pointer to determine up/down/drag
|
||||
super.handleEvent(mapBrowserEvent);
|
||||
//return false to stop propagation
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDownEvent(mapBrowserEvent) {
|
||||
const pixel = mapBrowserEvent.pixel;
|
||||
const map = mapBrowserEvent.map;
|
||||
|
||||
const extent = this.getExtent();
|
||||
let vertex = this.snapToVertex_(pixel, map);
|
||||
|
||||
//find the extent corner opposite the passed corner
|
||||
const getOpposingPoint = function(point) {
|
||||
let x_ = null;
|
||||
let y_ = null;
|
||||
if (point[0] == extent[0]) {
|
||||
x_ = extent[2];
|
||||
} else if (point[0] == extent[2]) {
|
||||
x_ = extent[0];
|
||||
}
|
||||
if (point[1] == extent[1]) {
|
||||
y_ = extent[3];
|
||||
} else if (point[1] == extent[3]) {
|
||||
y_ = extent[1];
|
||||
}
|
||||
if (x_ !== null && y_ !== null) {
|
||||
return [x_, y_];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
if (vertex && extent) {
|
||||
const x = (vertex[0] == extent[0] || vertex[0] == extent[2]) ? vertex[0] : null;
|
||||
const y = (vertex[1] == extent[1] || vertex[1] == extent[3]) ? vertex[1] : null;
|
||||
|
||||
//snap to point
|
||||
if (x !== null && y !== null) {
|
||||
this.pointerHandler_ = getPointHandler(getOpposingPoint(vertex));
|
||||
//snap to edge
|
||||
} else if (x !== null) {
|
||||
this.pointerHandler_ = getEdgeHandler(
|
||||
getOpposingPoint([x, extent[1]]),
|
||||
getOpposingPoint([x, extent[3]])
|
||||
);
|
||||
} else if (y !== null) {
|
||||
this.pointerHandler_ = getEdgeHandler(
|
||||
getOpposingPoint([extent[0], y]),
|
||||
getOpposingPoint([extent[2], y])
|
||||
);
|
||||
}
|
||||
//no snap - new bbox
|
||||
} else {
|
||||
vertex = map.getCoordinateFromPixel(pixel);
|
||||
this.setExtent([vertex[0], vertex[1], vertex[0], vertex[1]]);
|
||||
this.pointerHandler_ = getPointHandler(vertex);
|
||||
}
|
||||
return true; //event handled; start downup sequence
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDragEvent(mapBrowserEvent) {
|
||||
if (this.pointerHandler_) {
|
||||
const pixelCoordinate = mapBrowserEvent.coordinate;
|
||||
this.setExtent(this.pointerHandler_(pixelCoordinate));
|
||||
this.createOrUpdatePointerFeature_(pixelCoordinate);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(mapBrowserEvent) {
|
||||
this.pointerHandler_ = null;
|
||||
//If bbox is zero area, set to null;
|
||||
const extent = this.getExtent();
|
||||
if (!extent || getArea(extent) === 0) {
|
||||
this.setExtent(null);
|
||||
}
|
||||
return false; //Stop handling downup sequence
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -310,113 +403,6 @@ class ExtentInteraction extends PointerInteraction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Propagate event?
|
||||
* @this {ExtentInteraction}
|
||||
*/
|
||||
function handleEvent(mapBrowserEvent) {
|
||||
if (!(mapBrowserEvent instanceof MapBrowserPointerEvent)) {
|
||||
return true;
|
||||
}
|
||||
//display pointer (if not dragging)
|
||||
if (mapBrowserEvent.type == MapBrowserEventType.POINTERMOVE && !this.handlingDownUpSequence) {
|
||||
this.handlePointerMove_(mapBrowserEvent);
|
||||
}
|
||||
//call pointer to determine up/down/drag
|
||||
handlePointerEvent.call(this, mapBrowserEvent);
|
||||
//return false to stop propagation
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Event handled?
|
||||
* @this {ExtentInteraction}
|
||||
*/
|
||||
function handleDownEvent(mapBrowserEvent) {
|
||||
const pixel = mapBrowserEvent.pixel;
|
||||
const map = mapBrowserEvent.map;
|
||||
|
||||
const extent = this.getExtent();
|
||||
let vertex = this.snapToVertex_(pixel, map);
|
||||
|
||||
//find the extent corner opposite the passed corner
|
||||
const getOpposingPoint = function(point) {
|
||||
let x_ = null;
|
||||
let y_ = null;
|
||||
if (point[0] == extent[0]) {
|
||||
x_ = extent[2];
|
||||
} else if (point[0] == extent[2]) {
|
||||
x_ = extent[0];
|
||||
}
|
||||
if (point[1] == extent[1]) {
|
||||
y_ = extent[3];
|
||||
} else if (point[1] == extent[3]) {
|
||||
y_ = extent[1];
|
||||
}
|
||||
if (x_ !== null && y_ !== null) {
|
||||
return [x_, y_];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
if (vertex && extent) {
|
||||
const x = (vertex[0] == extent[0] || vertex[0] == extent[2]) ? vertex[0] : null;
|
||||
const y = (vertex[1] == extent[1] || vertex[1] == extent[3]) ? vertex[1] : null;
|
||||
|
||||
//snap to point
|
||||
if (x !== null && y !== null) {
|
||||
this.pointerHandler_ = getPointHandler(getOpposingPoint(vertex));
|
||||
//snap to edge
|
||||
} else if (x !== null) {
|
||||
this.pointerHandler_ = getEdgeHandler(
|
||||
getOpposingPoint([x, extent[1]]),
|
||||
getOpposingPoint([x, extent[3]])
|
||||
);
|
||||
} else if (y !== null) {
|
||||
this.pointerHandler_ = getEdgeHandler(
|
||||
getOpposingPoint([extent[0], y]),
|
||||
getOpposingPoint([extent[2], y])
|
||||
);
|
||||
}
|
||||
//no snap - new bbox
|
||||
} else {
|
||||
vertex = map.getCoordinateFromPixel(pixel);
|
||||
this.setExtent([vertex[0], vertex[1], vertex[0], vertex[1]]);
|
||||
this.pointerHandler_ = getPointHandler(vertex);
|
||||
}
|
||||
return true; //event handled; start downup sequence
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Event handled?
|
||||
* @this {ExtentInteraction}
|
||||
*/
|
||||
function handleDragEvent(mapBrowserEvent) {
|
||||
if (this.pointerHandler_) {
|
||||
const pixelCoordinate = mapBrowserEvent.coordinate;
|
||||
this.setExtent(this.pointerHandler_(pixelCoordinate));
|
||||
this.createOrUpdatePointerFeature_(pixelCoordinate);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {ExtentInteraction}
|
||||
*/
|
||||
function handleUpEvent(mapBrowserEvent) {
|
||||
this.pointerHandler_ = null;
|
||||
//If bbox is zero area, set to null;
|
||||
const extent = this.getExtent();
|
||||
if (!extent || getArea(extent) === 0) {
|
||||
this.setExtent(null);
|
||||
}
|
||||
return false; //Stop handling downup sequence
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default style for the drawn bbox
|
||||
*
|
||||
|
||||
@@ -38,6 +38,10 @@ class Interaction extends BaseObject {
|
||||
constructor(options) {
|
||||
super();
|
||||
|
||||
if (options.handleEvent) {
|
||||
this.handleEvent = options.handleEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("../PluggableMap.js").default}
|
||||
@@ -45,12 +49,6 @@ class Interaction extends BaseObject {
|
||||
this.map_ = null;
|
||||
|
||||
this.setActive(true);
|
||||
|
||||
/**
|
||||
* @type {function(import("../MapBrowserEvent.js").default):boolean}
|
||||
*/
|
||||
this.handleEvent = options.handleEvent;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +70,16 @@ class Interaction extends BaseObject {
|
||||
return this.map_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the {@link module:ol/MapBrowserEvent map browser event}.
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} `false` to stop event propagation.
|
||||
* @api
|
||||
*/
|
||||
handleEvent(mapBrowserEvent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate or deactivate the interaction.
|
||||
* @param {boolean} active Active.
|
||||
|
||||
@@ -27,7 +27,7 @@ import Interaction, {zoomByDelta} from '../interaction/Interaction.js';
|
||||
* {@link module:ol/Map~Map}. `document` never loses focus but, for any other
|
||||
* element, focus will have to be on, and returned to, this element if the keys
|
||||
* are to function.
|
||||
* See also {@link moudle:ol/interaction/KeyboardPan~KeyboardPan}.
|
||||
* See also {@link module:ol/interaction/KeyboardPan~KeyboardPan}.
|
||||
* @api
|
||||
*/
|
||||
class KeyboardZoom extends Interaction {
|
||||
|
||||
@@ -6,7 +6,6 @@ import Collection from '../Collection.js';
|
||||
import CollectionEventType from '../CollectionEventType.js';
|
||||
import Feature from '../Feature.js';
|
||||
import MapBrowserEventType from '../MapBrowserEventType.js';
|
||||
import MapBrowserPointerEvent from '../MapBrowserPointerEvent.js';
|
||||
import {equals} from '../array.js';
|
||||
import {equals as coordinatesEqual, distance as coordinateDistance, squaredDistance as squaredCoordinateDistance, squaredDistanceToSegment, closestOnSegment} from '../coordinate.js';
|
||||
import {listen, unlisten} from '../events.js';
|
||||
@@ -16,7 +15,7 @@ import {always, primaryAction, altKeyOnly, singleClick} from '../events/conditio
|
||||
import {boundingExtent, buffer, createOrUpdateFromCoordinate} from '../extent.js';
|
||||
import GeometryType from '../geom/GeometryType.js';
|
||||
import Point from '../geom/Point.js';
|
||||
import PointerInteraction, {handleEvent as handlePointerEvent} from '../interaction/Pointer.js';
|
||||
import PointerInteraction from '../interaction/Pointer.js';
|
||||
import VectorLayer from '../layer/Vector.js';
|
||||
import VectorSource from '../source/Vector.js';
|
||||
import VectorEventType from '../source/VectorEventType.js';
|
||||
@@ -63,7 +62,7 @@ const ModifyEventType = {
|
||||
* @property {Array<number>} [depth]
|
||||
* @property {Feature} feature
|
||||
* @property {import("../geom/SimpleGeometry.js").default} geometry
|
||||
* @property {number} index
|
||||
* @property {number} [index]
|
||||
* @property {Array<import("../extent.js").Extent>} segment
|
||||
* @property {Array<SegmentData>} [featureSegments]
|
||||
*/
|
||||
@@ -87,7 +86,7 @@ const ModifyEventType = {
|
||||
* features. Default is {@link module:ol/events/condition~always}.
|
||||
* @property {number} [pixelTolerance=10] Pixel tolerance for considering the
|
||||
* pointer close enough to a segment or vertex for editing.
|
||||
* @property {import("../style/Style.js").default|Array<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction} [style]
|
||||
* @property {import("../style/Style.js").StyleLike} [style]
|
||||
* Style used for the features being modified. By default the default edit
|
||||
* style is used (see {@link module:ol/style}).
|
||||
* @property {VectorSource} [source] The vector source with
|
||||
@@ -111,7 +110,7 @@ export class ModifyEvent extends Event {
|
||||
* @param {ModifyEventType} type Type.
|
||||
* @param {Collection<Feature>} features
|
||||
* The features modified.
|
||||
* @param {MapBrowserPointerEvent} mapBrowserPointerEvent
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserPointerEvent
|
||||
* Associated {@link module:ol/MapBrowserPointerEvent}.
|
||||
*/
|
||||
constructor(type, features, mapBrowserPointerEvent) {
|
||||
@@ -157,12 +156,7 @@ class Modify extends PointerInteraction {
|
||||
*/
|
||||
constructor(options) {
|
||||
|
||||
super({
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleDragEvent: handleDragEvent,
|
||||
handleEvent: handleEvent,
|
||||
handleUpEvent: handleUpEvent
|
||||
});
|
||||
super(/** @type {import("./Pointer.js").Options} */ (options));
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -170,7 +164,6 @@ class Modify extends PointerInteraction {
|
||||
*/
|
||||
this.condition_ = options.condition ? options.condition : primaryAction;
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Browser event.
|
||||
@@ -330,7 +323,7 @@ class Modify extends PointerInteraction {
|
||||
this.handleFeatureRemove_, this);
|
||||
|
||||
/**
|
||||
* @type {MapBrowserPointerEvent}
|
||||
* @type {import("../MapBrowserPointerEvent.js").default}
|
||||
* @private
|
||||
*/
|
||||
this.lastPointerEvent_ = null;
|
||||
@@ -355,7 +348,7 @@ class Modify extends PointerInteraction {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} evt Map browser event
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} evt Map browser event
|
||||
* @private
|
||||
*/
|
||||
willModifyFeatures_(evt) {
|
||||
@@ -375,7 +368,7 @@ class Modify extends PointerInteraction {
|
||||
// Remove the vertex feature if the collection of canditate features
|
||||
// is empty.
|
||||
if (this.vertexFeature_ && this.features_.getLength() === 0) {
|
||||
this.overlay_.getSource().removeFeature(this.vertexFeature_);
|
||||
/** @type {VectorSource} */ (this.overlay_.getSource()).removeFeature(this.vertexFeature_);
|
||||
this.vertexFeature_ = null;
|
||||
}
|
||||
unlisten(feature, EventType.CHANGE,
|
||||
@@ -408,7 +401,7 @@ class Modify extends PointerInteraction {
|
||||
*/
|
||||
setActive(active) {
|
||||
if (this.vertexFeature_ && !active) {
|
||||
this.overlay_.getSource().removeFeature(this.vertexFeature_);
|
||||
/** @type {VectorSource} */ (this.overlay_.getSource()).removeFeature(this.vertexFeature_);
|
||||
this.vertexFeature_ = null;
|
||||
}
|
||||
super.setActive(active);
|
||||
@@ -659,7 +652,7 @@ class Modify extends PointerInteraction {
|
||||
if (!vertexFeature) {
|
||||
vertexFeature = new Feature(new Point(coordinates));
|
||||
this.vertexFeature_ = vertexFeature;
|
||||
this.overlay_.getSource().addFeature(vertexFeature);
|
||||
/** @type {VectorSource} */ (this.overlay_.getSource()).addFeature(vertexFeature);
|
||||
} else {
|
||||
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
|
||||
geometry.setCoordinates(coordinates);
|
||||
@@ -667,6 +660,211 @@ class Modify extends PointerInteraction {
|
||||
return vertexFeature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the {@link module:ol/MapBrowserEvent map browser event} and may modify the geometry.
|
||||
* @override
|
||||
*/
|
||||
handleEvent(mapBrowserEvent) {
|
||||
if (!(/** @type {import("../MapBrowserPointerEvent.js").default} */ (mapBrowserEvent).pointerEvent)) {
|
||||
return true;
|
||||
}
|
||||
this.lastPointerEvent_ = mapBrowserEvent;
|
||||
|
||||
let handled;
|
||||
if (!mapBrowserEvent.map.getView().getInteracting() &&
|
||||
mapBrowserEvent.type == MapBrowserEventType.POINTERMOVE &&
|
||||
!this.handlingDownUpSequence) {
|
||||
this.handlePointerMove_(mapBrowserEvent);
|
||||
}
|
||||
if (this.vertexFeature_ && this.deleteCondition_(mapBrowserEvent)) {
|
||||
if (mapBrowserEvent.type != MapBrowserEventType.SINGLECLICK || !this.ignoreNextSingleClick_) {
|
||||
handled = this.removePoint();
|
||||
} else {
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mapBrowserEvent.type == MapBrowserEventType.SINGLECLICK) {
|
||||
this.ignoreNextSingleClick_ = false;
|
||||
}
|
||||
|
||||
return super.handleEvent(mapBrowserEvent) && !handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDragEvent(evt) {
|
||||
this.ignoreNextSingleClick_ = false;
|
||||
this.willModifyFeatures_(evt);
|
||||
|
||||
const vertex = evt.coordinate;
|
||||
for (let i = 0, ii = this.dragSegments_.length; i < ii; ++i) {
|
||||
const dragSegment = this.dragSegments_[i];
|
||||
const segmentData = dragSegment[0];
|
||||
const depth = segmentData.depth;
|
||||
const geometry = segmentData.geometry;
|
||||
let coordinates;
|
||||
const segment = segmentData.segment;
|
||||
const index = dragSegment[1];
|
||||
|
||||
while (vertex.length < geometry.getStride()) {
|
||||
vertex.push(segment[index][vertex.length]);
|
||||
}
|
||||
|
||||
switch (geometry.getType()) {
|
||||
case GeometryType.POINT:
|
||||
coordinates = vertex;
|
||||
segment[0] = segment[1] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_POINT:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[segmentData.index] = vertex;
|
||||
segment[0] = segment[1] = vertex;
|
||||
break;
|
||||
case GeometryType.LINE_STRING:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_LINE_STRING:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.POLYGON:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_POLYGON:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[1]][depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.CIRCLE:
|
||||
segment[0] = segment[1] = vertex;
|
||||
if (segmentData.index === CIRCLE_CENTER_INDEX) {
|
||||
this.changingFeature_ = true;
|
||||
geometry.setCenter(vertex);
|
||||
this.changingFeature_ = false;
|
||||
} else { // We're dragging the circle's circumference:
|
||||
this.changingFeature_ = true;
|
||||
geometry.setRadius(coordinateDistance(geometry.getCenter(), vertex));
|
||||
this.changingFeature_ = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// pass
|
||||
}
|
||||
|
||||
if (coordinates) {
|
||||
this.setGeometryCoordinates_(geometry, coordinates);
|
||||
}
|
||||
}
|
||||
this.createOrUpdateVertexFeature_(vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDownEvent(evt) {
|
||||
if (!this.condition_(evt)) {
|
||||
return false;
|
||||
}
|
||||
this.handlePointerAtPixel_(evt.pixel, evt.map);
|
||||
const pixelCoordinate = evt.map.getCoordinateFromPixel(evt.pixel);
|
||||
this.dragSegments_.length = 0;
|
||||
this.modified_ = false;
|
||||
const vertexFeature = this.vertexFeature_;
|
||||
if (vertexFeature) {
|
||||
const insertVertices = [];
|
||||
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
|
||||
const vertex = geometry.getCoordinates();
|
||||
const vertexExtent = boundingExtent([vertex]);
|
||||
const segmentDataMatches = this.rBush_.getInExtent(vertexExtent);
|
||||
const componentSegments = {};
|
||||
segmentDataMatches.sort(compareIndexes);
|
||||
for (let i = 0, ii = segmentDataMatches.length; i < ii; ++i) {
|
||||
const segmentDataMatch = segmentDataMatches[i];
|
||||
const segment = segmentDataMatch.segment;
|
||||
let uid = getUid(segmentDataMatch.feature);
|
||||
const depth = segmentDataMatch.depth;
|
||||
if (depth) {
|
||||
uid += '-' + depth.join('-'); // separate feature components
|
||||
}
|
||||
if (!componentSegments[uid]) {
|
||||
componentSegments[uid] = new Array(2);
|
||||
}
|
||||
if (segmentDataMatch.geometry.getType() === GeometryType.CIRCLE &&
|
||||
segmentDataMatch.index === CIRCLE_CIRCUMFERENCE_INDEX) {
|
||||
|
||||
const closestVertex = closestOnSegmentData(pixelCoordinate, segmentDataMatch);
|
||||
if (coordinatesEqual(closestVertex, vertex) && !componentSegments[uid][0]) {
|
||||
this.dragSegments_.push([segmentDataMatch, 0]);
|
||||
componentSegments[uid][0] = segmentDataMatch;
|
||||
}
|
||||
} else if (coordinatesEqual(segment[0], vertex) &&
|
||||
!componentSegments[uid][0]) {
|
||||
this.dragSegments_.push([segmentDataMatch, 0]);
|
||||
componentSegments[uid][0] = segmentDataMatch;
|
||||
} else if (coordinatesEqual(segment[1], vertex) &&
|
||||
!componentSegments[uid][1]) {
|
||||
|
||||
// prevent dragging closed linestrings by the connecting node
|
||||
if ((segmentDataMatch.geometry.getType() ===
|
||||
GeometryType.LINE_STRING ||
|
||||
segmentDataMatch.geometry.getType() ===
|
||||
GeometryType.MULTI_LINE_STRING) &&
|
||||
componentSegments[uid][0] &&
|
||||
componentSegments[uid][0].index === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.dragSegments_.push([segmentDataMatch, 1]);
|
||||
componentSegments[uid][1] = segmentDataMatch;
|
||||
} else if (this.insertVertexCondition_(evt) && getUid(segment) in this.vertexSegments_ &&
|
||||
(!componentSegments[uid][0] && !componentSegments[uid][1])) {
|
||||
insertVertices.push([segmentDataMatch, vertex]);
|
||||
}
|
||||
}
|
||||
if (insertVertices.length) {
|
||||
this.willModifyFeatures_(evt);
|
||||
}
|
||||
for (let j = insertVertices.length - 1; j >= 0; --j) {
|
||||
this.insertVertex_.apply(this, insertVertices[j]);
|
||||
}
|
||||
}
|
||||
return !!this.vertexFeature_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(evt) {
|
||||
for (let i = this.dragSegments_.length - 1; i >= 0; --i) {
|
||||
const segmentData = this.dragSegments_[i][0];
|
||||
const geometry = segmentData.geometry;
|
||||
if (geometry.getType() === GeometryType.CIRCLE) {
|
||||
// Update a circle object in the R* bush:
|
||||
const coordinates = geometry.getCenter();
|
||||
const centerSegmentData = segmentData.featureSegments[0];
|
||||
const circumferenceSegmentData = segmentData.featureSegments[1];
|
||||
centerSegmentData.segment[0] = centerSegmentData.segment[1] = coordinates;
|
||||
circumferenceSegmentData.segment[0] = circumferenceSegmentData.segment[1] = coordinates;
|
||||
this.rBush_.update(createOrUpdateFromCoordinate(coordinates), centerSegmentData);
|
||||
this.rBush_.update(geometry.getExtent(), circumferenceSegmentData);
|
||||
} else {
|
||||
this.rBush_.update(boundingExtent(segmentData.segment), segmentData);
|
||||
}
|
||||
}
|
||||
if (this.modified_) {
|
||||
this.dispatchEvent(new ModifyEvent(ModifyEventType.MODIFYEND, this.features_, evt));
|
||||
this.modified_ = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserEvent.js").default} evt Event.
|
||||
* @private
|
||||
@@ -701,6 +899,7 @@ class Modify extends PointerInteraction {
|
||||
const vertexPixel = map.getPixelFromCoordinate(vertex);
|
||||
let dist = coordinateDistance(pixel, vertexPixel);
|
||||
if (dist <= this.pixelTolerance_) {
|
||||
/** @type {Object<string, boolean>} */
|
||||
const vertexSegments = {};
|
||||
|
||||
if (node.geometry.getType() === GeometryType.CIRCLE &&
|
||||
@@ -738,7 +937,7 @@ class Modify extends PointerInteraction {
|
||||
}
|
||||
}
|
||||
if (this.vertexFeature_) {
|
||||
this.overlay_.getSource().removeFeature(this.vertexFeature_);
|
||||
/** @type {VectorSource} */ (this.overlay_.getSource()).removeFeature(this.vertexFeature_);
|
||||
this.vertexFeature_ = null;
|
||||
}
|
||||
}
|
||||
@@ -933,7 +1132,7 @@ class Modify extends PointerInteraction {
|
||||
}
|
||||
this.updateSegmentIndices_(geometry, index, segmentData.depth, -1);
|
||||
if (this.vertexFeature_) {
|
||||
this.overlay_.getSource().removeFeature(this.vertexFeature_);
|
||||
/** @type {VectorSource} */ (this.overlay_.getSource()).removeFeature(this.vertexFeature_);
|
||||
this.vertexFeature_ = null;
|
||||
}
|
||||
dragSegments.length = 0;
|
||||
@@ -984,223 +1183,6 @@ function compareIndexes(a, b) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} evt Event.
|
||||
* @return {boolean} Start drag sequence?
|
||||
* @this {Modify}
|
||||
*/
|
||||
function handleDownEvent(evt) {
|
||||
if (!this.condition_(evt)) {
|
||||
return false;
|
||||
}
|
||||
this.handlePointerAtPixel_(evt.pixel, evt.map);
|
||||
const pixelCoordinate = evt.map.getCoordinateFromPixel(evt.pixel);
|
||||
this.dragSegments_.length = 0;
|
||||
this.modified_ = false;
|
||||
const vertexFeature = this.vertexFeature_;
|
||||
if (vertexFeature) {
|
||||
const insertVertices = [];
|
||||
const geometry = /** @type {Point} */ (vertexFeature.getGeometry());
|
||||
const vertex = geometry.getCoordinates();
|
||||
const vertexExtent = boundingExtent([vertex]);
|
||||
const segmentDataMatches = this.rBush_.getInExtent(vertexExtent);
|
||||
const componentSegments = {};
|
||||
segmentDataMatches.sort(compareIndexes);
|
||||
for (let i = 0, ii = segmentDataMatches.length; i < ii; ++i) {
|
||||
const segmentDataMatch = segmentDataMatches[i];
|
||||
const segment = segmentDataMatch.segment;
|
||||
let uid = getUid(segmentDataMatch.feature);
|
||||
const depth = segmentDataMatch.depth;
|
||||
if (depth) {
|
||||
uid += '-' + depth.join('-'); // separate feature components
|
||||
}
|
||||
if (!componentSegments[uid]) {
|
||||
componentSegments[uid] = new Array(2);
|
||||
}
|
||||
if (segmentDataMatch.geometry.getType() === GeometryType.CIRCLE &&
|
||||
segmentDataMatch.index === CIRCLE_CIRCUMFERENCE_INDEX) {
|
||||
|
||||
const closestVertex = closestOnSegmentData(pixelCoordinate, segmentDataMatch);
|
||||
if (coordinatesEqual(closestVertex, vertex) && !componentSegments[uid][0]) {
|
||||
this.dragSegments_.push([segmentDataMatch, 0]);
|
||||
componentSegments[uid][0] = segmentDataMatch;
|
||||
}
|
||||
} else if (coordinatesEqual(segment[0], vertex) &&
|
||||
!componentSegments[uid][0]) {
|
||||
this.dragSegments_.push([segmentDataMatch, 0]);
|
||||
componentSegments[uid][0] = segmentDataMatch;
|
||||
} else if (coordinatesEqual(segment[1], vertex) &&
|
||||
!componentSegments[uid][1]) {
|
||||
|
||||
// prevent dragging closed linestrings by the connecting node
|
||||
if ((segmentDataMatch.geometry.getType() ===
|
||||
GeometryType.LINE_STRING ||
|
||||
segmentDataMatch.geometry.getType() ===
|
||||
GeometryType.MULTI_LINE_STRING) &&
|
||||
componentSegments[uid][0] &&
|
||||
componentSegments[uid][0].index === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.dragSegments_.push([segmentDataMatch, 1]);
|
||||
componentSegments[uid][1] = segmentDataMatch;
|
||||
} else if (this.insertVertexCondition_(evt) && getUid(segment) in this.vertexSegments_ &&
|
||||
(!componentSegments[uid][0] && !componentSegments[uid][1])) {
|
||||
insertVertices.push([segmentDataMatch, vertex]);
|
||||
}
|
||||
}
|
||||
if (insertVertices.length) {
|
||||
this.willModifyFeatures_(evt);
|
||||
}
|
||||
for (let j = insertVertices.length - 1; j >= 0; --j) {
|
||||
this.insertVertex_.apply(this, insertVertices[j]);
|
||||
}
|
||||
}
|
||||
return !!this.vertexFeature_;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} evt Event.
|
||||
* @this {Modify}
|
||||
*/
|
||||
function handleDragEvent(evt) {
|
||||
this.ignoreNextSingleClick_ = false;
|
||||
this.willModifyFeatures_(evt);
|
||||
|
||||
const vertex = evt.coordinate;
|
||||
for (let i = 0, ii = this.dragSegments_.length; i < ii; ++i) {
|
||||
const dragSegment = this.dragSegments_[i];
|
||||
const segmentData = dragSegment[0];
|
||||
const depth = segmentData.depth;
|
||||
const geometry = segmentData.geometry;
|
||||
let coordinates;
|
||||
const segment = segmentData.segment;
|
||||
const index = dragSegment[1];
|
||||
|
||||
while (vertex.length < geometry.getStride()) {
|
||||
vertex.push(segment[index][vertex.length]);
|
||||
}
|
||||
|
||||
switch (geometry.getType()) {
|
||||
case GeometryType.POINT:
|
||||
coordinates = vertex;
|
||||
segment[0] = segment[1] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_POINT:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[segmentData.index] = vertex;
|
||||
segment[0] = segment[1] = vertex;
|
||||
break;
|
||||
case GeometryType.LINE_STRING:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_LINE_STRING:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.POLYGON:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.MULTI_POLYGON:
|
||||
coordinates = geometry.getCoordinates();
|
||||
coordinates[depth[1]][depth[0]][segmentData.index + index] = vertex;
|
||||
segment[index] = vertex;
|
||||
break;
|
||||
case GeometryType.CIRCLE:
|
||||
segment[0] = segment[1] = vertex;
|
||||
if (segmentData.index === CIRCLE_CENTER_INDEX) {
|
||||
this.changingFeature_ = true;
|
||||
geometry.setCenter(vertex);
|
||||
this.changingFeature_ = false;
|
||||
} else { // We're dragging the circle's circumference:
|
||||
this.changingFeature_ = true;
|
||||
geometry.setRadius(coordinateDistance(geometry.getCenter(), vertex));
|
||||
this.changingFeature_ = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// pass
|
||||
}
|
||||
|
||||
if (coordinates) {
|
||||
this.setGeometryCoordinates_(geometry, coordinates);
|
||||
}
|
||||
}
|
||||
this.createOrUpdateVertexFeature_(vertex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} evt Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {Modify}
|
||||
*/
|
||||
function handleUpEvent(evt) {
|
||||
for (let i = this.dragSegments_.length - 1; i >= 0; --i) {
|
||||
const segmentData = this.dragSegments_[i][0];
|
||||
const geometry = segmentData.geometry;
|
||||
if (geometry.getType() === GeometryType.CIRCLE) {
|
||||
// Update a circle object in the R* bush:
|
||||
const coordinates = geometry.getCenter();
|
||||
const centerSegmentData = segmentData.featureSegments[0];
|
||||
const circumferenceSegmentData = segmentData.featureSegments[1];
|
||||
centerSegmentData.segment[0] = centerSegmentData.segment[1] = coordinates;
|
||||
circumferenceSegmentData.segment[0] = circumferenceSegmentData.segment[1] = coordinates;
|
||||
this.rBush_.update(createOrUpdateFromCoordinate(coordinates), centerSegmentData);
|
||||
this.rBush_.update(geometry.getExtent(), circumferenceSegmentData);
|
||||
} else {
|
||||
this.rBush_.update(boundingExtent(segmentData.segment), segmentData);
|
||||
}
|
||||
}
|
||||
if (this.modified_) {
|
||||
this.dispatchEvent(new ModifyEvent(ModifyEventType.MODIFYEND, this.features_, evt));
|
||||
this.modified_ = false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles the {@link module:ol/MapBrowserEvent map browser event} and may modify the
|
||||
* geometry.
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} `false` to stop event propagation.
|
||||
* @this {Modify}
|
||||
*/
|
||||
function handleEvent(mapBrowserEvent) {
|
||||
if (!(mapBrowserEvent instanceof MapBrowserPointerEvent)) {
|
||||
return true;
|
||||
}
|
||||
this.lastPointerEvent_ = mapBrowserEvent;
|
||||
|
||||
let handled;
|
||||
if (!mapBrowserEvent.map.getView().getInteracting() &&
|
||||
mapBrowserEvent.type == MapBrowserEventType.POINTERMOVE &&
|
||||
!this.handlingDownUpSequence) {
|
||||
this.handlePointerMove_(mapBrowserEvent);
|
||||
}
|
||||
if (this.vertexFeature_ && this.deleteCondition_(mapBrowserEvent)) {
|
||||
if (mapBrowserEvent.type != MapBrowserEventType.SINGLECLICK || !this.ignoreNextSingleClick_) {
|
||||
handled = this.removePoint();
|
||||
} else {
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mapBrowserEvent.type == MapBrowserEventType.SINGLECLICK) {
|
||||
this.ignoreNextSingleClick_ = false;
|
||||
}
|
||||
|
||||
return handlePointerEvent.call(this, mapBrowserEvent) && !handled;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance from a point to a line segment.
|
||||
*
|
||||
|
||||
@@ -54,11 +54,9 @@ class MouseWheelZoom extends Interaction {
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
|
||||
super({
|
||||
handleEvent: handleEvent
|
||||
});
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const options = opt_options || {};
|
||||
super(/** @type {import("./Interaction.js").InteractionOptions} */ (options));
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -110,9 +108,9 @@ class MouseWheelZoom extends Interaction {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
* @type {?}
|
||||
*/
|
||||
this.timeoutId_ = undefined;
|
||||
this.timeoutId_;
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -128,9 +126,9 @@ class MouseWheelZoom extends Interaction {
|
||||
this.trackpadEventGap_ = 400;
|
||||
|
||||
/**
|
||||
* @type {number|undefined}
|
||||
* @type {?}
|
||||
*/
|
||||
this.trackpadTimeoutId_ = undefined;
|
||||
this.trackpadTimeoutId_;
|
||||
|
||||
/**
|
||||
* The number of delta values per zoom level
|
||||
@@ -157,6 +155,127 @@ class MouseWheelZoom extends Interaction {
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the {@link module:ol/MapBrowserEvent map browser event} (if it was a mousewheel-event) and eventually
|
||||
* zooms the map.
|
||||
* @override
|
||||
*/
|
||||
handleEvent(mapBrowserEvent) {
|
||||
if (!this.condition_(mapBrowserEvent)) {
|
||||
return true;
|
||||
}
|
||||
const type = mapBrowserEvent.type;
|
||||
if (type !== EventType.WHEEL && type !== EventType.MOUSEWHEEL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mapBrowserEvent.preventDefault();
|
||||
|
||||
const map = mapBrowserEvent.map;
|
||||
const wheelEvent = /** @type {WheelEvent} */ (mapBrowserEvent.originalEvent);
|
||||
|
||||
if (this.useAnchor_) {
|
||||
this.lastAnchor_ = mapBrowserEvent.coordinate;
|
||||
}
|
||||
|
||||
// Delta normalisation inspired by
|
||||
// https://github.com/mapbox/mapbox-gl-js/blob/001c7b9/js/ui/handler/scroll_zoom.js
|
||||
let delta;
|
||||
if (mapBrowserEvent.type == EventType.WHEEL) {
|
||||
delta = wheelEvent.deltaY;
|
||||
if (FIREFOX &&
|
||||
wheelEvent.deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
|
||||
delta /= DEVICE_PIXEL_RATIO;
|
||||
}
|
||||
if (wheelEvent.deltaMode === WheelEvent.DOM_DELTA_LINE) {
|
||||
delta *= 40;
|
||||
}
|
||||
} else if (mapBrowserEvent.type == EventType.MOUSEWHEEL) {
|
||||
delta = -wheelEvent.wheelDeltaY;
|
||||
if (SAFARI) {
|
||||
delta /= 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (delta === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
if (this.startTime_ === undefined) {
|
||||
this.startTime_ = now;
|
||||
}
|
||||
|
||||
if (!this.mode_ || now - this.startTime_ > this.trackpadEventGap_) {
|
||||
this.mode_ = Math.abs(delta) < 4 ?
|
||||
Mode.TRACKPAD :
|
||||
Mode.WHEEL;
|
||||
}
|
||||
|
||||
if (this.mode_ === Mode.TRACKPAD) {
|
||||
const view = map.getView();
|
||||
if (this.trackpadTimeoutId_) {
|
||||
clearTimeout(this.trackpadTimeoutId_);
|
||||
} else {
|
||||
view.setHint(ViewHint.INTERACTING, 1);
|
||||
}
|
||||
this.trackpadTimeoutId_ = setTimeout(this.decrementInteractingHint_.bind(this), this.trackpadEventGap_);
|
||||
let resolution = view.getResolution() * Math.pow(2, delta / this.trackpadDeltaPerZoom_);
|
||||
const minResolution = view.getMinResolution();
|
||||
const maxResolution = view.getMaxResolution();
|
||||
let rebound = 0;
|
||||
if (resolution < minResolution) {
|
||||
resolution = Math.max(resolution, minResolution / this.trackpadZoomBuffer_);
|
||||
rebound = 1;
|
||||
} else if (resolution > maxResolution) {
|
||||
resolution = Math.min(resolution, maxResolution * this.trackpadZoomBuffer_);
|
||||
rebound = -1;
|
||||
}
|
||||
if (this.lastAnchor_) {
|
||||
const center = view.calculateCenterZoom(resolution, this.lastAnchor_);
|
||||
view.setCenter(view.constrainCenter(center));
|
||||
}
|
||||
view.setResolution(resolution);
|
||||
|
||||
if (rebound === 0 && this.constrainResolution_) {
|
||||
view.animate({
|
||||
resolution: view.constrainResolution(resolution, delta > 0 ? -1 : 1),
|
||||
easing: easeOut,
|
||||
anchor: this.lastAnchor_,
|
||||
duration: this.duration_
|
||||
});
|
||||
}
|
||||
|
||||
if (rebound > 0) {
|
||||
view.animate({
|
||||
resolution: minResolution,
|
||||
easing: easeOut,
|
||||
anchor: this.lastAnchor_,
|
||||
duration: 500
|
||||
});
|
||||
} else if (rebound < 0) {
|
||||
view.animate({
|
||||
resolution: maxResolution,
|
||||
easing: easeOut,
|
||||
anchor: this.lastAnchor_,
|
||||
duration: 500
|
||||
});
|
||||
}
|
||||
this.startTime_ = now;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.delta_ += delta;
|
||||
|
||||
const timeLeft = Math.max(this.timeout_ - (now - this.startTime_), 0);
|
||||
|
||||
clearTimeout(this.timeoutId_);
|
||||
this.timeoutId_ = setTimeout(this.handleWheelZoom_.bind(this, map), timeLeft);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {import("../PluggableMap.js").default} map Map.
|
||||
@@ -190,129 +309,4 @@ class MouseWheelZoom extends Interaction {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles the {@link module:ol/MapBrowserEvent map browser event} (if it was a
|
||||
* mousewheel-event) and eventually zooms the map.
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} Allow event propagation.
|
||||
* @this {MouseWheelZoom}
|
||||
*/
|
||||
function handleEvent(mapBrowserEvent) {
|
||||
if (!this.condition_(mapBrowserEvent)) {
|
||||
return true;
|
||||
}
|
||||
const type = mapBrowserEvent.type;
|
||||
if (type !== EventType.WHEEL && type !== EventType.MOUSEWHEEL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mapBrowserEvent.preventDefault();
|
||||
|
||||
const map = mapBrowserEvent.map;
|
||||
const wheelEvent = /** @type {WheelEvent} */ (mapBrowserEvent.originalEvent);
|
||||
|
||||
if (this.useAnchor_) {
|
||||
this.lastAnchor_ = mapBrowserEvent.coordinate;
|
||||
}
|
||||
|
||||
// Delta normalisation inspired by
|
||||
// https://github.com/mapbox/mapbox-gl-js/blob/001c7b9/js/ui/handler/scroll_zoom.js
|
||||
let delta;
|
||||
if (mapBrowserEvent.type == EventType.WHEEL) {
|
||||
delta = wheelEvent.deltaY;
|
||||
if (FIREFOX &&
|
||||
wheelEvent.deltaMode === WheelEvent.DOM_DELTA_PIXEL) {
|
||||
delta /= DEVICE_PIXEL_RATIO;
|
||||
}
|
||||
if (wheelEvent.deltaMode === WheelEvent.DOM_DELTA_LINE) {
|
||||
delta *= 40;
|
||||
}
|
||||
} else if (mapBrowserEvent.type == EventType.MOUSEWHEEL) {
|
||||
delta = -wheelEvent.wheelDeltaY;
|
||||
if (SAFARI) {
|
||||
delta /= 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (delta === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
if (this.startTime_ === undefined) {
|
||||
this.startTime_ = now;
|
||||
}
|
||||
|
||||
if (!this.mode_ || now - this.startTime_ > this.trackpadEventGap_) {
|
||||
this.mode_ = Math.abs(delta) < 4 ?
|
||||
Mode.TRACKPAD :
|
||||
Mode.WHEEL;
|
||||
}
|
||||
|
||||
if (this.mode_ === Mode.TRACKPAD) {
|
||||
const view = map.getView();
|
||||
if (this.trackpadTimeoutId_) {
|
||||
clearTimeout(this.trackpadTimeoutId_);
|
||||
} else {
|
||||
view.setHint(ViewHint.INTERACTING, 1);
|
||||
}
|
||||
this.trackpadTimeoutId_ = setTimeout(this.decrementInteractingHint_.bind(this), this.trackpadEventGap_);
|
||||
let resolution = view.getResolution() * Math.pow(2, delta / this.trackpadDeltaPerZoom_);
|
||||
const minResolution = view.getMinResolution();
|
||||
const maxResolution = view.getMaxResolution();
|
||||
let rebound = 0;
|
||||
if (resolution < minResolution) {
|
||||
resolution = Math.max(resolution, minResolution / this.trackpadZoomBuffer_);
|
||||
rebound = 1;
|
||||
} else if (resolution > maxResolution) {
|
||||
resolution = Math.min(resolution, maxResolution * this.trackpadZoomBuffer_);
|
||||
rebound = -1;
|
||||
}
|
||||
if (this.lastAnchor_) {
|
||||
const center = view.calculateCenterZoom(resolution, this.lastAnchor_);
|
||||
view.setCenter(view.constrainCenter(center));
|
||||
}
|
||||
view.setResolution(resolution);
|
||||
|
||||
if (rebound === 0 && this.constrainResolution_) {
|
||||
view.animate({
|
||||
resolution: view.constrainResolution(resolution, delta > 0 ? -1 : 1),
|
||||
easing: easeOut,
|
||||
anchor: this.lastAnchor_,
|
||||
duration: this.duration_
|
||||
});
|
||||
}
|
||||
|
||||
if (rebound > 0) {
|
||||
view.animate({
|
||||
resolution: minResolution,
|
||||
easing: easeOut,
|
||||
anchor: this.lastAnchor_,
|
||||
duration: 500
|
||||
});
|
||||
} else if (rebound < 0) {
|
||||
view.animate({
|
||||
resolution: maxResolution,
|
||||
easing: easeOut,
|
||||
anchor: this.lastAnchor_,
|
||||
duration: 500
|
||||
});
|
||||
}
|
||||
this.startTime_ = now;
|
||||
return false;
|
||||
}
|
||||
|
||||
this.delta_ += delta;
|
||||
|
||||
const timeLeft = Math.max(this.timeout_ - (now - this.startTime_), 0);
|
||||
|
||||
clearTimeout(this.timeoutId_);
|
||||
this.timeoutId_ = setTimeout(this.handleWheelZoom_.bind(this, map), timeLeft);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
export default MouseWheelZoom;
|
||||
|
||||
@@ -28,14 +28,15 @@ class PinchRotate extends PointerInteraction {
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
|
||||
super({
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleDragEvent: handleDragEvent,
|
||||
handleUpEvent: handleUpEvent,
|
||||
stopDown: FALSE
|
||||
});
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const options = opt_options || {};
|
||||
const pointerOptions = /** @type {import("./Pointer.js").Options} */ (options);
|
||||
|
||||
if (!pointerOptions.stopDown) {
|
||||
pointerOptions.stopDown = FALSE;
|
||||
}
|
||||
|
||||
super(pointerOptions);
|
||||
|
||||
/**
|
||||
* @private
|
||||
@@ -75,98 +76,89 @@ class PinchRotate extends PointerInteraction {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDragEvent(mapBrowserEvent) {
|
||||
let rotationDelta = 0.0;
|
||||
|
||||
const touch0 = this.targetPointers[0];
|
||||
const touch1 = this.targetPointers[1];
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @this {PinchRotate}
|
||||
*/
|
||||
function handleDragEvent(mapBrowserEvent) {
|
||||
let rotationDelta = 0.0;
|
||||
// angle between touches
|
||||
const angle = Math.atan2(
|
||||
touch1.clientY - touch0.clientY,
|
||||
touch1.clientX - touch0.clientX);
|
||||
|
||||
const touch0 = this.targetPointers[0];
|
||||
const touch1 = this.targetPointers[1];
|
||||
|
||||
// angle between touches
|
||||
const angle = Math.atan2(
|
||||
touch1.clientY - touch0.clientY,
|
||||
touch1.clientX - touch0.clientX);
|
||||
|
||||
if (this.lastAngle_ !== undefined) {
|
||||
const delta = angle - this.lastAngle_;
|
||||
this.rotationDelta_ += delta;
|
||||
if (!this.rotating_ &&
|
||||
Math.abs(this.rotationDelta_) > this.threshold_) {
|
||||
this.rotating_ = true;
|
||||
if (this.lastAngle_ !== undefined) {
|
||||
const delta = angle - this.lastAngle_;
|
||||
this.rotationDelta_ += delta;
|
||||
if (!this.rotating_ &&
|
||||
Math.abs(this.rotationDelta_) > this.threshold_) {
|
||||
this.rotating_ = true;
|
||||
}
|
||||
rotationDelta = delta;
|
||||
}
|
||||
rotationDelta = delta;
|
||||
}
|
||||
this.lastAngle_ = angle;
|
||||
this.lastAngle_ = angle;
|
||||
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
if (view.getConstraints().rotation === disable) {
|
||||
return;
|
||||
}
|
||||
|
||||
// rotate anchor point.
|
||||
// FIXME: should be the intersection point between the lines:
|
||||
// touch0,touch1 and previousTouch0,previousTouch1
|
||||
const viewportPosition = map.getViewport().getBoundingClientRect();
|
||||
const centroid = centroidFromPointers(this.targetPointers);
|
||||
centroid[0] -= viewportPosition.left;
|
||||
centroid[1] -= viewportPosition.top;
|
||||
this.anchor_ = map.getCoordinateFromPixel(centroid);
|
||||
|
||||
// rotate
|
||||
if (this.rotating_) {
|
||||
const rotation = view.getRotation();
|
||||
map.render();
|
||||
rotateWithoutConstraints(view, rotation + rotationDelta, this.anchor_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {PinchRotate}
|
||||
*/
|
||||
function handleUpEvent(mapBrowserEvent) {
|
||||
if (this.targetPointers.length < 2) {
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
if (view.getConstraints().rotation === disable) {
|
||||
return;
|
||||
}
|
||||
|
||||
// rotate anchor point.
|
||||
// FIXME: should be the intersection point between the lines:
|
||||
// touch0,touch1 and previousTouch0,previousTouch1
|
||||
const viewportPosition = map.getViewport().getBoundingClientRect();
|
||||
const centroid = centroidFromPointers(this.targetPointers);
|
||||
centroid[0] -= viewportPosition.left;
|
||||
centroid[1] -= viewportPosition.top;
|
||||
this.anchor_ = map.getCoordinateFromPixel(centroid);
|
||||
|
||||
// rotate
|
||||
if (this.rotating_) {
|
||||
const rotation = view.getRotation();
|
||||
rotate(view, rotation, this.anchor_, this.duration_);
|
||||
map.render();
|
||||
rotateWithoutConstraints(view, rotation + rotationDelta, this.anchor_);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Start drag sequence?
|
||||
* @this {PinchRotate}
|
||||
*/
|
||||
function handleDownEvent(mapBrowserEvent) {
|
||||
if (this.targetPointers.length >= 2) {
|
||||
const map = mapBrowserEvent.map;
|
||||
this.anchor_ = null;
|
||||
this.lastAngle_ = undefined;
|
||||
this.rotating_ = false;
|
||||
this.rotationDelta_ = 0.0;
|
||||
if (!this.handlingDownUpSequence) {
|
||||
map.getView().setHint(ViewHint.INTERACTING, 1);
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(mapBrowserEvent) {
|
||||
if (this.targetPointers.length < 2) {
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
if (this.rotating_) {
|
||||
const rotation = view.getRotation();
|
||||
rotate(view, rotation, this.anchor_, this.duration_);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDownEvent(mapBrowserEvent) {
|
||||
if (this.targetPointers.length >= 2) {
|
||||
const map = mapBrowserEvent.map;
|
||||
this.anchor_ = null;
|
||||
this.lastAngle_ = undefined;
|
||||
this.rotating_ = false;
|
||||
this.rotationDelta_ = 0.0;
|
||||
if (!this.handlingDownUpSequence) {
|
||||
map.getView().setHint(ViewHint.INTERACTING, 1);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,15 +27,16 @@ class PinchZoom extends PointerInteraction {
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
|
||||
super({
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleDragEvent: handleDragEvent,
|
||||
handleUpEvent: handleUpEvent,
|
||||
stopDown: FALSE
|
||||
});
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const pointerOptions = /** @type {import("./Pointer.js").Options} */ (options);
|
||||
|
||||
if (!pointerOptions.stopDown) {
|
||||
pointerOptions.stopDown = FALSE;
|
||||
}
|
||||
|
||||
super(pointerOptions);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
@@ -68,105 +69,96 @@ class PinchZoom extends PointerInteraction {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDragEvent(mapBrowserEvent) {
|
||||
let scaleDelta = 1.0;
|
||||
|
||||
const touch0 = this.targetPointers[0];
|
||||
const touch1 = this.targetPointers[1];
|
||||
const dx = touch0.clientX - touch1.clientX;
|
||||
const dy = touch0.clientY - touch1.clientY;
|
||||
|
||||
// distance between touches
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
if (this.lastDistance_ !== undefined) {
|
||||
scaleDelta = this.lastDistance_ / distance;
|
||||
}
|
||||
this.lastDistance_ = distance;
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @this {PinchZoom}
|
||||
*/
|
||||
function handleDragEvent(mapBrowserEvent) {
|
||||
let scaleDelta = 1.0;
|
||||
|
||||
const touch0 = this.targetPointers[0];
|
||||
const touch1 = this.targetPointers[1];
|
||||
const dx = touch0.clientX - touch1.clientX;
|
||||
const dy = touch0.clientY - touch1.clientY;
|
||||
|
||||
// distance between touches
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
if (this.lastDistance_ !== undefined) {
|
||||
scaleDelta = this.lastDistance_ / distance;
|
||||
}
|
||||
this.lastDistance_ = distance;
|
||||
|
||||
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
const resolution = view.getResolution();
|
||||
const maxResolution = view.getMaxResolution();
|
||||
const minResolution = view.getMinResolution();
|
||||
let newResolution = resolution * scaleDelta;
|
||||
if (newResolution > maxResolution) {
|
||||
scaleDelta = maxResolution / resolution;
|
||||
newResolution = maxResolution;
|
||||
} else if (newResolution < minResolution) {
|
||||
scaleDelta = minResolution / resolution;
|
||||
newResolution = minResolution;
|
||||
}
|
||||
|
||||
if (scaleDelta != 1.0) {
|
||||
this.lastScaleDelta_ = scaleDelta;
|
||||
}
|
||||
|
||||
// scale anchor point.
|
||||
const viewportPosition = map.getViewport().getBoundingClientRect();
|
||||
const centroid = centroidFromPointers(this.targetPointers);
|
||||
centroid[0] -= viewportPosition.left;
|
||||
centroid[1] -= viewportPosition.top;
|
||||
this.anchor_ = map.getCoordinateFromPixel(centroid);
|
||||
|
||||
// scale, bypass the resolution constraint
|
||||
map.render();
|
||||
zoomWithoutConstraints(view, newResolution, this.anchor_);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {PinchZoom}
|
||||
*/
|
||||
function handleUpEvent(mapBrowserEvent) {
|
||||
if (this.targetPointers.length < 2) {
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
const resolution = view.getResolution();
|
||||
if (this.constrainResolution_ ||
|
||||
resolution < view.getMinResolution() ||
|
||||
resolution > view.getMaxResolution()) {
|
||||
// Zoom to final resolution, with an animation, and provide a
|
||||
// direction not to zoom out/in if user was pinching in/out.
|
||||
// Direction is > 0 if pinching out, and < 0 if pinching in.
|
||||
const direction = this.lastScaleDelta_ - 1;
|
||||
zoom(view, resolution, this.anchor_, this.duration_, direction);
|
||||
const maxResolution = view.getMaxResolution();
|
||||
const minResolution = view.getMinResolution();
|
||||
let newResolution = resolution * scaleDelta;
|
||||
if (newResolution > maxResolution) {
|
||||
scaleDelta = maxResolution / resolution;
|
||||
newResolution = maxResolution;
|
||||
} else if (newResolution < minResolution) {
|
||||
scaleDelta = minResolution / resolution;
|
||||
newResolution = minResolution;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
|
||||
if (scaleDelta != 1.0) {
|
||||
this.lastScaleDelta_ = scaleDelta;
|
||||
}
|
||||
|
||||
// scale anchor point.
|
||||
const viewportPosition = map.getViewport().getBoundingClientRect();
|
||||
const centroid = centroidFromPointers(this.targetPointers);
|
||||
centroid[0] -= viewportPosition.left;
|
||||
centroid[1] -= viewportPosition.top;
|
||||
this.anchor_ = map.getCoordinateFromPixel(centroid);
|
||||
|
||||
// scale, bypass the resolution constraint
|
||||
map.render();
|
||||
zoomWithoutConstraints(view, newResolution, this.anchor_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Start drag sequence?
|
||||
* @this {PinchZoom}
|
||||
*/
|
||||
function handleDownEvent(mapBrowserEvent) {
|
||||
if (this.targetPointers.length >= 2) {
|
||||
const map = mapBrowserEvent.map;
|
||||
this.anchor_ = null;
|
||||
this.lastDistance_ = undefined;
|
||||
this.lastScaleDelta_ = 1;
|
||||
if (!this.handlingDownUpSequence) {
|
||||
map.getView().setHint(ViewHint.INTERACTING, 1);
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(mapBrowserEvent) {
|
||||
if (this.targetPointers.length < 2) {
|
||||
const map = mapBrowserEvent.map;
|
||||
const view = map.getView();
|
||||
view.setHint(ViewHint.INTERACTING, -1);
|
||||
const resolution = view.getResolution();
|
||||
if (this.constrainResolution_ ||
|
||||
resolution < view.getMinResolution() ||
|
||||
resolution > view.getMaxResolution()) {
|
||||
// Zoom to final resolution, with an animation, and provide a
|
||||
// direction not to zoom out/in if user was pinching in/out.
|
||||
// Direction is > 0 if pinching out, and < 0 if pinching in.
|
||||
const direction = this.lastScaleDelta_ - 1;
|
||||
zoom(view, resolution, this.anchor_, this.duration_, direction);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDownEvent(mapBrowserEvent) {
|
||||
if (this.targetPointers.length >= 2) {
|
||||
const map = mapBrowserEvent.map;
|
||||
this.anchor_ = null;
|
||||
this.lastDistance_ = undefined;
|
||||
this.lastScaleDelta_ = 1;
|
||||
if (!this.handlingDownUpSequence) {
|
||||
map.getView().setHint(ViewHint.INTERACTING, 1);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,49 +1,17 @@
|
||||
/**
|
||||
* @module ol/interaction/Pointer
|
||||
*/
|
||||
import {FALSE, VOID} from '../functions.js';
|
||||
import MapBrowserEventType from '../MapBrowserEventType.js';
|
||||
import MapBrowserPointerEvent from '../MapBrowserPointerEvent.js';
|
||||
import Interaction from '../interaction/Interaction.js';
|
||||
import {getValues} from '../obj.js';
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} mapBrowserEvent Event.
|
||||
* @this {PointerInteraction}
|
||||
*/
|
||||
const handleDragEvent = VOID;
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} mapBrowserEvent Event.
|
||||
* @return {boolean} Capture dragging.
|
||||
* @this {PointerInteraction}
|
||||
*/
|
||||
const handleUpEvent = FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} mapBrowserEvent Event.
|
||||
* @return {boolean} Capture dragging.
|
||||
* @this {PointerInteraction}
|
||||
*/
|
||||
const handleDownEvent = FALSE;
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} mapBrowserEvent Event.
|
||||
* @this {PointerInteraction}
|
||||
*/
|
||||
const handleMoveEvent = VOID;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {Object} Options
|
||||
* @property {function(MapBrowserPointerEvent):boolean} [handleDownEvent]
|
||||
* @property {function(import("../MapBrowserPointerEvent.js").default):boolean} [handleDownEvent]
|
||||
* Function handling "down" events. If the function returns `true` then a drag
|
||||
* sequence is started.
|
||||
* @property {function(MapBrowserPointerEvent)} [handleDragEvent]
|
||||
* @property {function(import("../MapBrowserPointerEvent.js").default)} [handleDragEvent]
|
||||
* Function handling "drag" events. This function is called on "move" events
|
||||
* during a drag sequence.
|
||||
* @property {function(import("../MapBrowserEvent.js").default):boolean} [handleEvent]
|
||||
@@ -51,14 +19,14 @@ const handleMoveEvent = VOID;
|
||||
* dispatched to the map. The function may return `false` to prevent the
|
||||
* propagation of the event to other interactions in the map's interactions
|
||||
* chain.
|
||||
* @property {function(MapBrowserPointerEvent)} [handleMoveEvent]
|
||||
* @property {function(import("../MapBrowserPointerEvent.js").default)} [handleMoveEvent]
|
||||
* Function handling "move" events. This function is called on "move" events,
|
||||
* also during a drag sequence (so during a drag sequence both the
|
||||
* `handleDragEvent` function and this function are called).
|
||||
* @property {function(MapBrowserPointerEvent):boolean} [handleUpEvent]
|
||||
* @property {function(import("../MapBrowserPointerEvent.js").default):boolean} [handleUpEvent]
|
||||
* Function handling "up" events. If the function returns `false` then the
|
||||
* current drag sequence is stopped.
|
||||
* @property {function(boolean):boolean} stopDown
|
||||
* @property {function(boolean):boolean} [stopDown]
|
||||
* Should the down event be propagated to other interactions, or should be
|
||||
* stopped?
|
||||
*/
|
||||
@@ -83,37 +51,27 @@ class PointerInteraction extends Interaction {
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super({
|
||||
handleEvent: options.handleEvent || handleEvent
|
||||
});
|
||||
super(/** @type {import("./Interaction.js").InteractionOptions} */ (options));
|
||||
|
||||
/**
|
||||
* @type {function(MapBrowserPointerEvent):boolean}
|
||||
* @private
|
||||
*/
|
||||
this.handleDownEvent_ = options.handleDownEvent ?
|
||||
options.handleDownEvent : handleDownEvent;
|
||||
if (options.handleDownEvent) {
|
||||
this.handleDownEvent = options.handleDownEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {function(MapBrowserPointerEvent)}
|
||||
* @private
|
||||
*/
|
||||
this.handleDragEvent_ = options.handleDragEvent ?
|
||||
options.handleDragEvent : handleDragEvent;
|
||||
if (options.handleDragEvent) {
|
||||
this.handleDragEvent = options.handleDragEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {function(MapBrowserPointerEvent)}
|
||||
* @private
|
||||
*/
|
||||
this.handleMoveEvent_ = options.handleMoveEvent ?
|
||||
options.handleMoveEvent : handleMoveEvent;
|
||||
if (options.handleMoveEvent) {
|
||||
this.handleMoveEvent = options.handleMoveEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {function(MapBrowserPointerEvent):boolean}
|
||||
* @private
|
||||
*/
|
||||
this.handleUpEvent_ = options.handleUpEvent ?
|
||||
options.handleUpEvent : handleUpEvent;
|
||||
if (options.handleUpEvent) {
|
||||
this.handleUpEvent = options.handleUpEvent;
|
||||
}
|
||||
|
||||
if (options.stopDown) {
|
||||
this.stopDown = options.stopDown;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
@@ -121,14 +79,6 @@ class PointerInteraction extends Interaction {
|
||||
*/
|
||||
this.handlingDownUpSequence = false;
|
||||
|
||||
/**
|
||||
* This function is used to determine if "down" events should be propagated
|
||||
* to other interactions or should be stopped.
|
||||
* @type {function(boolean):boolean}
|
||||
* @protected
|
||||
*/
|
||||
this.stopDown = options.stopDown ? options.stopDown : stopDown;
|
||||
|
||||
/**
|
||||
* @type {!Object<string, import("../pointer/PointerEvent.js").default>}
|
||||
* @private
|
||||
@@ -144,7 +94,87 @@ class PointerInteraction extends Interaction {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} mapBrowserEvent Event.
|
||||
* Handle pointer down events.
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} If the event was consumed.
|
||||
* @protected
|
||||
*/
|
||||
handleDownEvent(mapBrowserEvent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle pointer drag events.
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @protected
|
||||
*/
|
||||
handleDragEvent(mapBrowserEvent) {}
|
||||
|
||||
/**
|
||||
* Handles the {@link module:ol/MapBrowserEvent map browser event} and may call into
|
||||
* other functions, if event sequences like e.g. 'drag' or 'down-up' etc. are
|
||||
* detected.
|
||||
* @override
|
||||
* @api
|
||||
*/
|
||||
handleEvent(mapBrowserEvent) {
|
||||
if (!(/** @type {import("../MapBrowserPointerEvent.js").default} */ (mapBrowserEvent).pointerEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let stopEvent = false;
|
||||
this.updateTrackedPointers_(mapBrowserEvent);
|
||||
if (this.handlingDownUpSequence) {
|
||||
if (mapBrowserEvent.type == MapBrowserEventType.POINTERDRAG) {
|
||||
this.handleDragEvent(mapBrowserEvent);
|
||||
} else if (mapBrowserEvent.type == MapBrowserEventType.POINTERUP) {
|
||||
const handledUp = this.handleUpEvent(mapBrowserEvent);
|
||||
this.handlingDownUpSequence = handledUp && this.targetPointers.length > 0;
|
||||
}
|
||||
} else {
|
||||
if (mapBrowserEvent.type == MapBrowserEventType.POINTERDOWN) {
|
||||
const handled = this.handleDownEvent(mapBrowserEvent);
|
||||
if (handled) {
|
||||
mapBrowserEvent.preventDefault();
|
||||
}
|
||||
this.handlingDownUpSequence = handled;
|
||||
stopEvent = this.stopDown(handled);
|
||||
} else if (mapBrowserEvent.type == MapBrowserEventType.POINTERMOVE) {
|
||||
this.handleMoveEvent(mapBrowserEvent);
|
||||
}
|
||||
}
|
||||
return !stopEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle pointer move events.
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @protected
|
||||
*/
|
||||
handleMoveEvent(mapBrowserEvent) {}
|
||||
|
||||
/**
|
||||
* Handle pointer up events.
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} If the event was consumed.
|
||||
* @protected
|
||||
*/
|
||||
handleUpEvent(mapBrowserEvent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to determine if "down" events should be propagated
|
||||
* to other interactions or should be stopped.
|
||||
* @param {boolean} handled Was the event handled by the interaction?
|
||||
* @return {boolean} Should the `down` event be stopped?
|
||||
*/
|
||||
stopDown(handled) {
|
||||
return handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @private
|
||||
*/
|
||||
updateTrackedPointers_(mapBrowserEvent) {
|
||||
@@ -185,7 +215,7 @@ export function centroid(pointerEvents) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {MapBrowserPointerEvent} mapBrowserEvent Event.
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} mapBrowserEvent Event.
|
||||
* @return {boolean} Whether the event is a pointerdown, pointerdrag
|
||||
* or pointerup event.
|
||||
*/
|
||||
@@ -197,51 +227,4 @@ function isPointerDraggingEvent(mapBrowserEvent) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles the {@link module:ol/MapBrowserEvent map browser event} and may call into
|
||||
* other functions, if event sequences like e.g. 'drag' or 'down-up' etc. are
|
||||
* detected.
|
||||
* @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event.
|
||||
* @return {boolean} `false` to stop event propagation.
|
||||
* @this {PointerInteraction}
|
||||
* @api
|
||||
*/
|
||||
export function handleEvent(mapBrowserEvent) {
|
||||
if (!(mapBrowserEvent instanceof MapBrowserPointerEvent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let stopEvent = false;
|
||||
this.updateTrackedPointers_(mapBrowserEvent);
|
||||
if (this.handlingDownUpSequence) {
|
||||
if (mapBrowserEvent.type == MapBrowserEventType.POINTERDRAG) {
|
||||
this.handleDragEvent_(mapBrowserEvent);
|
||||
} else if (mapBrowserEvent.type == MapBrowserEventType.POINTERUP) {
|
||||
const handledUp = this.handleUpEvent_(mapBrowserEvent);
|
||||
this.handlingDownUpSequence = handledUp && this.targetPointers.length > 0;
|
||||
}
|
||||
} else {
|
||||
if (mapBrowserEvent.type == MapBrowserEventType.POINTERDOWN) {
|
||||
const handled = this.handleDownEvent_(mapBrowserEvent);
|
||||
if (handled) {
|
||||
mapBrowserEvent.preventDefault();
|
||||
}
|
||||
this.handlingDownUpSequence = handled;
|
||||
stopEvent = this.stopDown(handled);
|
||||
} else if (mapBrowserEvent.type == MapBrowserEventType.POINTERMOVE) {
|
||||
this.handleMoveEvent_(mapBrowserEvent);
|
||||
}
|
||||
}
|
||||
return !stopEvent;
|
||||
}
|
||||
|
||||
|
||||
export default PointerInteraction;
|
||||
|
||||
/**
|
||||
* @param {boolean} handled Was the event handled by the interaction?
|
||||
* @return {boolean} Should the `down` event be stopped?
|
||||
*/
|
||||
function stopDown(handled) {
|
||||
return handled;
|
||||
}
|
||||
|
||||
@@ -34,8 +34,7 @@ const SelectEventType = {
|
||||
* {@link module:ol/render/Feature} and an
|
||||
* {@link module:ol/layer/Layer} and returns `true` if the feature may be
|
||||
* selected or `false` otherwise.
|
||||
* @typedef {function((import("../Feature.js").default|import("../render/Feature.js").default), import("../layer/Layer.js").default):
|
||||
* boolean} FilterFunction
|
||||
* @typedef {function(import("../Feature.js").FeatureLike, import("../layer/Layer.js").default):boolean} FilterFunction
|
||||
*/
|
||||
|
||||
|
||||
@@ -61,7 +60,7 @@ const SelectEventType = {
|
||||
* in the map and should return `true` for layers that you want to be
|
||||
* selectable. If the option is absent, all visible layers will be considered
|
||||
* selectable.
|
||||
* @property {import("../style/Style.js").default|Array<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction} [style]
|
||||
* @property {import("../style/Style.js").StyleLike} [style]
|
||||
* Style for the selected features. By default the default edit style is used
|
||||
* (see {@link module:ol/style}).
|
||||
* @property {import("../events/condition.js").Condition} [removeCondition] A function
|
||||
@@ -251,11 +250,11 @@ class Select extends Interaction {
|
||||
* An association between selected feature (key)
|
||||
* and layer (value)
|
||||
* @private
|
||||
* @type {Object<number, import("../layer/Layer.js").default>}
|
||||
* @type {Object<string, import("../layer/Layer.js").default>}
|
||||
*/
|
||||
this.featureLayerAssociation_ = {};
|
||||
|
||||
const features = this.featureOverlay_.getSource().getFeaturesCollection();
|
||||
const features = this.getFeatures();
|
||||
listen(features, CollectionEventType.ADD,
|
||||
this.addFeature_, this);
|
||||
listen(features, CollectionEventType.REMOVE,
|
||||
@@ -263,13 +262,12 @@ class Select extends Interaction {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../Feature.js").default|import("../render/Feature.js").default} feature Feature.
|
||||
* @param {import("../Feature.js").FeatureLike} feature Feature.
|
||||
* @param {import("../layer/Layer.js").default} layer Layer.
|
||||
* @private
|
||||
*/
|
||||
addFeatureLayerAssociation_(feature, layer) {
|
||||
const key = getUid(feature);
|
||||
this.featureLayerAssociation_[key] = layer;
|
||||
this.featureLayerAssociation_[getUid(feature)] = layer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -278,7 +276,7 @@ class Select extends Interaction {
|
||||
* @api
|
||||
*/
|
||||
getFeatures() {
|
||||
return this.featureOverlay_.getSource().getFeaturesCollection();
|
||||
return /** @type {VectorSource} */ (this.featureOverlay_.getSource()).getFeaturesCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,14 +293,13 @@ class Select extends Interaction {
|
||||
* the (last) selected feature. Note that this will not work with any
|
||||
* programmatic method like pushing features to
|
||||
* {@link module:ol/interaction/Select~Select#getFeatures collection}.
|
||||
* @param {import("../Feature.js").default|import("../render/Feature.js").default} feature Feature
|
||||
* @param {import("../Feature.js").FeatureLike} feature Feature
|
||||
* @return {VectorLayer} Layer.
|
||||
* @api
|
||||
*/
|
||||
getLayer(feature) {
|
||||
const key = getUid(feature);
|
||||
return (
|
||||
/** @type {VectorLayer} */ (this.featureLayerAssociation_[key])
|
||||
/** @type {VectorLayer} */ (this.featureLayerAssociation_[getUid(feature)])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -335,8 +332,7 @@ class Select extends Interaction {
|
||||
*/
|
||||
setMap(map) {
|
||||
const currentMap = this.getMap();
|
||||
const selectedFeatures =
|
||||
this.featureOverlay_.getSource().getFeaturesCollection();
|
||||
const selectedFeatures = this.getFeatures();
|
||||
if (currentMap) {
|
||||
selectedFeatures.forEach(currentMap.unskipFeature.bind(currentMap));
|
||||
}
|
||||
@@ -370,12 +366,11 @@ class Select extends Interaction {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../Feature.js").default|import("../render/Feature.js").default} feature Feature.
|
||||
* @param {import("../Feature.js").FeatureLike} feature Feature.
|
||||
* @private
|
||||
*/
|
||||
removeFeatureLayerAssociation_(feature) {
|
||||
const key = getUid(feature);
|
||||
delete this.featureLayerAssociation_[key];
|
||||
delete this.featureLayerAssociation_[getUid(feature)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +391,7 @@ function handleEvent(mapBrowserEvent) {
|
||||
const toggle = this.toggleCondition_(mapBrowserEvent);
|
||||
const set = !add && !remove && !toggle;
|
||||
const map = mapBrowserEvent.map;
|
||||
const features = this.featureOverlay_.getSource().getFeaturesCollection();
|
||||
const features = this.getFeatures();
|
||||
const deselected = [];
|
||||
const selected = [];
|
||||
if (set) {
|
||||
@@ -407,7 +402,7 @@ function handleEvent(mapBrowserEvent) {
|
||||
map.forEachFeatureAtPixel(mapBrowserEvent.pixel,
|
||||
(
|
||||
/**
|
||||
* @param {import("../Feature.js").default|import("../render/Feature.js").default} feature Feature.
|
||||
* @param {import("../Feature.js").FeatureLike} feature Feature.
|
||||
* @param {import("../layer/Layer.js").default} layer Layer.
|
||||
* @return {boolean|undefined} Continue to iterate over the features.
|
||||
*/
|
||||
@@ -440,7 +435,7 @@ function handleEvent(mapBrowserEvent) {
|
||||
map.forEachFeatureAtPixel(mapBrowserEvent.pixel,
|
||||
(
|
||||
/**
|
||||
* @param {import("../Feature.js").default|import("../render/Feature.js").default} feature Feature.
|
||||
* @param {import("../Feature.js").FeatureLike} feature Feature.
|
||||
* @param {import("../layer/Layer.js").default} layer Layer.
|
||||
* @return {boolean|undefined} Continue to iterate over the features.
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
* @module ol/interaction/Snap
|
||||
*/
|
||||
import {getUid} from '../util.js';
|
||||
import {CollectionEvent} from '../Collection.js';
|
||||
import CollectionEventType from '../CollectionEventType.js';
|
||||
import {distance as coordinateDistance, squaredDistance as squaredCoordinateDistance, closestOnCircle, closestOnSegment, squaredDistanceToSegment} from '../coordinate.js';
|
||||
import {listen, unlistenByKey} from '../events.js';
|
||||
@@ -11,9 +10,8 @@ import {boundingExtent, createEmpty} from '../extent.js';
|
||||
import {TRUE, FALSE} from '../functions.js';
|
||||
import GeometryType from '../geom/GeometryType.js';
|
||||
import {fromCircle} from '../geom/Polygon.js';
|
||||
import PointerInteraction, {handleEvent as handlePointerEvent} from '../interaction/Pointer.js';
|
||||
import PointerInteraction from '../interaction/Pointer.js';
|
||||
import {getValues} from '../obj.js';
|
||||
import {VectorSourceEvent} from '../source/Vector.js';
|
||||
import VectorEventType from '../source/VectorEventType.js';
|
||||
import RBush from '../structs/RBush.js';
|
||||
|
||||
@@ -44,6 +42,19 @@ import RBush from '../structs/RBush.js';
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../source/Vector.js").VectorSourceEvent|import("../Collection.js").CollectionEvent} evt Event.
|
||||
* @return {import("../Feature.js").default} Feature.
|
||||
*/
|
||||
function getFeatureFromEvent(evt) {
|
||||
if (/** @type {import("../source/Vector.js").VectorSourceEvent} */ (evt).feature) {
|
||||
return /** @type {import("../source/Vector.js").VectorSourceEvent} */ (evt).feature;
|
||||
} else if (/** @type {import("../Collection.js").CollectionEvent} */ (evt).element) {
|
||||
return /** @type {import("../Feature.js").default} */ (/** @type {import("../Collection.js").CollectionEvent} */ (evt).element);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* Handles snapping of vector features while modifying or drawing them. The
|
||||
@@ -71,15 +82,20 @@ class Snap extends PointerInteraction {
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
|
||||
super({
|
||||
handleEvent: handleEvent,
|
||||
handleDownEvent: TRUE,
|
||||
handleUpEvent: handleUpEvent,
|
||||
stopDown: FALSE
|
||||
});
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
const pointerOptions = /** @type {import("./Pointer.js").Options} */ (options);
|
||||
|
||||
if (!pointerOptions.handleDownEvent) {
|
||||
pointerOptions.handleDownEvent = TRUE;
|
||||
}
|
||||
|
||||
if (!pointerOptions.stopDown) {
|
||||
pointerOptions.stopDown = FALSE;
|
||||
}
|
||||
|
||||
super(pointerOptions);
|
||||
|
||||
/**
|
||||
* @type {import("../source/Vector.js").default}
|
||||
* @private
|
||||
@@ -111,7 +127,7 @@ class Snap extends PointerInteraction {
|
||||
this.featuresListenerKeys_ = [];
|
||||
|
||||
/**
|
||||
* @type {Object<number, import("../events.js").EventsKey>}
|
||||
* @type {Object<string, import("../events.js").EventsKey>}
|
||||
* @private
|
||||
*/
|
||||
this.featureChangeListenerKeys_ = {};
|
||||
@@ -119,7 +135,7 @@ class Snap extends PointerInteraction {
|
||||
/**
|
||||
* Extents are preserved so indexed segment can be quickly removed
|
||||
* when its feature geometry changes
|
||||
* @type {Object<number, import("../extent.js").Extent>}
|
||||
* @type {Object<string, import("../extent.js").Extent>}
|
||||
* @private
|
||||
*/
|
||||
this.indexedFeaturesExtents_ = {};
|
||||
@@ -128,7 +144,7 @@ class Snap extends PointerInteraction {
|
||||
* If a feature geometry changes while a pointer drag|move event occurs, the
|
||||
* feature doesn't get updated right away. It will be at the next 'pointerup'
|
||||
* event fired.
|
||||
* @type {!Object<number, import("../Feature.js").default>}
|
||||
* @type {!Object<string, import("../Feature.js").default>}
|
||||
* @private
|
||||
*/
|
||||
this.pendingFeatures_ = {};
|
||||
@@ -234,37 +250,37 @@ class Snap extends PointerInteraction {
|
||||
} else if (this.source_) {
|
||||
features = this.source_.getFeatures();
|
||||
}
|
||||
return (
|
||||
/** @type {!Array<import("../Feature.js").default>|!import("../Collection.js").default<import("../Feature.js").default>} */ (features)
|
||||
);
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../source/Vector.js").default|import("../Collection.js").CollectionEvent} evt Event.
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleEvent(evt) {
|
||||
const result = this.snapTo(evt.pixel, evt.coordinate, evt.map);
|
||||
if (result.snapped) {
|
||||
evt.coordinate = result.vertex.slice(0, 2);
|
||||
evt.pixel = result.vertexPixel;
|
||||
}
|
||||
return super.handleEvent(evt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../source/Vector.js").VectorSourceEvent|import("../Collection.js").CollectionEvent} evt Event.
|
||||
* @private
|
||||
*/
|
||||
handleFeatureAdd_(evt) {
|
||||
let feature;
|
||||
if (evt instanceof VectorSourceEvent) {
|
||||
feature = evt.feature;
|
||||
} else if (evt instanceof CollectionEvent) {
|
||||
feature = evt.element;
|
||||
}
|
||||
this.addFeature(/** @type {import("../Feature.js").default} */ (feature));
|
||||
const feature = getFeatureFromEvent(evt);
|
||||
this.addFeature(feature);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../source/Vector.js").default|import("../Collection.js").CollectionEvent} evt Event.
|
||||
* @param {import("../source/Vector.js").VectorSourceEvent|import("../Collection.js").CollectionEvent} evt Event.
|
||||
* @private
|
||||
*/
|
||||
handleFeatureRemove_(evt) {
|
||||
let feature;
|
||||
if (evt instanceof VectorSourceEvent) {
|
||||
feature = evt.feature;
|
||||
} else if (evt instanceof CollectionEvent) {
|
||||
feature = evt.element;
|
||||
}
|
||||
this.removeFeature(/** @type {import("../Feature.js").default} */ (feature));
|
||||
const feature = getFeatureFromEvent(evt);
|
||||
this.removeFeature(feature);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,6 +299,18 @@ class Snap extends PointerInteraction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(evt) {
|
||||
const featuresToUpdate = getValues(this.pendingFeatures_);
|
||||
if (featuresToUpdate.length) {
|
||||
featuresToUpdate.forEach(this.updateFeature_.bind(this));
|
||||
this.pendingFeatures_ = {};
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a feature from the collection of features that we may snap to.
|
||||
* @param {import("../Feature.js").default} feature Feature
|
||||
@@ -319,7 +347,7 @@ class Snap extends PointerInteraction {
|
||||
setMap(map) {
|
||||
const currentMap = this.getMap();
|
||||
const keys = this.featuresListenerKeys_;
|
||||
const features = this.getFeatures_();
|
||||
const features = /** @type {Array<import("../Feature.js").default>} */ (this.getFeatures_());
|
||||
|
||||
if (currentMap) {
|
||||
keys.forEach(unlistenByKey);
|
||||
@@ -587,37 +615,6 @@ class Snap extends PointerInteraction {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle all pointer events events.
|
||||
* @param {import("../MapBrowserEvent.js").default} evt A move event.
|
||||
* @return {boolean} Pass the event to other interactions.
|
||||
* @this {Snap}
|
||||
*/
|
||||
export function handleEvent(evt) {
|
||||
const result = this.snapTo(evt.pixel, evt.coordinate, evt.map);
|
||||
if (result.snapped) {
|
||||
evt.coordinate = result.vertex.slice(0, 2);
|
||||
evt.pixel = result.vertexPixel;
|
||||
}
|
||||
return handlePointerEvent.call(this, evt);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} evt Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {Snap}
|
||||
*/
|
||||
function handleUpEvent(evt) {
|
||||
const featuresToUpdate = getValues(this.pendingFeatures_);
|
||||
if (featuresToUpdate.length) {
|
||||
featuresToUpdate.forEach(this.updateFeature_.bind(this));
|
||||
this.pendingFeatures_ = {};
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sort segments by distance, helper function
|
||||
* @param {SegmentData} a The first segment data.
|
||||
|
||||
@@ -98,15 +98,10 @@ class Translate extends PointerInteraction {
|
||||
* @param {Options=} opt_options Options.
|
||||
*/
|
||||
constructor(opt_options) {
|
||||
super({
|
||||
handleDownEvent: handleDownEvent,
|
||||
handleDragEvent: handleDragEvent,
|
||||
handleMoveEvent: handleMoveEvent,
|
||||
handleUpEvent: handleUpEvent
|
||||
});
|
||||
|
||||
const options = opt_options ? opt_options : {};
|
||||
|
||||
super(/** @type {import("./Pointer.js").Options} */ (options));
|
||||
|
||||
/**
|
||||
* The last position we translated to.
|
||||
* @type {import("../coordinate.js").Coordinate}
|
||||
@@ -160,6 +155,86 @@ class Translate extends PointerInteraction {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDownEvent(event) {
|
||||
this.lastFeature_ = this.featuresAtPixel_(event.pixel, event.map);
|
||||
if (!this.lastCoordinate_ && this.lastFeature_) {
|
||||
this.lastCoordinate_ = event.coordinate;
|
||||
this.handleMoveEvent(event);
|
||||
|
||||
const features = this.features_ || new Collection([this.lastFeature_]);
|
||||
|
||||
this.dispatchEvent(
|
||||
new TranslateEvent(
|
||||
TranslateEventType.TRANSLATESTART, features,
|
||||
event.coordinate));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleUpEvent(event) {
|
||||
if (this.lastCoordinate_) {
|
||||
this.lastCoordinate_ = null;
|
||||
this.handleMoveEvent(event);
|
||||
|
||||
const features = this.features_ || new Collection([this.lastFeature_]);
|
||||
|
||||
this.dispatchEvent(
|
||||
new TranslateEvent(
|
||||
TranslateEventType.TRANSLATEEND, features,
|
||||
event.coordinate));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleDragEvent(event) {
|
||||
if (this.lastCoordinate_) {
|
||||
const newCoordinate = event.coordinate;
|
||||
const deltaX = newCoordinate[0] - this.lastCoordinate_[0];
|
||||
const deltaY = newCoordinate[1] - this.lastCoordinate_[1];
|
||||
|
||||
const features = this.features_ || new Collection([this.lastFeature_]);
|
||||
|
||||
features.forEach(function(feature) {
|
||||
const geom = feature.getGeometry();
|
||||
geom.translate(deltaX, deltaY);
|
||||
feature.setGeometry(geom);
|
||||
});
|
||||
|
||||
this.lastCoordinate_ = newCoordinate;
|
||||
this.dispatchEvent(
|
||||
new TranslateEvent(
|
||||
TranslateEventType.TRANSLATING, features,
|
||||
newCoordinate));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
handleMoveEvent(event) {
|
||||
const elem = event.map.getViewport();
|
||||
|
||||
// Change the cursor to grab/grabbing if hovering any of the features managed
|
||||
// by the interaction
|
||||
if (this.featuresAtPixel_(event.pixel, event.map)) {
|
||||
elem.classList.remove(this.lastCoordinate_ ? 'ol-grab' : 'ol-grabbing');
|
||||
elem.classList.add(this.lastCoordinate_ ? 'ol-grabbing' : 'ol-grab');
|
||||
} else {
|
||||
elem.classList.remove('ol-grab', 'ol-grabbing');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to see if the given coordinates intersects any of our selected
|
||||
* features.
|
||||
@@ -234,95 +309,4 @@ class Translate extends PointerInteraction {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} event Event.
|
||||
* @return {boolean} Start drag sequence?
|
||||
* @this {Translate}
|
||||
*/
|
||||
function handleDownEvent(event) {
|
||||
this.lastFeature_ = this.featuresAtPixel_(event.pixel, event.map);
|
||||
if (!this.lastCoordinate_ && this.lastFeature_) {
|
||||
this.lastCoordinate_ = event.coordinate;
|
||||
handleMoveEvent.call(this, event);
|
||||
|
||||
const features = this.features_ || new Collection([this.lastFeature_]);
|
||||
|
||||
this.dispatchEvent(
|
||||
new TranslateEvent(
|
||||
TranslateEventType.TRANSLATESTART, features,
|
||||
event.coordinate));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} event Event.
|
||||
* @return {boolean} Stop drag sequence?
|
||||
* @this {Translate}
|
||||
*/
|
||||
function handleUpEvent(event) {
|
||||
if (this.lastCoordinate_) {
|
||||
this.lastCoordinate_ = null;
|
||||
handleMoveEvent.call(this, event);
|
||||
|
||||
const features = this.features_ || new Collection([this.lastFeature_]);
|
||||
|
||||
this.dispatchEvent(
|
||||
new TranslateEvent(
|
||||
TranslateEventType.TRANSLATEEND, features,
|
||||
event.coordinate));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserPointerEvent.js").default} event Event.
|
||||
* @this {Translate}
|
||||
*/
|
||||
function handleDragEvent(event) {
|
||||
if (this.lastCoordinate_) {
|
||||
const newCoordinate = event.coordinate;
|
||||
const deltaX = newCoordinate[0] - this.lastCoordinate_[0];
|
||||
const deltaY = newCoordinate[1] - this.lastCoordinate_[1];
|
||||
|
||||
const features = this.features_ || new Collection([this.lastFeature_]);
|
||||
|
||||
features.forEach(function(feature) {
|
||||
const geom = feature.getGeometry();
|
||||
geom.translate(deltaX, deltaY);
|
||||
feature.setGeometry(geom);
|
||||
});
|
||||
|
||||
this.lastCoordinate_ = newCoordinate;
|
||||
this.dispatchEvent(
|
||||
new TranslateEvent(
|
||||
TranslateEventType.TRANSLATING, features,
|
||||
newCoordinate));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("../MapBrowserEvent.js").default} event Event.
|
||||
* @this {Translate}
|
||||
*/
|
||||
function handleMoveEvent(event) {
|
||||
const elem = event.map.getViewport();
|
||||
|
||||
// Change the cursor to grab/grabbing if hovering any of the features managed
|
||||
// by the interaction
|
||||
if (this.featuresAtPixel_(event.pixel, event.map)) {
|
||||
elem.classList.remove(this.lastCoordinate_ ? 'ol-grab' : 'ol-grabbing');
|
||||
elem.classList.add(this.lastCoordinate_ ? 'ol-grabbing' : 'ol-grab');
|
||||
} else {
|
||||
elem.classList.remove('ol-grab', 'ol-grabbing');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default Translate;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* @module ol/layer/Base
|
||||
*/
|
||||
import {abstract} from '../util.js';
|
||||
import BaseObject from '../Object.js';
|
||||
import LayerProperty from '../layer/Property.js';
|
||||
import {clamp} from '../math.js';
|
||||
@@ -43,8 +44,8 @@ class BaseLayer extends BaseObject {
|
||||
super();
|
||||
|
||||
/**
|
||||
* @type {Object<string, *>}
|
||||
*/
|
||||
* @type {Object<string, *>}
|
||||
*/
|
||||
const properties = assign({}, options);
|
||||
properties[LayerProperty.OPACITY] =
|
||||
options.opacity !== undefined ? options.opacity : 1;
|
||||
@@ -59,190 +60,199 @@ class BaseLayer extends BaseObject {
|
||||
this.setProperties(properties);
|
||||
|
||||
/**
|
||||
* @type {import("./Layer.js").State}
|
||||
* @private
|
||||
*/
|
||||
this.state_ = /** @type {import("./Layer.js").State} */ ({
|
||||
layer: /** @type {import("./Layer.js").default} */ (this),
|
||||
managed: true
|
||||
});
|
||||
* @type {import("./Layer.js").State}
|
||||
* @private
|
||||
*/
|
||||
this.state_ = null;
|
||||
|
||||
/**
|
||||
* The layer type.
|
||||
* @type {import("../LayerType.js").default}
|
||||
* @protected;
|
||||
*/
|
||||
* The layer type.
|
||||
* @type {import("../LayerType.js").default}
|
||||
* @protected;
|
||||
*/
|
||||
this.type;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the layer type (used when creating a layer renderer).
|
||||
* @return {import("../LayerType.js").default} The layer type.
|
||||
*/
|
||||
* Get the layer type (used when creating a layer renderer).
|
||||
* @return {import("../LayerType.js").default} The layer type.
|
||||
*/
|
||||
getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import("./Layer.js").State} Layer state.
|
||||
*/
|
||||
* @return {import("./Layer.js").State} Layer state.
|
||||
*/
|
||||
getLayerState() {
|
||||
this.state_.opacity = clamp(this.getOpacity(), 0, 1);
|
||||
this.state_.sourceState = this.getSourceState();
|
||||
this.state_.visible = this.getVisible();
|
||||
this.state_.extent = this.getExtent();
|
||||
this.state_.zIndex = this.getZIndex() || 0;
|
||||
this.state_.maxResolution = this.getMaxResolution();
|
||||
this.state_.minResolution = Math.max(this.getMinResolution(), 0);
|
||||
/** @type {import("./Layer.js").State} */
|
||||
const state = this.state_ || /** @type {?} */ ({
|
||||
layer: this,
|
||||
managed: true
|
||||
});
|
||||
state.opacity = clamp(this.getOpacity(), 0, 1);
|
||||
state.sourceState = this.getSourceState();
|
||||
state.visible = this.getVisible();
|
||||
state.extent = this.getExtent();
|
||||
state.zIndex = this.getZIndex() || 0;
|
||||
state.maxResolution = this.getMaxResolution();
|
||||
state.minResolution = Math.max(this.getMinResolution(), 0);
|
||||
this.state_ = state;
|
||||
|
||||
return this.state_;
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {Array<import("./Layer.js").default>=} opt_array Array of layers (to be
|
||||
* modified in place).
|
||||
* @return {Array<import("./Layer.js").default>} Array of layers.
|
||||
*/
|
||||
getLayersArray(opt_array) {}
|
||||
* @abstract
|
||||
* @param {Array<import("./Layer.js").default>=} opt_array Array of layers (to be
|
||||
* modified in place).
|
||||
* @return {Array<import("./Layer.js").default>} Array of layers.
|
||||
*/
|
||||
getLayersArray(opt_array) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {Array<import("./Layer.js").State>=} opt_states Optional list of layer
|
||||
* states (to be modified in place).
|
||||
* @return {Array<import("./Layer.js").State>} List of layer states.
|
||||
*/
|
||||
getLayerStatesArray(opt_states) {}
|
||||
* @abstract
|
||||
* @param {Array<import("./Layer.js").State>=} opt_states Optional list of layer
|
||||
* states (to be modified in place).
|
||||
* @return {Array<import("./Layer.js").State>} List of layer states.
|
||||
*/
|
||||
getLayerStatesArray(opt_states) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link module:ol/extent~Extent extent} of the layer or `undefined` if it
|
||||
* will be visible regardless of extent.
|
||||
* @return {import("../extent.js").Extent|undefined} The layer extent.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Return the {@link module:ol/extent~Extent extent} of the layer or `undefined` if it
|
||||
* will be visible regardless of extent.
|
||||
* @return {import("../extent.js").Extent|undefined} The layer extent.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getExtent() {
|
||||
return (
|
||||
/** @type {import("../extent.js").Extent|undefined} */ (this.get(LayerProperty.EXTENT))
|
||||
/** @type {import("../extent.js").Extent|undefined} */ (this.get(LayerProperty.EXTENT))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum resolution of the layer.
|
||||
* @return {number} The maximum resolution of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Return the maximum resolution of the layer.
|
||||
* @return {number} The maximum resolution of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getMaxResolution() {
|
||||
return /** @type {number} */ (this.get(LayerProperty.MAX_RESOLUTION));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the minimum resolution of the layer.
|
||||
* @return {number} The minimum resolution of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Return the minimum resolution of the layer.
|
||||
* @return {number} The minimum resolution of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getMinResolution() {
|
||||
return /** @type {number} */ (this.get(LayerProperty.MIN_RESOLUTION));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the opacity of the layer (between 0 and 1).
|
||||
* @return {number} The opacity of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Return the opacity of the layer (between 0 and 1).
|
||||
* @return {number} The opacity of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getOpacity() {
|
||||
return /** @type {number} */ (this.get(LayerProperty.OPACITY));
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {import("../source/State.js").default} Source state.
|
||||
*/
|
||||
getSourceState() {}
|
||||
* @abstract
|
||||
* @return {import("../source/State.js").default} Source state.
|
||||
*/
|
||||
getSourceState() {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the visibility of the layer (`true` or `false`).
|
||||
* @return {boolean} The visibility of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Return the visibility of the layer (`true` or `false`).
|
||||
* @return {boolean} The visibility of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getVisible() {
|
||||
return /** @type {boolean} */ (this.get(LayerProperty.VISIBLE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Z-index of the layer, which is used to order layers before
|
||||
* rendering. The default Z-index is 0.
|
||||
* @return {number} The Z-index of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Return the Z-index of the layer, which is used to order layers before
|
||||
* rendering. The default Z-index is 0.
|
||||
* @return {number} The Z-index of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
getZIndex() {
|
||||
return /** @type {number} */ (this.get(LayerProperty.Z_INDEX));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the extent at which the layer is visible. If `undefined`, the layer
|
||||
* will be visible at all extents.
|
||||
* @param {import("../extent.js").Extent|undefined} extent The extent of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Set the extent at which the layer is visible. If `undefined`, the layer
|
||||
* will be visible at all extents.
|
||||
* @param {import("../extent.js").Extent|undefined} extent The extent of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setExtent(extent) {
|
||||
this.set(LayerProperty.EXTENT, extent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum resolution at which the layer is visible.
|
||||
* @param {number} maxResolution The maximum resolution of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Set the maximum resolution at which the layer is visible.
|
||||
* @param {number} maxResolution The maximum resolution of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setMaxResolution(maxResolution) {
|
||||
this.set(LayerProperty.MAX_RESOLUTION, maxResolution);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum resolution at which the layer is visible.
|
||||
* @param {number} minResolution The minimum resolution of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Set the minimum resolution at which the layer is visible.
|
||||
* @param {number} minResolution The minimum resolution of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setMinResolution(minResolution) {
|
||||
this.set(LayerProperty.MIN_RESOLUTION, minResolution);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the opacity of the layer, allowed values range from 0 to 1.
|
||||
* @param {number} opacity The opacity of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Set the opacity of the layer, allowed values range from 0 to 1.
|
||||
* @param {number} opacity The opacity of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setOpacity(opacity) {
|
||||
this.set(LayerProperty.OPACITY, opacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the visibility of the layer (`true` or `false`).
|
||||
* @param {boolean} visible The visibility of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Set the visibility of the layer (`true` or `false`).
|
||||
* @param {boolean} visible The visibility of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setVisible(visible) {
|
||||
this.set(LayerProperty.VISIBLE, visible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Z-index of the layer, which is used to order layers before rendering.
|
||||
* The default Z-index is 0.
|
||||
* @param {number} zindex The z-index of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
* Set Z-index of the layer, which is used to order layers before rendering.
|
||||
* The default Z-index is 0.
|
||||
* @param {number} zindex The z-index of the layer.
|
||||
* @observable
|
||||
* @api
|
||||
*/
|
||||
setZIndex(zindex) {
|
||||
this.set(LayerProperty.Z_INDEX, zindex);
|
||||
}
|
||||
|
||||
@@ -84,9 +84,8 @@ class LayerGroup extends BaseLayer {
|
||||
if (Array.isArray(layers)) {
|
||||
layers = new Collection(layers.slice(), {unique: true});
|
||||
} else {
|
||||
assert(layers instanceof Collection,
|
||||
assert(typeof /** @type {?} */ (layers).getArray === 'function',
|
||||
43); // Expected `layers` to be an array or a `Collection`
|
||||
layers = layers;
|
||||
}
|
||||
} else {
|
||||
layers = new Collection(undefined, {unique: true});
|
||||
@@ -104,7 +103,6 @@ class LayerGroup extends BaseLayer {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../events/Event.js").default} event Event.
|
||||
* @private
|
||||
*/
|
||||
handleLayersChanged_() {
|
||||
@@ -125,7 +123,7 @@ class LayerGroup extends BaseLayer {
|
||||
const layersArray = layers.getArray();
|
||||
for (let i = 0, ii = layersArray.length; i < ii; i++) {
|
||||
const layer = layersArray[i];
|
||||
this.listenerKeys_[getUid(layer).toString()] = [
|
||||
this.listenerKeys_[getUid(layer)] = [
|
||||
listen(layer, ObjectEventType.PROPERTYCHANGE, this.handleLayerChange_, this),
|
||||
listen(layer, EventType.CHANGE, this.handleLayerChange_, this)
|
||||
];
|
||||
@@ -140,8 +138,7 @@ class LayerGroup extends BaseLayer {
|
||||
*/
|
||||
handleLayersAdd_(collectionEvent) {
|
||||
const layer = /** @type {import("./Base.js").default} */ (collectionEvent.element);
|
||||
const key = getUid(layer).toString();
|
||||
this.listenerKeys_[key] = [
|
||||
this.listenerKeys_[getUid(layer)] = [
|
||||
listen(layer, ObjectEventType.PROPERTYCHANGE, this.handleLayerChange_, this),
|
||||
listen(layer, EventType.CHANGE, this.handleLayerChange_, this)
|
||||
];
|
||||
@@ -154,7 +151,7 @@ class LayerGroup extends BaseLayer {
|
||||
*/
|
||||
handleLayersRemove_(collectionEvent) {
|
||||
const layer = /** @type {import("./Base.js").default} */ (collectionEvent.element);
|
||||
const key = getUid(layer).toString();
|
||||
const key = getUid(layer);
|
||||
this.listenerKeys_[key].forEach(unlistenByKey);
|
||||
delete this.listenerKeys_[key];
|
||||
this.changed();
|
||||
|
||||
@@ -35,7 +35,7 @@ import SourceState from '../source/State.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} State
|
||||
* @property {import("./Layer.js").default} layer
|
||||
* @property {import("./Base.js").default} layer
|
||||
* @property {number} opacity
|
||||
* @property {SourceState} sourceState
|
||||
* @property {boolean} visible
|
||||
@@ -192,13 +192,14 @@ class Layer extends BaseLayer {
|
||||
}
|
||||
if (map) {
|
||||
this.mapPrecomposeKey_ = listen(map, RenderEventType.PRECOMPOSE, function(evt) {
|
||||
const renderEvent = /** @type {import("../render/Event.js").default} */ (evt);
|
||||
const layerState = this.getLayerState();
|
||||
layerState.managed = false;
|
||||
if (this.getZIndex() === undefined) {
|
||||
layerState.zIndex = Infinity;
|
||||
}
|
||||
evt.frameState.layerStatesArray.push(layerState);
|
||||
evt.frameState.layerStates[getUid(this)] = layerState;
|
||||
renderEvent.frameState.layerStatesArray.push(layerState);
|
||||
renderEvent.frameState.layerStates[getUid(this)] = layerState;
|
||||
}, this);
|
||||
this.mapRenderKey_ = listen(this, EventType.CHANGE, map.render, map);
|
||||
this.changed();
|
||||
|
||||
@@ -41,7 +41,7 @@ import {createDefaultStyle, toFunction as toStyleFunction} from '../style/Style.
|
||||
* @property {boolean} [declutter=false] Declutter images and text. Decluttering is applied to all
|
||||
* image and text styles, and the priority is defined by the z-index of the style. Lower z-index
|
||||
* means higher priority.
|
||||
* @property {import("../style/Style.js").default|Array<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction} [style] Layer style. See
|
||||
* @property {import("../style/Style.js").StyleLike} [style] Layer style. See
|
||||
* {@link module:ol/style} for default style which will be used if this is not defined.
|
||||
* @property {boolean} [updateWhileAnimating=false] When set to `true` and `renderMode`
|
||||
* is `vector`, feature batches will be recreated during animations. This means that no
|
||||
@@ -54,22 +54,6 @@ import {createDefaultStyle, toFunction as toStyleFunction} from '../style/Style.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
* Render mode for vector layers:
|
||||
* * `'image'`: Vector layers are rendered as images. Great performance, but
|
||||
* point symbols and texts are always rotated with the view and pixels are
|
||||
* scaled during zoom animations.
|
||||
* * `'vector'`: Vector layers are rendered as vectors. Most accurate rendering
|
||||
* even during animations, but slower performance.
|
||||
* @api
|
||||
*/
|
||||
export const RenderType = {
|
||||
IMAGE: 'image',
|
||||
VECTOR: 'vector'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @enum {string}
|
||||
* @private
|
||||
@@ -119,7 +103,7 @@ class VectorLayer extends Layer {
|
||||
|
||||
/**
|
||||
* User provided style.
|
||||
* @type {import("../style/Style.js").default|Array<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction}
|
||||
* @type {import("../style/Style.js").StyleLike}
|
||||
* @private
|
||||
*/
|
||||
this.style_ = null;
|
||||
@@ -196,7 +180,7 @@ class VectorLayer extends Layer {
|
||||
/**
|
||||
* Get the style for features. This returns whatever was passed to the `style`
|
||||
* option at construction or to the `setStyle` method.
|
||||
* @return {import("../style/Style.js").default|Array<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction}
|
||||
* @return {import("../style/Style.js").StyleLike}
|
||||
* Layer style.
|
||||
* @api
|
||||
*/
|
||||
|
||||
@@ -70,7 +70,7 @@ export const RenderType = {
|
||||
* image and text styles, and the priority is defined by the z-index of the style. Lower z-index
|
||||
* means higher priority. When set to `true`, a `renderMode` of `'image'` will be overridden with
|
||||
* `'hybrid'`.
|
||||
* @property {import("../style/Style.js").default|Array<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction} [style] Layer style. See
|
||||
* @property {import("../style/Style.js").StyleLike} [style] Layer style. See
|
||||
* {@link module:ol/style} for default style which will be used if this is not defined.
|
||||
* @property {boolean} [updateWhileAnimating=false] When set to `true`, feature batches will be
|
||||
* recreated during animations. This means that no vectors will be shown clipped, but the setting
|
||||
@@ -82,7 +82,7 @@ export const RenderType = {
|
||||
* means no preloading.
|
||||
* @property {import("../render.js").OrderFunction} [renderOrder] Render order. Function to be used when sorting
|
||||
* features before rendering. By default features are drawn in the order that they are created.
|
||||
* @property {import("../style/Style.js").default|Array<import("../style/Style.js").default>|import("../style/Style.js").StyleFunction} [style] Layer style. See
|
||||
* @property {import("../style/Style.js").StyleLike} [style] Layer style. See
|
||||
* {@link module:ol/style} for default style which will be used if this is not defined.
|
||||
* @property {boolean} [useInterimTilesOnError=true] Use interim tiles on error.
|
||||
*/
|
||||
@@ -116,11 +116,11 @@ class VectorTileLayer extends VectorLayer {
|
||||
}
|
||||
options.renderMode = renderMode;
|
||||
|
||||
const baseOptions = assign({}, options);
|
||||
|
||||
const baseOptions = /** @type {Object} */ (assign({}, options));
|
||||
delete baseOptions.preload;
|
||||
delete baseOptions.useInterimTilesOnError;
|
||||
super(baseOptions);
|
||||
|
||||
super(/** @type {import("./Vector.js").Options} */ (baseOptions));
|
||||
|
||||
this.setPreload(options.preload ? options.preload : 0);
|
||||
this.setUseInterimTilesOnError(options.useInterimTilesOnError !== undefined ?
|
||||
|
||||
@@ -35,7 +35,7 @@ export const cosh = (function() {
|
||||
} else {
|
||||
// … else, use the reference implementation of MDN:
|
||||
cosh = function(x) {
|
||||
const y = Math.exp(x);
|
||||
const y = /** @type {Math} */ (Math).exp(x);
|
||||
return (y + 1 / y) / 2;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/**
|
||||
* @module ol/pixel
|
||||
*/
|
||||
|
||||
/**
|
||||
* An array with two elements, representing a pixel. The first element is the
|
||||
* x-coordinate, the second the y-coordinate of the pixel.
|
||||
|
||||
@@ -226,7 +226,7 @@ class MouseSource extends EventSource {
|
||||
* @param {import("./PointerEventHandler.js").default} dispatcher Event handler.
|
||||
* @return {Object} The copied event.
|
||||
*/
|
||||
function prepareEvent(inEvent, dispatcher) {
|
||||
export function prepareEvent(inEvent, dispatcher) {
|
||||
const e = dispatcher.cloneEvent(inEvent, inEvent);
|
||||
|
||||
// forward mouse preventDefault
|
||||
|
||||
@@ -171,6 +171,7 @@ class MsSource extends EventSource {
|
||||
* @return {Object} The copied event.
|
||||
*/
|
||||
prepareEvent_(inEvent) {
|
||||
/** @type {MSPointerEvent|Object} */
|
||||
let e = inEvent;
|
||||
if (typeof inEvent.pointerType === 'number') {
|
||||
e = this.dispatcher.cloneEvent(inEvent, inEvent);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import Event from '../events/Event.js';
|
||||
import _Event from '../events/Event.js';
|
||||
|
||||
|
||||
/**
|
||||
@@ -42,7 +42,7 @@ import Event from '../events/Event.js';
|
||||
let HAS_BUTTONS = false;
|
||||
|
||||
|
||||
class PointerEvent extends Event {
|
||||
class PointerEvent extends _Event {
|
||||
|
||||
/**
|
||||
* A class for pointer events.
|
||||
@@ -69,12 +69,12 @@ class PointerEvent extends Event {
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.buttons = this.getButtons_(eventDict);
|
||||
this.buttons = getButtons(eventDict);
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.pressure = this.getPressure_(eventDict, this.buttons);
|
||||
this.pressure = getPressure(eventDict, this.buttons);
|
||||
|
||||
// MouseEvent related properties
|
||||
|
||||
@@ -200,64 +200,65 @@ class PointerEvent extends Event {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object<string, ?>} eventDict The event dictionary.
|
||||
* @return {number} Button indicator.
|
||||
*/
|
||||
getButtons_(eventDict) {
|
||||
// According to the w3c spec,
|
||||
// http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button
|
||||
// MouseEvent.button == 0 can mean either no mouse button depressed, or the
|
||||
// left mouse button depressed.
|
||||
//
|
||||
// As of now, the only way to distinguish between the two states of
|
||||
// MouseEvent.button is by using the deprecated MouseEvent.which property, as
|
||||
// this maps mouse buttons to positive integers > 0, and uses 0 to mean that
|
||||
// no mouse button is held.
|
||||
//
|
||||
// MouseEvent.which is derived from MouseEvent.button at MouseEvent creation,
|
||||
// but initMouseEvent does not expose an argument with which to set
|
||||
// MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set
|
||||
// MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectations
|
||||
// of app developers.
|
||||
//
|
||||
// The only way to propagate the correct state of MouseEvent.which and
|
||||
// MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which == 0
|
||||
// is to call initMouseEvent with a buttonArg value of -1.
|
||||
//
|
||||
// This is fixed with DOM Level 4's use of buttons
|
||||
let buttons;
|
||||
if (eventDict.buttons || HAS_BUTTONS) {
|
||||
buttons = eventDict.buttons;
|
||||
} else {
|
||||
switch (eventDict.which) {
|
||||
case 1: buttons = 1; break;
|
||||
case 2: buttons = 4; break;
|
||||
case 3: buttons = 2; break;
|
||||
default: buttons = 0;
|
||||
}
|
||||
}
|
||||
return buttons;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object<string, ?>} eventDict The event dictionary.
|
||||
* @param {number} buttons Button indicator.
|
||||
* @return {number} The pressure.
|
||||
*/
|
||||
getPressure_(eventDict, buttons) {
|
||||
// Spec requires that pointers without pressure specified use 0.5 for down
|
||||
// state and 0 for up state.
|
||||
let pressure = 0;
|
||||
if (eventDict.pressure) {
|
||||
pressure = eventDict.pressure;
|
||||
} else {
|
||||
pressure = buttons ? 0.5 : 0;
|
||||
|
||||
/**
|
||||
* @param {Object<string, ?>} eventDict The event dictionary.
|
||||
* @return {number} Button indicator.
|
||||
*/
|
||||
function getButtons(eventDict) {
|
||||
// According to the w3c spec,
|
||||
// http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button
|
||||
// MouseEvent.button == 0 can mean either no mouse button depressed, or the
|
||||
// left mouse button depressed.
|
||||
//
|
||||
// As of now, the only way to distinguish between the two states of
|
||||
// MouseEvent.button is by using the deprecated MouseEvent.which property, as
|
||||
// this maps mouse buttons to positive integers > 0, and uses 0 to mean that
|
||||
// no mouse button is held.
|
||||
//
|
||||
// MouseEvent.which is derived from MouseEvent.button at MouseEvent creation,
|
||||
// but initMouseEvent does not expose an argument with which to set
|
||||
// MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set
|
||||
// MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectations
|
||||
// of app developers.
|
||||
//
|
||||
// The only way to propagate the correct state of MouseEvent.which and
|
||||
// MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which == 0
|
||||
// is to call initMouseEvent with a buttonArg value of -1.
|
||||
//
|
||||
// This is fixed with DOM Level 4's use of buttons
|
||||
let buttons;
|
||||
if (eventDict.buttons || HAS_BUTTONS) {
|
||||
buttons = eventDict.buttons;
|
||||
} else {
|
||||
switch (eventDict.which) {
|
||||
case 1: buttons = 1; break;
|
||||
case 2: buttons = 4; break;
|
||||
case 3: buttons = 2; break;
|
||||
default: buttons = 0;
|
||||
}
|
||||
return pressure;
|
||||
}
|
||||
return buttons;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object<string, ?>} eventDict The event dictionary.
|
||||
* @param {number} buttons Button indicator.
|
||||
* @return {number} The pressure.
|
||||
*/
|
||||
function getPressure(eventDict, buttons) {
|
||||
// Spec requires that pointers without pressure specified use 0.5 for down
|
||||
// state and 0 for up state.
|
||||
let pressure = 0;
|
||||
if (eventDict.pressure) {
|
||||
pressure = eventDict.pressure;
|
||||
} else {
|
||||
pressure = buttons ? 0.5 : 0;
|
||||
}
|
||||
return pressure;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ import {listen, unlisten} from '../events.js';
|
||||
import EventTarget from '../events/Target.js';
|
||||
import {POINTER, MSPOINTER, TOUCH} from '../has.js';
|
||||
import PointerEventType from '../pointer/EventType.js';
|
||||
import MouseSource from '../pointer/MouseSource.js';
|
||||
import MouseSource, {prepareEvent as prepareMouseEvent} from '../pointer/MouseSource.js';
|
||||
import MsSource from '../pointer/MsSource.js';
|
||||
import NativeSource from '../pointer/NativeSource.js';
|
||||
import PointerEvent from '../pointer/PointerEvent.js';
|
||||
@@ -366,7 +366,7 @@ class PointerEventHandler extends EventTarget {
|
||||
* @param {string} inType A string representing the type of event to create.
|
||||
* @param {Object} data Pointer event data.
|
||||
* @param {Event} event The event.
|
||||
* @return {import("./PointerEvent.js").default} A PointerEvent of type `inType`.
|
||||
* @return {PointerEvent} A PointerEvent of type `inType`.
|
||||
*/
|
||||
makeEvent(inType, data, event) {
|
||||
return new PointerEvent(inType, event, data);
|
||||
@@ -398,11 +398,11 @@ class PointerEventHandler extends EventTarget {
|
||||
* This proxy method is required for the legacy IE support.
|
||||
* @param {string} eventType The pointer event type.
|
||||
* @param {Event} event The event.
|
||||
* @return {import("./PointerEvent.js").default} The wrapped event.
|
||||
* @return {PointerEvent} The wrapped event.
|
||||
*/
|
||||
wrapMouseEvent(eventType, event) {
|
||||
const pointerEvent = this.makeEvent(
|
||||
eventType, MouseSource.prepareEvent(event, this), event);
|
||||
eventType, prepareMouseEvent(event, this), event);
|
||||
return pointerEvent;
|
||||
}
|
||||
|
||||
|
||||
@@ -137,9 +137,9 @@ class TouchSource extends EventSource {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number|undefined}
|
||||
* @type {?}
|
||||
*/
|
||||
this.resetId_ = undefined;
|
||||
this.resetId_;
|
||||
|
||||
/**
|
||||
* Mouse event timeout: This should be long enough to
|
||||
@@ -228,9 +228,9 @@ class TouchSource extends EventSource {
|
||||
e.detail = this.clickCount_;
|
||||
e.button = 0;
|
||||
e.buttons = 1;
|
||||
e.width = inTouch.webkitRadiusX || inTouch.radiusX || 0;
|
||||
e.height = inTouch.webkitRadiusY || inTouch.radiusY || 0;
|
||||
e.pressure = inTouch.webkitForce || inTouch.force || 0.5;
|
||||
e.width = inTouch.radiusX || 0;
|
||||
e.height = inTouch.radiusY || 0;
|
||||
e.pressure = inTouch.force || 0.5;
|
||||
e.isPrimary = this.isPrimaryTouch_(inTouch);
|
||||
e.pointerType = POINTER_TYPE;
|
||||
|
||||
@@ -300,12 +300,12 @@ class TouchSource extends EventSource {
|
||||
if (count >= touchList.length) {
|
||||
const d = [];
|
||||
for (let i = 0; i < count; ++i) {
|
||||
const key = keys[i];
|
||||
const key = Number(keys[i]);
|
||||
const value = this.pointerMap[key];
|
||||
// Never remove pointerId == 1, which is mouse.
|
||||
// Touch identifiers are 2 smaller than their pointerId, which is the
|
||||
// index in pointermap.
|
||||
if (key != /** @type {string} */ (POINTER_ID) && !this.findTouch_(touchList, key - 2)) {
|
||||
if (key != POINTER_ID && !this.findTouch_(touchList, key - 2)) {
|
||||
d.push(value.out);
|
||||
}
|
||||
}
|
||||
@@ -348,7 +348,7 @@ class TouchSource extends EventSource {
|
||||
this.dispatcher.move(event, browserEvent);
|
||||
if (outEvent && outTarget !== event.target) {
|
||||
outEvent.relatedTarget = event.target;
|
||||
event.relatedTarget = outTarget;
|
||||
/** @type {Object} */ (event).relatedTarget = outTarget;
|
||||
// recover from retargeting by shadow
|
||||
outEvent.target = outTarget;
|
||||
if (event.target) {
|
||||
@@ -356,8 +356,8 @@ class TouchSource extends EventSource {
|
||||
this.dispatcher.enterOver(event, browserEvent);
|
||||
} else {
|
||||
// clean up case when finger leaves the screen
|
||||
event.target = outTarget;
|
||||
event.relatedTarget = null;
|
||||
/** @type {Object} */ (event).target = outTarget;
|
||||
/** @type {Object} */ (event).relatedTarget = null;
|
||||
this.cancelOut_(browserEvent, event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ import {add as addTransformFunc, clear as clearTransformFuncs, get as getTransfo
|
||||
/**
|
||||
* A projection as {@link module:ol/proj/Projection}, SRS identifier
|
||||
* string or undefined.
|
||||
* @typedef {import("./proj/Projection.js").default|string|undefined} ProjectionLike
|
||||
* @typedef {Projection|string|undefined} ProjectionLike
|
||||
* @api
|
||||
*/
|
||||
|
||||
@@ -129,7 +129,7 @@ export function identityTransform(input, opt_output, opt_dimension) {
|
||||
* Add a Projection object to the list of supported projections that can be
|
||||
* looked up by their code.
|
||||
*
|
||||
* @param {import("./proj/Projection.js").default} projection Projection instance.
|
||||
* @param {Projection} projection Projection instance.
|
||||
* @api
|
||||
*/
|
||||
export function addProjection(projection) {
|
||||
@@ -139,7 +139,7 @@ export function addProjection(projection) {
|
||||
|
||||
|
||||
/**
|
||||
* @param {Array<import("./proj/Projection.js").default>} projections Projections.
|
||||
* @param {Array<Projection>} projections Projections.
|
||||
*/
|
||||
export function addProjections(projections) {
|
||||
projections.forEach(addProjection);
|
||||
@@ -152,13 +152,13 @@ export function addProjections(projections) {
|
||||
* @param {ProjectionLike} projectionLike Either a code string which is
|
||||
* a combination of authority and identifier such as "EPSG:4326", or an
|
||||
* existing projection object, or undefined.
|
||||
* @return {import("./proj/Projection.js").default} Projection object, or null if not in list.
|
||||
* @return {Projection} Projection object, or null if not in list.
|
||||
* @api
|
||||
*/
|
||||
export function get(projectionLike) {
|
||||
return typeof projectionLike === 'string' ?
|
||||
projections.get(/** @type {string} */ (projectionLike)) :
|
||||
(/** @type {import("./proj/Projection.js").default} */ (projectionLike) || null);
|
||||
(/** @type {Projection} */ (projectionLike) || null);
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ export function get(projectionLike) {
|
||||
* @param {ProjectionLike} projection The projection.
|
||||
* @param {number} resolution Nominal resolution in projection units.
|
||||
* @param {import("./coordinate.js").Coordinate} point Point to find adjusted resolution at.
|
||||
* @param {import("./proj/Units.js").default=} opt_units Units to get the point resolution in.
|
||||
* @param {Units=} opt_units Units to get the point resolution in.
|
||||
* Default is the projection's units.
|
||||
* @return {number} Point resolution.
|
||||
* @api
|
||||
@@ -223,7 +223,7 @@ export function getPointResolution(projection, resolution, point, opt_units) {
|
||||
* Registers transformation functions that don't alter coordinates. Those allow
|
||||
* to transform between projections with equal meaning.
|
||||
*
|
||||
* @param {Array<import("./proj/Projection.js").default>} projections Projections.
|
||||
* @param {Array<Projection>} projections Projections.
|
||||
* @api
|
||||
*/
|
||||
export function addEquivalentProjections(projections) {
|
||||
@@ -242,9 +242,9 @@ export function addEquivalentProjections(projections) {
|
||||
* Registers transformation functions to convert coordinates in any projection
|
||||
* in projection1 to any projection in projection2.
|
||||
*
|
||||
* @param {Array<import("./proj/Projection.js").default>} projections1 Projections with equal
|
||||
* @param {Array<Projection>} projections1 Projections with equal
|
||||
* meaning.
|
||||
* @param {Array<import("./proj/Projection.js").default>} projections2 Projections with equal
|
||||
* @param {Array<Projection>} projections2 Projections with equal
|
||||
* meaning.
|
||||
* @param {TransformFunction} forwardTransform Transformation from any
|
||||
* projection in projection1 to any projection in projection2.
|
||||
@@ -271,9 +271,9 @@ export function clearAllProjections() {
|
||||
|
||||
|
||||
/**
|
||||
* @param {import("./proj/Projection.js").default|string|undefined} projection Projection.
|
||||
* @param {Projection|string|undefined} projection Projection.
|
||||
* @param {string} defaultCode Default code.
|
||||
* @return {import("./proj/Projection.js").default} Projection.
|
||||
* @return {Projection} Projection.
|
||||
*/
|
||||
export function createProjection(projection, defaultCode) {
|
||||
if (!projection) {
|
||||
@@ -282,7 +282,7 @@ export function createProjection(projection, defaultCode) {
|
||||
return get(projection);
|
||||
} else {
|
||||
return (
|
||||
/** @type {import("./proj/Projection.js").default} */ (projection)
|
||||
/** @type {Projection} */ (projection)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -387,8 +387,8 @@ export function toLonLat(coordinate, opt_projection) {
|
||||
* projection does represent the same geographic point as the same coordinate in
|
||||
* the other projection.
|
||||
*
|
||||
* @param {import("./proj/Projection.js").default} projection1 Projection 1.
|
||||
* @param {import("./proj/Projection.js").default} projection2 Projection 2.
|
||||
* @param {Projection} projection1 Projection 1.
|
||||
* @param {Projection} projection2 Projection 2.
|
||||
* @return {boolean} Equivalent.
|
||||
* @api
|
||||
*/
|
||||
@@ -410,8 +410,8 @@ export function equivalent(projection1, projection2) {
|
||||
* Searches in the list of transform functions for the function for converting
|
||||
* coordinates from the source projection to the destination projection.
|
||||
*
|
||||
* @param {import("./proj/Projection.js").default} sourceProjection Source Projection object.
|
||||
* @param {import("./proj/Projection.js").default} destinationProjection Destination Projection
|
||||
* @param {Projection} sourceProjection Source Projection object.
|
||||
* @param {Projection} destinationProjection Destination Projection
|
||||
* object.
|
||||
* @return {TransformFunction} Transform function.
|
||||
*/
|
||||
@@ -483,8 +483,8 @@ export function transformExtent(extent, source, destination) {
|
||||
* Transforms the given point to the destination projection.
|
||||
*
|
||||
* @param {import("./coordinate.js").Coordinate} point Point.
|
||||
* @param {import("./proj/Projection.js").default} sourceProjection Source projection.
|
||||
* @param {import("./proj/Projection.js").default} destinationProjection Destination projection.
|
||||
* @param {Projection} sourceProjection Source projection.
|
||||
* @param {Projection} destinationProjection Destination projection.
|
||||
* @return {import("./coordinate.js").Coordinate} Point.
|
||||
*/
|
||||
export function transformWithProjections(point, sourceProjection, destinationProjection) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import CanvasImmediateRenderer from './render/canvas/Immediate.js';
|
||||
/**
|
||||
* @typedef {Object} State
|
||||
* @property {CanvasRenderingContext2D} context Canvas context that the layer is being rendered to.
|
||||
* @property {import("./Feature.js").default|import("./render/Feature.js").default} feature
|
||||
* @property {import("./Feature.js").FeatureLike} feature
|
||||
* @property {import("./geom/SimpleGeometry.js").default} geometry
|
||||
* @property {number} pixelRatio Pixel ratio used by the layer renderer.
|
||||
* @property {number} resolution Resolution that the render batch was created and optimized for.
|
||||
@@ -23,8 +23,7 @@ import CanvasImmediateRenderer from './render/canvas/Immediate.js';
|
||||
* It takes two instances of {@link module:ol/Feature} or
|
||||
* {@link module:ol/render/Feature} and returns a `{number}`.
|
||||
*
|
||||
* @typedef {function((import("./Feature.js").default|import("./render/Feature.js").default),
|
||||
* (import("./Feature.js").default|import("./render/Feature.js").default)):number} OrderFunction
|
||||
* @typedef {function(import("./Feature.js").FeatureLike, import("./Feature.js").FeatureLike):number} OrderFunction
|
||||
*/
|
||||
|
||||
|
||||
@@ -60,7 +59,7 @@ import CanvasImmediateRenderer from './render/canvas/Immediate.js';
|
||||
*
|
||||
* @param {CanvasRenderingContext2D} context Canvas context.
|
||||
* @param {ToContextOptions=} opt_options Options.
|
||||
* @return {import("./render/canvas/Immediate.js").default} Canvas Immediate.
|
||||
* @return {CanvasImmediateRenderer} Canvas Immediate.
|
||||
* @api
|
||||
*/
|
||||
export function toContext(context, opt_options) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/**
|
||||
* @module ol/render/Feature
|
||||
*/
|
||||
import {VOID} from '../functions.js';
|
||||
import {extend} from '../array.js';
|
||||
import {createOrUpdateFromCoordinate, createOrUpdateFromFlatCoordinates, getCenter, getHeight} from '../extent.js';
|
||||
import GeometryType from '../geom/GeometryType.js';
|
||||
@@ -24,7 +23,7 @@ const tmpTransform = createTransform();
|
||||
* structure, optimized for vector tile rendering and styling. Geometry access
|
||||
* through the API is limited to getting the type and extent of the geometry.
|
||||
*
|
||||
* @param {import("../geom/GeometryType.js").default} type Geometry type.
|
||||
* @param {GeometryType} type Geometry type.
|
||||
* @param {Array<number>} flatCoordinates Flat coordinates. These always need
|
||||
* to be right-handed for polygons.
|
||||
* @param {Array<number>|Array<Array<number>>} ends Ends or Endss.
|
||||
@@ -47,7 +46,7 @@ class RenderFeature {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("../geom/GeometryType.js").default}
|
||||
* @type {GeometryType}
|
||||
*/
|
||||
this.type_ = type;
|
||||
|
||||
@@ -116,7 +115,7 @@ class RenderFeature {
|
||||
if (!this.flatInteriorPoints_) {
|
||||
const flatCenter = getCenter(this.getExtent());
|
||||
this.flatInteriorPoints_ = getInteriorPointOfArray(
|
||||
this.flatCoordinates_, 0, this.ends_, 2, flatCenter, 0);
|
||||
this.flatCoordinates_, 0, /** @type {Array<number>} */ (this.ends_), 2, flatCenter, 0);
|
||||
}
|
||||
return this.flatInteriorPoints_;
|
||||
}
|
||||
@@ -127,9 +126,9 @@ class RenderFeature {
|
||||
getFlatInteriorPoints() {
|
||||
if (!this.flatInteriorPoints_) {
|
||||
const flatCenters = linearRingssCenter(
|
||||
this.flatCoordinates_, 0, this.ends_, 2);
|
||||
this.flatCoordinates_, 0, /** @type {Array<Array<number>>} */ (this.ends_), 2);
|
||||
this.flatInteriorPoints_ = getInteriorPointsOfMultiArray(
|
||||
this.flatCoordinates_, 0, this.ends_, 2, flatCenters);
|
||||
this.flatCoordinates_, 0, /** @type {Array<Array<number>>} */ (this.ends_), 2, flatCenters);
|
||||
}
|
||||
return this.flatInteriorPoints_;
|
||||
}
|
||||
@@ -153,7 +152,7 @@ class RenderFeature {
|
||||
this.flatMidpoints_ = [];
|
||||
const flatCoordinates = this.flatCoordinates_;
|
||||
let offset = 0;
|
||||
const ends = this.ends_;
|
||||
const ends = /** @type {Array<number>} */ (this.ends_);
|
||||
for (let i = 0, ii = ends.length; i < ii; ++i) {
|
||||
const end = ends[i];
|
||||
const midpoint = interpolatePoint(
|
||||
@@ -192,6 +191,14 @@ class RenderFeature {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} squaredTolerance Squared tolerance.
|
||||
* @return {RenderFeature} Simplified geometry.
|
||||
*/
|
||||
getSimplifiedGeometry(squaredTolerance) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the feature properties.
|
||||
* @return {Object<string, *>} Feature properties.
|
||||
@@ -208,9 +215,16 @@ class RenderFeature {
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {undefined}
|
||||
*/
|
||||
getStyleFunction() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of this feature's geometry.
|
||||
* @return {import("../geom/GeometryType.js").default} Geometry type.
|
||||
* @return {GeometryType} Geometry type.
|
||||
* @api
|
||||
*/
|
||||
getType() {
|
||||
@@ -255,18 +269,4 @@ RenderFeature.prototype.getFlatCoordinates =
|
||||
RenderFeature.prototype.getOrientedFlatCoordinates;
|
||||
|
||||
|
||||
/**
|
||||
* Get the feature for working with its geometry.
|
||||
* @return {RenderFeature} Feature.
|
||||
*/
|
||||
RenderFeature.prototype.getSimplifiedGeometry =
|
||||
RenderFeature.prototype.getGeometry;
|
||||
|
||||
|
||||
/**
|
||||
* @return {undefined}
|
||||
*/
|
||||
RenderFeature.prototype.getStyleFunction = VOID;
|
||||
|
||||
|
||||
export default RenderFeature;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/**
|
||||
* @module ol/render/ReplayGroup
|
||||
*/
|
||||
import {abstract} from '../util.js';
|
||||
|
||||
/**
|
||||
* Base class for replay groups.
|
||||
*/
|
||||
@@ -11,13 +13,26 @@ class ReplayGroup {
|
||||
* @param {import("./ReplayType.js").default} replayType Replay type.
|
||||
* @return {import("./VectorContext.js").default} Replay.
|
||||
*/
|
||||
getReplay(zIndex, replayType) {}
|
||||
getReplay(zIndex, replayType) {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @return {boolean} Is empty.
|
||||
*/
|
||||
isEmpty() {}
|
||||
isEmpty() {
|
||||
return abstract();
|
||||
}
|
||||
|
||||
/**
|
||||
* @abstract
|
||||
* @param {boolean} group Group with previous replay
|
||||
* @return {Array<*>} The resulting instruction group
|
||||
*/
|
||||
addDeclutter(group) {
|
||||
return abstract();
|
||||
}
|
||||
}
|
||||
|
||||
export default ReplayGroup;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user