Automated class transform

npx lebab --replace src --transform class
This commit is contained in:
Tim Schaub
2018-07-16 16:18:16 -06:00
parent 60e85e7d89
commit 7b4a73f3b9
145 changed files with 32886 additions and 33713 deletions
+49 -60
View File
@@ -65,7 +65,8 @@ inherits(CollectionEvent, Event);
* @template T * @template T
* @api * @api
*/ */
const Collection = function(opt_array, opt_options) { class Collection {
constructor(opt_array, opt_options) {
BaseObject.call(this); BaseObject.call(this);
@@ -91,53 +92,47 @@ const Collection = function(opt_array, opt_options) {
this.updateLength_(); this.updateLength_();
}; }
inherits(Collection, BaseObject); /**
/**
* Remove all elements from the collection. * Remove all elements from the collection.
* @api * @api
*/ */
Collection.prototype.clear = function() { clear() {
while (this.getLength() > 0) { while (this.getLength() > 0) {
this.pop(); this.pop();
} }
}; }
/**
/**
* Add elements to the collection. This pushes each item in the provided array * Add elements to the collection. This pushes each item in the provided array
* to the end of the collection. * to the end of the collection.
* @param {!Array.<T>} arr Array. * @param {!Array.<T>} arr Array.
* @return {module:ol/Collection.<T>} This collection. * @return {module:ol/Collection.<T>} This collection.
* @api * @api
*/ */
Collection.prototype.extend = function(arr) { extend(arr) {
for (let i = 0, ii = arr.length; i < ii; ++i) { for (let i = 0, ii = arr.length; i < ii; ++i) {
this.push(arr[i]); this.push(arr[i]);
} }
return this; return this;
}; }
/**
/**
* Iterate over each element, calling the provided callback. * Iterate over each element, calling the provided callback.
* @param {function(T, number, Array.<T>): *} f The function to call * @param {function(T, number, Array.<T>): *} f The function to call
* for every element. This function takes 3 arguments (the element, the * for every element. This function takes 3 arguments (the element, the
* index and the array). The return value is ignored. * index and the array). The return value is ignored.
* @api * @api
*/ */
Collection.prototype.forEach = function(f) { forEach(f) {
const array = this.array_; const array = this.array_;
for (let i = 0, ii = array.length; i < ii; ++i) { for (let i = 0, ii = array.length; i < ii; ++i) {
f(array[i], i, array); f(array[i], i, array);
} }
}; }
/**
/**
* Get a reference to the underlying Array object. Warning: if the array * Get a reference to the underlying Array object. Warning: if the array
* is mutated, no events will be dispatched by the collection, and the * is mutated, no events will be dispatched by the collection, and the
* collection's "length" property won't be in sync with the actual length * collection's "length" property won't be in sync with the actual length
@@ -145,40 +140,37 @@ Collection.prototype.forEach = function(f) {
* @return {!Array.<T>} Array. * @return {!Array.<T>} Array.
* @api * @api
*/ */
Collection.prototype.getArray = function() { getArray() {
return this.array_; return this.array_;
}; }
/**
/**
* Get the element at the provided index. * Get the element at the provided index.
* @param {number} index Index. * @param {number} index Index.
* @return {T} Element. * @return {T} Element.
* @api * @api
*/ */
Collection.prototype.item = function(index) { item(index) {
return this.array_[index]; return this.array_[index];
}; }
/**
/**
* Get the length of this collection. * Get the length of this collection.
* @return {number} The length of the array. * @return {number} The length of the array.
* @observable * @observable
* @api * @api
*/ */
Collection.prototype.getLength = function() { getLength() {
return /** @type {number} */ (this.get(Property.LENGTH)); return /** @type {number} */ (this.get(Property.LENGTH));
}; }
/**
/**
* Insert an element at the provided index. * Insert an element at the provided index.
* @param {number} index Index. * @param {number} index Index.
* @param {T} elem Element. * @param {T} elem Element.
* @api * @api
*/ */
Collection.prototype.insertAt = function(index, elem) { insertAt(index, elem) {
if (this.unique_) { if (this.unique_) {
this.assertUnique_(elem); this.assertUnique_(elem);
} }
@@ -186,43 +178,40 @@ Collection.prototype.insertAt = function(index, elem) {
this.updateLength_(); this.updateLength_();
this.dispatchEvent( this.dispatchEvent(
new CollectionEvent(CollectionEventType.ADD, elem)); new CollectionEvent(CollectionEventType.ADD, elem));
}; }
/**
/**
* Remove the last element of the collection and return it. * Remove the last element of the collection and return it.
* Return `undefined` if the collection is empty. * Return `undefined` if the collection is empty.
* @return {T|undefined} Element. * @return {T|undefined} Element.
* @api * @api
*/ */
Collection.prototype.pop = function() { pop() {
return this.removeAt(this.getLength() - 1); return this.removeAt(this.getLength() - 1);
}; }
/**
/**
* Insert the provided element at the end of the collection. * Insert the provided element at the end of the collection.
* @param {T} elem Element. * @param {T} elem Element.
* @return {number} New length of the collection. * @return {number} New length of the collection.
* @api * @api
*/ */
Collection.prototype.push = function(elem) { push(elem) {
if (this.unique_) { if (this.unique_) {
this.assertUnique_(elem); this.assertUnique_(elem);
} }
const n = this.getLength(); const n = this.getLength();
this.insertAt(n, elem); this.insertAt(n, elem);
return this.getLength(); return this.getLength();
}; }
/**
/**
* Remove the first occurrence of an element from the collection. * Remove the first occurrence of an element from the collection.
* @param {T} elem Element. * @param {T} elem Element.
* @return {T|undefined} The removed element or undefined if none found. * @return {T|undefined} The removed element or undefined if none found.
* @api * @api
*/ */
Collection.prototype.remove = function(elem) { remove(elem) {
const arr = this.array_; const arr = this.array_;
for (let i = 0, ii = arr.length; i < ii; ++i) { for (let i = 0, ii = arr.length; i < ii; ++i) {
if (arr[i] === elem) { if (arr[i] === elem) {
@@ -230,32 +219,30 @@ Collection.prototype.remove = function(elem) {
} }
} }
return undefined; return undefined;
}; }
/**
/**
* Remove the element at the provided index and return it. * Remove the element at the provided index and return it.
* Return `undefined` if the collection does not contain this index. * Return `undefined` if the collection does not contain this index.
* @param {number} index Index. * @param {number} index Index.
* @return {T|undefined} Value. * @return {T|undefined} Value.
* @api * @api
*/ */
Collection.prototype.removeAt = function(index) { removeAt(index) {
const prev = this.array_[index]; const prev = this.array_[index];
this.array_.splice(index, 1); this.array_.splice(index, 1);
this.updateLength_(); this.updateLength_();
this.dispatchEvent(new CollectionEvent(CollectionEventType.REMOVE, prev)); this.dispatchEvent(new CollectionEvent(CollectionEventType.REMOVE, prev));
return prev; return prev;
}; }
/**
/**
* Set the element at the provided index. * Set the element at the provided index.
* @param {number} index Index. * @param {number} index Index.
* @param {T} elem Element. * @param {T} elem Element.
* @api * @api
*/ */
Collection.prototype.setAt = function(index, elem) { setAt(index, elem) {
const n = this.getLength(); const n = this.getLength();
if (index < n) { if (index < n) {
if (this.unique_) { if (this.unique_) {
@@ -273,28 +260,30 @@ Collection.prototype.setAt = function(index, elem) {
} }
this.insertAt(index, elem); this.insertAt(index, elem);
} }
}; }
/**
/**
* @private * @private
*/ */
Collection.prototype.updateLength_ = function() { updateLength_() {
this.set(Property.LENGTH, this.array_.length); this.set(Property.LENGTH, this.array_.length);
}; }
/**
/**
* @private * @private
* @param {T} elem Element. * @param {T} elem Element.
* @param {number=} opt_except Optional index to ignore. * @param {number=} opt_except Optional index to ignore.
*/ */
Collection.prototype.assertUnique_ = function(elem, opt_except) { assertUnique_(elem, opt_except) {
for (let i = 0, ii = this.array_.length; i < ii; ++i) { for (let i = 0, ii = this.array_.length; i < ii; ++i) {
if (this.array_[i] === elem && i !== opt_except) { if (this.array_[i] === elem && i !== opt_except) {
throw new AssertionError(58); throw new AssertionError(58);
} }
} }
}; }
}
inherits(Collection, BaseObject);
export default Collection; export default Collection;
+11 -11
View File
@@ -7,7 +7,17 @@ import {UNDEFINED} from './functions.js';
* Objects that need to clean up after themselves. * Objects that need to clean up after themselves.
* @constructor * @constructor
*/ */
const Disposable = function() {}; class Disposable {
/**
* Clean up.
*/
dispose() {
if (!this.disposed_) {
this.disposed_ = true;
this.disposeInternal();
}
}
}
/** /**
* The object has already been disposed. * The object has already been disposed.
@@ -16,16 +26,6 @@ const Disposable = function() {};
*/ */
Disposable.prototype.disposed_ = false; Disposable.prototype.disposed_ = false;
/**
* Clean up.
*/
Disposable.prototype.dispose = function() {
if (!this.disposed_) {
this.disposed_ = true;
this.disposeInternal();
}
};
/** /**
* Extension point for disposable objects. * Extension point for disposable objects.
* @protected * @protected
+42 -52
View File
@@ -59,7 +59,8 @@ import Style from './style/Style.js';
* associated with a `geometry` key. * associated with a `geometry` key.
* @api * @api
*/ */
const Feature = function(opt_geometryOrProperties) { class Feature {
constructor(opt_geometryOrProperties) {
BaseObject.call(this); BaseObject.call(this);
@@ -109,18 +110,15 @@ const Feature = function(opt_geometryOrProperties) {
this.setProperties(properties); this.setProperties(properties);
} }
} }
}; }
inherits(Feature, BaseObject); /**
/**
* Clone this feature. If the original feature has a geometry it * Clone this feature. If the original feature has a geometry it
* is also cloned. The feature id is not set in the clone. * is also cloned. The feature id is not set in the clone.
* @return {module:ol/Feature} The clone. * @return {module:ol/Feature} The clone.
* @api * @api
*/ */
Feature.prototype.clone = function() { clone() {
const clone = new Feature(this.getProperties()); const clone = new Feature(this.getProperties());
clone.setGeometryName(this.getGeometryName()); clone.setGeometryName(this.getGeometryName());
const geometry = this.getGeometry(); const geometry = this.getGeometry();
@@ -132,10 +130,9 @@ Feature.prototype.clone = function() {
clone.setStyle(style); clone.setStyle(style);
} }
return clone; return clone;
}; }
/**
/**
* Get the feature's default geometry. A feature may have any number of named * Get the feature's default geometry. A feature may have any number of named
* geometries. The "default" geometry (the one that is rendered by default) is * geometries. The "default" geometry (the one that is rendered by default) is
* set when calling {@link module:ol/Feature~Feature#setGeometry}. * set when calling {@link module:ol/Feature~Feature#setGeometry}.
@@ -143,71 +140,65 @@ Feature.prototype.clone = function() {
* @api * @api
* @observable * @observable
*/ */
Feature.prototype.getGeometry = function() { getGeometry() {
return ( return (
/** @type {module:ol/geom/Geometry|undefined} */ (this.get(this.geometryName_)) /** @type {module:ol/geom/Geometry|undefined} */ (this.get(this.geometryName_))
); );
}; }
/**
/**
* Get the feature identifier. This is a stable identifier for the feature and * Get the feature identifier. This is a stable identifier for the feature and
* is either set when reading data from a remote source or set explicitly by * is either set when reading data from a remote source or set explicitly by
* calling {@link module:ol/Feature~Feature#setId}. * calling {@link module:ol/Feature~Feature#setId}.
* @return {number|string|undefined} Id. * @return {number|string|undefined} Id.
* @api * @api
*/ */
Feature.prototype.getId = function() { getId() {
return this.id_; return this.id_;
}; }
/**
/**
* Get the name of the feature's default geometry. By default, the default * Get the name of the feature's default geometry. By default, the default
* geometry is named `geometry`. * geometry is named `geometry`.
* @return {string} Get the property name associated with the default geometry * @return {string} Get the property name associated with the default geometry
* for this feature. * for this feature.
* @api * @api
*/ */
Feature.prototype.getGeometryName = function() { getGeometryName() {
return this.geometryName_; return this.geometryName_;
}; }
/**
/**
* Get the feature's style. Will return what was provided to the * Get the feature's style. Will return what was provided to the
* {@link module:ol/Feature~Feature#setStyle} method. * {@link module:ol/Feature~Feature#setStyle} method.
* @return {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction} The feature style. * @return {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction} The feature style.
* @api * @api
*/ */
Feature.prototype.getStyle = function() { getStyle() {
return this.style_; return this.style_;
}; }
/**
/**
* Get the feature's style function. * Get the feature's style function.
* @return {module:ol/style/Style~StyleFunction|undefined} Return a function * @return {module:ol/style/Style~StyleFunction|undefined} Return a function
* representing the current style of this feature. * representing the current style of this feature.
* @api * @api
*/ */
Feature.prototype.getStyleFunction = function() { getStyleFunction() {
return this.styleFunction_; return this.styleFunction_;
}; }
/**
/**
* @private * @private
*/ */
Feature.prototype.handleGeometryChange_ = function() { handleGeometryChange_() {
this.changed(); this.changed();
}; }
/**
/**
* @private * @private
*/ */
Feature.prototype.handleGeometryChanged_ = function() { handleGeometryChanged_() {
if (this.geometryChangeKey_) { if (this.geometryChangeKey_) {
unlistenByKey(this.geometryChangeKey_); unlistenByKey(this.geometryChangeKey_);
this.geometryChangeKey_ = null; this.geometryChangeKey_ = null;
@@ -218,22 +209,20 @@ Feature.prototype.handleGeometryChanged_ = function() {
EventType.CHANGE, this.handleGeometryChange_, this); EventType.CHANGE, this.handleGeometryChange_, this);
} }
this.changed(); this.changed();
}; }
/**
/**
* Set the default geometry for the feature. This will update the property * Set the default geometry for the feature. This will update the property
* with the name returned by {@link module:ol/Feature~Feature#getGeometryName}. * with the name returned by {@link module:ol/Feature~Feature#getGeometryName}.
* @param {module:ol/geom/Geometry|undefined} geometry The new geometry. * @param {module:ol/geom/Geometry|undefined} geometry The new geometry.
* @api * @api
* @observable * @observable
*/ */
Feature.prototype.setGeometry = function(geometry) { setGeometry(geometry) {
this.set(this.geometryName_, geometry); this.set(this.geometryName_, geometry);
}; }
/**
/**
* Set the style for the feature. This can be a single style object, an array * 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 * 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). * styles. If it is `null` the feature has no style (a `null` style).
@@ -241,14 +230,13 @@ Feature.prototype.setGeometry = function(geometry) {
* @api * @api
* @fires module:ol/events/Event~Event#event:change * @fires module:ol/events/Event~Event#event:change
*/ */
Feature.prototype.setStyle = function(style) { setStyle(style) {
this.style_ = style; this.style_ = style;
this.styleFunction_ = !style ? undefined : createStyleFunction(style); this.styleFunction_ = !style ? undefined : createStyleFunction(style);
this.changed(); this.changed();
}; }
/**
/**
* Set the feature id. The feature id is considered stable and may be used when * Set the feature id. The feature id is considered stable and may be used when
* requesting features or comparing identifiers returned from a remote source. * requesting features or comparing identifiers returned from a remote source.
* The feature id can be used with the * The feature id can be used with the
@@ -257,20 +245,19 @@ Feature.prototype.setStyle = function(style) {
* @api * @api
* @fires module:ol/events/Event~Event#event:change * @fires module:ol/events/Event~Event#event:change
*/ */
Feature.prototype.setId = function(id) { setId(id) {
this.id_ = id; this.id_ = id;
this.changed(); this.changed();
}; }
/**
/**
* Set the property name to be used when getting the feature's default geometry. * Set the property name to be used when getting the feature's default geometry.
* When calling {@link module:ol/Feature~Feature#getGeometry}, the value of the property with * When calling {@link module:ol/Feature~Feature#getGeometry}, the value of the property with
* this name will be returned. * this name will be returned.
* @param {string} name The property name of the default geometry. * @param {string} name The property name of the default geometry.
* @api * @api
*/ */
Feature.prototype.setGeometryName = function(name) { setGeometryName(name) {
unlisten( unlisten(
this, getChangeEventType(this.geometryName_), this, getChangeEventType(this.geometryName_),
this.handleGeometryChanged_, this); this.handleGeometryChanged_, this);
@@ -279,7 +266,10 @@ Feature.prototype.setGeometryName = function(name) {
this, getChangeEventType(this.geometryName_), this, getChangeEventType(this.geometryName_),
this.handleGeometryChanged_, this); this.handleGeometryChanged_, this);
this.handleGeometryChanged_(); this.handleGeometryChanged_();
}; }
}
inherits(Feature, BaseObject);
/** /**
+63 -76
View File
@@ -49,7 +49,8 @@ import {get as getProjection, getTransformFromProjections, identityTransform} fr
* @param {module:ol/Geolocation~Options=} opt_options Options. * @param {module:ol/Geolocation~Options=} opt_options Options.
* @api * @api
*/ */
const Geolocation = function(opt_options) { class Geolocation {
constructor(opt_options) {
BaseObject.call(this); BaseObject.call(this);
@@ -90,24 +91,20 @@ const Geolocation = function(opt_options) {
this.setTracking(options.tracking !== undefined ? options.tracking : false); this.setTracking(options.tracking !== undefined ? options.tracking : false);
}; }
inherits(Geolocation, BaseObject); /**
/**
* @inheritDoc * @inheritDoc
*/ */
Geolocation.prototype.disposeInternal = function() { disposeInternal() {
this.setTracking(false); this.setTracking(false);
BaseObject.prototype.disposeInternal.call(this); BaseObject.prototype.disposeInternal.call(this);
}; }
/**
/**
* @private * @private
*/ */
Geolocation.prototype.handleProjectionChanged_ = function() { handleProjectionChanged_() {
const projection = this.getProjection(); const projection = this.getProjection();
if (projection) { if (projection) {
this.transform_ = getTransformFromProjections( this.transform_ = getTransformFromProjections(
@@ -116,13 +113,12 @@ Geolocation.prototype.handleProjectionChanged_ = function() {
this.set(GeolocationProperty.POSITION, this.transform_(this.position_)); this.set(GeolocationProperty.POSITION, this.transform_(this.position_));
} }
} }
}; }
/**
/**
* @private * @private
*/ */
Geolocation.prototype.handleTrackingChanged_ = function() { handleTrackingChanged_() {
if (GEOLOCATION) { if (GEOLOCATION) {
const tracking = this.getTracking(); const tracking = this.getTracking();
if (tracking && this.watchId_ === undefined) { if (tracking && this.watchId_ === undefined) {
@@ -135,14 +131,13 @@ Geolocation.prototype.handleTrackingChanged_ = function() {
this.watchId_ = undefined; this.watchId_ = undefined;
} }
} }
}; }
/**
/**
* @private * @private
* @param {GeolocationPosition} position position event. * @param {GeolocationPosition} position position event.
*/ */
Geolocation.prototype.positionChange_ = function(position) { positionChange_(position) {
const coords = position.coords; const coords = position.coords;
this.set(GeolocationProperty.ACCURACY, coords.accuracy); this.set(GeolocationProperty.ACCURACY, coords.accuracy);
this.set(GeolocationProperty.ALTITUDE, this.set(GeolocationProperty.ALTITUDE,
@@ -166,75 +161,70 @@ Geolocation.prototype.positionChange_ = function(position) {
geometry.applyTransform(this.transform_); geometry.applyTransform(this.transform_);
this.set(GeolocationProperty.ACCURACY_GEOMETRY, geometry); this.set(GeolocationProperty.ACCURACY_GEOMETRY, geometry);
this.changed(); this.changed();
}; }
/** /**
* Triggered when the Geolocation returns an error. * Triggered when the Geolocation returns an error.
* @event error * @event error
* @api * @api
*/ */
/** /**
* @private * @private
* @param {GeolocationPositionError} error error object. * @param {GeolocationPositionError} error error object.
*/ */
Geolocation.prototype.positionError_ = function(error) { positionError_(error) {
error.type = EventType.ERROR; error.type = EventType.ERROR;
this.setTracking(false); this.setTracking(false);
this.dispatchEvent(/** @type {{type: string, target: undefined}} */ (error)); this.dispatchEvent(/** @type {{type: string, target: undefined}} */ (error));
}; }
/**
/**
* Get the accuracy of the position in meters. * Get the accuracy of the position in meters.
* @return {number|undefined} The accuracy of the position measurement in * @return {number|undefined} The accuracy of the position measurement in
* meters. * meters.
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.getAccuracy = function() { getAccuracy() {
return /** @type {number|undefined} */ (this.get(GeolocationProperty.ACCURACY)); return /** @type {number|undefined} */ (this.get(GeolocationProperty.ACCURACY));
}; }
/**
/**
* Get a geometry of the position accuracy. * Get a geometry of the position accuracy.
* @return {?module:ol/geom/Polygon} A geometry of the position accuracy. * @return {?module:ol/geom/Polygon} A geometry of the position accuracy.
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.getAccuracyGeometry = function() { getAccuracyGeometry() {
return ( return (
/** @type {?module:ol/geom/Polygon} */ (this.get(GeolocationProperty.ACCURACY_GEOMETRY) || null) /** @type {?module:ol/geom/Polygon} */ (this.get(GeolocationProperty.ACCURACY_GEOMETRY) || null)
); );
}; }
/**
/**
* Get the altitude associated with the position. * Get the altitude associated with the position.
* @return {number|undefined} The altitude of the position in meters above mean * @return {number|undefined} The altitude of the position in meters above mean
* sea level. * sea level.
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.getAltitude = function() { getAltitude() {
return /** @type {number|undefined} */ (this.get(GeolocationProperty.ALTITUDE)); return /** @type {number|undefined} */ (this.get(GeolocationProperty.ALTITUDE));
}; }
/**
/**
* Get the altitude accuracy of the position. * Get the altitude accuracy of the position.
* @return {number|undefined} The accuracy of the altitude measurement in * @return {number|undefined} The accuracy of the altitude measurement in
* meters. * meters.
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.getAltitudeAccuracy = function() { getAltitudeAccuracy() {
return /** @type {number|undefined} */ (this.get(GeolocationProperty.ALTITUDE_ACCURACY)); return /** @type {number|undefined} */ (this.get(GeolocationProperty.ALTITUDE_ACCURACY));
}; }
/**
/**
* Get the heading as radians clockwise from North. * Get the heading as radians clockwise from North.
* Note: depending on the browser, the heading is only defined if the `enableHighAccuracy` * Note: depending on the browser, the heading is only defined if the `enableHighAccuracy`
* is set to `true` in the tracking options. * is set to `true` in the tracking options.
@@ -242,63 +232,58 @@ Geolocation.prototype.getAltitudeAccuracy = function() {
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.getHeading = function() { getHeading() {
return /** @type {number|undefined} */ (this.get(GeolocationProperty.HEADING)); return /** @type {number|undefined} */ (this.get(GeolocationProperty.HEADING));
}; }
/**
/**
* Get the position of the device. * Get the position of the device.
* @return {module:ol/coordinate~Coordinate|undefined} The current position of the device reported * @return {module:ol/coordinate~Coordinate|undefined} The current position of the device reported
* in the current projection. * in the current projection.
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.getPosition = function() { getPosition() {
return ( return (
/** @type {module:ol/coordinate~Coordinate|undefined} */ (this.get(GeolocationProperty.POSITION)) /** @type {module:ol/coordinate~Coordinate|undefined} */ (this.get(GeolocationProperty.POSITION))
); );
}; }
/**
/**
* Get the projection associated with the position. * Get the projection associated with the position.
* @return {module:ol/proj/Projection|undefined} The projection the position is * @return {module:ol/proj/Projection|undefined} The projection the position is
* reported in. * reported in.
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.getProjection = function() { getProjection() {
return ( return (
/** @type {module:ol/proj/Projection|undefined} */ (this.get(GeolocationProperty.PROJECTION)) /** @type {module:ol/proj/Projection|undefined} */ (this.get(GeolocationProperty.PROJECTION))
); );
}; }
/**
/**
* Get the speed in meters per second. * Get the speed in meters per second.
* @return {number|undefined} The instantaneous speed of the device in meters * @return {number|undefined} The instantaneous speed of the device in meters
* per second. * per second.
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.getSpeed = function() { getSpeed() {
return /** @type {number|undefined} */ (this.get(GeolocationProperty.SPEED)); return /** @type {number|undefined} */ (this.get(GeolocationProperty.SPEED));
}; }
/**
/**
* Determine if the device location is being tracked. * Determine if the device location is being tracked.
* @return {boolean} The device location is being tracked. * @return {boolean} The device location is being tracked.
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.getTracking = function() { getTracking() {
return /** @type {boolean} */ (this.get(GeolocationProperty.TRACKING)); return /** @type {boolean} */ (this.get(GeolocationProperty.TRACKING));
}; }
/**
/**
* Get the tracking options. * Get the tracking options.
* @see http://www.w3.org/TR/geolocation-API/#position-options * @see http://www.w3.org/TR/geolocation-API/#position-options
* @return {GeolocationPositionOptions|undefined} PositionOptions as defined by * @return {GeolocationPositionOptions|undefined} PositionOptions as defined by
@@ -307,35 +292,32 @@ Geolocation.prototype.getTracking = function() {
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.getTrackingOptions = function() { getTrackingOptions() {
return /** @type {GeolocationPositionOptions|undefined} */ (this.get(GeolocationProperty.TRACKING_OPTIONS)); return /** @type {GeolocationPositionOptions|undefined} */ (this.get(GeolocationProperty.TRACKING_OPTIONS));
}; }
/**
/**
* Set the projection to use for transforming the coordinates. * Set the projection to use for transforming the coordinates.
* @param {module:ol/proj~ProjectionLike} projection The projection the position is * @param {module:ol/proj~ProjectionLike} projection The projection the position is
* reported in. * reported in.
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.setProjection = function(projection) { setProjection(projection) {
this.set(GeolocationProperty.PROJECTION, getProjection(projection)); this.set(GeolocationProperty.PROJECTION, getProjection(projection));
}; }
/**
/**
* Enable or disable tracking. * Enable or disable tracking.
* @param {boolean} tracking Enable tracking. * @param {boolean} tracking Enable tracking.
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.setTracking = function(tracking) { setTracking(tracking) {
this.set(GeolocationProperty.TRACKING, tracking); this.set(GeolocationProperty.TRACKING, tracking);
}; }
/**
/**
* Set the tracking options. * Set the tracking options.
* @see http://www.w3.org/TR/geolocation-API/#position-options * @see http://www.w3.org/TR/geolocation-API/#position-options
* @param {GeolocationPositionOptions} options PositionOptions as defined by the * @param {GeolocationPositionOptions} options PositionOptions as defined by the
@@ -344,7 +326,12 @@ Geolocation.prototype.setTracking = function(tracking) {
* @observable * @observable
* @api * @api
*/ */
Geolocation.prototype.setTrackingOptions = function(options) { setTrackingOptions(options) {
this.set(GeolocationProperty.TRACKING_OPTIONS, options); this.set(GeolocationProperty.TRACKING_OPTIONS, options);
}; }
}
inherits(Geolocation, BaseObject);
export default Geolocation; export default Geolocation;
+47 -57
View File
@@ -116,7 +116,8 @@ const INTERVALS = [
* @param {module:ol/Graticule~Options=} opt_options Options. * @param {module:ol/Graticule~Options=} opt_options Options.
* @api * @api
*/ */
const Graticule = function(opt_options) { class Graticule {
constructor(opt_options) {
const options = opt_options || {}; const options = opt_options || {};
/** /**
@@ -317,10 +318,9 @@ const Graticule = function(opt_options) {
} }
this.setMap(options.map !== undefined ? options.map : null); this.setMap(options.map !== undefined ? options.map : null);
}; }
/**
/**
* @param {number} lon Longitude. * @param {number} lon Longitude.
* @param {number} minLat Minimal latitude. * @param {number} minLat Minimal latitude.
* @param {number} maxLat Maximal latitude. * @param {number} maxLat Maximal latitude.
@@ -330,7 +330,7 @@ const Graticule = function(opt_options) {
* @return {number} Index. * @return {number} Index.
* @private * @private
*/ */
Graticule.prototype.addMeridian_ = function(lon, minLat, maxLat, squaredTolerance, extent, index) { addMeridian_(lon, minLat, maxLat, squaredTolerance, extent, index) {
const lineString = this.getMeridian_(lon, minLat, maxLat, squaredTolerance, index); const lineString = this.getMeridian_(lon, minLat, maxLat, squaredTolerance, index);
if (intersects(lineString.getExtent(), extent)) { if (intersects(lineString.getExtent(), extent)) {
if (this.meridiansLabels_) { if (this.meridiansLabels_) {
@@ -343,16 +343,16 @@ Graticule.prototype.addMeridian_ = function(lon, minLat, maxLat, squaredToleranc
this.meridians_[index++] = lineString; this.meridians_[index++] = lineString;
} }
return index; return index;
}; }
/** /**
* @param {module:ol/geom/LineString} lineString Meridian * @param {module:ol/geom/LineString} lineString Meridian
* @param {module:ol/extent~Extent} extent Extent. * @param {module:ol/extent~Extent} extent Extent.
* @param {number} index Index. * @param {number} index Index.
* @return {module:ol/geom/Point} Meridian point. * @return {module:ol/geom/Point} Meridian point.
* @private * @private
*/ */
Graticule.prototype.getMeridianPoint_ = function(lineString, extent, index) { getMeridianPoint_(lineString, extent, index) {
const flatCoordinates = lineString.getFlatCoordinates(); const flatCoordinates = lineString.getFlatCoordinates();
const clampedBottom = Math.max(extent[1], flatCoordinates[1]); const clampedBottom = Math.max(extent[1], flatCoordinates[1]);
const clampedTop = Math.min(extent[3], flatCoordinates[flatCoordinates.length - 1]); const clampedTop = Math.min(extent[3], flatCoordinates[flatCoordinates.length - 1]);
@@ -368,10 +368,9 @@ Graticule.prototype.getMeridianPoint_ = function(lineString, extent, index) {
point = new Point(coordinate); point = new Point(coordinate);
} }
return point; return point;
}; }
/**
/**
* @param {number} lat Latitude. * @param {number} lat Latitude.
* @param {number} minLon Minimal longitude. * @param {number} minLon Minimal longitude.
* @param {number} maxLon Maximal longitude. * @param {number} maxLon Maximal longitude.
@@ -381,7 +380,7 @@ Graticule.prototype.getMeridianPoint_ = function(lineString, extent, index) {
* @return {number} Index. * @return {number} Index.
* @private * @private
*/ */
Graticule.prototype.addParallel_ = function(lat, minLon, maxLon, squaredTolerance, extent, index) { addParallel_(lat, minLon, maxLon, squaredTolerance, extent, index) {
const lineString = this.getParallel_(lat, minLon, maxLon, squaredTolerance, index); const lineString = this.getParallel_(lat, minLon, maxLon, squaredTolerance, index);
if (intersects(lineString.getExtent(), extent)) { if (intersects(lineString.getExtent(), extent)) {
if (this.parallelsLabels_) { if (this.parallelsLabels_) {
@@ -394,17 +393,16 @@ Graticule.prototype.addParallel_ = function(lat, minLon, maxLon, squaredToleranc
this.parallels_[index++] = lineString; this.parallels_[index++] = lineString;
} }
return index; return index;
}; }
/**
/**
* @param {module:ol/geom/LineString} lineString Parallels. * @param {module:ol/geom/LineString} lineString Parallels.
* @param {module:ol/extent~Extent} extent Extent. * @param {module:ol/extent~Extent} extent Extent.
* @param {number} index Index. * @param {number} index Index.
* @return {module:ol/geom/Point} Parallel point. * @return {module:ol/geom/Point} Parallel point.
* @private * @private
*/ */
Graticule.prototype.getParallelPoint_ = function(lineString, extent, index) { getParallelPoint_(lineString, extent, index) {
const flatCoordinates = lineString.getFlatCoordinates(); const flatCoordinates = lineString.getFlatCoordinates();
const clampedLeft = Math.max(extent[0], flatCoordinates[0]); const clampedLeft = Math.max(extent[0], flatCoordinates[0]);
const clampedRight = Math.min(extent[2], flatCoordinates[flatCoordinates.length - 2]); const clampedRight = Math.min(extent[2], flatCoordinates[flatCoordinates.length - 2]);
@@ -420,17 +418,16 @@ Graticule.prototype.getParallelPoint_ = function(lineString, extent, index) {
point = new Point(coordinate); point = new Point(coordinate);
} }
return point; return point;
}; }
/**
/**
* @param {module:ol/extent~Extent} extent Extent. * @param {module:ol/extent~Extent} extent Extent.
* @param {module:ol/coordinate~Coordinate} center Center. * @param {module:ol/coordinate~Coordinate} center Center.
* @param {number} resolution Resolution. * @param {number} resolution Resolution.
* @param {number} squaredTolerance Squared tolerance. * @param {number} squaredTolerance Squared tolerance.
* @private * @private
*/ */
Graticule.prototype.createGraticule_ = function(extent, center, resolution, squaredTolerance) { createGraticule_(extent, center, resolution, squaredTolerance) {
const interval = this.getInterval_(resolution); const interval = this.getInterval_(resolution);
if (interval == -1) { if (interval == -1) {
@@ -515,15 +512,14 @@ Graticule.prototype.createGraticule_ = function(extent, center, resolution, squa
this.parallelsLabels_.length = idx; this.parallelsLabels_.length = idx;
} }
}; }
/**
/**
* @param {number} resolution Resolution. * @param {number} resolution Resolution.
* @return {number} The interval in degrees. * @return {number} The interval in degrees.
* @private * @private
*/ */
Graticule.prototype.getInterval_ = function(resolution) { getInterval_(resolution) {
const centerLon = this.projectionCenterLonLat_[0]; const centerLon = this.projectionCenterLonLat_[0];
const centerLat = this.projectionCenterLonLat_[1]; const centerLat = this.projectionCenterLonLat_[1];
let interval = -1; let interval = -1;
@@ -547,20 +543,18 @@ Graticule.prototype.getInterval_ = function(resolution) {
interval = INTERVALS[i]; interval = INTERVALS[i];
} }
return interval; return interval;
}; }
/**
/**
* Get the map associated with this graticule. * Get the map associated with this graticule.
* @return {module:ol/PluggableMap} The map. * @return {module:ol/PluggableMap} The map.
* @api * @api
*/ */
Graticule.prototype.getMap = function() { getMap() {
return this.map_; return this.map_;
}; }
/**
/**
* @param {number} lon Longitude. * @param {number} lon Longitude.
* @param {number} minLat Minimal latitude. * @param {number} minLat Minimal latitude.
* @param {number} maxLat Maximal latitude. * @param {number} maxLat Maximal latitude.
@@ -569,7 +563,7 @@ Graticule.prototype.getMap = function() {
* @param {number} index Index. * @param {number} index Index.
* @private * @private
*/ */
Graticule.prototype.getMeridian_ = function(lon, minLat, maxLat, squaredTolerance, index) { getMeridian_(lon, minLat, maxLat, squaredTolerance, index) {
const flatCoordinates = meridian(lon, minLat, maxLat, this.projection_, squaredTolerance); const flatCoordinates = meridian(lon, minLat, maxLat, this.projection_, squaredTolerance);
let lineString = this.meridians_[index]; let lineString = this.meridians_[index];
if (!lineString) { if (!lineString) {
@@ -579,20 +573,18 @@ Graticule.prototype.getMeridian_ = function(lon, minLat, maxLat, squaredToleranc
lineString.changed(); lineString.changed();
} }
return lineString; return lineString;
}; }
/**
/**
* Get the list of meridians. Meridians are lines of equal longitude. * Get the list of meridians. Meridians are lines of equal longitude.
* @return {Array.<module:ol/geom/LineString>} The meridians. * @return {Array.<module:ol/geom/LineString>} The meridians.
* @api * @api
*/ */
Graticule.prototype.getMeridians = function() { getMeridians() {
return this.meridians_; return this.meridians_;
}; }
/**
/**
* @param {number} lat Latitude. * @param {number} lat Latitude.
* @param {number} minLon Minimal longitude. * @param {number} minLon Minimal longitude.
* @param {number} maxLon Maximal longitude. * @param {number} maxLon Maximal longitude.
@@ -601,7 +593,7 @@ Graticule.prototype.getMeridians = function() {
* @param {number} index Index. * @param {number} index Index.
* @private * @private
*/ */
Graticule.prototype.getParallel_ = function(lat, minLon, maxLon, squaredTolerance, index) { getParallel_(lat, minLon, maxLon, squaredTolerance, index) {
const flatCoordinates = parallel(lat, minLon, maxLon, this.projection_, squaredTolerance); const flatCoordinates = parallel(lat, minLon, maxLon, this.projection_, squaredTolerance);
let lineString = this.parallels_[index]; let lineString = this.parallels_[index];
if (!lineString) { if (!lineString) {
@@ -611,24 +603,22 @@ Graticule.prototype.getParallel_ = function(lat, minLon, maxLon, squaredToleranc
lineString.changed(); lineString.changed();
} }
return lineString; return lineString;
}; }
/**
/**
* Get the list of parallels. Parallels are lines of equal latitude. * Get the list of parallels. Parallels are lines of equal latitude.
* @return {Array.<module:ol/geom/LineString>} The parallels. * @return {Array.<module:ol/geom/LineString>} The parallels.
* @api * @api
*/ */
Graticule.prototype.getParallels = function() { getParallels() {
return this.parallels_; return this.parallels_;
}; }
/**
/**
* @param {module:ol/render/Event} e Event. * @param {module:ol/render/Event} e Event.
* @private * @private
*/ */
Graticule.prototype.handlePostCompose_ = function(e) { handlePostCompose_(e) {
const vectorContext = e.vectorContext; const vectorContext = e.vectorContext;
const frameState = e.frameState; const frameState = e.frameState;
const extent = frameState.extent; const extent = frameState.extent;
@@ -677,14 +667,13 @@ Graticule.prototype.handlePostCompose_ = function(e) {
vectorContext.drawGeometry(labelData.geom); vectorContext.drawGeometry(labelData.geom);
} }
} }
}; }
/**
/**
* @param {module:ol/proj/Projection} projection Projection. * @param {module:ol/proj/Projection} projection Projection.
* @private * @private
*/ */
Graticule.prototype.updateProjectionInfo_ = function(projection) { updateProjectionInfo_(projection) {
const epsg4326Projection = getProjection('EPSG:4326'); const epsg4326Projection = getProjection('EPSG:4326');
const worldExtent = projection.getWorldExtent(); const worldExtent = projection.getWorldExtent();
@@ -707,16 +696,15 @@ Graticule.prototype.updateProjectionInfo_ = function(projection) {
this.projectionCenterLonLat_ = this.toLonLatTransform_(getCenter(projection.getExtent())); this.projectionCenterLonLat_ = this.toLonLatTransform_(getCenter(projection.getExtent()));
this.projection_ = projection; this.projection_ = projection;
}; }
/**
/**
* Set the map for this graticule. The graticule will be rendered on the * Set the map for this graticule. The graticule will be rendered on the
* provided map. * provided map.
* @param {module:ol/PluggableMap} map Map. * @param {module:ol/PluggableMap} map Map.
* @api * @api
*/ */
Graticule.prototype.setMap = function(map) { setMap(map) {
if (this.map_) { if (this.map_) {
unlistenByKey(this.postcomposeListenerKey_); unlistenByKey(this.postcomposeListenerKey_);
this.postcomposeListenerKey_ = null; this.postcomposeListenerKey_ = null;
@@ -727,5 +715,7 @@ Graticule.prototype.setMap = function(map) {
map.render(); map.render();
} }
this.map_ = map; this.map_ = map;
}; }
}
export default Graticule; export default Graticule;
+25 -28
View File
@@ -38,7 +38,8 @@ import {getHeight} from './extent.js';
* @param {?string} crossOrigin Cross origin. * @param {?string} crossOrigin Cross origin.
* @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function. * @param {module:ol/Image~LoadFunction} imageLoadFunction Image load function.
*/ */
const ImageWrapper = function(extent, resolution, pixelRatio, src, crossOrigin, imageLoadFunction) { class ImageWrapper {
constructor(extent, resolution, pixelRatio, src, crossOrigin, imageLoadFunction) {
ImageBase.call(this, extent, resolution, pixelRatio, ImageState.IDLE); ImageBase.call(this, extent, resolution, pixelRatio, ImageState.IDLE);
@@ -75,55 +76,49 @@ const ImageWrapper = function(extent, resolution, pixelRatio, src, crossOrigin,
*/ */
this.imageLoadFunction_ = imageLoadFunction; this.imageLoadFunction_ = imageLoadFunction;
}; }
inherits(ImageWrapper, ImageBase); /**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
ImageWrapper.prototype.getImage = function() { getImage() {
return this.image_; return this.image_;
}; }
/**
/**
* Tracks loading or read errors. * Tracks loading or read errors.
* *
* @private * @private
*/ */
ImageWrapper.prototype.handleImageError_ = function() { handleImageError_() {
this.state = ImageState.ERROR; this.state = ImageState.ERROR;
this.unlistenImage_(); this.unlistenImage_();
this.changed(); this.changed();
}; }
/**
/**
* Tracks successful image load. * Tracks successful image load.
* *
* @private * @private
*/ */
ImageWrapper.prototype.handleImageLoad_ = function() { handleImageLoad_() {
if (this.resolution === undefined) { if (this.resolution === undefined) {
this.resolution = getHeight(this.extent) / this.image_.height; this.resolution = getHeight(this.extent) / this.image_.height;
} }
this.state = ImageState.LOADED; this.state = ImageState.LOADED;
this.unlistenImage_(); this.unlistenImage_();
this.changed(); this.changed();
}; }
/**
/**
* Load the image or retry if loading previously failed. * Load the image or retry if loading previously failed.
* Loading is taken care of by the tile queue, and calling this method is * Loading is taken care of by the tile queue, and calling this method is
* only needed for preloading or for reloading in case of an error. * only needed for preloading or for reloading in case of an error.
* @override * @override
* @api * @api
*/ */
ImageWrapper.prototype.load = function() { load() {
if (this.state == ImageState.IDLE || this.state == ImageState.ERROR) { if (this.state == ImageState.IDLE || this.state == ImageState.ERROR) {
this.state = ImageState.LOADING; this.state = ImageState.LOADING;
this.changed(); this.changed();
@@ -135,25 +130,27 @@ ImageWrapper.prototype.load = function() {
]; ];
this.imageLoadFunction_(this, this.src_); this.imageLoadFunction_(this, this.src_);
} }
}; }
/**
/**
* @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image Image. * @param {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} image Image.
*/ */
ImageWrapper.prototype.setImage = function(image) { setImage(image) {
this.image_ = image; this.image_ = image;
}; }
/**
/**
* Discards event handlers which listen for load completion or errors. * Discards event handlers which listen for load completion or errors.
* *
* @private * @private
*/ */
ImageWrapper.prototype.unlistenImage_ = function() { unlistenImage_() {
this.imageListenerKeys_.forEach(unlistenByKey); this.imageListenerKeys_.forEach(unlistenByKey);
this.imageListenerKeys_ = null; this.imageListenerKeys_ = null;
}; }
}
inherits(ImageWrapper, ImageBase);
export default ImageWrapper; export default ImageWrapper;
+51 -55
View File
@@ -14,7 +14,8 @@ import EventType from './events/EventType.js';
* @param {number} pixelRatio Pixel ratio. * @param {number} pixelRatio Pixel ratio.
* @param {module:ol/ImageState} state State. * @param {module:ol/ImageState} state State.
*/ */
const ImageBase = function(extent, resolution, pixelRatio, state) { class ImageBase {
constructor(extent, resolution, pixelRatio, state) {
EventTarget.call(this); EventTarget.call(this);
@@ -42,62 +43,57 @@ const ImageBase = function(extent, resolution, pixelRatio, state) {
*/ */
this.state = state; this.state = state;
}; }
/**
* @protected
*/
changed() {
this.dispatchEvent(EventType.CHANGE);
}
/**
* @return {module:ol/extent~Extent} Extent.
*/
getExtent() {
return this.extent;
}
/**
* @abstract
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
*/
getImage() {}
/**
* @return {number} PixelRatio.
*/
getPixelRatio() {
return this.pixelRatio_;
}
/**
* @return {number} Resolution.
*/
getResolution() {
return /** @type {number} */ (this.resolution);
}
/**
* @return {module:ol/ImageState} State.
*/
getState() {
return this.state;
}
/**
* Load not yet loaded URI.
* @abstract
*/
load() {}
}
inherits(ImageBase, EventTarget); inherits(ImageBase, EventTarget);
/**
* @protected
*/
ImageBase.prototype.changed = function() {
this.dispatchEvent(EventType.CHANGE);
};
/**
* @return {module:ol/extent~Extent} Extent.
*/
ImageBase.prototype.getExtent = function() {
return this.extent;
};
/**
* @abstract
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
*/
ImageBase.prototype.getImage = function() {};
/**
* @return {number} PixelRatio.
*/
ImageBase.prototype.getPixelRatio = function() {
return this.pixelRatio_;
};
/**
* @return {number} Resolution.
*/
ImageBase.prototype.getResolution = function() {
return /** @type {number} */ (this.resolution);
};
/**
* @return {module:ol/ImageState} State.
*/
ImageBase.prototype.getState = function() {
return this.state;
};
/**
* Load not yet loaded URI.
* @abstract
*/
ImageBase.prototype.load = function() {};
export default ImageBase; export default ImageBase;
+20 -20
View File
@@ -26,7 +26,8 @@ import ImageState from './ImageState.js';
* @param {module:ol/ImageCanvas~Loader=} opt_loader Optional loader function to * @param {module:ol/ImageCanvas~Loader=} opt_loader Optional loader function to
* support asynchronous canvas drawing. * support asynchronous canvas drawing.
*/ */
const ImageCanvas = function(extent, resolution, pixelRatio, canvas, opt_loader) { class ImageCanvas {
constructor(extent, resolution, pixelRatio, canvas, opt_loader) {
/** /**
* Optional canvas loader function. * Optional canvas loader function.
@@ -51,26 +52,22 @@ const ImageCanvas = function(extent, resolution, pixelRatio, canvas, opt_loader)
*/ */
this.error_ = null; this.error_ = null;
}; }
inherits(ImageCanvas, ImageBase); /**
/**
* Get any error associated with asynchronous rendering. * Get any error associated with asynchronous rendering.
* @return {Error} Any error that occurred during rendering. * @return {Error} Any error that occurred during rendering.
*/ */
ImageCanvas.prototype.getError = function() { getError() {
return this.error_; return this.error_;
}; }
/**
/**
* Handle async drawing complete. * Handle async drawing complete.
* @param {Error} err Any error during drawing. * @param {Error} err Any error during drawing.
* @private * @private
*/ */
ImageCanvas.prototype.handleLoad_ = function(err) { handleLoad_(err) {
if (err) { if (err) {
this.error_ = err; this.error_ = err;
this.state = ImageState.ERROR; this.state = ImageState.ERROR;
@@ -78,25 +75,28 @@ ImageCanvas.prototype.handleLoad_ = function(err) {
this.state = ImageState.LOADED; this.state = ImageState.LOADED;
} }
this.changed(); this.changed();
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
ImageCanvas.prototype.load = function() { load() {
if (this.state == ImageState.IDLE) { if (this.state == ImageState.IDLE) {
this.state = ImageState.LOADING; this.state = ImageState.LOADING;
this.changed(); this.changed();
this.loader_(this.handleLoad_.bind(this)); this.loader_(this.handleLoad_.bind(this));
} }
}; }
/**
/**
* @return {HTMLCanvasElement} Canvas element. * @return {HTMLCanvasElement} Canvas element.
*/ */
ImageCanvas.prototype.getImage = function() { getImage() {
return this.canvas_; return this.canvas_;
}; }
}
inherits(ImageCanvas, ImageBase);
export default ImageCanvas; export default ImageCanvas;
+27 -32
View File
@@ -24,7 +24,8 @@ import EventType from './events/EventType.js';
* @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function. * @param {module:ol/Tile~LoadFunction} tileLoadFunction Tile load function.
* @param {module:ol/Tile~Options=} opt_options Tile options. * @param {module:ol/Tile~Options=} opt_options Tile options.
*/ */
const ImageTile = function(tileCoord, state, src, crossOrigin, tileLoadFunction, opt_options) { class ImageTile {
constructor(tileCoord, state, src, crossOrigin, tileLoadFunction, opt_options) {
Tile.call(this, tileCoord, state, opt_options); Tile.call(this, tileCoord, state, opt_options);
@@ -63,15 +64,12 @@ const ImageTile = function(tileCoord, state, src, crossOrigin, tileLoadFunction,
*/ */
this.tileLoadFunction_ = tileLoadFunction; this.tileLoadFunction_ = tileLoadFunction;
}; }
inherits(ImageTile, Tile); /**
/**
* @inheritDoc * @inheritDoc
*/ */
ImageTile.prototype.disposeInternal = function() { disposeInternal() {
if (this.state == TileState.LOADING) { if (this.state == TileState.LOADING) {
this.unlistenImage_(); this.unlistenImage_();
this.image_ = getBlankImage(); this.image_ = getBlankImage();
@@ -82,46 +80,42 @@ ImageTile.prototype.disposeInternal = function() {
this.state = TileState.ABORT; this.state = TileState.ABORT;
this.changed(); this.changed();
Tile.prototype.disposeInternal.call(this); Tile.prototype.disposeInternal.call(this);
}; }
/**
/**
* Get the HTML image element for this tile (may be a Canvas, Image, or Video). * Get the HTML image element for this tile (may be a Canvas, Image, or Video).
* @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image. * @return {HTMLCanvasElement|HTMLImageElement|HTMLVideoElement} Image.
* @api * @api
*/ */
ImageTile.prototype.getImage = function() { getImage() {
return this.image_; return this.image_;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
ImageTile.prototype.getKey = function() { getKey() {
return this.src_; return this.src_;
}; }
/**
/**
* Tracks loading or read errors. * Tracks loading or read errors.
* *
* @private * @private
*/ */
ImageTile.prototype.handleImageError_ = function() { handleImageError_() {
this.state = TileState.ERROR; this.state = TileState.ERROR;
this.unlistenImage_(); this.unlistenImage_();
this.image_ = getBlankImage(); this.image_ = getBlankImage();
this.changed(); this.changed();
}; }
/**
/**
* Tracks successful image load. * Tracks successful image load.
* *
* @private * @private
*/ */
ImageTile.prototype.handleImageLoad_ = function() { handleImageLoad_() {
if (this.image_.naturalWidth && this.image_.naturalHeight) { if (this.image_.naturalWidth && this.image_.naturalHeight) {
this.state = TileState.LOADED; this.state = TileState.LOADED;
} else { } else {
@@ -129,14 +123,13 @@ ImageTile.prototype.handleImageLoad_ = function() {
} }
this.unlistenImage_(); this.unlistenImage_();
this.changed(); this.changed();
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
ImageTile.prototype.load = function() { load() {
if (this.state == TileState.ERROR) { if (this.state == TileState.ERROR) {
this.state = TileState.IDLE; this.state = TileState.IDLE;
this.image_ = new Image(); this.image_ = new Image();
@@ -155,18 +148,20 @@ ImageTile.prototype.load = function() {
]; ];
this.tileLoadFunction_(this, this.src_); this.tileLoadFunction_(this, this.src_);
} }
}; }
/**
/**
* Discards event handlers which listen for load completion or errors. * Discards event handlers which listen for load completion or errors.
* *
* @private * @private
*/ */
ImageTile.prototype.unlistenImage_ = function() { unlistenImage_() {
this.imageListenerKeys_.forEach(unlistenByKey); this.imageListenerKeys_.forEach(unlistenByKey);
this.imageListenerKeys_ = null; this.imageListenerKeys_ = null;
}; }
}
inherits(ImageTile, Tile);
/** /**
+20 -22
View File
@@ -14,7 +14,8 @@
* @struct * @struct
* @api * @api
*/ */
const Kinetic = function(decay, minVelocity, delay) { class Kinetic {
constructor(decay, minVelocity, delay) {
/** /**
* @private * @private
@@ -51,32 +52,29 @@ const Kinetic = function(decay, minVelocity, delay) {
* @type {number} * @type {number}
*/ */
this.initialVelocity_ = 0; this.initialVelocity_ = 0;
}; }
/**
/**
* FIXME empty description for jsdoc * FIXME empty description for jsdoc
*/ */
Kinetic.prototype.begin = function() { begin() {
this.points_.length = 0; this.points_.length = 0;
this.angle_ = 0; this.angle_ = 0;
this.initialVelocity_ = 0; this.initialVelocity_ = 0;
}; }
/**
/**
* @param {number} x X. * @param {number} x X.
* @param {number} y Y. * @param {number} y Y.
*/ */
Kinetic.prototype.update = function(x, y) { update(x, y) {
this.points_.push(x, y, Date.now()); this.points_.push(x, y, Date.now());
}; }
/**
/**
* @return {boolean} Whether we should do kinetic animation. * @return {boolean} Whether we should do kinetic animation.
*/ */
Kinetic.prototype.end = function() { end() {
if (this.points_.length < 6) { if (this.points_.length < 6) {
// at least 2 points are required (i.e. there must be at least 6 elements // at least 2 points are required (i.e. there must be at least 6 elements
// in the array) // in the array)
@@ -109,21 +107,21 @@ Kinetic.prototype.end = function() {
this.angle_ = Math.atan2(dy, dx); this.angle_ = Math.atan2(dy, dx);
this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / duration; this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / duration;
return this.initialVelocity_ > this.minVelocity_; return this.initialVelocity_ > this.minVelocity_;
}; }
/**
/**
* @return {number} Total distance travelled (pixels). * @return {number} Total distance travelled (pixels).
*/ */
Kinetic.prototype.getDistance = function() { getDistance() {
return (this.minVelocity_ - this.initialVelocity_) / this.decay_; return (this.minVelocity_ - this.initialVelocity_) / this.decay_;
}; }
/**
/**
* @return {number} Angle of the kinetic panning animation (radians). * @return {number} Angle of the kinetic panning animation (radians).
*/ */
Kinetic.prototype.getAngle = function() { getAngle() {
return this.angle_; return this.angle_;
}; }
}
export default Kinetic; export default Kinetic;
+8 -6
View File
@@ -66,7 +66,8 @@ import CanvasVectorTileLayerRenderer from './renderer/canvas/VectorTileLayer.js'
* @fires module:ol/render/Event~RenderEvent#precompose * @fires module:ol/render/Event~RenderEvent#precompose
* @api * @api
*/ */
const Map = function(options) { class Map {
constructor(options) {
options = assign({}, options); options = assign({}, options);
if (!options.controls) { if (!options.controls) {
options.controls = defaultControls(); options.controls = defaultControls();
@@ -76,11 +77,9 @@ const Map = function(options) {
} }
PluggableMap.call(this, options); PluggableMap.call(this, options);
}; }
inherits(Map, PluggableMap); createRenderer() {
Map.prototype.createRenderer = function() {
const renderer = new CanvasMapRenderer(this); const renderer = new CanvasMapRenderer(this);
renderer.registerLayerRenderers([ renderer.registerLayerRenderers([
CanvasImageLayerRenderer, CanvasImageLayerRenderer,
@@ -89,6 +88,9 @@ Map.prototype.createRenderer = function() {
CanvasVectorTileLayerRenderer CanvasVectorTileLayerRenderer
]); ]);
return renderer; return renderer;
}; }
}
inherits(Map, PluggableMap);
export default Map; export default Map;
+14 -12
View File
@@ -17,7 +17,8 @@ import MapEvent from './MapEvent.js';
* @param {boolean=} opt_dragging Is the map currently being dragged? * @param {boolean=} opt_dragging Is the map currently being dragged?
* @param {?module:ol/PluggableMap~FrameState=} opt_frameState Frame state. * @param {?module:ol/PluggableMap~FrameState=} opt_frameState Frame state.
*/ */
const MapBrowserEvent = function(type, map, browserEvent, opt_dragging, opt_frameState) { class MapBrowserEvent {
constructor(type, map, browserEvent, opt_dragging, opt_frameState) {
MapEvent.call(this, type, map, opt_frameState); MapEvent.call(this, type, map, opt_frameState);
@@ -52,31 +53,32 @@ const MapBrowserEvent = function(type, map, browserEvent, opt_dragging, opt_fram
*/ */
this.dragging = opt_dragging !== undefined ? opt_dragging : false; this.dragging = opt_dragging !== undefined ? opt_dragging : false;
}; }
inherits(MapBrowserEvent, MapEvent); /**
/**
* Prevents the default browser action. * Prevents the default browser action.
* @see https://developer.mozilla.org/en-US/docs/Web/API/event.preventDefault * @see https://developer.mozilla.org/en-US/docs/Web/API/event.preventDefault
* @override * @override
* @api * @api
*/ */
MapBrowserEvent.prototype.preventDefault = function() { preventDefault() {
MapEvent.prototype.preventDefault.call(this); MapEvent.prototype.preventDefault.call(this);
this.originalEvent.preventDefault(); this.originalEvent.preventDefault();
}; }
/**
/**
* Prevents further propagation of the current event. * Prevents further propagation of the current event.
* @see https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation * @see https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation
* @override * @override
* @api * @api
*/ */
MapBrowserEvent.prototype.stopPropagation = function() { stopPropagation() {
MapEvent.prototype.stopPropagation.call(this); MapEvent.prototype.stopPropagation.call(this);
this.originalEvent.stopPropagation(); this.originalEvent.stopPropagation();
}; }
}
inherits(MapBrowserEvent, MapEvent);
export default MapBrowserEvent; export default MapBrowserEvent;
+35 -40
View File
@@ -18,7 +18,8 @@ import PointerEventHandler from './pointer/PointerEventHandler.js';
* @constructor * @constructor
* @extends {module:ol/events/EventTarget} * @extends {module:ol/events/EventTarget}
*/ */
const MapBrowserEventHandler = function(map, moveTolerance) { class MapBrowserEventHandler {
constructor(map, moveTolerance) {
EventTarget.call(this); EventTarget.call(this);
@@ -110,17 +111,14 @@ const MapBrowserEventHandler = function(map, moveTolerance) {
PointerEventType.POINTERMOVE, PointerEventType.POINTERMOVE,
this.relayEvent_, this); this.relayEvent_, this);
}; }
inherits(MapBrowserEventHandler, EventTarget); /**
/**
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer * @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
* event. * event.
* @private * @private
*/ */
MapBrowserEventHandler.prototype.emulateClick_ = function(pointerEvent) { emulateClick_(pointerEvent) {
let newEvent = new MapBrowserPointerEvent( let newEvent = new MapBrowserPointerEvent(
MapBrowserEventType.CLICK, this.map_, pointerEvent); MapBrowserEventType.CLICK, this.map_, pointerEvent);
this.dispatchEvent(newEvent); this.dispatchEvent(newEvent);
@@ -140,17 +138,16 @@ MapBrowserEventHandler.prototype.emulateClick_ = function(pointerEvent) {
this.dispatchEvent(newEvent); this.dispatchEvent(newEvent);
}.bind(this), 250); }.bind(this), 250);
} }
}; }
/**
/**
* Keeps track on how many pointers are currently active. * Keeps track on how many pointers are currently active.
* *
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer * @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
* event. * event.
* @private * @private
*/ */
MapBrowserEventHandler.prototype.updateActivePointers_ = function(pointerEvent) { updateActivePointers_(pointerEvent) {
const event = pointerEvent; const event = pointerEvent;
if (event.type == MapBrowserEventType.POINTERUP || if (event.type == MapBrowserEventType.POINTERUP ||
@@ -160,15 +157,14 @@ MapBrowserEventHandler.prototype.updateActivePointers_ = function(pointerEvent)
this.trackedTouches_[event.pointerId] = true; this.trackedTouches_[event.pointerId] = true;
} }
this.activePointers_ = Object.keys(this.trackedTouches_).length; this.activePointers_ = Object.keys(this.trackedTouches_).length;
}; }
/**
/**
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer * @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
* event. * event.
* @private * @private
*/ */
MapBrowserEventHandler.prototype.handlePointerUp_ = function(pointerEvent) { handlePointerUp_(pointerEvent) {
this.updateActivePointers_(pointerEvent); this.updateActivePointers_(pointerEvent);
const newEvent = new MapBrowserPointerEvent( const newEvent = new MapBrowserPointerEvent(
MapBrowserEventType.POINTERUP, this.map_, pointerEvent); MapBrowserEventType.POINTERUP, this.map_, pointerEvent);
@@ -192,26 +188,24 @@ MapBrowserEventHandler.prototype.handlePointerUp_ = function(pointerEvent) {
this.documentPointerEventHandler_.dispose(); this.documentPointerEventHandler_.dispose();
this.documentPointerEventHandler_ = null; this.documentPointerEventHandler_ = null;
} }
}; }
/**
/**
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer * @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
* event. * event.
* @return {boolean} If the left mouse button was pressed. * @return {boolean} If the left mouse button was pressed.
* @private * @private
*/ */
MapBrowserEventHandler.prototype.isMouseActionButton_ = function(pointerEvent) { isMouseActionButton_(pointerEvent) {
return pointerEvent.button === 0; return pointerEvent.button === 0;
}; }
/**
/**
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer * @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
* event. * event.
* @private * @private
*/ */
MapBrowserEventHandler.prototype.handlePointerDown_ = function(pointerEvent) { handlePointerDown_(pointerEvent) {
this.updateActivePointers_(pointerEvent); this.updateActivePointers_(pointerEvent);
const newEvent = new MapBrowserPointerEvent( const newEvent = new MapBrowserPointerEvent(
MapBrowserEventType.POINTERDOWN, this.map_, pointerEvent); MapBrowserEventType.POINTERDOWN, this.map_, pointerEvent);
@@ -252,15 +246,14 @@ MapBrowserEventHandler.prototype.handlePointerDown_ = function(pointerEvent) {
this.handlePointerUp_, this) this.handlePointerUp_, this)
); );
} }
}; }
/**
/**
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer * @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
* event. * event.
* @private * @private
*/ */
MapBrowserEventHandler.prototype.handlePointerMove_ = function(pointerEvent) { handlePointerMove_(pointerEvent) {
// Between pointerdown and pointerup, pointermove events are triggered. // Between pointerdown and pointerup, pointermove events are triggered.
// To avoid a 'false' touchmove event to be dispatched, we test if the pointer // To avoid a 'false' touchmove event to be dispatched, we test if the pointer
// moved a significant distance. // moved a significant distance.
@@ -277,40 +270,37 @@ MapBrowserEventHandler.prototype.handlePointerMove_ = function(pointerEvent) {
// https://code.google.com/p/android/issues/detail?id=19827 // https://code.google.com/p/android/issues/detail?id=19827
// ex: Galaxy Tab P3110 + Android 4.1.1 // ex: Galaxy Tab P3110 + Android 4.1.1
pointerEvent.preventDefault(); pointerEvent.preventDefault();
}; }
/**
/**
* Wrap and relay a pointer event. Note that this requires that the type * Wrap and relay a pointer event. Note that this requires that the type
* string for the MapBrowserPointerEvent matches the PointerEvent type. * string for the MapBrowserPointerEvent matches the PointerEvent type.
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer * @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
* event. * event.
* @private * @private
*/ */
MapBrowserEventHandler.prototype.relayEvent_ = function(pointerEvent) { relayEvent_(pointerEvent) {
const dragging = !!(this.down_ && this.isMoving_(pointerEvent)); const dragging = !!(this.down_ && this.isMoving_(pointerEvent));
this.dispatchEvent(new MapBrowserPointerEvent( this.dispatchEvent(new MapBrowserPointerEvent(
pointerEvent.type, this.map_, pointerEvent, dragging)); pointerEvent.type, this.map_, pointerEvent, dragging));
}; }
/**
/**
* @param {module:ol/pointer/PointerEvent} pointerEvent Pointer * @param {module:ol/pointer/PointerEvent} pointerEvent Pointer
* event. * event.
* @return {boolean} Is moving. * @return {boolean} Is moving.
* @private * @private
*/ */
MapBrowserEventHandler.prototype.isMoving_ = function(pointerEvent) { isMoving_(pointerEvent) {
return this.dragging_ || return this.dragging_ ||
Math.abs(pointerEvent.clientX - this.down_.clientX) > this.moveTolerance_ || Math.abs(pointerEvent.clientX - this.down_.clientX) > this.moveTolerance_ ||
Math.abs(pointerEvent.clientY - this.down_.clientY) > this.moveTolerance_; Math.abs(pointerEvent.clientY - this.down_.clientY) > this.moveTolerance_;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
MapBrowserEventHandler.prototype.disposeInternal = function() { disposeInternal() {
if (this.relayedListenerKey_) { if (this.relayedListenerKey_) {
unlistenByKey(this.relayedListenerKey_); unlistenByKey(this.relayedListenerKey_);
this.relayedListenerKey_ = null; this.relayedListenerKey_ = null;
@@ -332,5 +322,10 @@ MapBrowserEventHandler.prototype.disposeInternal = function() {
this.pointerEventHandler_ = null; this.pointerEventHandler_ = null;
} }
EventTarget.prototype.disposeInternal.call(this); EventTarget.prototype.disposeInternal.call(this);
}; }
}
inherits(MapBrowserEventHandler, EventTarget);
export default MapBrowserEventHandler; export default MapBrowserEventHandler;
+96 -101
View File
@@ -87,7 +87,8 @@ inherits(ObjectEvent, Event);
* @fires module:ol/Object~ObjectEvent * @fires module:ol/Object~ObjectEvent
* @api * @api
*/ */
const BaseObject = function(opt_values) { class BaseObject {
constructor(opt_values) {
Observable.call(this); Observable.call(this);
// Call {@link module:ol~getUid} to ensure that the order of objects' ids is // Call {@link module:ol~getUid} to ensure that the order of objects' ids is
@@ -105,7 +106,100 @@ const BaseObject = function(opt_values) {
if (opt_values !== undefined) { if (opt_values !== undefined) {
this.setProperties(opt_values); this.setProperties(opt_values);
} }
}; }
/**
* Gets a value.
* @param {string} key Key name.
* @return {*} Value.
* @api
*/
get(key) {
let value;
if (this.values_.hasOwnProperty(key)) {
value = this.values_[key];
}
return value;
}
/**
* Get a list of object property names.
* @return {Array.<string>} List of property names.
* @api
*/
getKeys() {
return Object.keys(this.values_);
}
/**
* Get an object of all property names and values.
* @return {Object.<string, *>} Object.
* @api
*/
getProperties() {
return assign({}, this.values_);
}
/**
* @param {string} key Key name.
* @param {*} oldValue Old value.
*/
notify(key, oldValue) {
let eventType;
eventType = getChangeEventType(key);
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
eventType = ObjectEventType.PROPERTYCHANGE;
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
}
/**
* Sets a value.
* @param {string} key Key name.
* @param {*} value Value.
* @param {boolean=} opt_silent Update without triggering an event.
* @api
*/
set(key, value, opt_silent) {
if (opt_silent) {
this.values_[key] = value;
} else {
const oldValue = this.values_[key];
this.values_[key] = value;
if (oldValue !== value) {
this.notify(key, oldValue);
}
}
}
/**
* Sets a collection of key-value pairs. Note that this changes any existing
* properties and adds new ones (it does not remove any existing properties).
* @param {Object.<string, *>} values Values.
* @param {boolean=} opt_silent Update without triggering an event.
* @api
*/
setProperties(values, opt_silent) {
for (const key in values) {
this.set(key, values[key], opt_silent);
}
}
/**
* Unsets a property.
* @param {string} key Key name.
* @param {boolean=} opt_silent Unset without triggering an event.
* @api
*/
unset(key, opt_silent) {
if (key in this.values_) {
const oldValue = this.values_[key];
delete this.values_[key];
if (!opt_silent) {
this.notify(key, oldValue);
}
}
}
}
inherits(BaseObject, Observable); inherits(BaseObject, Observable);
@@ -127,103 +221,4 @@ export function getChangeEventType(key) {
} }
/**
* Gets a value.
* @param {string} key Key name.
* @return {*} Value.
* @api
*/
BaseObject.prototype.get = function(key) {
let value;
if (this.values_.hasOwnProperty(key)) {
value = this.values_[key];
}
return value;
};
/**
* Get a list of object property names.
* @return {Array.<string>} List of property names.
* @api
*/
BaseObject.prototype.getKeys = function() {
return Object.keys(this.values_);
};
/**
* Get an object of all property names and values.
* @return {Object.<string, *>} Object.
* @api
*/
BaseObject.prototype.getProperties = function() {
return assign({}, this.values_);
};
/**
* @param {string} key Key name.
* @param {*} oldValue Old value.
*/
BaseObject.prototype.notify = function(key, oldValue) {
let eventType;
eventType = getChangeEventType(key);
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
eventType = ObjectEventType.PROPERTYCHANGE;
this.dispatchEvent(new ObjectEvent(eventType, key, oldValue));
};
/**
* Sets a value.
* @param {string} key Key name.
* @param {*} value Value.
* @param {boolean=} opt_silent Update without triggering an event.
* @api
*/
BaseObject.prototype.set = function(key, value, opt_silent) {
if (opt_silent) {
this.values_[key] = value;
} else {
const oldValue = this.values_[key];
this.values_[key] = value;
if (oldValue !== value) {
this.notify(key, oldValue);
}
}
};
/**
* Sets a collection of key-value pairs. Note that this changes any existing
* properties and adds new ones (it does not remove any existing properties).
* @param {Object.<string, *>} values Values.
* @param {boolean=} opt_silent Update without triggering an event.
* @api
*/
BaseObject.prototype.setProperties = function(values, opt_silent) {
for (const key in values) {
this.set(key, values[key], opt_silent);
}
};
/**
* Unsets a property.
* @param {string} key Key name.
* @param {boolean=} opt_silent Unset without triggering an event.
* @api
*/
BaseObject.prototype.unset = function(key, opt_silent) {
if (key in this.values_) {
const oldValue = this.values_[key];
delete this.values_[key];
if (!opt_silent) {
this.notify(key, oldValue);
}
}
};
export default BaseObject; export default BaseObject;
+84 -85
View File
@@ -20,7 +20,8 @@ import EventType from './events/EventType.js';
* @struct * @struct
* @api * @api
*/ */
const Observable = function() { class Observable {
constructor() {
EventTarget.call(this); EventTarget.call(this);
@@ -30,7 +31,88 @@ const Observable = function() {
*/ */
this.revision_ = 0; this.revision_ = 0;
}; }
/**
* Increases the revision counter and dispatches a 'change' event.
* @api
*/
changed() {
++this.revision_;
this.dispatchEvent(EventType.CHANGE);
}
/**
* Get the version number for this object. Each time the object is modified,
* its version number will be incremented.
* @return {number} Revision.
* @api
*/
getRevision() {
return this.revision_;
}
/**
* Listen for a certain type of event.
* @param {string|Array.<string>} type The event type or array of event types.
* @param {function(?): ?} listener The listener function.
* @return {module:ol/events~EventsKey|Array.<module:ol/events~EventsKey>} Unique key for the listener. If
* called with an array of event types as the first argument, the return
* will be an array of keys.
* @api
*/
on(type, listener) {
if (Array.isArray(type)) {
const len = type.length;
const keys = new Array(len);
for (let i = 0; i < len; ++i) {
keys[i] = listen(this, type[i], listener);
}
return keys;
} else {
return listen(this, /** @type {string} */ (type), listener);
}
}
/**
* Listen once for a certain type of event.
* @param {string|Array.<string>} type The event type or array of event types.
* @param {function(?): ?} listener The listener function.
* @return {module:ol/events~EventsKey|Array.<module:ol/events~EventsKey>} Unique key for the listener. If
* called with an array of event types as the first argument, the return
* will be an array of keys.
* @api
*/
once(type, listener) {
if (Array.isArray(type)) {
const len = type.length;
const keys = new Array(len);
for (let i = 0; i < len; ++i) {
keys[i] = listenOnce(this, type[i], listener);
}
return keys;
} else {
return listenOnce(this, /** @type {string} */ (type), listener);
}
}
/**
* Unlisten for a certain type of event.
* @param {string|Array.<string>} type The event type or array of event types.
* @param {function(?): ?} listener The listener function.
* @api
*/
un(type, listener) {
if (Array.isArray(type)) {
for (let i = 0, ii = type.length; i < ii; ++i) {
unlisten(this, type[i], listener);
}
return;
} else {
unlisten(this, /** @type {string} */ (type), listener);
}
}
}
inherits(Observable, EventTarget); inherits(Observable, EventTarget);
@@ -52,16 +134,6 @@ export function unByKey(key) {
} }
/**
* Increases the revision counter and dispatches a 'change' event.
* @api
*/
Observable.prototype.changed = function() {
++this.revision_;
this.dispatchEvent(EventType.CHANGE);
};
/** /**
* Dispatches an event and calls all listeners listening for events * Dispatches an event and calls all listeners listening for events
* of this type. The event parameter can either be a string or an * of this type. The event parameter can either be a string or an
@@ -76,77 +148,4 @@ Observable.prototype.changed = function() {
Observable.prototype.dispatchEvent; Observable.prototype.dispatchEvent;
/**
* Get the version number for this object. Each time the object is modified,
* its version number will be incremented.
* @return {number} Revision.
* @api
*/
Observable.prototype.getRevision = function() {
return this.revision_;
};
/**
* Listen for a certain type of event.
* @param {string|Array.<string>} type The event type or array of event types.
* @param {function(?): ?} listener The listener function.
* @return {module:ol/events~EventsKey|Array.<module:ol/events~EventsKey>} Unique key for the listener. If
* called with an array of event types as the first argument, the return
* will be an array of keys.
* @api
*/
Observable.prototype.on = function(type, listener) {
if (Array.isArray(type)) {
const len = type.length;
const keys = new Array(len);
for (let i = 0; i < len; ++i) {
keys[i] = listen(this, type[i], listener);
}
return keys;
} else {
return listen(this, /** @type {string} */ (type), listener);
}
};
/**
* Listen once for a certain type of event.
* @param {string|Array.<string>} type The event type or array of event types.
* @param {function(?): ?} listener The listener function.
* @return {module:ol/events~EventsKey|Array.<module:ol/events~EventsKey>} Unique key for the listener. If
* called with an array of event types as the first argument, the return
* will be an array of keys.
* @api
*/
Observable.prototype.once = function(type, listener) {
if (Array.isArray(type)) {
const len = type.length;
const keys = new Array(len);
for (let i = 0; i < len; ++i) {
keys[i] = listenOnce(this, type[i], listener);
}
return keys;
} else {
return listenOnce(this, /** @type {string} */ (type), listener);
}
};
/**
* Unlisten for a certain type of event.
* @param {string|Array.<string>} type The event type or array of event types.
* @param {function(?): ?} listener The listener function.
* @api
*/
Observable.prototype.un = function(type, listener) {
if (Array.isArray(type)) {
for (let i = 0, ii = type.length; i < ii; ++i) {
unlisten(this, type[i], listener);
}
return;
} else {
unlisten(this, /** @type {string} */ (type), listener);
}
};
export default Observable; export default Observable;
+76 -96
View File
@@ -98,7 +98,8 @@ const Property = {
* @param {module:ol/Overlay~Options} options Overlay options. * @param {module:ol/Overlay~Options} options Overlay options.
* @api * @api
*/ */
const Overlay = function(options) { class Overlay {
constructor(options) {
BaseObject.call(this); BaseObject.call(this);
@@ -211,101 +212,91 @@ const Overlay = function(options) {
this.setPosition(options.position); this.setPosition(options.position);
} }
}; }
inherits(Overlay, BaseObject); /**
/**
* Get the DOM element of this overlay. * Get the DOM element of this overlay.
* @return {HTMLElement|undefined} The Element containing the overlay. * @return {HTMLElement|undefined} The Element containing the overlay.
* @observable * @observable
* @api * @api
*/ */
Overlay.prototype.getElement = function() { getElement() {
return /** @type {HTMLElement|undefined} */ (this.get(Property.ELEMENT)); return /** @type {HTMLElement|undefined} */ (this.get(Property.ELEMENT));
}; }
/**
/**
* Get the overlay identifier which is set on constructor. * Get the overlay identifier which is set on constructor.
* @return {number|string|undefined} Id. * @return {number|string|undefined} Id.
* @api * @api
*/ */
Overlay.prototype.getId = function() { getId() {
return this.id; return this.id;
}; }
/**
/**
* Get the map associated with this overlay. * Get the map associated with this overlay.
* @return {module:ol/PluggableMap|undefined} The map that the * @return {module:ol/PluggableMap|undefined} The map that the
* overlay is part of. * overlay is part of.
* @observable * @observable
* @api * @api
*/ */
Overlay.prototype.getMap = function() { getMap() {
return ( return (
/** @type {module:ol/PluggableMap|undefined} */ (this.get(Property.MAP)) /** @type {module:ol/PluggableMap|undefined} */ (this.get(Property.MAP))
); );
}; }
/**
/**
* Get the offset of this overlay. * Get the offset of this overlay.
* @return {Array.<number>} The offset. * @return {Array.<number>} The offset.
* @observable * @observable
* @api * @api
*/ */
Overlay.prototype.getOffset = function() { getOffset() {
return /** @type {Array.<number>} */ (this.get(Property.OFFSET)); return /** @type {Array.<number>} */ (this.get(Property.OFFSET));
}; }
/**
/**
* Get the current position of this overlay. * Get the current position of this overlay.
* @return {module:ol/coordinate~Coordinate|undefined} The spatial point that the overlay is * @return {module:ol/coordinate~Coordinate|undefined} The spatial point that the overlay is
* anchored at. * anchored at.
* @observable * @observable
* @api * @api
*/ */
Overlay.prototype.getPosition = function() { getPosition() {
return ( return (
/** @type {module:ol/coordinate~Coordinate|undefined} */ (this.get(Property.POSITION)) /** @type {module:ol/coordinate~Coordinate|undefined} */ (this.get(Property.POSITION))
); );
}; }
/**
/**
* Get the current positioning of this overlay. * Get the current positioning of this overlay.
* @return {module:ol/OverlayPositioning} How the overlay is positioned * @return {module:ol/OverlayPositioning} How the overlay is positioned
* relative to its point on the map. * relative to its point on the map.
* @observable * @observable
* @api * @api
*/ */
Overlay.prototype.getPositioning = function() { getPositioning() {
return ( return (
/** @type {module:ol/OverlayPositioning} */ (this.get(Property.POSITIONING)) /** @type {module:ol/OverlayPositioning} */ (this.get(Property.POSITIONING))
); );
}; }
/**
/**
* @protected * @protected
*/ */
Overlay.prototype.handleElementChanged = function() { handleElementChanged() {
removeChildren(this.element); removeChildren(this.element);
const element = this.getElement(); const element = this.getElement();
if (element) { if (element) {
this.element.appendChild(element); this.element.appendChild(element);
} }
}; }
/**
/**
* @protected * @protected
*/ */
Overlay.prototype.handleMapChanged = function() { handleMapChanged() {
if (this.mapPostrenderListenerKey) { if (this.mapPostrenderListenerKey) {
removeNode(this.element); removeNode(this.element);
unlistenByKey(this.mapPostrenderListenerKey); unlistenByKey(this.mapPostrenderListenerKey);
@@ -324,79 +315,71 @@ Overlay.prototype.handleMapChanged = function() {
container.appendChild(this.element); container.appendChild(this.element);
} }
} }
}; }
/**
/**
* @protected * @protected
*/ */
Overlay.prototype.render = function() { render() {
this.updatePixelPosition(); this.updatePixelPosition();
}; }
/**
/**
* @protected * @protected
*/ */
Overlay.prototype.handleOffsetChanged = function() { handleOffsetChanged() {
this.updatePixelPosition(); this.updatePixelPosition();
}; }
/**
/**
* @protected * @protected
*/ */
Overlay.prototype.handlePositionChanged = function() { handlePositionChanged() {
this.updatePixelPosition(); this.updatePixelPosition();
if (this.get(Property.POSITION) && this.autoPan) { if (this.get(Property.POSITION) && this.autoPan) {
this.panIntoView(); this.panIntoView();
} }
}; }
/**
/**
* @protected * @protected
*/ */
Overlay.prototype.handlePositioningChanged = function() { handlePositioningChanged() {
this.updatePixelPosition(); this.updatePixelPosition();
}; }
/**
/**
* Set the DOM element to be associated with this overlay. * Set the DOM element to be associated with this overlay.
* @param {HTMLElement|undefined} element The Element containing the overlay. * @param {HTMLElement|undefined} element The Element containing the overlay.
* @observable * @observable
* @api * @api
*/ */
Overlay.prototype.setElement = function(element) { setElement(element) {
this.set(Property.ELEMENT, element); this.set(Property.ELEMENT, element);
}; }
/**
/**
* Set the map to be associated with this overlay. * Set the map to be associated with this overlay.
* @param {module:ol/PluggableMap|undefined} map The map that the * @param {module:ol/PluggableMap|undefined} map The map that the
* overlay is part of. * overlay is part of.
* @observable * @observable
* @api * @api
*/ */
Overlay.prototype.setMap = function(map) { setMap(map) {
this.set(Property.MAP, map); this.set(Property.MAP, map);
}; }
/**
/**
* Set the offset for this overlay. * Set the offset for this overlay.
* @param {Array.<number>} offset Offset. * @param {Array.<number>} offset Offset.
* @observable * @observable
* @api * @api
*/ */
Overlay.prototype.setOffset = function(offset) { setOffset(offset) {
this.set(Property.OFFSET, offset); this.set(Property.OFFSET, offset);
}; }
/**
/**
* Set the position for this overlay. If the position is `undefined` the * Set the position for this overlay. If the position is `undefined` the
* overlay is hidden. * overlay is hidden.
* @param {module:ol/coordinate~Coordinate|undefined} position The spatial point that the overlay * @param {module:ol/coordinate~Coordinate|undefined} position The spatial point that the overlay
@@ -404,17 +387,16 @@ Overlay.prototype.setOffset = function(offset) {
* @observable * @observable
* @api * @api
*/ */
Overlay.prototype.setPosition = function(position) { setPosition(position) {
this.set(Property.POSITION, position); this.set(Property.POSITION, position);
}; }
/**
/**
* Pan the map so that the overlay is entirely visible in the current viewport * Pan the map so that the overlay is entirely visible in the current viewport
* (if necessary). * (if necessary).
* @protected * @protected
*/ */
Overlay.prototype.panIntoView = function() { panIntoView() {
const map = this.getMap(); const map = this.getMap();
if (!map || !map.getTargetElement()) { if (!map || !map.getTargetElement()) {
@@ -464,17 +446,16 @@ Overlay.prototype.panIntoView = function() {
}); });
} }
} }
}; }
/**
/**
* Get the extent of an element relative to the document * Get the extent of an element relative to the document
* @param {HTMLElement|undefined} element The element. * @param {HTMLElement|undefined} element The element.
* @param {module:ol/size~Size|undefined} size The size of the element. * @param {module:ol/size~Size|undefined} size The size of the element.
* @return {module:ol/extent~Extent} The extent. * @return {module:ol/extent~Extent} The extent.
* @protected * @protected
*/ */
Overlay.prototype.getRect = function(element, size) { getRect(element, size) {
const box = element.getBoundingClientRect(); const box = element.getBoundingClientRect();
const offsetX = box.left + window.pageXOffset; const offsetX = box.left + window.pageXOffset;
const offsetY = box.top + window.pageYOffset; const offsetY = box.top + window.pageYOffset;
@@ -484,39 +465,36 @@ Overlay.prototype.getRect = function(element, size) {
offsetX + size[0], offsetX + size[0],
offsetY + size[1] offsetY + size[1]
]; ];
}; }
/**
/**
* Set the positioning for this overlay. * Set the positioning for this overlay.
* @param {module:ol/OverlayPositioning} positioning how the overlay is * @param {module:ol/OverlayPositioning} positioning how the overlay is
* positioned relative to its point on the map. * positioned relative to its point on the map.
* @observable * @observable
* @api * @api
*/ */
Overlay.prototype.setPositioning = function(positioning) { setPositioning(positioning) {
this.set(Property.POSITIONING, positioning); this.set(Property.POSITIONING, positioning);
}; }
/**
/**
* Modify the visibility of the element. * Modify the visibility of the element.
* @param {boolean} visible Element visibility. * @param {boolean} visible Element visibility.
* @protected * @protected
*/ */
Overlay.prototype.setVisible = function(visible) { setVisible(visible) {
if (this.rendered.visible !== visible) { if (this.rendered.visible !== visible) {
this.element.style.display = visible ? '' : 'none'; this.element.style.display = visible ? '' : 'none';
this.rendered.visible = visible; this.rendered.visible = visible;
} }
}; }
/**
/**
* Update pixel position. * Update pixel position.
* @protected * @protected
*/ */
Overlay.prototype.updatePixelPosition = function() { updatePixelPosition() {
const map = this.getMap(); const map = this.getMap();
const position = this.getPosition(); const position = this.getPosition();
if (!map || !map.isRendered() || !position) { if (!map || !map.isRendered() || !position) {
@@ -527,15 +505,14 @@ Overlay.prototype.updatePixelPosition = function() {
const pixel = map.getPixelFromCoordinate(position); const pixel = map.getPixelFromCoordinate(position);
const mapSize = map.getSize(); const mapSize = map.getSize();
this.updateRenderedPosition(pixel, mapSize); this.updateRenderedPosition(pixel, mapSize);
}; }
/**
/**
* @param {module:ol~Pixel} pixel The pixel location. * @param {module:ol~Pixel} pixel The pixel location.
* @param {module:ol/size~Size|undefined} mapSize The map size. * @param {module:ol/size~Size|undefined} mapSize The map size.
* @protected * @protected
*/ */
Overlay.prototype.updateRenderedPosition = function(pixel, mapSize) { updateRenderedPosition(pixel, mapSize) {
const style = this.element.style; const style = this.element.style;
const offset = this.getOffset(); const offset = this.getOffset();
@@ -593,15 +570,18 @@ Overlay.prototype.updateRenderedPosition = function(pixel, mapSize) {
this.rendered.top_ = style.top = top; this.rendered.top_ = style.top = top;
} }
} }
}; }
/**
/**
* returns the options this Overlay has been created with * returns the options this Overlay has been created with
* @return {module:ol/Overlay~Options} overlay options * @return {module:ol/Overlay~Options} overlay options
*/ */
Overlay.prototype.getOptions = function() { getOptions() {
return this.options; return this.options;
}; }
}
inherits(Overlay, BaseObject);
export default Overlay; export default Overlay;
+167 -218
View File
@@ -140,7 +140,8 @@ import {create as createTransform, apply as applyTransform} from './transform.js
* @fires module:ol/render/Event~RenderEvent#precompose * @fires module:ol/render/Event~RenderEvent#precompose
* @api * @api
*/ */
const PluggableMap = function(options) { class PluggableMap {
constructor(options) {
BaseObject.call(this); BaseObject.call(this);
@@ -458,78 +459,69 @@ const PluggableMap = function(options) {
event.element.setMap(null); event.element.setMap(null);
}, this); }, this);
}; }
inherits(PluggableMap, BaseObject); createRenderer() {
PluggableMap.prototype.createRenderer = function() {
throw new Error('Use a map type that has a createRenderer method'); throw new Error('Use a map type that has a createRenderer method');
}; }
/**
/**
* Add the given control to the map. * Add the given control to the map.
* @param {module:ol/control/Control} control Control. * @param {module:ol/control/Control} control Control.
* @api * @api
*/ */
PluggableMap.prototype.addControl = function(control) { addControl(control) {
this.getControls().push(control); this.getControls().push(control);
}; }
/**
/**
* Add the given interaction to the map. * Add the given interaction to the map.
* @param {module:ol/interaction/Interaction} interaction Interaction to add. * @param {module:ol/interaction/Interaction} interaction Interaction to add.
* @api * @api
*/ */
PluggableMap.prototype.addInteraction = function(interaction) { addInteraction(interaction) {
this.getInteractions().push(interaction); this.getInteractions().push(interaction);
}; }
/**
/**
* Adds the given layer to the top of this map. If you want to add a layer * Adds the given layer to the top of this map. If you want to add a layer
* elsewhere in the stack, use `getLayers()` and the methods available on * elsewhere in the stack, use `getLayers()` and the methods available on
* {@link module:ol/Collection~Collection}. * {@link module:ol/Collection~Collection}.
* @param {module:ol/layer/Base} layer Layer. * @param {module:ol/layer/Base} layer Layer.
* @api * @api
*/ */
PluggableMap.prototype.addLayer = function(layer) { addLayer(layer) {
const layers = this.getLayerGroup().getLayers(); const layers = this.getLayerGroup().getLayers();
layers.push(layer); layers.push(layer);
}; }
/**
/**
* Add the given overlay to the map. * Add the given overlay to the map.
* @param {module:ol/Overlay} overlay Overlay. * @param {module:ol/Overlay} overlay Overlay.
* @api * @api
*/ */
PluggableMap.prototype.addOverlay = function(overlay) { addOverlay(overlay) {
this.getOverlays().push(overlay); this.getOverlays().push(overlay);
}; }
/**
/**
* This deals with map's overlay collection changes. * This deals with map's overlay collection changes.
* @param {module:ol/Overlay} overlay Overlay. * @param {module:ol/Overlay} overlay Overlay.
* @private * @private
*/ */
PluggableMap.prototype.addOverlayInternal_ = function(overlay) { addOverlayInternal_(overlay) {
const id = overlay.getId(); const id = overlay.getId();
if (id !== undefined) { if (id !== undefined) {
this.overlayIdIndex_[id.toString()] = overlay; this.overlayIdIndex_[id.toString()] = overlay;
} }
overlay.setMap(this); overlay.setMap(this);
}; }
/**
/**
* *
* @inheritDoc * @inheritDoc
*/ */
PluggableMap.prototype.disposeInternal = function() { disposeInternal() {
this.mapBrowserEventHandler_.dispose(); this.mapBrowserEventHandler_.dispose();
unlisten(this.viewport_, EventType.CONTEXTMENU, this.handleBrowserEvent, this); unlisten(this.viewport_, EventType.CONTEXTMENU, this.handleBrowserEvent, this);
unlisten(this.viewport_, EventType.WHEEL, this.handleBrowserEvent, this); unlisten(this.viewport_, EventType.WHEEL, this.handleBrowserEvent, this);
@@ -544,10 +536,9 @@ PluggableMap.prototype.disposeInternal = function() {
} }
this.setTarget(null); this.setTarget(null);
BaseObject.prototype.disposeInternal.call(this); BaseObject.prototype.disposeInternal.call(this);
}; }
/**
/**
* Detect features that intersect a pixel on the viewport, and execute a * Detect features that intersect a pixel on the viewport, and execute a
* callback with each intersecting feature. Layers included in the detection can * callback with each intersecting feature. Layers included in the detection can
* be configured through the `layerFilter` option in `opt_options`. * be configured through the `layerFilter` option in `opt_options`.
@@ -566,7 +557,7 @@ PluggableMap.prototype.disposeInternal = function() {
* @template S,T * @template S,T
* @api * @api
*/ */
PluggableMap.prototype.forEachFeatureAtPixel = function(pixel, callback, opt_options) { forEachFeatureAtPixel(pixel, callback, opt_options) {
if (!this.frameState_) { if (!this.frameState_) {
return; return;
} }
@@ -579,10 +570,9 @@ PluggableMap.prototype.forEachFeatureAtPixel = function(pixel, callback, opt_opt
return this.renderer_.forEachFeatureAtCoordinate( return this.renderer_.forEachFeatureAtCoordinate(
coordinate, this.frameState_, hitTolerance, callback, null, coordinate, this.frameState_, hitTolerance, callback, null,
layerFilter, null); layerFilter, null);
}; }
/**
/**
* Get all features that intersect a pixel on the viewport. * Get all features that intersect a pixel on the viewport.
* @param {module:ol~Pixel} pixel Pixel. * @param {module:ol~Pixel} pixel Pixel.
* @param {module:ol/PluggableMap~AtPixelOptions=} opt_options Optional options. * @param {module:ol/PluggableMap~AtPixelOptions=} opt_options Optional options.
@@ -590,7 +580,7 @@ PluggableMap.prototype.forEachFeatureAtPixel = function(pixel, callback, opt_opt
* `null` if none were found. * `null` if none were found.
* @api * @api
*/ */
PluggableMap.prototype.getFeaturesAtPixel = function(pixel, opt_options) { getFeaturesAtPixel(pixel, opt_options) {
let features = null; let features = null;
this.forEachFeatureAtPixel(pixel, function(feature) { this.forEachFeatureAtPixel(pixel, function(feature) {
if (!features) { if (!features) {
@@ -599,9 +589,9 @@ PluggableMap.prototype.getFeaturesAtPixel = function(pixel, opt_options) {
features.push(feature); features.push(feature);
}, opt_options); }, opt_options);
return features; return features;
}; }
/** /**
* Detect layers that have a color value at a pixel on the viewport, and * Detect layers that have a color value at a pixel on the viewport, and
* execute a callback with each matching layer. Layers included in the * execute a callback with each matching layer. Layers included in the
* detection can be configured through `opt_layerFilter`. * detection can be configured through `opt_layerFilter`.
@@ -618,7 +608,7 @@ PluggableMap.prototype.getFeaturesAtPixel = function(pixel, opt_options) {
* @template S,T * @template S,T
* @api * @api
*/ */
PluggableMap.prototype.forEachLayerAtPixel = function(pixel, callback, opt_options) { forEachLayerAtPixel(pixel, callback, opt_options) {
if (!this.frameState_) { if (!this.frameState_) {
return; return;
} }
@@ -628,10 +618,9 @@ PluggableMap.prototype.forEachLayerAtPixel = function(pixel, callback, opt_optio
const layerFilter = options.layerFilter || TRUE; const layerFilter = options.layerFilter || TRUE;
return this.renderer_.forEachLayerAtPixel( return this.renderer_.forEachLayerAtPixel(
pixel, this.frameState_, hitTolerance, callback, null, layerFilter, null); pixel, this.frameState_, hitTolerance, callback, null, layerFilter, null);
}; }
/**
/**
* Detect if features intersect a pixel on the viewport. Layers included in the * Detect if features intersect a pixel on the viewport. Layers included in the
* detection can be configured through `opt_layerFilter`. * detection can be configured through `opt_layerFilter`.
* @param {module:ol~Pixel} pixel Pixel. * @param {module:ol~Pixel} pixel Pixel.
@@ -640,7 +629,7 @@ PluggableMap.prototype.forEachLayerAtPixel = function(pixel, callback, opt_optio
* @template U * @template U
* @api * @api
*/ */
PluggableMap.prototype.hasFeatureAtPixel = function(pixel, opt_options) { hasFeatureAtPixel(pixel, opt_options) {
if (!this.frameState_) { if (!this.frameState_) {
return false; return false;
} }
@@ -651,37 +640,34 @@ PluggableMap.prototype.hasFeatureAtPixel = function(pixel, opt_options) {
opt_options.hitTolerance * this.frameState_.pixelRatio : 0; opt_options.hitTolerance * this.frameState_.pixelRatio : 0;
return this.renderer_.hasFeatureAtCoordinate( return this.renderer_.hasFeatureAtCoordinate(
coordinate, this.frameState_, hitTolerance, layerFilter, null); coordinate, this.frameState_, hitTolerance, layerFilter, null);
}; }
/**
/**
* Returns the coordinate in view projection for a browser event. * Returns the coordinate in view projection for a browser event.
* @param {Event} event Event. * @param {Event} event Event.
* @return {module:ol/coordinate~Coordinate} Coordinate. * @return {module:ol/coordinate~Coordinate} Coordinate.
* @api * @api
*/ */
PluggableMap.prototype.getEventCoordinate = function(event) { getEventCoordinate(event) {
return this.getCoordinateFromPixel(this.getEventPixel(event)); return this.getCoordinateFromPixel(this.getEventPixel(event));
}; }
/**
/**
* Returns the map pixel position for a browser event relative to the viewport. * Returns the map pixel position for a browser event relative to the viewport.
* @param {Event} event Event. * @param {Event} event Event.
* @return {module:ol~Pixel} Pixel. * @return {module:ol~Pixel} Pixel.
* @api * @api
*/ */
PluggableMap.prototype.getEventPixel = function(event) { getEventPixel(event) {
const viewportPosition = this.viewport_.getBoundingClientRect(); const viewportPosition = this.viewport_.getBoundingClientRect();
const eventPosition = event.changedTouches ? event.changedTouches[0] : event; const eventPosition = event.changedTouches ? event.changedTouches[0] : event;
return [ return [
eventPosition.clientX - viewportPosition.left, eventPosition.clientX - viewportPosition.left,
eventPosition.clientY - viewportPosition.top eventPosition.clientY - viewportPosition.top
]; ];
}; }
/**
/**
* Get the target in which this map is rendered. * Get the target in which this map is rendered.
* Note that this returns what is entered as an option or in setTarget: * Note that this returns what is entered as an option or in setTarget:
* if that was an element, it returns an element; if a string, it returns that. * if that was an element, it returns an element; if a string, it returns that.
@@ -690,68 +676,63 @@ PluggableMap.prototype.getEventPixel = function(event) {
* @observable * @observable
* @api * @api
*/ */
PluggableMap.prototype.getTarget = function() { getTarget() {
return /** @type {HTMLElement|string|undefined} */ (this.get(MapProperty.TARGET)); return /** @type {HTMLElement|string|undefined} */ (this.get(MapProperty.TARGET));
}; }
/**
/**
* Get the DOM element into which this map is rendered. In contrast to * Get the DOM element into which this map is rendered. In contrast to
* `getTarget` this method always return an `Element`, or `null` if the * `getTarget` this method always return an `Element`, or `null` if the
* map has no target. * map has no target.
* @return {HTMLElement} The element that the map is rendered in. * @return {HTMLElement} The element that the map is rendered in.
* @api * @api
*/ */
PluggableMap.prototype.getTargetElement = function() { getTargetElement() {
const target = this.getTarget(); const target = this.getTarget();
if (target !== undefined) { if (target !== undefined) {
return typeof target === 'string' ? document.getElementById(target) : target; return typeof target === 'string' ? document.getElementById(target) : target;
} else { } else {
return null; return null;
} }
}; }
/**
/**
* Get the coordinate for a given pixel. This returns a coordinate in the * Get the coordinate for a given pixel. This returns a coordinate in the
* map view projection. * map view projection.
* @param {module:ol~Pixel} pixel Pixel position in the map viewport. * @param {module:ol~Pixel} pixel Pixel position in the map viewport.
* @return {module:ol/coordinate~Coordinate} The coordinate for the pixel position. * @return {module:ol/coordinate~Coordinate} The coordinate for the pixel position.
* @api * @api
*/ */
PluggableMap.prototype.getCoordinateFromPixel = function(pixel) { getCoordinateFromPixel(pixel) {
const frameState = this.frameState_; const frameState = this.frameState_;
if (!frameState) { if (!frameState) {
return null; return null;
} else { } else {
return applyTransform(frameState.pixelToCoordinateTransform, pixel.slice()); return applyTransform(frameState.pixelToCoordinateTransform, pixel.slice());
} }
}; }
/**
/**
* Get the map controls. Modifying this collection changes the controls * Get the map controls. Modifying this collection changes the controls
* associated with the map. * associated with the map.
* @return {module:ol/Collection.<module:ol/control/Control>} Controls. * @return {module:ol/Collection.<module:ol/control/Control>} Controls.
* @api * @api
*/ */
PluggableMap.prototype.getControls = function() { getControls() {
return this.controls; return this.controls;
}; }
/**
/**
* Get the map overlays. Modifying this collection changes the overlays * Get the map overlays. Modifying this collection changes the overlays
* associated with the map. * associated with the map.
* @return {module:ol/Collection.<module:ol/Overlay>} Overlays. * @return {module:ol/Collection.<module:ol/Overlay>} Overlays.
* @api * @api
*/ */
PluggableMap.prototype.getOverlays = function() { getOverlays() {
return this.overlays_; return this.overlays_;
}; }
/**
/**
* Get an overlay by its identifier (the value returned by overlay.getId()). * Get an overlay by its identifier (the value returned by overlay.getId()).
* Note that the index treats string and numeric identifiers as the same. So * Note that the index treats string and numeric identifiers as the same. So
* `map.getOverlayById(2)` will return an overlay with id `'2'` or `2`. * `map.getOverlayById(2)` will return an overlay with id `'2'` or `2`.
@@ -759,13 +740,12 @@ PluggableMap.prototype.getOverlays = function() {
* @return {module:ol/Overlay} Overlay. * @return {module:ol/Overlay} Overlay.
* @api * @api
*/ */
PluggableMap.prototype.getOverlayById = function(id) { getOverlayById(id) {
const overlay = this.overlayIdIndex_[id.toString()]; const overlay = this.overlayIdIndex_[id.toString()];
return overlay !== undefined ? overlay : null; return overlay !== undefined ? overlay : null;
}; }
/**
/**
* Get the map interactions. Modifying this collection changes the interactions * Get the map interactions. Modifying this collection changes the interactions
* associated with the map. * associated with the map.
* *
@@ -773,130 +753,120 @@ PluggableMap.prototype.getOverlayById = function(id) {
* @return {module:ol/Collection.<module:ol/interaction/Interaction>} Interactions. * @return {module:ol/Collection.<module:ol/interaction/Interaction>} Interactions.
* @api * @api
*/ */
PluggableMap.prototype.getInteractions = function() { getInteractions() {
return this.interactions; return this.interactions;
}; }
/**
/**
* Get the layergroup associated with this map. * Get the layergroup associated with this map.
* @return {module:ol/layer/Group} A layer group containing the layers in this map. * @return {module:ol/layer/Group} A layer group containing the layers in this map.
* @observable * @observable
* @api * @api
*/ */
PluggableMap.prototype.getLayerGroup = function() { getLayerGroup() {
return ( return (
/** @type {module:ol/layer/Group} */ (this.get(MapProperty.LAYERGROUP)) /** @type {module:ol/layer/Group} */ (this.get(MapProperty.LAYERGROUP))
); );
}; }
/**
/**
* Get the collection of layers associated with this map. * Get the collection of layers associated with this map.
* @return {!module:ol/Collection.<module:ol/layer/Base>} Layers. * @return {!module:ol/Collection.<module:ol/layer/Base>} Layers.
* @api * @api
*/ */
PluggableMap.prototype.getLayers = function() { getLayers() {
const layers = this.getLayerGroup().getLayers(); const layers = this.getLayerGroup().getLayers();
return layers; return layers;
}; }
/**
/**
* Get the pixel for a coordinate. This takes a coordinate in the map view * Get the pixel for a coordinate. This takes a coordinate in the map view
* projection and returns the corresponding pixel. * projection and returns the corresponding pixel.
* @param {module:ol/coordinate~Coordinate} coordinate A map coordinate. * @param {module:ol/coordinate~Coordinate} coordinate A map coordinate.
* @return {module:ol~Pixel} A pixel position in the map viewport. * @return {module:ol~Pixel} A pixel position in the map viewport.
* @api * @api
*/ */
PluggableMap.prototype.getPixelFromCoordinate = function(coordinate) { getPixelFromCoordinate(coordinate) {
const frameState = this.frameState_; const frameState = this.frameState_;
if (!frameState) { if (!frameState) {
return null; return null;
} else { } else {
return applyTransform(frameState.coordinateToPixelTransform, coordinate.slice(0, 2)); return applyTransform(frameState.coordinateToPixelTransform, coordinate.slice(0, 2));
} }
}; }
/**
/**
* Get the map renderer. * Get the map renderer.
* @return {module:ol/renderer/Map} Renderer * @return {module:ol/renderer/Map} Renderer
*/ */
PluggableMap.prototype.getRenderer = function() { getRenderer() {
return this.renderer_; return this.renderer_;
}; }
/**
/**
* Get the size of this map. * Get the size of this map.
* @return {module:ol/size~Size|undefined} The size in pixels of the map in the DOM. * @return {module:ol/size~Size|undefined} The size in pixels of the map in the DOM.
* @observable * @observable
* @api * @api
*/ */
PluggableMap.prototype.getSize = function() { getSize() {
return ( return (
/** @type {module:ol/size~Size|undefined} */ (this.get(MapProperty.SIZE)) /** @type {module:ol/size~Size|undefined} */ (this.get(MapProperty.SIZE))
); );
}; }
/**
/**
* Get the view associated with this map. A view manages properties such as * Get the view associated with this map. A view manages properties such as
* center and resolution. * center and resolution.
* @return {module:ol/View} The view that controls this map. * @return {module:ol/View} The view that controls this map.
* @observable * @observable
* @api * @api
*/ */
PluggableMap.prototype.getView = function() { getView() {
return ( return (
/** @type {module:ol/View} */ (this.get(MapProperty.VIEW)) /** @type {module:ol/View} */ (this.get(MapProperty.VIEW))
); );
}; }
/**
/**
* Get the element that serves as the map viewport. * Get the element that serves as the map viewport.
* @return {HTMLElement} Viewport. * @return {HTMLElement} Viewport.
* @api * @api
*/ */
PluggableMap.prototype.getViewport = function() { getViewport() {
return this.viewport_; return this.viewport_;
}; }
/**
/**
* Get the element that serves as the container for overlays. Elements added to * Get the element that serves as the container for overlays. Elements added to
* this container will let mousedown and touchstart events through to the map, * this container will let mousedown and touchstart events through to the map,
* so clicks and gestures on an overlay will trigger {@link module:ol/MapBrowserEvent~MapBrowserEvent} * so clicks and gestures on an overlay will trigger {@link module:ol/MapBrowserEvent~MapBrowserEvent}
* events. * events.
* @return {!HTMLElement} The map's overlay container. * @return {!HTMLElement} The map's overlay container.
*/ */
PluggableMap.prototype.getOverlayContainer = function() { getOverlayContainer() {
return this.overlayContainer_; return this.overlayContainer_;
}; }
/**
/**
* Get the element that serves as a container for overlays that don't allow * Get the element that serves as a container for overlays that don't allow
* event propagation. Elements added to this container won't let mousedown and * event propagation. Elements added to this container won't let mousedown and
* touchstart events through to the map, so clicks and gestures on an overlay * touchstart events through to the map, so clicks and gestures on an overlay
* don't trigger any {@link module:ol/MapBrowserEvent~MapBrowserEvent}. * don't trigger any {@link module:ol/MapBrowserEvent~MapBrowserEvent}.
* @return {!HTMLElement} The map's overlay container that stops events. * @return {!HTMLElement} The map's overlay container that stops events.
*/ */
PluggableMap.prototype.getOverlayContainerStopEvent = function() { getOverlayContainerStopEvent() {
return this.overlayContainerStopEvent_; return this.overlayContainerStopEvent_;
}; }
/**
/**
* @param {module:ol/Tile} tile Tile. * @param {module:ol/Tile} tile Tile.
* @param {string} tileSourceKey Tile source key. * @param {string} tileSourceKey Tile source key.
* @param {module:ol/coordinate~Coordinate} tileCenter Tile center. * @param {module:ol/coordinate~Coordinate} tileCenter Tile center.
* @param {number} tileResolution Tile resolution. * @param {number} tileResolution Tile resolution.
* @return {number} Tile priority. * @return {number} Tile priority.
*/ */
PluggableMap.prototype.getTilePriority = function(tile, tileSourceKey, tileCenter, tileResolution) { getTilePriority(tile, tileSourceKey, tileCenter, tileResolution) {
// Filter out tiles at higher zoom levels than the current zoom level, or that // Filter out tiles at higher zoom levels than the current zoom level, or that
// are outside the visible extent. // are outside the visible extent.
const frameState = this.frameState_; const frameState = this.frameState_;
@@ -916,24 +886,22 @@ PluggableMap.prototype.getTilePriority = function(tile, tileSourceKey, tileCente
const deltaY = tileCenter[1] - frameState.focus[1]; const deltaY = tileCenter[1] - frameState.focus[1];
return 65536 * Math.log(tileResolution) + return 65536 * Math.log(tileResolution) +
Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution; Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution;
}; }
/**
/**
* @param {Event} browserEvent Browser event. * @param {Event} browserEvent Browser event.
* @param {string=} opt_type Type. * @param {string=} opt_type Type.
*/ */
PluggableMap.prototype.handleBrowserEvent = function(browserEvent, opt_type) { handleBrowserEvent(browserEvent, opt_type) {
const type = opt_type || browserEvent.type; const type = opt_type || browserEvent.type;
const mapBrowserEvent = new MapBrowserEvent(type, this, browserEvent); const mapBrowserEvent = new MapBrowserEvent(type, this, browserEvent);
this.handleMapBrowserEvent(mapBrowserEvent); this.handleMapBrowserEvent(mapBrowserEvent);
}; }
/**
/**
* @param {module:ol/MapBrowserEvent} mapBrowserEvent The event to handle. * @param {module:ol/MapBrowserEvent} mapBrowserEvent The event to handle.
*/ */
PluggableMap.prototype.handleMapBrowserEvent = function(mapBrowserEvent) { handleMapBrowserEvent(mapBrowserEvent) {
if (!this.frameState_) { if (!this.frameState_) {
// With no view defined, we cannot translate pixels into geographical // With no view defined, we cannot translate pixels into geographical
// coordinates so interactions cannot be used. // coordinates so interactions cannot be used.
@@ -954,13 +922,12 @@ PluggableMap.prototype.handleMapBrowserEvent = function(mapBrowserEvent) {
} }
} }
} }
}; }
/**
/**
* @protected * @protected
*/ */
PluggableMap.prototype.handlePostRender = function() { handlePostRender() {
const frameState = this.frameState_; const frameState = this.frameState_;
@@ -999,21 +966,19 @@ PluggableMap.prototype.handlePostRender = function() {
postRenderFunctions[i](this, frameState); postRenderFunctions[i](this, frameState);
} }
postRenderFunctions.length = 0; postRenderFunctions.length = 0;
}; }
/**
/**
* @private * @private
*/ */
PluggableMap.prototype.handleSizeChanged_ = function() { handleSizeChanged_() {
this.render(); this.render();
}; }
/**
/**
* @private * @private
*/ */
PluggableMap.prototype.handleTargetChanged_ = function() { handleTargetChanged_() {
// target may be undefined, null, a string or an Element. // target may be undefined, null, a string or an Element.
// If it's a string we convert it to an Element before proceeding. // If it's a string we convert it to an Element before proceeding.
// If it's not now an Element we remove the viewport from the DOM. // If it's not now an Element we remove the viewport from the DOM.
@@ -1057,29 +1022,26 @@ PluggableMap.prototype.handleTargetChanged_ = function() {
this.updateSize(); this.updateSize();
// updateSize calls setSize, so no need to call this.render // updateSize calls setSize, so no need to call this.render
// ourselves here. // ourselves here.
}; }
/**
/**
* @private * @private
*/ */
PluggableMap.prototype.handleTileChange_ = function() { handleTileChange_() {
this.render(); this.render();
}; }
/**
/**
* @private * @private
*/ */
PluggableMap.prototype.handleViewPropertyChanged_ = function() { handleViewPropertyChanged_() {
this.render(); this.render();
}; }
/**
/**
* @private * @private
*/ */
PluggableMap.prototype.handleViewChanged_ = function() { handleViewChanged_() {
if (this.viewPropertyListenerKey_) { if (this.viewPropertyListenerKey_) {
unlistenByKey(this.viewPropertyListenerKey_); unlistenByKey(this.viewPropertyListenerKey_);
this.viewPropertyListenerKey_ = null; this.viewPropertyListenerKey_ = null;
@@ -1099,13 +1061,12 @@ PluggableMap.prototype.handleViewChanged_ = function() {
this.handleViewPropertyChanged_, this); this.handleViewPropertyChanged_, this);
} }
this.render(); this.render();
}; }
/**
/**
* @private * @private
*/ */
PluggableMap.prototype.handleLayerGroupChanged_ = function() { handleLayerGroupChanged_() {
if (this.layerGroupPropertyListenerKeys_) { if (this.layerGroupPropertyListenerKeys_) {
this.layerGroupPropertyListenerKeys_.forEach(unlistenByKey); this.layerGroupPropertyListenerKeys_.forEach(unlistenByKey);
this.layerGroupPropertyListenerKeys_ = null; this.layerGroupPropertyListenerKeys_ = null;
@@ -1122,94 +1083,86 @@ PluggableMap.prototype.handleLayerGroupChanged_ = function() {
]; ];
} }
this.render(); this.render();
}; }
/**
/**
* @return {boolean} Is rendered. * @return {boolean} Is rendered.
*/ */
PluggableMap.prototype.isRendered = function() { isRendered() {
return !!this.frameState_; return !!this.frameState_;
}; }
/**
/**
* Requests an immediate render in a synchronous manner. * Requests an immediate render in a synchronous manner.
* @api * @api
*/ */
PluggableMap.prototype.renderSync = function() { renderSync() {
if (this.animationDelayKey_) { if (this.animationDelayKey_) {
cancelAnimationFrame(this.animationDelayKey_); cancelAnimationFrame(this.animationDelayKey_);
} }
this.animationDelay_(); this.animationDelay_();
}; }
/**
/**
* Request a map rendering (at the next animation frame). * Request a map rendering (at the next animation frame).
* @api * @api
*/ */
PluggableMap.prototype.render = function() { render() {
if (this.animationDelayKey_ === undefined) { if (this.animationDelayKey_ === undefined) {
this.animationDelayKey_ = requestAnimationFrame(this.animationDelay_); this.animationDelayKey_ = requestAnimationFrame(this.animationDelay_);
} }
}; }
/**
/**
* Remove the given control from the map. * Remove the given control from the map.
* @param {module:ol/control/Control} control Control. * @param {module:ol/control/Control} control Control.
* @return {module:ol/control/Control|undefined} The removed control (or undefined * @return {module:ol/control/Control|undefined} The removed control (or undefined
* if the control was not found). * if the control was not found).
* @api * @api
*/ */
PluggableMap.prototype.removeControl = function(control) { removeControl(control) {
return this.getControls().remove(control); return this.getControls().remove(control);
}; }
/**
/**
* Remove the given interaction from the map. * Remove the given interaction from the map.
* @param {module:ol/interaction/Interaction} interaction Interaction to remove. * @param {module:ol/interaction/Interaction} interaction Interaction to remove.
* @return {module:ol/interaction/Interaction|undefined} The removed interaction (or * @return {module:ol/interaction/Interaction|undefined} The removed interaction (or
* undefined if the interaction was not found). * undefined if the interaction was not found).
* @api * @api
*/ */
PluggableMap.prototype.removeInteraction = function(interaction) { removeInteraction(interaction) {
return this.getInteractions().remove(interaction); return this.getInteractions().remove(interaction);
}; }
/**
/**
* Removes the given layer from the map. * Removes the given layer from the map.
* @param {module:ol/layer/Base} layer Layer. * @param {module:ol/layer/Base} layer Layer.
* @return {module:ol/layer/Base|undefined} The removed layer (or undefined if the * @return {module:ol/layer/Base|undefined} The removed layer (or undefined if the
* layer was not found). * layer was not found).
* @api * @api
*/ */
PluggableMap.prototype.removeLayer = function(layer) { removeLayer(layer) {
const layers = this.getLayerGroup().getLayers(); const layers = this.getLayerGroup().getLayers();
return layers.remove(layer); return layers.remove(layer);
}; }
/**
/**
* Remove the given overlay from the map. * Remove the given overlay from the map.
* @param {module:ol/Overlay} overlay Overlay. * @param {module:ol/Overlay} overlay Overlay.
* @return {module:ol/Overlay|undefined} The removed overlay (or undefined * @return {module:ol/Overlay|undefined} The removed overlay (or undefined
* if the overlay was not found). * if the overlay was not found).
* @api * @api
*/ */
PluggableMap.prototype.removeOverlay = function(overlay) { removeOverlay(overlay) {
return this.getOverlays().remove(overlay); return this.getOverlays().remove(overlay);
}; }
/**
/**
* @param {number} time Time. * @param {number} time Time.
* @private * @private
*/ */
PluggableMap.prototype.renderFrame_ = function(time) { renderFrame_(time) {
let viewState; let viewState;
const size = this.getSize(); const size = this.getSize();
@@ -1295,70 +1248,64 @@ PluggableMap.prototype.renderFrame_ = function(time) {
setTimeout(this.handlePostRender.bind(this), 0); setTimeout(this.handlePostRender.bind(this), 0);
}; }
/**
/**
* Sets the layergroup of this map. * Sets the layergroup of this map.
* @param {module:ol/layer/Group} layerGroup A layer group containing the layers in this map. * @param {module:ol/layer/Group} layerGroup A layer group containing the layers in this map.
* @observable * @observable
* @api * @api
*/ */
PluggableMap.prototype.setLayerGroup = function(layerGroup) { setLayerGroup(layerGroup) {
this.set(MapProperty.LAYERGROUP, layerGroup); this.set(MapProperty.LAYERGROUP, layerGroup);
}; }
/**
/**
* Set the size of this map. * Set the size of this map.
* @param {module:ol/size~Size|undefined} size The size in pixels of the map in the DOM. * @param {module:ol/size~Size|undefined} size The size in pixels of the map in the DOM.
* @observable * @observable
* @api * @api
*/ */
PluggableMap.prototype.setSize = function(size) { setSize(size) {
this.set(MapProperty.SIZE, size); this.set(MapProperty.SIZE, size);
}; }
/**
/**
* Set the target element to render this map into. * Set the target element to render this map into.
* @param {HTMLElement|string|undefined} target The Element or id of the Element * @param {HTMLElement|string|undefined} target The Element or id of the Element
* that the map is rendered in. * that the map is rendered in.
* @observable * @observable
* @api * @api
*/ */
PluggableMap.prototype.setTarget = function(target) { setTarget(target) {
this.set(MapProperty.TARGET, target); this.set(MapProperty.TARGET, target);
}; }
/**
/**
* Set the view for this map. * Set the view for this map.
* @param {module:ol/View} view The view that controls this map. * @param {module:ol/View} view The view that controls this map.
* @observable * @observable
* @api * @api
*/ */
PluggableMap.prototype.setView = function(view) { setView(view) {
this.set(MapProperty.VIEW, view); this.set(MapProperty.VIEW, view);
}; }
/**
/**
* @param {module:ol/Feature} feature Feature. * @param {module:ol/Feature} feature Feature.
*/ */
PluggableMap.prototype.skipFeature = function(feature) { skipFeature(feature) {
const featureUid = getUid(feature).toString(); const featureUid = getUid(feature).toString();
this.skippedFeatureUids_[featureUid] = true; this.skippedFeatureUids_[featureUid] = true;
this.render(); this.render();
}; }
/**
/**
* Force a recalculation of the map viewport size. This should be called when * Force a recalculation of the map viewport size. This should be called when
* third-party code changes the size of the map viewport. * third-party code changes the size of the map viewport.
* @api * @api
*/ */
PluggableMap.prototype.updateSize = function() { updateSize() {
const targetElement = this.getTargetElement(); const targetElement = this.getTargetElement();
if (!targetElement) { if (!targetElement) {
@@ -1378,17 +1325,19 @@ PluggableMap.prototype.updateSize = function() {
parseFloat(computedStyle['borderBottomWidth']) parseFloat(computedStyle['borderBottomWidth'])
]); ]);
} }
}; }
/**
/**
* @param {module:ol/Feature} feature Feature. * @param {module:ol/Feature} feature Feature.
*/ */
PluggableMap.prototype.unskipFeature = function(feature) { unskipFeature(feature) {
const featureUid = getUid(feature).toString(); const featureUid = getUid(feature).toString();
delete this.skippedFeatureUids_[featureUid]; delete this.skippedFeatureUids_[featureUid];
this.render(); this.render();
}; }
}
inherits(PluggableMap, BaseObject);
/** /**
+43 -47
View File
@@ -47,7 +47,8 @@ import {visibleAtResolution} from '../layer/Layer.js';
* @param {module:ol/control/Attribution~Options=} opt_options Attribution options. * @param {module:ol/control/Attribution~Options=} opt_options Attribution options.
* @api * @api
*/ */
const Attribution = function(opt_options) { class Attribution {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -141,18 +142,15 @@ const Attribution = function(opt_options) {
*/ */
this.renderedVisible_ = true; this.renderedVisible_ = true;
}; }
inherits(Attribution, Control); /**
/**
* Get a list of visible attributions. * Get a list of visible attributions.
* @param {module:ol/PluggableMap~FrameState} frameState Frame state. * @param {module:ol/PluggableMap~FrameState} frameState Frame state.
* @return {Array.<string>} Attributions. * @return {Array.<string>} Attributions.
* @private * @private
*/ */
Attribution.prototype.getSourceAttributions_ = function(frameState) { getSourceAttributions_(frameState) {
/** /**
* Used to determine if an attribution already exists. * Used to determine if an attribution already exists.
* @type {!Object.<string, boolean>} * @type {!Object.<string, boolean>}
@@ -203,25 +201,13 @@ Attribution.prototype.getSourceAttributions_ = function(frameState) {
} }
} }
return visibleAttributions; return visibleAttributions;
}; }
/**
/**
* Update the attribution element.
* @param {module:ol/MapEvent} mapEvent Map event.
* @this {module:ol/control/Attribution}
* @api
*/
export function render(mapEvent) {
this.updateElement_(mapEvent.frameState);
}
/**
* @private * @private
* @param {?module:ol/PluggableMap~FrameState} frameState Frame state. * @param {?module:ol/PluggableMap~FrameState} frameState Frame state.
*/ */
Attribution.prototype.updateElement_ = function(frameState) { updateElement_(frameState) {
if (!frameState) { if (!frameState) {
if (this.renderedVisible_) { if (this.renderedVisible_) {
this.element.style.display = 'none'; this.element.style.display = 'none';
@@ -252,23 +238,21 @@ Attribution.prototype.updateElement_ = function(frameState) {
} }
this.renderedAttributions_ = attributions; this.renderedAttributions_ = attributions;
}; }
/**
/**
* @param {MouseEvent} event The event to handle * @param {MouseEvent} event The event to handle
* @private * @private
*/ */
Attribution.prototype.handleClick_ = function(event) { handleClick_(event) {
event.preventDefault(); event.preventDefault();
this.handleToggle_(); this.handleToggle_();
}; }
/**
/**
* @private * @private
*/ */
Attribution.prototype.handleToggle_ = function() { handleToggle_() {
this.element.classList.toggle(CLASS_COLLAPSED); this.element.classList.toggle(CLASS_COLLAPSED);
if (this.collapsed_) { if (this.collapsed_) {
replaceNode(this.collapseLabel_, this.label_); replaceNode(this.collapseLabel_, this.label_);
@@ -276,25 +260,23 @@ Attribution.prototype.handleToggle_ = function() {
replaceNode(this.label_, this.collapseLabel_); replaceNode(this.label_, this.collapseLabel_);
} }
this.collapsed_ = !this.collapsed_; this.collapsed_ = !this.collapsed_;
}; }
/**
/**
* Return `true` if the attribution is collapsible, `false` otherwise. * Return `true` if the attribution is collapsible, `false` otherwise.
* @return {boolean} True if the widget is collapsible. * @return {boolean} True if the widget is collapsible.
* @api * @api
*/ */
Attribution.prototype.getCollapsible = function() { getCollapsible() {
return this.collapsible_; return this.collapsible_;
}; }
/**
/**
* Set whether the attribution should be collapsible. * Set whether the attribution should be collapsible.
* @param {boolean} collapsible True if the widget is collapsible. * @param {boolean} collapsible True if the widget is collapsible.
* @api * @api
*/ */
Attribution.prototype.setCollapsible = function(collapsible) { setCollapsible(collapsible) {
if (this.collapsible_ === collapsible) { if (this.collapsible_ === collapsible) {
return; return;
} }
@@ -303,31 +285,45 @@ Attribution.prototype.setCollapsible = function(collapsible) {
if (!collapsible && this.collapsed_) { if (!collapsible && this.collapsed_) {
this.handleToggle_(); this.handleToggle_();
} }
}; }
/**
/**
* Collapse or expand the attribution according to the passed parameter. Will * Collapse or expand the attribution according to the passed parameter. Will
* not do anything if the attribution isn't collapsible or if the current * not do anything if the attribution isn't collapsible or if the current
* collapsed state is already the one requested. * collapsed state is already the one requested.
* @param {boolean} collapsed True if the widget is collapsed. * @param {boolean} collapsed True if the widget is collapsed.
* @api * @api
*/ */
Attribution.prototype.setCollapsed = function(collapsed) { setCollapsed(collapsed) {
if (!this.collapsible_ || this.collapsed_ === collapsed) { if (!this.collapsible_ || this.collapsed_ === collapsed) {
return; return;
} }
this.handleToggle_(); this.handleToggle_();
}; }
/**
/**
* Return `true` when the attribution is currently collapsed or `false` * Return `true` when the attribution is currently collapsed or `false`
* otherwise. * otherwise.
* @return {boolean} True if the widget is collapsed. * @return {boolean} True if the widget is collapsed.
* @api * @api
*/ */
Attribution.prototype.getCollapsed = function() { getCollapsed() {
return this.collapsed_; return this.collapsed_;
}; }
}
inherits(Attribution, Control);
/**
* Update the attribution element.
* @param {module:ol/MapEvent} mapEvent Map event.
* @this {module:ol/control/Attribution}
* @api
*/
export function render(mapEvent) {
this.updateElement_(mapEvent.frameState);
}
export default Attribution; export default Attribution;
+20 -20
View File
@@ -49,7 +49,8 @@ import {listen, unlistenByKey} from '../events.js';
* @param {module:ol/control/Control~Options} options Control options. * @param {module:ol/control/Control~Options} options Control options.
* @api * @api
*/ */
const Control = function(options) { class Control {
constructor(options) {
BaseObject.call(this); BaseObject.call(this);
@@ -86,38 +87,33 @@ const Control = function(options) {
this.setTarget(options.target); this.setTarget(options.target);
} }
}; }
inherits(Control, BaseObject); /**
/**
* @inheritDoc * @inheritDoc
*/ */
Control.prototype.disposeInternal = function() { disposeInternal() {
removeNode(this.element); removeNode(this.element);
BaseObject.prototype.disposeInternal.call(this); BaseObject.prototype.disposeInternal.call(this);
}; }
/**
/**
* Get the map associated with this control. * Get the map associated with this control.
* @return {module:ol/PluggableMap} Map. * @return {module:ol/PluggableMap} Map.
* @api * @api
*/ */
Control.prototype.getMap = function() { getMap() {
return this.map_; return this.map_;
}; }
/**
/**
* Remove the control from its current map and attach it to the new map. * Remove the control from its current map and attach it to the new map.
* Subclasses may set up event handlers to get notified about changes to * Subclasses may set up event handlers to get notified about changes to
* the map here. * the map here.
* @param {module:ol/PluggableMap} map Map. * @param {module:ol/PluggableMap} map Map.
* @api * @api
*/ */
Control.prototype.setMap = function(map) { setMap(map) {
if (this.map_) { if (this.map_) {
removeNode(this.element); removeNode(this.element);
} }
@@ -136,10 +132,9 @@ Control.prototype.setMap = function(map) {
} }
map.render(); map.render();
} }
}; }
/**
/**
* This function is used to set a target element for the control. It has no * This function is used to set a target element for the control. It has no
* effect if it is called after the control has been added to the map (i.e. * effect if it is called after the control has been added to the map (i.e.
* after `setMap` is called on the control). If no `target` is set in the * after `setMap` is called on the control). If no `target` is set in the
@@ -148,9 +143,14 @@ Control.prototype.setMap = function(map) {
* @param {Element|string} target Target. * @param {Element|string} target Target.
* @api * @api
*/ */
Control.prototype.setTarget = function(target) { setTarget(target) {
this.target_ = typeof target === 'string' ? this.target_ = typeof target === 'string' ?
document.getElementById(target) : document.getElementById(target) :
target; target;
}; }
}
inherits(Control, BaseObject);
export default Control; export default Control;
+19 -20
View File
@@ -67,7 +67,8 @@ const getChangeType = (function() {
* @param {module:ol/control/FullScreen~Options=} opt_options Options. * @param {module:ol/control/FullScreen~Options=} opt_options Options.
* @api * @api
*/ */
const FullScreen = function(opt_options) { class FullScreen {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -130,25 +131,21 @@ const FullScreen = function(opt_options) {
*/ */
this.source_ = options.source; this.source_ = options.source;
}; }
inherits(FullScreen, Control); /**
/**
* @param {MouseEvent} event The event to handle * @param {MouseEvent} event The event to handle
* @private * @private
*/ */
FullScreen.prototype.handleClick_ = function(event) { handleClick_(event) {
event.preventDefault(); event.preventDefault();
this.handleFullScreen_(); this.handleFullScreen_();
}; }
/**
/**
* @private * @private
*/ */
FullScreen.prototype.handleFullScreen_ = function() { handleFullScreen_() {
if (!isFullScreenSupported()) { if (!isFullScreenSupported()) {
return; return;
} }
@@ -174,13 +171,12 @@ FullScreen.prototype.handleFullScreen_ = function() {
requestFullScreen(element); requestFullScreen(element);
} }
} }
}; }
/**
/**
* @private * @private
*/ */
FullScreen.prototype.handleFullScreenChange_ = function() { handleFullScreenChange_() {
const button = this.element.firstElementChild; const button = this.element.firstElementChild;
const map = this.getMap(); const map = this.getMap();
if (isFullScreen()) { if (isFullScreen()) {
@@ -193,14 +189,13 @@ FullScreen.prototype.handleFullScreenChange_ = function() {
if (map) { if (map) {
map.updateSize(); map.updateSize();
} }
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
FullScreen.prototype.setMap = function(map) { setMap(map) {
Control.prototype.setMap.call(this, map); Control.prototype.setMap.call(this, map);
if (map) { if (map) {
this.listenerKeys.push(listen(document, this.listenerKeys.push(listen(document,
@@ -208,7 +203,11 @@ FullScreen.prototype.setMap = function(map) {
this.handleFullScreenChange_, this) this.handleFullScreenChange_, this)
); );
} }
}; }
}
inherits(FullScreen, Control);
/** /**
* @return {boolean} Fullscreen is supported by the current platform. * @return {boolean} Fullscreen is supported by the current platform.
+52 -59
View File
@@ -52,7 +52,8 @@ const COORDINATE_FORMAT = 'coordinateFormat';
* options. * options.
* @api * @api
*/ */
const MousePosition = function(opt_options) { class MousePosition {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -112,40 +113,16 @@ const MousePosition = function(opt_options) {
*/ */
this.lastMouseMovePixel_ = null; this.lastMouseMovePixel_ = null;
};
inherits(MousePosition, Control);
/**
* Update the mouseposition element.
* @param {module:ol/MapEvent} mapEvent Map event.
* @this {module:ol/control/MousePosition}
* @api
*/
export function render(mapEvent) {
const frameState = mapEvent.frameState;
if (!frameState) {
this.mapProjection_ = null;
} else {
if (this.mapProjection_ != frameState.viewState.projection) {
this.mapProjection_ = frameState.viewState.projection;
this.transform_ = null;
} }
}
this.updateHTML_(this.lastMouseMovePixel_);
}
/**
/**
* @private * @private
*/ */
MousePosition.prototype.handleProjectionChanged_ = function() { handleProjectionChanged_() {
this.transform_ = null; this.transform_ = null;
}; }
/**
/**
* Return the coordinate format type used to render the current position or * Return the coordinate format type used to render the current position or
* undefined. * undefined.
* @return {module:ol/coordinate~CoordinateFormat|undefined} The format to render the current * @return {module:ol/coordinate~CoordinateFormat|undefined} The format to render the current
@@ -153,53 +130,49 @@ MousePosition.prototype.handleProjectionChanged_ = function() {
* @observable * @observable
* @api * @api
*/ */
MousePosition.prototype.getCoordinateFormat = function() { getCoordinateFormat() {
return ( return (
/** @type {module:ol/coordinate~CoordinateFormat|undefined} */ (this.get(COORDINATE_FORMAT)) /** @type {module:ol/coordinate~CoordinateFormat|undefined} */ (this.get(COORDINATE_FORMAT))
); );
}; }
/**
/**
* Return the projection that is used to report the mouse position. * Return the projection that is used to report the mouse position.
* @return {module:ol/proj/Projection|undefined} The projection to report mouse * @return {module:ol/proj/Projection|undefined} The projection to report mouse
* position in. * position in.
* @observable * @observable
* @api * @api
*/ */
MousePosition.prototype.getProjection = function() { getProjection() {
return ( return (
/** @type {module:ol/proj/Projection|undefined} */ (this.get(PROJECTION)) /** @type {module:ol/proj/Projection|undefined} */ (this.get(PROJECTION))
); );
}; }
/**
/**
* @param {Event} event Browser event. * @param {Event} event Browser event.
* @protected * @protected
*/ */
MousePosition.prototype.handleMouseMove = function(event) { handleMouseMove(event) {
const map = this.getMap(); const map = this.getMap();
this.lastMouseMovePixel_ = map.getEventPixel(event); this.lastMouseMovePixel_ = map.getEventPixel(event);
this.updateHTML_(this.lastMouseMovePixel_); this.updateHTML_(this.lastMouseMovePixel_);
}; }
/**
/**
* @param {Event} event Browser event. * @param {Event} event Browser event.
* @protected * @protected
*/ */
MousePosition.prototype.handleMouseOut = function(event) { handleMouseOut(event) {
this.updateHTML_(null); this.updateHTML_(null);
this.lastMouseMovePixel_ = null; this.lastMouseMovePixel_ = null;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
MousePosition.prototype.setMap = function(map) { setMap(map) {
Control.prototype.setMap.call(this, map); Control.prototype.setMap.call(this, map);
if (map) { if (map) {
const viewport = map.getViewport(); const viewport = map.getViewport();
@@ -212,38 +185,35 @@ MousePosition.prototype.setMap = function(map) {
); );
} }
} }
}; }
/**
/**
* Set the coordinate format type used to render the current position. * Set the coordinate format type used to render the current position.
* @param {module:ol/coordinate~CoordinateFormat} format The format to render the current * @param {module:ol/coordinate~CoordinateFormat} format The format to render the current
* position in. * position in.
* @observable * @observable
* @api * @api
*/ */
MousePosition.prototype.setCoordinateFormat = function(format) { setCoordinateFormat(format) {
this.set(COORDINATE_FORMAT, format); this.set(COORDINATE_FORMAT, format);
}; }
/**
/**
* Set the projection that is used to report the mouse position. * Set the projection that is used to report the mouse position.
* @param {module:ol/proj~ProjectionLike} projection The projection to report mouse * @param {module:ol/proj~ProjectionLike} projection The projection to report mouse
* position in. * position in.
* @observable * @observable
* @api * @api
*/ */
MousePosition.prototype.setProjection = function(projection) { setProjection(projection) {
this.set(PROJECTION, getProjection(projection)); this.set(PROJECTION, getProjection(projection));
}; }
/**
/**
* @param {?module:ol~Pixel} pixel Pixel. * @param {?module:ol~Pixel} pixel Pixel.
* @private * @private
*/ */
MousePosition.prototype.updateHTML_ = function(pixel) { updateHTML_(pixel) {
let html = this.undefinedHTML_; let html = this.undefinedHTML_;
if (pixel && this.mapProjection_) { if (pixel && this.mapProjection_) {
if (!this.transform_) { if (!this.transform_) {
@@ -271,7 +241,30 @@ MousePosition.prototype.updateHTML_ = function(pixel) {
this.element.innerHTML = html; this.element.innerHTML = html;
this.renderedHTML_ = html; this.renderedHTML_ = html;
} }
}; }
}
inherits(MousePosition, Control);
/**
* Update the mouseposition element.
* @param {module:ol/MapEvent} mapEvent Map event.
* @this {module:ol/control/MousePosition}
* @api
*/
export function render(mapEvent) {
const frameState = mapEvent.frameState;
if (!frameState) {
this.mapProjection_ = null;
} else {
if (this.mapProjection_ != frameState.viewState.projection) {
this.mapProjection_ = frameState.viewState.projection;
this.transform_ = null;
}
}
this.updateHTML_(this.lastMouseMovePixel_);
}
export default MousePosition; export default MousePosition;
+71 -85
View File
@@ -66,7 +66,8 @@ const MIN_RATIO = 0.1;
* @param {module:ol/control/OverviewMap~Options=} opt_options OverviewMap options. * @param {module:ol/control/OverviewMap~Options=} opt_options OverviewMap options.
* @api * @api
*/ */
const OverviewMap = function(opt_options) { class OverviewMap {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -222,16 +223,13 @@ const OverviewMap = function(opt_options) {
window.addEventListener('mousemove', move); window.addEventListener('mousemove', move);
window.addEventListener('mouseup', endMoving); window.addEventListener('mouseup', endMoving);
}); });
}; }
inherits(OverviewMap, Control); /**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
OverviewMap.prototype.setMap = function(map) { setMap(map) {
const oldMap = this.getMap(); const oldMap = this.getMap();
if (map === oldMap) { if (map === oldMap) {
return; return;
@@ -265,15 +263,14 @@ OverviewMap.prototype.setMap = function(map) {
} }
} }
} }
}; }
/**
/**
* Handle map property changes. This only deals with changes to the map's view. * Handle map property changes. This only deals with changes to the map's view.
* @param {module:ol/Object~ObjectEvent} event The propertychange event. * @param {module:ol/Object~ObjectEvent} event The propertychange event.
* @private * @private
*/ */
OverviewMap.prototype.handleMapPropertyChange_ = function(event) { handleMapPropertyChange_(event) {
if (event.key === MapProperty.VIEW) { if (event.key === MapProperty.VIEW) {
const oldView = /** @type {module:ol/View} */ (event.oldValue); const oldView = /** @type {module:ol/View} */ (event.oldValue);
if (oldView) { if (oldView) {
@@ -282,57 +279,41 @@ OverviewMap.prototype.handleMapPropertyChange_ = function(event) {
const newView = this.getMap().getView(); const newView = this.getMap().getView();
this.bindView_(newView); this.bindView_(newView);
} }
}; }
/**
/**
* Register listeners for view property changes. * Register listeners for view property changes.
* @param {module:ol/View} view The view. * @param {module:ol/View} view The view.
* @private * @private
*/ */
OverviewMap.prototype.bindView_ = function(view) { bindView_(view) {
listen(view, listen(view,
getChangeEventType(ViewProperty.ROTATION), getChangeEventType(ViewProperty.ROTATION),
this.handleRotationChanged_, this); this.handleRotationChanged_, this);
}; }
/**
/**
* Unregister listeners for view property changes. * Unregister listeners for view property changes.
* @param {module:ol/View} view The view. * @param {module:ol/View} view The view.
* @private * @private
*/ */
OverviewMap.prototype.unbindView_ = function(view) { unbindView_(view) {
unlisten(view, unlisten(view,
getChangeEventType(ViewProperty.ROTATION), getChangeEventType(ViewProperty.ROTATION),
this.handleRotationChanged_, this); this.handleRotationChanged_, this);
}; }
/**
/**
* Handle rotation changes to the main map. * Handle rotation changes to the main map.
* TODO: This should rotate the extent rectrangle instead of the * TODO: This should rotate the extent rectrangle instead of the
* overview map's view. * overview map's view.
* @private * @private
*/ */
OverviewMap.prototype.handleRotationChanged_ = function() { handleRotationChanged_() {
this.ovmap_.getView().setRotation(this.getMap().getView().getRotation()); this.ovmap_.getView().setRotation(this.getMap().getView().getRotation());
}; }
/**
/**
* Update the overview map element.
* @param {module:ol/MapEvent} mapEvent Map event.
* @this {module:ol/control/OverviewMap}
* @api
*/
export function render(mapEvent) {
this.validateExtent_();
this.updateBox_();
}
/**
* Reset the overview map extent if the box size (width or * Reset the overview map extent if the box size (width or
* height) is less than the size of the overview map size times minRatio * height) is less than the size of the overview map size times minRatio
* or is greater than the size of the overview size times maxRatio. * or is greater than the size of the overview size times maxRatio.
@@ -343,7 +324,7 @@ export function render(mapEvent) {
* main map center location. * main map center location.
* @private * @private
*/ */
OverviewMap.prototype.validateExtent_ = function() { validateExtent_() {
const map = this.getMap(); const map = this.getMap();
const ovmap = this.ovmap_; const ovmap = this.ovmap_;
@@ -380,15 +361,14 @@ OverviewMap.prototype.validateExtent_ = function() {
} else if (!containsExtent(ovextent, extent)) { } else if (!containsExtent(ovextent, extent)) {
this.recenter_(); this.recenter_();
} }
}; }
/**
/**
* Reset the overview map extent to half calculated min and max ratio times * Reset the overview map extent to half calculated min and max ratio times
* the extent of the main map. * the extent of the main map.
* @private * @private
*/ */
OverviewMap.prototype.resetExtent_ = function() { resetExtent_() {
if (MAX_RATIO === 0 || MIN_RATIO === 0) { if (MAX_RATIO === 0 || MIN_RATIO === 0) {
return; return;
} }
@@ -411,15 +391,14 @@ OverviewMap.prototype.resetExtent_ = function() {
const ratio = 1 / (Math.pow(2, steps / 2) * MIN_RATIO); const ratio = 1 / (Math.pow(2, steps / 2) * MIN_RATIO);
scaleFromCenter(extent, ratio); scaleFromCenter(extent, ratio);
ovview.fit(extent); ovview.fit(extent);
}; }
/**
/**
* Set the center of the overview map to the map center without changing its * Set the center of the overview map to the map center without changing its
* resolution. * resolution.
* @private * @private
*/ */
OverviewMap.prototype.recenter_ = function() { recenter_() {
const map = this.getMap(); const map = this.getMap();
const ovmap = this.ovmap_; const ovmap = this.ovmap_;
@@ -428,14 +407,13 @@ OverviewMap.prototype.recenter_ = function() {
const ovview = ovmap.getView(); const ovview = ovmap.getView();
ovview.setCenter(view.getCenter()); ovview.setCenter(view.getCenter());
}; }
/**
/**
* Update the box using the main map extent * Update the box using the main map extent
* @private * @private
*/ */
OverviewMap.prototype.updateBox_ = function() { updateBox_() {
const map = this.getMap(); const map = this.getMap();
const ovmap = this.ovmap_; const ovmap = this.ovmap_;
@@ -467,17 +445,15 @@ OverviewMap.prototype.updateBox_ = function() {
box.style.width = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution) + 'px'; box.style.width = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution) + 'px';
box.style.height = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution) + 'px'; box.style.height = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution) + 'px';
} }
}; }
/**
/**
* @param {number} rotation Target rotation. * @param {number} rotation Target rotation.
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate. * @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
* @return {module:ol/coordinate~Coordinate|undefined} Coordinate for rotation and center anchor. * @return {module:ol/coordinate~Coordinate|undefined} Coordinate for rotation and center anchor.
* @private * @private
*/ */
OverviewMap.prototype.calculateCoordinateRotate_ = function( calculateCoordinateRotate_(rotation, coordinate) {
rotation, coordinate) {
let coordinateRotate; let coordinateRotate;
const map = this.getMap(); const map = this.getMap();
@@ -494,23 +470,21 @@ OverviewMap.prototype.calculateCoordinateRotate_ = function(
addCoordinate(coordinateRotate, currentCenter); addCoordinate(coordinateRotate, currentCenter);
} }
return coordinateRotate; return coordinateRotate;
}; }
/**
/**
* @param {MouseEvent} event The event to handle * @param {MouseEvent} event The event to handle
* @private * @private
*/ */
OverviewMap.prototype.handleClick_ = function(event) { handleClick_(event) {
event.preventDefault(); event.preventDefault();
this.handleToggle_(); this.handleToggle_();
}; }
/**
/**
* @private * @private
*/ */
OverviewMap.prototype.handleToggle_ = function() { handleToggle_() {
this.element.classList.toggle(CLASS_COLLAPSED); this.element.classList.toggle(CLASS_COLLAPSED);
if (this.collapsed_) { if (this.collapsed_) {
replaceNode(this.collapseLabel_, this.label_); replaceNode(this.collapseLabel_, this.label_);
@@ -531,25 +505,23 @@ OverviewMap.prototype.handleToggle_ = function() {
}, },
this); this);
} }
}; }
/**
/**
* Return `true` if the overview map is collapsible, `false` otherwise. * Return `true` if the overview map is collapsible, `false` otherwise.
* @return {boolean} True if the widget is collapsible. * @return {boolean} True if the widget is collapsible.
* @api * @api
*/ */
OverviewMap.prototype.getCollapsible = function() { getCollapsible() {
return this.collapsible_; return this.collapsible_;
}; }
/**
/**
* Set whether the overview map should be collapsible. * Set whether the overview map should be collapsible.
* @param {boolean} collapsible True if the widget is collapsible. * @param {boolean} collapsible True if the widget is collapsible.
* @api * @api
*/ */
OverviewMap.prototype.setCollapsible = function(collapsible) { setCollapsible(collapsible) {
if (this.collapsible_ === collapsible) { if (this.collapsible_ === collapsible) {
return; return;
} }
@@ -558,40 +530,54 @@ OverviewMap.prototype.setCollapsible = function(collapsible) {
if (!collapsible && this.collapsed_) { if (!collapsible && this.collapsed_) {
this.handleToggle_(); this.handleToggle_();
} }
}; }
/**
/**
* Collapse or expand the overview map according to the passed parameter. Will * Collapse or expand the overview map according to the passed parameter. Will
* not do anything if the overview map isn't collapsible or if the current * not do anything if the overview map isn't collapsible or if the current
* collapsed state is already the one requested. * collapsed state is already the one requested.
* @param {boolean} collapsed True if the widget is collapsed. * @param {boolean} collapsed True if the widget is collapsed.
* @api * @api
*/ */
OverviewMap.prototype.setCollapsed = function(collapsed) { setCollapsed(collapsed) {
if (!this.collapsible_ || this.collapsed_ === collapsed) { if (!this.collapsible_ || this.collapsed_ === collapsed) {
return; return;
} }
this.handleToggle_(); this.handleToggle_();
}; }
/**
/**
* Determine if the overview map is collapsed. * Determine if the overview map is collapsed.
* @return {boolean} The overview map is collapsed. * @return {boolean} The overview map is collapsed.
* @api * @api
*/ */
OverviewMap.prototype.getCollapsed = function() { getCollapsed() {
return this.collapsed_; return this.collapsed_;
}; }
/**
/**
* Return the overview map. * Return the overview map.
* @return {module:ol/PluggableMap} Overview map. * @return {module:ol/PluggableMap} Overview map.
* @api * @api
*/ */
OverviewMap.prototype.getOverviewMap = function() { getOverviewMap() {
return this.ovmap_; return this.ovmap_;
}; }
}
inherits(OverviewMap, Control);
/**
* Update the overview map element.
* @param {module:ol/MapEvent} mapEvent Map event.
* @this {module:ol/control/OverviewMap}
* @api
*/
export function render(mapEvent) {
this.validateExtent_();
this.updateBox_();
}
export default OverviewMap; export default OverviewMap;
+12 -12
View File
@@ -38,7 +38,8 @@ import {inherits} from '../util.js';
* @param {module:ol/control/Rotate~Options=} opt_options Rotate options. * @param {module:ol/control/Rotate~Options=} opt_options Rotate options.
* @api * @api
*/ */
const Rotate = function(opt_options) { class Rotate {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -107,29 +108,25 @@ const Rotate = function(opt_options) {
this.element.classList.add(CLASS_HIDDEN); this.element.classList.add(CLASS_HIDDEN);
} }
}; }
inherits(Rotate, Control); /**
/**
* @param {MouseEvent} event The event to handle * @param {MouseEvent} event The event to handle
* @private * @private
*/ */
Rotate.prototype.handleClick_ = function(event) { handleClick_(event) {
event.preventDefault(); event.preventDefault();
if (this.callResetNorth_ !== undefined) { if (this.callResetNorth_ !== undefined) {
this.callResetNorth_(); this.callResetNorth_();
} else { } else {
this.resetNorth_(); this.resetNorth_();
} }
}; }
/**
/**
* @private * @private
*/ */
Rotate.prototype.resetNorth_ = function() { resetNorth_() {
const map = this.getMap(); const map = this.getMap();
const view = map.getView(); const view = map.getView();
if (!view) { if (!view) {
@@ -148,7 +145,10 @@ Rotate.prototype.resetNorth_ = function() {
view.setRotation(0); view.setRotation(0);
} }
} }
}; }
}
inherits(Rotate, Control);
/** /**
+35 -36
View File
@@ -64,7 +64,8 @@ const LEADING_DIGITS = [1, 2, 5];
* @param {module:ol/control/ScaleLine~Options=} opt_options Scale line options. * @param {module:ol/control/ScaleLine~Options=} opt_options Scale line options.
* @api * @api
*/ */
const ScaleLine = function(opt_options) { class ScaleLine {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -128,65 +129,42 @@ const ScaleLine = function(opt_options) {
this.setUnits(/** @type {module:ol/control/ScaleLine~Units} */ (options.units) || this.setUnits(/** @type {module:ol/control/ScaleLine~Units} */ (options.units) ||
Units.METRIC); Units.METRIC);
}; }
inherits(ScaleLine, Control); /**
/**
* Return the units to use in the scale line. * Return the units to use in the scale line.
* @return {module:ol/control/ScaleLine~Units|undefined} The units * @return {module:ol/control/ScaleLine~Units|undefined} The units
* to use in the scale line. * to use in the scale line.
* @observable * @observable
* @api * @api
*/ */
ScaleLine.prototype.getUnits = function() { getUnits() {
return ( return (
/** @type {module:ol/control/ScaleLine~Units|undefined} */ (this.get(UNITS_PROP)) /** @type {module:ol/control/ScaleLine~Units|undefined} */ (this.get(UNITS_PROP))
); );
};
/**
* Update the scale line element.
* @param {module:ol/MapEvent} mapEvent Map event.
* @this {module:ol/control/ScaleLine}
* @api
*/
export function render(mapEvent) {
const frameState = mapEvent.frameState;
if (!frameState) {
this.viewState_ = null;
} else {
this.viewState_ = frameState.viewState;
} }
this.updateElement_();
}
/**
/**
* @private * @private
*/ */
ScaleLine.prototype.handleUnitsChanged_ = function() { handleUnitsChanged_() {
this.updateElement_(); this.updateElement_();
}; }
/**
/**
* Set the units to use in the scale line. * Set the units to use in the scale line.
* @param {module:ol/control/ScaleLine~Units} units The units to use in the scale line. * @param {module:ol/control/ScaleLine~Units} units The units to use in the scale line.
* @observable * @observable
* @api * @api
*/ */
ScaleLine.prototype.setUnits = function(units) { setUnits(units) {
this.set(UNITS_PROP, units); this.set(UNITS_PROP, units);
}; }
/**
/**
* @private * @private
*/ */
ScaleLine.prototype.updateElement_ = function() { updateElement_() {
const viewState = this.viewState_; const viewState = this.viewState_;
if (!viewState) { if (!viewState) {
@@ -303,6 +281,27 @@ ScaleLine.prototype.updateElement_ = function() {
this.renderedVisible_ = true; this.renderedVisible_ = true;
} }
}; }
}
inherits(ScaleLine, Control);
/**
* Update the scale line element.
* @param {module:ol/MapEvent} mapEvent Map event.
* @this {module:ol/control/ScaleLine}
* @api
*/
export function render(mapEvent) {
const frameState = mapEvent.frameState;
if (!frameState) {
this.viewState_ = null;
} else {
this.viewState_ = frameState.viewState;
}
this.updateElement_();
}
export default ScaleLine; export default ScaleLine;
+14 -12
View File
@@ -36,7 +36,8 @@ import {easeOut} from '../easing.js';
* @param {module:ol/control/Zoom~Options=} opt_options Zoom options. * @param {module:ol/control/Zoom~Options=} opt_options Zoom options.
* @api * @api
*/ */
const Zoom = function(opt_options) { class Zoom {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -91,27 +92,23 @@ const Zoom = function(opt_options) {
*/ */
this.duration_ = options.duration !== undefined ? options.duration : 250; this.duration_ = options.duration !== undefined ? options.duration : 250;
}; }
inherits(Zoom, Control); /**
/**
* @param {number} delta Zoom delta. * @param {number} delta Zoom delta.
* @param {MouseEvent} event The event to handle * @param {MouseEvent} event The event to handle
* @private * @private
*/ */
Zoom.prototype.handleClick_ = function(delta, event) { handleClick_(delta, event) {
event.preventDefault(); event.preventDefault();
this.zoomByDelta_(delta); this.zoomByDelta_(delta);
}; }
/**
/**
* @param {number} delta Zoom delta. * @param {number} delta Zoom delta.
* @private * @private
*/ */
Zoom.prototype.zoomByDelta_ = function(delta) { zoomByDelta_(delta) {
const map = this.getMap(); const map = this.getMap();
const view = map.getView(); const view = map.getView();
if (!view) { if (!view) {
@@ -135,5 +132,10 @@ Zoom.prototype.zoomByDelta_ = function(delta) {
view.setResolution(newResolution); view.setResolution(newResolution);
} }
} }
}; }
}
inherits(Zoom, Control);
export default Zoom; export default Zoom;
+155 -163
View File
@@ -47,7 +47,8 @@ const Direction = {
* @param {module:ol/control/ZoomSlider~Options=} opt_options Zoom slider options. * @param {module:ol/control/ZoomSlider~Options=} opt_options Zoom slider options.
* @api * @api
*/ */
const ZoomSlider = function(opt_options) { class ZoomSlider {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -146,39 +147,34 @@ const ZoomSlider = function(opt_options) {
element: containerElement, element: containerElement,
render: options.render || render render: options.render || render
}); });
}; }
inherits(ZoomSlider, Control); /**
/**
* @inheritDoc * @inheritDoc
*/ */
ZoomSlider.prototype.disposeInternal = function() { disposeInternal() {
this.dragger_.dispose(); this.dragger_.dispose();
Control.prototype.disposeInternal.call(this); Control.prototype.disposeInternal.call(this);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
ZoomSlider.prototype.setMap = function(map) { setMap(map) {
Control.prototype.setMap.call(this, map); Control.prototype.setMap.call(this, map);
if (map) { if (map) {
map.render(); map.render();
} }
}; }
/**
/**
* Initializes the slider element. This will determine and set this controls * Initializes the slider element. This will determine and set this controls
* direction_ and also constrain the dragging of the thumb to always be within * direction_ and also constrain the dragging of the thumb to always be within
* the bounds of the container. * the bounds of the container.
* *
* @private * @private
*/ */
ZoomSlider.prototype.initSlider_ = function() { initSlider_() {
const container = this.element; const container = this.element;
const containerSize = { const containerSize = {
width: container.offsetWidth, height: container.offsetHeight width: container.offsetWidth, height: container.offsetHeight
@@ -202,7 +198,150 @@ ZoomSlider.prototype.initSlider_ = function() {
this.heightLimit_ = containerSize.height - thumbHeight; this.heightLimit_ = containerSize.height - thumbHeight;
} }
this.sliderInitialized_ = true; this.sliderInitialized_ = true;
}; }
/**
* @param {MouseEvent} event The browser event to handle.
* @private
*/
handleContainerClick_(event) {
const view = this.getMap().getView();
const relativePosition = this.getRelativePosition_(
event.offsetX - this.thumbSize_[0] / 2,
event.offsetY - this.thumbSize_[1] / 2);
const resolution = this.getResolutionForPosition_(relativePosition);
view.animate({
resolution: view.constrainResolution(resolution),
duration: this.duration_,
easing: easeOut
});
}
/**
* Handle dragger start events.
* @param {module:ol/pointer/PointerEvent} event The drag event.
* @private
*/
handleDraggerStart_(event) {
if (!this.dragging_ && event.originalEvent.target === this.element.firstElementChild) {
this.getMap().getView().setHint(ViewHint.INTERACTING, 1);
this.previousX_ = event.clientX;
this.previousY_ = event.clientY;
this.dragging_ = true;
}
}
/**
* Handle dragger drag events.
*
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
* @private
*/
handleDraggerDrag_(event) {
if (this.dragging_) {
const element = 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 relativePosition = this.getRelativePosition_(deltaX, deltaY);
this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
this.getMap().getView().setResolution(this.currentResolution_);
this.setThumbPosition_(this.currentResolution_);
this.previousX_ = event.clientX;
this.previousY_ = event.clientY;
}
}
/**
* Handle dragger end events.
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
* @private
*/
handleDraggerEnd_(event) {
if (this.dragging_) {
const view = this.getMap().getView();
view.setHint(ViewHint.INTERACTING, -1);
view.animate({
resolution: view.constrainResolution(this.currentResolution_),
duration: this.duration_,
easing: easeOut
});
this.dragging_ = false;
this.previousX_ = undefined;
this.previousY_ = undefined;
}
}
/**
* Positions the thumb inside its container according to the given resolution.
*
* @param {number} res The res.
* @private
*/
setThumbPosition_(res) {
const position = this.getPositionForResolution_(res);
const thumb = this.element.firstElementChild;
if (this.direction_ == Direction.HORIZONTAL) {
thumb.style.left = this.widthLimit_ * position + 'px';
} else {
thumb.style.top = this.heightLimit_ * position + 'px';
}
}
/**
* Calculates the relative position of the thumb given x and y offsets. The
* relative position scales from 0 to 1. The x and y offsets are assumed to be
* in pixel units within the dragger limits.
*
* @param {number} x Pixel position relative to the left of the slider.
* @param {number} y Pixel position relative to the top of the slider.
* @return {number} The relative position of the thumb.
* @private
*/
getRelativePosition_(x, y) {
let amount;
if (this.direction_ === Direction.HORIZONTAL) {
amount = x / this.widthLimit_;
} else {
amount = y / this.heightLimit_;
}
return clamp(amount, 0, 1);
}
/**
* Calculates the corresponding resolution of the thumb given its relative
* position (where 0 is the minimum and 1 is the maximum).
*
* @param {number} position The relative position of the thumb.
* @return {number} The corresponding resolution.
* @private
*/
getResolutionForPosition_(position) {
const fn = this.getMap().getView().getResolutionForValueFunction();
return fn(1 - position);
}
/**
* Determines the relative position of the slider for the given resolution. A
* relative position of 0 corresponds to the minimum view resolution. A
* relative position of 1 corresponds to the maximum view resolution.
*
* @param {number} res The resolution.
* @return {number} The relative position value (between 0 and 1).
* @private
*/
getPositionForResolution_(res) {
const fn = this.getMap().getView().getValueForResolutionFunction();
return 1 - fn(res);
}
}
inherits(ZoomSlider, Control);
/** /**
@@ -226,151 +365,4 @@ export function render(mapEvent) {
} }
/**
* @param {MouseEvent} event The browser event to handle.
* @private
*/
ZoomSlider.prototype.handleContainerClick_ = function(event) {
const view = this.getMap().getView();
const relativePosition = this.getRelativePosition_(
event.offsetX - this.thumbSize_[0] / 2,
event.offsetY - this.thumbSize_[1] / 2);
const resolution = this.getResolutionForPosition_(relativePosition);
view.animate({
resolution: view.constrainResolution(resolution),
duration: this.duration_,
easing: easeOut
});
};
/**
* Handle dragger start events.
* @param {module:ol/pointer/PointerEvent} event The drag event.
* @private
*/
ZoomSlider.prototype.handleDraggerStart_ = function(event) {
if (!this.dragging_ && event.originalEvent.target === this.element.firstElementChild) {
this.getMap().getView().setHint(ViewHint.INTERACTING, 1);
this.previousX_ = event.clientX;
this.previousY_ = event.clientY;
this.dragging_ = true;
}
};
/**
* Handle dragger drag events.
*
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
* @private
*/
ZoomSlider.prototype.handleDraggerDrag_ = function(event) {
if (this.dragging_) {
const element = 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 relativePosition = this.getRelativePosition_(deltaX, deltaY);
this.currentResolution_ = this.getResolutionForPosition_(relativePosition);
this.getMap().getView().setResolution(this.currentResolution_);
this.setThumbPosition_(this.currentResolution_);
this.previousX_ = event.clientX;
this.previousY_ = event.clientY;
}
};
/**
* Handle dragger end events.
* @param {module:ol/pointer/PointerEvent|Event} event The drag event.
* @private
*/
ZoomSlider.prototype.handleDraggerEnd_ = function(event) {
if (this.dragging_) {
const view = this.getMap().getView();
view.setHint(ViewHint.INTERACTING, -1);
view.animate({
resolution: view.constrainResolution(this.currentResolution_),
duration: this.duration_,
easing: easeOut
});
this.dragging_ = false;
this.previousX_ = undefined;
this.previousY_ = undefined;
}
};
/**
* Positions the thumb inside its container according to the given resolution.
*
* @param {number} res The res.
* @private
*/
ZoomSlider.prototype.setThumbPosition_ = function(res) {
const position = this.getPositionForResolution_(res);
const thumb = this.element.firstElementChild;
if (this.direction_ == Direction.HORIZONTAL) {
thumb.style.left = this.widthLimit_ * position + 'px';
} else {
thumb.style.top = this.heightLimit_ * position + 'px';
}
};
/**
* Calculates the relative position of the thumb given x and y offsets. The
* relative position scales from 0 to 1. The x and y offsets are assumed to be
* in pixel units within the dragger limits.
*
* @param {number} x Pixel position relative to the left of the slider.
* @param {number} y Pixel position relative to the top of the slider.
* @return {number} The relative position of the thumb.
* @private
*/
ZoomSlider.prototype.getRelativePosition_ = function(x, y) {
let amount;
if (this.direction_ === Direction.HORIZONTAL) {
amount = x / this.widthLimit_;
} else {
amount = y / this.heightLimit_;
}
return clamp(amount, 0, 1);
};
/**
* Calculates the corresponding resolution of the thumb given its relative
* position (where 0 is the minimum and 1 is the maximum).
*
* @param {number} position The relative position of the thumb.
* @return {number} The corresponding resolution.
* @private
*/
ZoomSlider.prototype.getResolutionForPosition_ = function(position) {
const fn = this.getMap().getView().getResolutionForValueFunction();
return fn(1 - position);
};
/**
* Determines the relative position of the slider for the given resolution. A
* relative position of 0 corresponds to the minimum view resolution. A
* relative position of 1 corresponds to the maximum view resolution.
*
* @param {number} res The resolution.
* @return {number} The relative position value (between 0 and 1).
* @private
*/
ZoomSlider.prototype.getPositionForResolution_ = function(res) {
const fn = this.getMap().getView().getValueForResolutionFunction();
return 1 - fn(res);
};
export default ZoomSlider; export default ZoomSlider;
+14 -12
View File
@@ -31,7 +31,8 @@ import {CLASS_CONTROL, CLASS_UNSELECTABLE} from '../css.js';
* @param {module:ol/control/ZoomToExtent~Options=} opt_options Options. * @param {module:ol/control/ZoomToExtent~Options=} opt_options Options.
* @api * @api
*/ */
const ZoomToExtent = function(opt_options) { class ZoomToExtent {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
/** /**
@@ -62,28 +63,29 @@ const ZoomToExtent = function(opt_options) {
element: element, element: element,
target: options.target target: options.target
}); });
}; }
inherits(ZoomToExtent, Control); /**
/**
* @param {MouseEvent} event The event to handle * @param {MouseEvent} event The event to handle
* @private * @private
*/ */
ZoomToExtent.prototype.handleClick_ = function(event) { handleClick_(event) {
event.preventDefault(); event.preventDefault();
this.handleZoomToExtent(); this.handleZoomToExtent();
}; }
/**
/**
* @protected * @protected
*/ */
ZoomToExtent.prototype.handleZoomToExtent = function() { handleZoomToExtent() {
const map = this.getMap(); const map = this.getMap();
const view = map.getView(); const view = map.getView();
const extent = !this.extent ? view.getProjection().getExtent() : this.extent; const extent = !this.extent ? view.getProjection().getExtent() : this.extent;
view.fit(extent); view.fit(extent);
}; }
}
inherits(ZoomToExtent, Control);
export default ZoomToExtent; export default ZoomToExtent;
+26 -28
View File
@@ -31,7 +31,8 @@ import Event from '../events/Event.js';
* @constructor * @constructor
* @extends {module:ol/Disposable} * @extends {module:ol/Disposable}
*/ */
const EventTarget = function() { class EventTarget {
constructor() {
Disposable.call(this); Disposable.call(this);
@@ -53,16 +54,13 @@ const EventTarget = function() {
*/ */
this.listeners_ = {}; this.listeners_ = {};
}; }
inherits(EventTarget, Disposable); /**
/**
* @param {string} type Type. * @param {string} type Type.
* @param {module:ol/events~ListenerFunction} listener Listener. * @param {module:ol/events~ListenerFunction} listener Listener.
*/ */
EventTarget.prototype.addEventListener = function(type, listener) { addEventListener(type, listener) {
let listeners = this.listeners_[type]; let listeners = this.listeners_[type];
if (!listeners) { if (!listeners) {
listeners = this.listeners_[type] = []; listeners = this.listeners_[type] = [];
@@ -70,17 +68,16 @@ EventTarget.prototype.addEventListener = function(type, listener) {
if (listeners.indexOf(listener) === -1) { if (listeners.indexOf(listener) === -1) {
listeners.push(listener); listeners.push(listener);
} }
}; }
/**
/**
* @param {{type: string, * @param {{type: string,
* target: (EventTarget|module:ol/events/EventTarget|undefined)}|module:ol/events/Event| * target: (EventTarget|module:ol/events/EventTarget|undefined)}|module:ol/events/Event|
* string} event Event or event type. * string} event Event or event type.
* @return {boolean|undefined} `false` if anyone called preventDefault on the * @return {boolean|undefined} `false` if anyone called preventDefault on the
* event object or if any of the listeners returned false. * event object or if any of the listeners returned false.
*/ */
EventTarget.prototype.dispatchEvent = function(event) { dispatchEvent(event) {
const evt = typeof event === 'string' ? new Event(event) : event; const evt = typeof event === 'string' ? new Event(event) : event;
const type = evt.type; const type = evt.type;
evt.target = this; evt.target = this;
@@ -109,46 +106,42 @@ EventTarget.prototype.dispatchEvent = function(event) {
} }
return propagate; return propagate;
} }
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
EventTarget.prototype.disposeInternal = function() { disposeInternal() {
unlistenAll(this); unlistenAll(this);
}; }
/**
/**
* Get the listeners for a specified event type. Listeners are returned in the * Get the listeners for a specified event type. Listeners are returned in the
* order that they will be called in. * order that they will be called in.
* *
* @param {string} type Type. * @param {string} type Type.
* @return {Array.<module:ol/events~ListenerFunction>} Listeners. * @return {Array.<module:ol/events~ListenerFunction>} Listeners.
*/ */
EventTarget.prototype.getListeners = function(type) { getListeners(type) {
return this.listeners_[type]; return this.listeners_[type];
}; }
/**
/**
* @param {string=} opt_type Type. If not provided, * @param {string=} opt_type Type. If not provided,
* `true` will be returned if this EventTarget has any listeners. * `true` will be returned if this EventTarget has any listeners.
* @return {boolean} Has listeners. * @return {boolean} Has listeners.
*/ */
EventTarget.prototype.hasListener = function(opt_type) { hasListener(opt_type) {
return opt_type ? return opt_type ?
opt_type in this.listeners_ : opt_type in this.listeners_ :
Object.keys(this.listeners_).length > 0; Object.keys(this.listeners_).length > 0;
}; }
/**
/**
* @param {string} type Type. * @param {string} type Type.
* @param {module:ol/events~ListenerFunction} listener Listener. * @param {module:ol/events~ListenerFunction} listener Listener.
*/ */
EventTarget.prototype.removeEventListener = function(type, listener) { removeEventListener(type, listener) {
const listeners = this.listeners_[type]; const listeners = this.listeners_[type];
if (listeners) { if (listeners) {
const index = listeners.indexOf(listener); const index = listeners.indexOf(listener);
@@ -163,5 +156,10 @@ EventTarget.prototype.removeEventListener = function(type, listener) {
} }
} }
} }
}; }
}
inherits(EventTarget, Disposable);
export default EventTarget; export default EventTarget;
+130 -134
View File
@@ -63,7 +63,8 @@ GEOMETRY_WRITERS[GeometryType.MULTI_POLYGON] = writeMultiPolygonGeometry;
* @param {module:ol/format/EsriJSON~Options=} opt_options Options. * @param {module:ol/format/EsriJSON~Options=} opt_options Options.
* @api * @api
*/ */
const EsriJSON = function(opt_options) { class EsriJSON {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -76,7 +77,134 @@ const EsriJSON = function(opt_options) {
*/ */
this.geometryName_ = options.geometryName; this.geometryName_ = options.geometryName;
}; }
/**
* @inheritDoc
*/
readFeatureFromObject(object, opt_options) {
const esriJSONFeature = /** @type {EsriJSONFeature} */ (object);
const geometry = readGeometry(esriJSONFeature.geometry, opt_options);
const feature = new Feature();
if (this.geometryName_) {
feature.setGeometryName(this.geometryName_);
}
feature.setGeometry(geometry);
if (opt_options && opt_options.idField &&
esriJSONFeature.attributes[opt_options.idField]) {
feature.setId(/** @type {number} */(esriJSONFeature.attributes[opt_options.idField]));
}
if (esriJSONFeature.attributes) {
feature.setProperties(esriJSONFeature.attributes);
}
return feature;
}
/**
* @inheritDoc
*/
readFeaturesFromObject(object, opt_options) {
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
const options = opt_options ? opt_options : {};
if (esriJSONObject.features) {
const esriJSONFeatureCollection = /** @type {EsriJSONFeatureCollection} */ (object);
/** @type {Array.<module:ol/Feature>} */
const features = [];
const esriJSONFeatures = esriJSONFeatureCollection.features;
options.idField = object.objectIdFieldName;
for (let i = 0, ii = esriJSONFeatures.length; i < ii; ++i) {
features.push(this.readFeatureFromObject(esriJSONFeatures[i], options));
}
return features;
} else {
return [this.readFeatureFromObject(object, options)];
}
}
/**
* @inheritDoc
*/
readGeometryFromObject(object, opt_options) {
return readGeometry(/** @type {EsriJSONGeometry} */(object), opt_options);
}
/**
* @inheritDoc
*/
readProjectionFromObject(object) {
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
if (esriJSONObject.spatialReference && esriJSONObject.spatialReference.wkid) {
const crs = esriJSONObject.spatialReference.wkid;
return getProjection('EPSG:' + crs);
} else {
return null;
}
}
/**
* Encode a geometry as a EsriJSON object.
*
* @param {module:ol/geom/Geometry} geometry Geometry.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {EsriJSONGeometry} Object.
* @override
* @api
*/
writeGeometryObject(geometry, opt_options) {
return writeGeometry(geometry, this.adaptOptions(opt_options));
}
/**
* Encode a feature as a esriJSON Feature object.
*
* @param {module:ol/Feature} feature Feature.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {Object} Object.
* @override
* @api
*/
writeFeatureObject(feature, opt_options) {
opt_options = this.adaptOptions(opt_options);
const object = {};
const geometry = feature.getGeometry();
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()
});
}
}
const properties = feature.getProperties();
delete properties[feature.getGeometryName()];
if (!isEmpty(properties)) {
object['attributes'] = properties;
} else {
object['attributes'] = {};
}
return object;
}
/**
* Encode an array of features as a EsriJSON object.
*
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {Object} EsriJSON Object.
* @override
* @api
*/
writeFeaturesObject(features, opt_options) {
opt_options = this.adaptOptions(opt_options);
const objects = [];
for (let i = 0, ii = features.length; i < ii; ++i) {
objects.push(this.writeFeatureObject(features[i], opt_options));
}
return /** @type {EsriJSONFeatureCollection} */ ({
'features': objects
});
}
}
inherits(EsriJSON, JSONFeature); inherits(EsriJSON, JSONFeature);
@@ -439,50 +567,6 @@ EsriJSON.prototype.readFeature;
EsriJSON.prototype.readFeatures; EsriJSON.prototype.readFeatures;
/**
* @inheritDoc
*/
EsriJSON.prototype.readFeatureFromObject = function(object, opt_options) {
const esriJSONFeature = /** @type {EsriJSONFeature} */ (object);
const geometry = readGeometry(esriJSONFeature.geometry, opt_options);
const feature = new Feature();
if (this.geometryName_) {
feature.setGeometryName(this.geometryName_);
}
feature.setGeometry(geometry);
if (opt_options && opt_options.idField &&
esriJSONFeature.attributes[opt_options.idField]) {
feature.setId(/** @type {number} */(esriJSONFeature.attributes[opt_options.idField]));
}
if (esriJSONFeature.attributes) {
feature.setProperties(esriJSONFeature.attributes);
}
return feature;
};
/**
* @inheritDoc
*/
EsriJSON.prototype.readFeaturesFromObject = function(object, opt_options) {
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
const options = opt_options ? opt_options : {};
if (esriJSONObject.features) {
const esriJSONFeatureCollection = /** @type {EsriJSONFeatureCollection} */ (object);
/** @type {Array.<module:ol/Feature>} */
const features = [];
const esriJSONFeatures = esriJSONFeatureCollection.features;
options.idField = object.objectIdFieldName;
for (let i = 0, ii = esriJSONFeatures.length; i < ii; ++i) {
features.push(this.readFeatureFromObject(esriJSONFeatures[i], options));
}
return features;
} else {
return [this.readFeatureFromObject(object, options)];
}
};
/** /**
* Read a geometry from a EsriJSON source. * Read a geometry from a EsriJSON source.
* *
@@ -495,14 +579,6 @@ EsriJSON.prototype.readFeaturesFromObject = function(object, opt_options) {
EsriJSON.prototype.readGeometry; EsriJSON.prototype.readGeometry;
/**
* @inheritDoc
*/
EsriJSON.prototype.readGeometryFromObject = function(object, opt_options) {
return readGeometry(/** @type {EsriJSONGeometry} */(object), opt_options);
};
/** /**
* Read the projection from a EsriJSON source. * Read the projection from a EsriJSON source.
* *
@@ -514,20 +590,6 @@ EsriJSON.prototype.readGeometryFromObject = function(object, opt_options) {
EsriJSON.prototype.readProjection; EsriJSON.prototype.readProjection;
/**
* @inheritDoc
*/
EsriJSON.prototype.readProjectionFromObject = function(object) {
const esriJSONObject = /** @type {EsriJSONObject} */ (object);
if (esriJSONObject.spatialReference && esriJSONObject.spatialReference.wkid) {
const crs = esriJSONObject.spatialReference.wkid;
return getProjection('EPSG:' + crs);
} else {
return null;
}
};
/** /**
* @param {module:ol/geom/Geometry} geometry Geometry. * @param {module:ol/geom/Geometry} geometry Geometry.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options. * @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
@@ -552,20 +614,6 @@ function writeGeometry(geometry, opt_options) {
EsriJSON.prototype.writeGeometry; EsriJSON.prototype.writeGeometry;
/**
* Encode a geometry as a EsriJSON object.
*
* @param {module:ol/geom/Geometry} geometry Geometry.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {EsriJSONGeometry} Object.
* @override
* @api
*/
EsriJSON.prototype.writeGeometryObject = function(geometry, opt_options) {
return writeGeometry(geometry, this.adaptOptions(opt_options));
};
/** /**
* Encode a feature as a EsriJSON Feature string. * Encode a feature as a EsriJSON Feature string.
* *
@@ -578,38 +626,6 @@ EsriJSON.prototype.writeGeometryObject = function(geometry, opt_options) {
EsriJSON.prototype.writeFeature; EsriJSON.prototype.writeFeature;
/**
* Encode a feature as a esriJSON Feature object.
*
* @param {module:ol/Feature} feature Feature.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {Object} Object.
* @override
* @api
*/
EsriJSON.prototype.writeFeatureObject = function(feature, opt_options) {
opt_options = this.adaptOptions(opt_options);
const object = {};
const geometry = feature.getGeometry();
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()
});
}
}
const properties = feature.getProperties();
delete properties[feature.getGeometryName()];
if (!isEmpty(properties)) {
object['attributes'] = properties;
} else {
object['attributes'] = {};
}
return object;
};
/** /**
* Encode an array of features as EsriJSON. * Encode an array of features as EsriJSON.
* *
@@ -622,24 +638,4 @@ EsriJSON.prototype.writeFeatureObject = function(feature, opt_options) {
EsriJSON.prototype.writeFeatures; EsriJSON.prototype.writeFeatures;
/**
* Encode an array of features as a EsriJSON object.
*
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {Object} EsriJSON Object.
* @override
* @api
*/
EsriJSON.prototype.writeFeaturesObject = function(features, opt_options) {
opt_options = this.adaptOptions(opt_options);
const objects = [];
for (let i = 0, ii = features.length; i < ii; ++i) {
objects.push(this.writeFeatureObject(features[i], opt_options));
}
return /** @type {EsriJSONFeatureCollection} */ ({
'features': objects
});
};
export default EsriJSON; export default EsriJSON;
+29 -38
View File
@@ -60,7 +60,8 @@ import {get as getProjection, equivalent as equivalentProjection, transformExten
* @abstract * @abstract
* @api * @api
*/ */
const FeatureFormat = function() { class FeatureFormat {
constructor() {
/** /**
* @protected * @protected
@@ -74,17 +75,16 @@ const FeatureFormat = function() {
*/ */
this.defaultFeatureProjection = null; this.defaultFeatureProjection = null;
}; }
/**
/**
* Adds the data projection to the read options. * Adds the data projection to the read options.
* @param {Document|Node|Object|string} source Source. * @param {Document|Node|Object|string} source Source.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options. * @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
* @return {module:ol/format/Feature~ReadOptions|undefined} Options. * @return {module:ol/format/Feature~ReadOptions|undefined} Options.
* @protected * @protected
*/ */
FeatureFormat.prototype.getReadOptions = function(source, opt_options) { getReadOptions(source, opt_options) {
let options; let options;
if (opt_options) { if (opt_options) {
options = { options = {
@@ -94,10 +94,9 @@ FeatureFormat.prototype.getReadOptions = function(source, opt_options) {
}; };
} }
return this.adaptOptions(options); return this.adaptOptions(options);
}; }
/**
/**
* Sets the `dataProjection` on the options, if no `dataProjection` * Sets the `dataProjection` on the options, if no `dataProjection`
* is set. * is set.
* @param {module:ol/format/Feature~WriteOptions|module:ol/format/Feature~ReadOptions|undefined} options * @param {module:ol/format/Feature~WriteOptions|module:ol/format/Feature~ReadOptions|undefined} options
@@ -106,31 +105,28 @@ FeatureFormat.prototype.getReadOptions = function(source, opt_options) {
* @return {module:ol/format/Feature~WriteOptions|module:ol/format/Feature~ReadOptions|undefined} * @return {module:ol/format/Feature~WriteOptions|module:ol/format/Feature~ReadOptions|undefined}
* Updated options. * Updated options.
*/ */
FeatureFormat.prototype.adaptOptions = function(options) { adaptOptions(options) {
return assign({ return assign({
dataProjection: this.dataProjection, dataProjection: this.dataProjection,
featureProjection: this.defaultFeatureProjection featureProjection: this.defaultFeatureProjection
}, options); }, options);
}; }
/**
/**
* Get the extent from the source of the last {@link readFeatures} call. * Get the extent from the source of the last {@link readFeatures} call.
* @return {module:ol/extent~Extent} Tile extent. * @return {module:ol/extent~Extent} Tile extent.
*/ */
FeatureFormat.prototype.getLastExtent = function() { getLastExtent() {
return null; return null;
}; }
/**
/**
* @abstract * @abstract
* @return {module:ol/format/FormatType} Format. * @return {module:ol/format/FormatType} Format.
*/ */
FeatureFormat.prototype.getType = function() {}; getType() {}
/**
/**
* Read a single feature from a source. * Read a single feature from a source.
* *
* @abstract * @abstract
@@ -138,10 +134,9 @@ FeatureFormat.prototype.getType = function() {};
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options. * @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @return {module:ol/Feature} Feature. * @return {module:ol/Feature} Feature.
*/ */
FeatureFormat.prototype.readFeature = function(source, opt_options) {}; readFeature(source, opt_options) {}
/**
/**
* Read all features from a source. * Read all features from a source.
* *
* @abstract * @abstract
@@ -149,10 +144,9 @@ FeatureFormat.prototype.readFeature = function(source, opt_options) {};
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options. * @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @return {Array.<module:ol/Feature>} Features. * @return {Array.<module:ol/Feature>} Features.
*/ */
FeatureFormat.prototype.readFeatures = function(source, opt_options) {}; readFeatures(source, opt_options) {}
/**
/**
* Read a single geometry from a source. * Read a single geometry from a source.
* *
* @abstract * @abstract
@@ -160,20 +154,18 @@ FeatureFormat.prototype.readFeatures = function(source, opt_options) {};
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options. * @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @return {module:ol/geom/Geometry} Geometry. * @return {module:ol/geom/Geometry} Geometry.
*/ */
FeatureFormat.prototype.readGeometry = function(source, opt_options) {}; readGeometry(source, opt_options) {}
/**
/**
* Read the projection from a source. * Read the projection from a source.
* *
* @abstract * @abstract
* @param {Document|Node|Object|string} source Source. * @param {Document|Node|Object|string} source Source.
* @return {module:ol/proj/Projection} Projection. * @return {module:ol/proj/Projection} Projection.
*/ */
FeatureFormat.prototype.readProjection = function(source) {}; readProjection(source) {}
/**
/**
* Encode a feature in this format. * Encode a feature in this format.
* *
* @abstract * @abstract
@@ -181,10 +173,9 @@ FeatureFormat.prototype.readProjection = function(source) {};
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options. * @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {string} Result. * @return {string} Result.
*/ */
FeatureFormat.prototype.writeFeature = function(feature, opt_options) {}; writeFeature(feature, opt_options) {}
/**
/**
* Encode an array of features in this format. * Encode an array of features in this format.
* *
* @abstract * @abstract
@@ -192,10 +183,9 @@ FeatureFormat.prototype.writeFeature = function(feature, opt_options) {};
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options. * @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {string} Result. * @return {string} Result.
*/ */
FeatureFormat.prototype.writeFeatures = function(features, opt_options) {}; writeFeatures(features, opt_options) {}
/**
/**
* Write a single geometry in this format. * Write a single geometry in this format.
* *
* @abstract * @abstract
@@ -203,7 +193,8 @@ FeatureFormat.prototype.writeFeatures = function(features, opt_options) {};
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options. * @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {string} Result. * @return {string} Result.
*/ */
FeatureFormat.prototype.writeGeometry = function(geometry, opt_options) {}; writeGeometry(geometry, opt_options) {}
}
export default FeatureFormat; export default FeatureFormat;
+95 -119
View File
@@ -30,7 +30,8 @@ const schemaLocation = GMLNS + ' http://schemas.opengis.net/gml/2.1.2/feature.xs
* @extends {module:ol/format/GMLBase} * @extends {module:ol/format/GMLBase}
* @api * @api
*/ */
const GML2 = function(opt_options) { class GML2 {
constructor(opt_options) {
const options = /** @type {module:ol/format/GMLBase~Options} */ const options = /** @type {module:ol/format/GMLBase~Options} */
(opt_options ? opt_options : {}); (opt_options ? opt_options : {});
@@ -46,18 +47,15 @@ const GML2 = function(opt_options) {
this.schemaLocation = options.schemaLocation ? this.schemaLocation = options.schemaLocation ?
options.schemaLocation : schemaLocation; options.schemaLocation : schemaLocation;
}; }
inherits(GML2, GMLBase); /**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @private * @private
* @return {Array.<number>|undefined} Flat coordinates. * @return {Array.<number>|undefined} Flat coordinates.
*/ */
GML2.prototype.readFlatCoordinates_ = function(node, objectStack) { readFlatCoordinates_(node, objectStack) {
const s = getAllTextContent(node, false).replace(/^\s*|\s*$/g, ''); const s = getAllTextContent(node, false).replace(/^\s*|\s*$/g, '');
const context = /** @type {module:ol/xml~NodeStackItem} */ (objectStack[0]); const context = /** @type {module:ol/xml~NodeStackItem} */ (objectStack[0]);
const containerSrs = context['srsName']; const containerSrs = context['srsName'];
@@ -82,31 +80,29 @@ GML2.prototype.readFlatCoordinates_ = function(node, objectStack) {
} }
} }
return flatCoordinates; return flatCoordinates;
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @private * @private
* @return {module:ol/extent~Extent|undefined} Envelope. * @return {module:ol/extent~Extent|undefined} Envelope.
*/ */
GML2.prototype.readBox_ = function(node, objectStack) { readBox_(node, objectStack) {
/** @type {Array.<number>} */ /** @type {Array.<number>} */
const flatCoordinates = pushParseAndPop([null], const flatCoordinates = pushParseAndPop([null],
this.BOX_PARSERS_, node, objectStack, this); this.BOX_PARSERS_, node, objectStack, this);
return createOrUpdate(flatCoordinates[1][0], return createOrUpdate(flatCoordinates[1][0],
flatCoordinates[1][1], flatCoordinates[1][3], flatCoordinates[1][1], flatCoordinates[1][3],
flatCoordinates[1][4]); flatCoordinates[1][4]);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @private * @private
*/ */
GML2.prototype.innerBoundaryIsParser_ = function(node, objectStack) { innerBoundaryIsParser_(node, objectStack) {
/** @type {Array.<number>|undefined} */ /** @type {Array.<number>|undefined} */
const flatLinearRing = pushParseAndPop(undefined, const flatLinearRing = pushParseAndPop(undefined,
this.RING_PARSERS, node, objectStack, this); this.RING_PARSERS, node, objectStack, this);
@@ -115,15 +111,14 @@ GML2.prototype.innerBoundaryIsParser_ = function(node, objectStack) {
(objectStack[objectStack.length - 1]); (objectStack[objectStack.length - 1]);
flatLinearRings.push(flatLinearRing); flatLinearRings.push(flatLinearRing);
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @private * @private
*/ */
GML2.prototype.outerBoundaryIsParser_ = function(node, objectStack) { outerBoundaryIsParser_(node, objectStack) {
/** @type {Array.<number>|undefined} */ /** @type {Array.<number>|undefined} */
const flatLinearRing = pushParseAndPop(undefined, const flatLinearRing = pushParseAndPop(undefined,
this.RING_PARSERS, node, objectStack, this); this.RING_PARSERS, node, objectStack, this);
@@ -132,10 +127,9 @@ GML2.prototype.outerBoundaryIsParser_ = function(node, objectStack) {
(objectStack[objectStack.length - 1]); (objectStack[objectStack.length - 1]);
flatLinearRings[0] = flatLinearRing; flatLinearRings[0] = flatLinearRing;
} }
}; }
/**
/**
* @const * @const
* @param {*} value Value. * @param {*} value Value.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
@@ -143,7 +137,7 @@ GML2.prototype.outerBoundaryIsParser_ = function(node, objectStack) {
* @return {Node|undefined} Node. * @return {Node|undefined} Node.
* @private * @private
*/ */
GML2.prototype.GEOMETRY_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) { GEOMETRY_NODE_FACTORY_(value, objectStack, opt_nodeName) {
const context = objectStack[objectStack.length - 1]; const context = objectStack[objectStack.length - 1];
const multiSurface = context['multiSurface']; const multiSurface = context['multiSurface'];
const surface = context['surface']; const surface = context['surface'];
@@ -163,15 +157,14 @@ GML2.prototype.GEOMETRY_NODE_FACTORY_ = function(value, objectStack, opt_nodeNam
} }
return createElementNS('http://www.opengis.net/gml', return createElementNS('http://www.opengis.net/gml',
nodeName); nodeName);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/Feature} feature Feature. * @param {module:ol/Feature} feature Feature.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
*/ */
GML2.prototype.writeFeatureElement = function(node, feature, objectStack) { writeFeatureElement(node, feature, objectStack) {
const fid = feature.getId(); const fid = feature.getId();
if (fid) { if (fid) {
node.setAttribute('fid', fid); node.setAttribute('fid', fid);
@@ -210,16 +203,15 @@ GML2.prototype.writeFeatureElement = function(node, feature, objectStack) {
makeSimpleNodeFactory(undefined, featureNS), makeSimpleNodeFactory(undefined, featureNS),
values, values,
objectStack, keys); objectStack, keys);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/LineString} geometry LineString geometry. * @param {module:ol/geom/LineString} geometry LineString geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeCurveOrLineString_ = function(node, geometry, objectStack) { writeCurveOrLineString_(node, geometry, objectStack) {
const context = objectStack[objectStack.length - 1]; const context = objectStack[objectStack.length - 1];
const srsName = context['srsName']; const srsName = context['srsName'];
if (node.nodeName !== 'LineStringSegment' && srsName) { if (node.nodeName !== 'LineStringSegment' && srsName) {
@@ -236,31 +228,29 @@ GML2.prototype.writeCurveOrLineString_ = function(node, geometry, objectStack) {
this.writeCurveSegments_(segments, this.writeCurveSegments_(segments,
geometry, objectStack); geometry, objectStack);
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/LineString} line LineString geometry. * @param {module:ol/geom/LineString} line LineString geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeLineStringOrCurveMember_ = function(node, line, objectStack) { writeLineStringOrCurveMember_(node, line, objectStack) {
const child = this.GEOMETRY_NODE_FACTORY_(line, objectStack); const child = this.GEOMETRY_NODE_FACTORY_(line, objectStack);
if (child) { if (child) {
node.appendChild(child); node.appendChild(child);
this.writeCurveOrLineString_(child, line, objectStack); this.writeCurveOrLineString_(child, line, objectStack);
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/MultiLineString} geometry MultiLineString geometry. * @param {module:ol/geom/MultiLineString} geometry MultiLineString geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeMultiCurveOrLineString_ = function(node, geometry, objectStack) { writeMultiCurveOrLineString_(node, geometry, objectStack) {
const context = objectStack[objectStack.length - 1]; const context = objectStack[objectStack.length - 1];
const hasZ = context['hasZ']; const hasZ = context['hasZ'];
const srsName = context['srsName']; const srsName = context['srsName'];
@@ -273,15 +263,14 @@ GML2.prototype.writeMultiCurveOrLineString_ = function(node, geometry, objectSta
this.LINESTRINGORCURVEMEMBER_SERIALIZERS_, this.LINESTRINGORCURVEMEMBER_SERIALIZERS_,
this.MULTIGEOMETRY_MEMBER_NODE_FACTORY_, lines, this.MULTIGEOMETRY_MEMBER_NODE_FACTORY_, lines,
objectStack, undefined, this); objectStack, undefined, this);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/Geometry|module:ol/extent~Extent} geometry Geometry. * @param {module:ol/geom/Geometry|module:ol/extent~Extent} geometry Geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
*/ */
GML2.prototype.writeGeometryElement = function(node, geometry, objectStack) { writeGeometryElement(node, geometry, objectStack) {
const context = /** @type {module:ol/format/Feature~WriteOptions} */ (objectStack[objectStack.length - 1]); const context = /** @type {module:ol/format/Feature~WriteOptions} */ (objectStack[objectStack.length - 1]);
const item = assign({}, context); const item = assign({}, context);
item.node = node; item.node = node;
@@ -300,31 +289,29 @@ GML2.prototype.writeGeometryElement = function(node, geometry, objectStack) {
(item), this.GEOMETRY_SERIALIZERS_, (item), this.GEOMETRY_SERIALIZERS_,
this.GEOMETRY_NODE_FACTORY_, [value], this.GEOMETRY_NODE_FACTORY_, [value],
objectStack, undefined, this); objectStack, undefined, this);
}; }
/**
/**
* @param {string} namespaceURI XML namespace. * @param {string} namespaceURI XML namespace.
* @returns {Node} coordinates node. * @returns {Node} coordinates node.
* @private * @private
*/ */
GML2.prototype.createCoordinatesNode_ = function(namespaceURI) { createCoordinatesNode_(namespaceURI) {
const coordinates = createElementNS(namespaceURI, 'coordinates'); const coordinates = createElementNS(namespaceURI, 'coordinates');
coordinates.setAttribute('decimal', '.'); coordinates.setAttribute('decimal', '.');
coordinates.setAttribute('cs', ','); coordinates.setAttribute('cs', ',');
coordinates.setAttribute('ts', ' '); coordinates.setAttribute('ts', ' ');
return coordinates; return coordinates;
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/LineString|module:ol/geom/LinearRing} value Geometry. * @param {module:ol/geom/LineString|module:ol/geom/LinearRing} value Geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeCoordinates_ = function(node, value, objectStack) { writeCoordinates_(node, value, objectStack) {
const context = objectStack[objectStack.length - 1]; const context = objectStack[objectStack.length - 1];
const hasZ = context['hasZ']; const hasZ = context['hasZ'];
const srsName = context['srsName']; const srsName = context['srsName'];
@@ -337,29 +324,27 @@ GML2.prototype.writeCoordinates_ = function(node, value, objectStack) {
parts[i] = this.getCoords_(point, srsName, hasZ); parts[i] = this.getCoords_(point, srsName, hasZ);
} }
writeStringTextNode(node, parts.join(' ')); writeStringTextNode(node, parts.join(' '));
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/LineString} line LineString geometry. * @param {module:ol/geom/LineString} line LineString geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeCurveSegments_ = function(node, line, objectStack) { writeCurveSegments_(node, line, objectStack) {
const child = createElementNS(node.namespaceURI, 'LineStringSegment'); const child = createElementNS(node.namespaceURI, 'LineStringSegment');
node.appendChild(child); node.appendChild(child);
this.writeCurveOrLineString_(child, line, objectStack); this.writeCurveOrLineString_(child, line, objectStack);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/Polygon} geometry Polygon geometry. * @param {module:ol/geom/Polygon} geometry Polygon geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeSurfaceOrPolygon_ = function(node, geometry, objectStack) { writeSurfaceOrPolygon_(node, geometry, objectStack) {
const context = objectStack[objectStack.length - 1]; const context = objectStack[objectStack.length - 1];
const hasZ = context['hasZ']; const hasZ = context['hasZ'];
const srsName = context['srsName']; const srsName = context['srsName'];
@@ -379,17 +364,16 @@ GML2.prototype.writeSurfaceOrPolygon_ = function(node, geometry, objectStack) {
this.writeSurfacePatches_( this.writeSurfacePatches_(
patches, geometry, objectStack); patches, geometry, objectStack);
} }
}; }
/**
/**
* @param {*} value Value. * @param {*} value Value.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @param {string=} opt_nodeName Node name. * @param {string=} opt_nodeName Node name.
* @return {Node} Node. * @return {Node} Node.
* @private * @private
*/ */
GML2.prototype.RING_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) { RING_NODE_FACTORY_(value, objectStack, opt_nodeName) {
const context = objectStack[objectStack.length - 1]; const context = objectStack[objectStack.length - 1];
const parentNode = context.node; const parentNode = context.node;
const exteriorWritten = context['exteriorWritten']; const exteriorWritten = context['exteriorWritten'];
@@ -398,43 +382,40 @@ GML2.prototype.RING_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
} }
return createElementNS(parentNode.namespaceURI, return createElementNS(parentNode.namespaceURI,
exteriorWritten !== undefined ? 'innerBoundaryIs' : 'outerBoundaryIs'); exteriorWritten !== undefined ? 'innerBoundaryIs' : 'outerBoundaryIs');
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/Polygon} polygon Polygon geometry. * @param {module:ol/geom/Polygon} polygon Polygon geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeSurfacePatches_ = function(node, polygon, objectStack) { writeSurfacePatches_(node, polygon, objectStack) {
const child = createElementNS(node.namespaceURI, 'PolygonPatch'); const child = createElementNS(node.namespaceURI, 'PolygonPatch');
node.appendChild(child); node.appendChild(child);
this.writeSurfaceOrPolygon_(child, polygon, objectStack); this.writeSurfaceOrPolygon_(child, polygon, objectStack);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/LinearRing} ring LinearRing geometry. * @param {module:ol/geom/LinearRing} ring LinearRing geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeRing_ = function(node, ring, objectStack) { writeRing_(node, ring, objectStack) {
const linearRing = createElementNS(node.namespaceURI, 'LinearRing'); const linearRing = createElementNS(node.namespaceURI, 'LinearRing');
node.appendChild(linearRing); node.appendChild(linearRing);
this.writeLinearRing_(linearRing, ring, objectStack); this.writeLinearRing_(linearRing, ring, objectStack);
}; }
/**
/**
* @param {Array.<number>} point Point geometry. * @param {Array.<number>} point Point geometry.
* @param {string=} opt_srsName Optional srsName * @param {string=} opt_srsName Optional srsName
* @param {boolean=} opt_hasZ whether the geometry has a Z coordinate (is 3D) or not. * @param {boolean=} opt_hasZ whether the geometry has a Z coordinate (is 3D) or not.
* @return {string} The coords string. * @return {string} The coords string.
* @private * @private
*/ */
GML2.prototype.getCoords_ = function(point, opt_srsName, opt_hasZ) { getCoords_(point, opt_srsName, opt_hasZ) {
let axisOrientation = 'enu'; let axisOrientation = 'enu';
if (opt_srsName) { if (opt_srsName) {
axisOrientation = getProjection(opt_srsName).getAxisOrientation(); axisOrientation = getProjection(opt_srsName).getAxisOrientation();
@@ -449,16 +430,15 @@ GML2.prototype.getCoords_ = function(point, opt_srsName, opt_hasZ) {
} }
return coords; return coords;
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/Point} geometry Point geometry. * @param {module:ol/geom/Point} geometry Point geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writePoint_ = function(node, geometry, objectStack) { writePoint_(node, geometry, objectStack) {
const context = objectStack[objectStack.length - 1]; const context = objectStack[objectStack.length - 1];
const hasZ = context['hasZ']; const hasZ = context['hasZ'];
const srsName = context['srsName']; const srsName = context['srsName'];
@@ -470,16 +450,15 @@ GML2.prototype.writePoint_ = function(node, geometry, objectStack) {
const point = geometry.getCoordinates(); const point = geometry.getCoordinates();
const coord = this.getCoords_(point, srsName, hasZ); const coord = this.getCoords_(point, srsName, hasZ);
writeStringTextNode(coordinates, coord); writeStringTextNode(coordinates, coord);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/MultiPoint} geometry MultiPoint geometry. * @param {module:ol/geom/MultiPoint} geometry MultiPoint geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeMultiPoint_ = function(node, geometry, objectStack) { writeMultiPoint_(node, geometry, objectStack) {
const context = objectStack[objectStack.length - 1]; const context = objectStack[objectStack.length - 1];
const hasZ = context['hasZ']; const hasZ = context['hasZ'];
const srsName = context['srsName']; const srsName = context['srsName'];
@@ -491,29 +470,27 @@ GML2.prototype.writeMultiPoint_ = function(node, geometry, objectStack) {
this.POINTMEMBER_SERIALIZERS_, this.POINTMEMBER_SERIALIZERS_,
makeSimpleNodeFactory('pointMember'), points, makeSimpleNodeFactory('pointMember'), points,
objectStack, undefined, this); objectStack, undefined, this);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/Point} point Point geometry. * @param {module:ol/geom/Point} point Point geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writePointMember_ = function(node, point, objectStack) { writePointMember_(node, point, objectStack) {
const child = createElementNS(node.namespaceURI, 'Point'); const child = createElementNS(node.namespaceURI, 'Point');
node.appendChild(child); node.appendChild(child);
this.writePoint_(child, point, objectStack); this.writePoint_(child, point, objectStack);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/LinearRing} geometry LinearRing geometry. * @param {module:ol/geom/LinearRing} geometry LinearRing geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeLinearRing_ = function(node, geometry, objectStack) { writeLinearRing_(node, geometry, objectStack) {
const context = objectStack[objectStack.length - 1]; const context = objectStack[objectStack.length - 1];
const srsName = context['srsName']; const srsName = context['srsName'];
if (srsName) { if (srsName) {
@@ -522,16 +499,15 @@ GML2.prototype.writeLinearRing_ = function(node, geometry, objectStack) {
const coordinates = this.createCoordinatesNode_(node.namespaceURI); const coordinates = this.createCoordinatesNode_(node.namespaceURI);
node.appendChild(coordinates); node.appendChild(coordinates);
this.writeCoordinates_(coordinates, geometry, objectStack); this.writeCoordinates_(coordinates, geometry, objectStack);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/MultiPolygon} geometry MultiPolygon geometry. * @param {module:ol/geom/MultiPolygon} geometry MultiPolygon geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeMultiSurfaceOrPolygon_ = function(node, geometry, objectStack) { writeMultiSurfaceOrPolygon_(node, geometry, objectStack) {
const context = objectStack[objectStack.length - 1]; const context = objectStack[objectStack.length - 1];
const hasZ = context['hasZ']; const hasZ = context['hasZ'];
const srsName = context['srsName']; const srsName = context['srsName'];
@@ -544,32 +520,30 @@ GML2.prototype.writeMultiSurfaceOrPolygon_ = function(node, geometry, objectStac
this.SURFACEORPOLYGONMEMBER_SERIALIZERS_, this.SURFACEORPOLYGONMEMBER_SERIALIZERS_,
this.MULTIGEOMETRY_MEMBER_NODE_FACTORY_, polygons, this.MULTIGEOMETRY_MEMBER_NODE_FACTORY_, polygons,
objectStack, undefined, this); objectStack, undefined, this);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/geom/Polygon} polygon Polygon geometry. * @param {module:ol/geom/Polygon} polygon Polygon geometry.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeSurfaceOrPolygonMember_ = function(node, polygon, objectStack) { writeSurfaceOrPolygonMember_(node, polygon, objectStack) {
const child = this.GEOMETRY_NODE_FACTORY_( const child = this.GEOMETRY_NODE_FACTORY_(
polygon, objectStack); polygon, objectStack);
if (child) { if (child) {
node.appendChild(child); node.appendChild(child);
this.writeSurfaceOrPolygon_(child, polygon, objectStack); this.writeSurfaceOrPolygon_(child, polygon, objectStack);
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/extent~Extent} extent Extent. * @param {module:ol/extent~Extent} extent Extent.
* @param {Array.<*>} objectStack Node stack. * @param {Array.<*>} objectStack Node stack.
* @private * @private
*/ */
GML2.prototype.writeEnvelope = function(node, extent, objectStack) { writeEnvelope(node, extent, objectStack) {
const context = objectStack[objectStack.length - 1]; const context = objectStack[objectStack.length - 1];
const srsName = context['srsName']; const srsName = context['srsName'];
if (srsName) { if (srsName) {
@@ -582,7 +556,24 @@ GML2.prototype.writeEnvelope = function(node, extent, objectStack) {
OBJECT_PROPERTY_NODE_FACTORY, OBJECT_PROPERTY_NODE_FACTORY,
values, values,
objectStack, keys, this); objectStack, keys, this);
}; }
/**
* @const
* @param {*} value Value.
* @param {Array.<*>} objectStack Object stack.
* @param {string=} opt_nodeName Node name.
* @return {Node|undefined} Node.
* @private
*/
MULTIGEOMETRY_MEMBER_NODE_FACTORY_(value, objectStack, opt_nodeName) {
const parentNode = objectStack[objectStack.length - 1].node;
return createElementNS('http://www.opengis.net/gml',
MULTIGEOMETRY_TO_MEMBER_NODENAME[parentNode.nodeName]);
}
}
inherits(GML2, GMLBase);
/** /**
@@ -597,21 +588,6 @@ const MULTIGEOMETRY_TO_MEMBER_NODENAME = {
}; };
/**
* @const
* @param {*} value Value.
* @param {Array.<*>} objectStack Object stack.
* @param {string=} opt_nodeName Node name.
* @return {Node|undefined} Node.
* @private
*/
GML2.prototype.MULTIGEOMETRY_MEMBER_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
const parentNode = objectStack[objectStack.length - 1].node;
return createElementNS('http://www.opengis.net/gml',
MULTIGEOMETRY_TO_MEMBER_NODENAME[parentNode.nodeName]);
};
/** /**
* @const * @const
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>} * @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
+590 -628
View File
File diff suppressed because it is too large Load Diff
+96 -110
View File
@@ -75,7 +75,8 @@ export const GMLNS = 'http://www.opengis.net/gml';
* Optional configuration object. * Optional configuration object.
* @extends {module:ol/format/XMLFeature} * @extends {module:ol/format/XMLFeature}
*/ */
const GMLBase = function(opt_options) { class GMLBase {
constructor(opt_options) {
const options = /** @type {module:ol/format/GMLBase~Options} */ (opt_options ? opt_options : {}); const options = /** @type {module:ol/format/GMLBase~Options} */ (opt_options ? opt_options : {});
/** /**
@@ -112,31 +113,14 @@ const GMLBase = function(opt_options) {
}; };
XMLFeature.call(this); XMLFeature.call(this);
}; }
inherits(GMLBase, XMLFeature); /**
/**
* A regular expression that matches if a string only contains whitespace
* characters. It will e.g. match `''`, `' '`, `'\n'` etc. The non-breaking
* space (0xa0) is explicitly included as IE doesn't include it in its
* definition of `\s`.
*
* Information from `goog.string.isEmptyOrWhitespace`: https://github.com/google/closure-library/blob/e877b1e/closure/goog/string/string.js#L156-L160
*
* @const
* @type {RegExp}
*/
const ONLY_WHITESPACE_RE = /^[\s\xa0]*$/;
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @return {Array.<module:ol/Feature> | undefined} Features. * @return {Array.<module:ol/Feature> | undefined} Features.
*/ */
GMLBase.prototype.readFeaturesInternal = function(node, objectStack) { readFeaturesInternal(node, objectStack) {
const localName = node.localName; const localName = node.localName;
let features = null; let features = null;
if (localName == 'FeatureCollection') { if (localName == 'FeatureCollection') {
@@ -217,15 +201,14 @@ GMLBase.prototype.readFeaturesInternal = function(node, objectStack) {
features = []; features = [];
} }
return features; return features;
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @return {module:ol/geom/Geometry|undefined} Geometry. * @return {module:ol/geom/Geometry|undefined} Geometry.
*/ */
GMLBase.prototype.readGeometryElement = function(node, objectStack) { readGeometryElement(node, objectStack) {
const context = /** @type {Object} */ (objectStack[0]); const context = /** @type {Object} */ (objectStack[0]);
context['srsName'] = node.firstElementChild.getAttribute('srsName'); context['srsName'] = node.firstElementChild.getAttribute('srsName');
context['srsDimension'] = node.firstElementChild.getAttribute('srsDimension'); context['srsDimension'] = node.firstElementChild.getAttribute('srsDimension');
@@ -238,15 +221,14 @@ GMLBase.prototype.readGeometryElement = function(node, objectStack) {
} else { } else {
return undefined; return undefined;
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @return {module:ol/Feature} Feature. * @return {module:ol/Feature} Feature.
*/ */
GMLBase.prototype.readFeatureElement = function(node, objectStack) { readFeatureElement(node, objectStack) {
let n; let n;
const fid = node.getAttribute('fid') || getAttributeNS(node, GMLNS, 'id'); const fid = node.getAttribute('fid') || getAttributeNS(node, GMLNS, 'id');
const values = {}; const values = {};
@@ -280,28 +262,26 @@ GMLBase.prototype.readFeatureElement = function(node, objectStack) {
feature.setId(fid); feature.setId(fid);
} }
return feature; return feature;
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @return {module:ol/geom/Point|undefined} Point. * @return {module:ol/geom/Point|undefined} Point.
*/ */
GMLBase.prototype.readPoint = function(node, objectStack) { readPoint(node, objectStack) {
const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack); const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack);
if (flatCoordinates) { if (flatCoordinates) {
return new Point(flatCoordinates, GeometryLayout.XYZ); return new Point(flatCoordinates, GeometryLayout.XYZ);
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @return {module:ol/geom/MultiPoint|undefined} MultiPoint. * @return {module:ol/geom/MultiPoint|undefined} MultiPoint.
*/ */
GMLBase.prototype.readMultiPoint = function(node, objectStack) { readMultiPoint(node, objectStack) {
/** @type {Array.<Array.<number>>} */ /** @type {Array.<Array.<number>>} */
const coordinates = pushParseAndPop([], const coordinates = pushParseAndPop([],
this.MULTIPOINT_PARSERS_, node, objectStack, this); this.MULTIPOINT_PARSERS_, node, objectStack, this);
@@ -310,74 +290,68 @@ GMLBase.prototype.readMultiPoint = function(node, objectStack) {
} else { } else {
return undefined; return undefined;
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @return {module:ol/geom/MultiLineString|undefined} MultiLineString. * @return {module:ol/geom/MultiLineString|undefined} MultiLineString.
*/ */
GMLBase.prototype.readMultiLineString = function(node, objectStack) { readMultiLineString(node, objectStack) {
/** @type {Array.<module:ol/geom/LineString>} */ /** @type {Array.<module:ol/geom/LineString>} */
const lineStrings = pushParseAndPop([], const lineStrings = pushParseAndPop([],
this.MULTILINESTRING_PARSERS_, node, objectStack, this); this.MULTILINESTRING_PARSERS_, node, objectStack, this);
if (lineStrings) { if (lineStrings) {
return new MultiLineString(lineStrings); return new MultiLineString(lineStrings);
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @return {module:ol/geom/MultiPolygon|undefined} MultiPolygon. * @return {module:ol/geom/MultiPolygon|undefined} MultiPolygon.
*/ */
GMLBase.prototype.readMultiPolygon = function(node, objectStack) { readMultiPolygon(node, objectStack) {
/** @type {Array.<module:ol/geom/Polygon>} */ /** @type {Array.<module:ol/geom/Polygon>} */
const polygons = pushParseAndPop([], this.MULTIPOLYGON_PARSERS_, node, objectStack, this); const polygons = pushParseAndPop([], this.MULTIPOLYGON_PARSERS_, node, objectStack, this);
if (polygons) { if (polygons) {
return new MultiPolygon(polygons); return new MultiPolygon(polygons);
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @private * @private
*/ */
GMLBase.prototype.pointMemberParser_ = function(node, objectStack) { pointMemberParser_(node, objectStack) {
parseNode(this.POINTMEMBER_PARSERS_, node, objectStack, this); parseNode(this.POINTMEMBER_PARSERS_, node, objectStack, this);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @private * @private
*/ */
GMLBase.prototype.lineStringMemberParser_ = function(node, objectStack) { lineStringMemberParser_(node, objectStack) {
parseNode(this.LINESTRINGMEMBER_PARSERS_, node, objectStack, this); parseNode(this.LINESTRINGMEMBER_PARSERS_, node, objectStack, this);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @private * @private
*/ */
GMLBase.prototype.polygonMemberParser_ = function(node, objectStack) { polygonMemberParser_(node, objectStack) {
parseNode(this.POLYGONMEMBER_PARSERS_, node, objectStack, this); parseNode(this.POLYGONMEMBER_PARSERS_, node, objectStack, this);
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @return {module:ol/geom/LineString|undefined} LineString. * @return {module:ol/geom/LineString|undefined} LineString.
*/ */
GMLBase.prototype.readLineString = function(node, objectStack) { readLineString(node, objectStack) {
const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack); const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack);
if (flatCoordinates) { if (flatCoordinates) {
const lineString = new LineString(flatCoordinates, GeometryLayout.XYZ); const lineString = new LineString(flatCoordinates, GeometryLayout.XYZ);
@@ -385,16 +359,15 @@ GMLBase.prototype.readLineString = function(node, objectStack) {
} else { } else {
return undefined; return undefined;
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @private * @private
* @return {Array.<number>|undefined} LinearRing flat coordinates. * @return {Array.<number>|undefined} LinearRing flat coordinates.
*/ */
GMLBase.prototype.readFlatLinearRing_ = function(node, objectStack) { readFlatLinearRing_(node, objectStack) {
const ring = pushParseAndPop(null, const ring = pushParseAndPop(null,
this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node, this.GEOMETRY_FLAT_COORDINATES_PARSERS_, node,
objectStack, this); objectStack, this);
@@ -403,28 +376,26 @@ GMLBase.prototype.readFlatLinearRing_ = function(node, objectStack) {
} else { } else {
return undefined; return undefined;
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @return {module:ol/geom/LinearRing|undefined} LinearRing. * @return {module:ol/geom/LinearRing|undefined} LinearRing.
*/ */
GMLBase.prototype.readLinearRing = function(node, objectStack) { readLinearRing(node, objectStack) {
const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack); const flatCoordinates = this.readFlatCoordinatesFromNode_(node, objectStack);
if (flatCoordinates) { if (flatCoordinates) {
return new LinearRing(flatCoordinates, GeometryLayout.XYZ); return new LinearRing(flatCoordinates, GeometryLayout.XYZ);
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @return {module:ol/geom/Polygon|undefined} Polygon. * @return {module:ol/geom/Polygon|undefined} Polygon.
*/ */
GMLBase.prototype.readPolygon = function(node, objectStack) { readPolygon(node, objectStack) {
/** @type {Array.<Array.<number>>} */ /** @type {Array.<Array.<number>>} */
const flatLinearRings = pushParseAndPop([null], const flatLinearRings = pushParseAndPop([null],
this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this); this.FLAT_LINEAR_RINGS_PARSERS_, node, objectStack, this);
@@ -440,18 +411,65 @@ GMLBase.prototype.readPolygon = function(node, objectStack) {
} else { } else {
return undefined; return undefined;
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @private * @private
* @return {Array.<number>} Flat coordinates. * @return {Array.<number>} Flat coordinates.
*/ */
GMLBase.prototype.readFlatCoordinatesFromNode_ = function(node, objectStack) { 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);
}; }
/**
* @inheritDoc
*/
readGeometryFromNode(node, opt_options) {
const geometry = this.readGeometryElement(node,
[this.getReadOptions(node, opt_options ? opt_options : {})]);
return geometry ? geometry : null;
}
/**
* @inheritDoc
*/
readFeaturesFromNode(node, opt_options) {
const options = {
featureType: this.featureType,
featureNS: this.featureNS
};
if (opt_options) {
assign(options, this.getReadOptions(node, opt_options));
}
const features = this.readFeaturesInternal(node, [options]);
return features || [];
}
/**
* @inheritDoc
*/
readProjectionFromNode(node) {
return getProjection(this.srsName ? this.srsName : node.firstElementChild.getAttribute('srsName'));
}
}
inherits(GMLBase, XMLFeature);
/**
* A regular expression that matches if a string only contains whitespace
* characters. It will e.g. match `''`, `' '`, `'\n'` etc. The non-breaking
* space (0xa0) is explicitly included as IE doesn't include it in its
* definition of `\s`.
*
* Information from `goog.string.isEmptyOrWhitespace`: https://github.com/google/closure-library/blob/e877b1e/closure/goog/string/string.js#L156-L160
*
* @const
* @type {RegExp}
*/
const ONLY_WHITESPACE_RE = /^[\s\xa0]*$/;
/** /**
@@ -541,16 +559,6 @@ GMLBase.prototype.RING_PARSERS = {
}; };
/**
* @inheritDoc
*/
GMLBase.prototype.readGeometryFromNode = function(node, opt_options) {
const geometry = this.readGeometryElement(node,
[this.getReadOptions(node, opt_options ? opt_options : {})]);
return geometry ? geometry : null;
};
/** /**
* Read all features from a GML FeatureCollection. * Read all features from a GML FeatureCollection.
* *
@@ -563,26 +571,4 @@ GMLBase.prototype.readGeometryFromNode = function(node, opt_options) {
GMLBase.prototype.readFeatures; GMLBase.prototype.readFeatures;
/**
* @inheritDoc
*/
GMLBase.prototype.readFeaturesFromNode = function(node, opt_options) {
const options = {
featureType: this.featureType,
featureNS: this.featureNS
};
if (opt_options) {
assign(options, this.getReadOptions(node, opt_options));
}
const features = this.readFeaturesInternal(node, [options]);
return features || [];
};
/**
* @inheritDoc
*/
GMLBase.prototype.readProjectionFromNode = function(node) {
return getProjection(this.srsName ? this.srsName : node.firstElementChild.getAttribute('srsName'));
};
export default GMLBase; export default GMLBase;
+88 -88
View File
@@ -43,7 +43,8 @@ import {createElementNS, makeArrayPusher, makeArraySerializer, makeChildAppender
* @param {module:ol/format/GPX~Options=} opt_options Options. * @param {module:ol/format/GPX~Options=} opt_options Options.
* @api * @api
*/ */
const GPX = function(opt_options) { class GPX {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -59,7 +60,92 @@ const GPX = function(opt_options) {
* @private * @private
*/ */
this.readExtensions_ = options.readExtensions; this.readExtensions_ = options.readExtensions;
}; }
/**
* @param {Array.<module:ol/Feature>} features List of features.
* @private
*/
handleReadExtensions_(features) {
if (!features) {
features = [];
}
for (let i = 0, ii = features.length; i < ii; ++i) {
const feature = features[i];
if (this.readExtensions_) {
const extensionsNode = feature.get('extensionsNode_') || null;
this.readExtensions_(feature, extensionsNode);
}
feature.set('extensionsNode_', undefined);
}
}
/**
* @inheritDoc
*/
readFeatureFromNode(node, opt_options) {
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
return null;
}
const featureReader = FEATURE_READER[node.localName];
if (!featureReader) {
return null;
}
const feature = featureReader(node, [this.getReadOptions(node, opt_options)]);
if (!feature) {
return null;
}
this.handleReadExtensions_([feature]);
return feature;
}
/**
* @inheritDoc
*/
readFeaturesFromNode(node, opt_options) {
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
return [];
}
if (node.localName == 'gpx') {
/** @type {Array.<module:ol/Feature>} */
const features = pushParseAndPop([], GPX_PARSERS,
node, [this.getReadOptions(node, opt_options)]);
if (features) {
this.handleReadExtensions_(features);
return features;
} else {
return [];
}
}
return [];
}
/**
* Encode an array of features in the GPX format as an XML node.
* LineString geometries are output as routes (`<rte>`), and MultiLineString
* as tracks (`<trk>`).
*
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
* @return {Node} Node.
* @override
* @api
*/
writeFeaturesNode(features, opt_options) {
opt_options = this.adaptOptions(opt_options);
//FIXME Serialize metadata
const gpx = createElementNS('http://www.topografix.com/GPX/1/1', 'gpx');
const xmlnsUri = 'http://www.w3.org/2000/xmlns/';
gpx.setAttributeNS(xmlnsUri, 'xmlns:xsi', XML_SCHEMA_INSTANCE_URI);
gpx.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', SCHEMA_LOCATION);
gpx.setAttribute('version', '1.1');
gpx.setAttribute('creator', 'OpenLayers');
pushSerializeAndPop(/** @type {module:ol/xml~NodeStackItem} */
({node: gpx}), GPX_SERIALIZERS, GPX_NODE_FACTORY, features, [opt_options]);
return gpx;
}
}
inherits(GPX, XMLFeature); inherits(GPX, XMLFeature);
@@ -614,25 +700,6 @@ function readWpt(node, objectStack) {
} }
/**
* @param {Array.<module:ol/Feature>} features List of features.
* @private
*/
GPX.prototype.handleReadExtensions_ = function(features) {
if (!features) {
features = [];
}
for (let i = 0, ii = features.length; i < ii; ++i) {
const feature = features[i];
if (this.readExtensions_) {
const extensionsNode = feature.get('extensionsNode_') || null;
this.readExtensions_(feature, extensionsNode);
}
feature.set('extensionsNode_', undefined);
}
};
/** /**
* Read the first feature from a GPX source. * Read the first feature from a GPX source.
* Routes (`<rte>`) are converted into LineString geometries, and tracks (`<trk>`) * Routes (`<rte>`) are converted into LineString geometries, and tracks (`<trk>`)
@@ -647,26 +714,6 @@ GPX.prototype.handleReadExtensions_ = function(features) {
GPX.prototype.readFeature; GPX.prototype.readFeature;
/**
* @inheritDoc
*/
GPX.prototype.readFeatureFromNode = function(node, opt_options) {
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
return null;
}
const featureReader = FEATURE_READER[node.localName];
if (!featureReader) {
return null;
}
const feature = featureReader(node, [this.getReadOptions(node, opt_options)]);
if (!feature) {
return null;
}
this.handleReadExtensions_([feature]);
return feature;
};
/** /**
* Read all features from a GPX source. * Read all features from a GPX source.
* Routes (`<rte>`) are converted into LineString geometries, and tracks (`<trk>`) * Routes (`<rte>`) are converted into LineString geometries, and tracks (`<trk>`)
@@ -681,28 +728,6 @@ GPX.prototype.readFeatureFromNode = function(node, opt_options) {
GPX.prototype.readFeatures; GPX.prototype.readFeatures;
/**
* @inheritDoc
*/
GPX.prototype.readFeaturesFromNode = function(node, opt_options) {
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
return [];
}
if (node.localName == 'gpx') {
/** @type {Array.<module:ol/Feature>} */
const features = pushParseAndPop([], GPX_PARSERS,
node, [this.getReadOptions(node, opt_options)]);
if (features) {
this.handleReadExtensions_(features);
return features;
} else {
return [];
}
}
return [];
};
/** /**
* Read the projection from a GPX source. * Read the projection from a GPX source.
* *
@@ -874,29 +899,4 @@ function writeWpt(node, feature, objectStack) {
GPX.prototype.writeFeatures; GPX.prototype.writeFeatures;
/**
* Encode an array of features in the GPX format as an XML node.
* LineString geometries are output as routes (`<rte>`), and MultiLineString
* as tracks (`<trk>`).
*
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
* @return {Node} Node.
* @override
* @api
*/
GPX.prototype.writeFeaturesNode = function(features, opt_options) {
opt_options = this.adaptOptions(opt_options);
//FIXME Serialize metadata
const gpx = createElementNS('http://www.topografix.com/GPX/1/1', 'gpx');
const xmlnsUri = 'http://www.w3.org/2000/xmlns/';
gpx.setAttributeNS(xmlnsUri, 'xmlns:xsi', XML_SCHEMA_INSTANCE_URI);
gpx.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', SCHEMA_LOCATION);
gpx.setAttribute('version', '1.1');
gpx.setAttribute('creator', 'OpenLayers');
pushSerializeAndPop(/** @type {module:ol/xml~NodeStackItem} */
({node: gpx}), GPX_SERIALIZERS, GPX_NODE_FACTORY, features, [opt_options]);
return gpx;
};
export default GPX; export default GPX;
+155 -158
View File
@@ -42,7 +42,8 @@ import {get as getProjection} from '../proj.js';
* @param {module:ol/format/GeoJSON~Options=} opt_options Options. * @param {module:ol/format/GeoJSON~Options=} opt_options Options.
* @api * @api
*/ */
const GeoJSON = function(opt_options) { class GeoJSON {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -73,7 +74,159 @@ const GeoJSON = function(opt_options) {
*/ */
this.extractGeometryName_ = options.extractGeometryName; this.extractGeometryName_ = options.extractGeometryName;
}; }
/**
* @inheritDoc
*/
readFeatureFromObject(object, opt_options) {
/**
* @type {GeoJSONFeature}
*/
let geoJSONFeature = null;
if (object.type === 'Feature') {
geoJSONFeature = /** @type {GeoJSONFeature} */ (object);
} else {
geoJSONFeature = /** @type {GeoJSONFeature} */ ({
type: 'Feature',
geometry: /** @type {GeoJSONGeometry|GeoJSONGeometryCollection} */ (object)
});
}
const geometry = readGeometry(geoJSONFeature.geometry, opt_options);
const feature = new Feature();
if (this.geometryName_) {
feature.setGeometryName(this.geometryName_);
} else if (this.extractGeometryName_ && geoJSONFeature.geometry_name !== undefined) {
feature.setGeometryName(geoJSONFeature.geometry_name);
}
feature.setGeometry(geometry);
if (geoJSONFeature.id !== undefined) {
feature.setId(geoJSONFeature.id);
}
if (geoJSONFeature.properties) {
feature.setProperties(geoJSONFeature.properties);
}
return feature;
}
/**
* @inheritDoc
*/
readFeaturesFromObject(object, opt_options) {
const geoJSONObject = /** @type {GeoJSONObject} */ (object);
/** @type {Array.<module:ol/Feature>} */
let features = null;
if (geoJSONObject.type === 'FeatureCollection') {
const geoJSONFeatureCollection = /** @type {GeoJSONFeatureCollection} */ (object);
features = [];
const geoJSONFeatures = geoJSONFeatureCollection.features;
for (let i = 0, ii = geoJSONFeatures.length; i < ii; ++i) {
features.push(this.readFeatureFromObject(geoJSONFeatures[i], opt_options));
}
} else {
features = [this.readFeatureFromObject(object, opt_options)];
}
return features;
}
/**
* @inheritDoc
*/
readGeometryFromObject(object, opt_options) {
return readGeometry(/** @type {GeoJSONGeometry} */ (object), opt_options);
}
/**
* @inheritDoc
*/
readProjectionFromObject(object) {
const geoJSONObject = /** @type {GeoJSONObject} */ (object);
const crs = geoJSONObject.crs;
let projection;
if (crs) {
if (crs.type == 'name') {
projection = getProjection(crs.properties.name);
} else {
assert(false, 36); // Unknown SRS type
}
} else {
projection = this.dataProjection;
}
return (
/** @type {module:ol/proj/Projection} */ (projection)
);
}
/**
* Encode a feature as a GeoJSON Feature object.
*
* @param {module:ol/Feature} feature Feature.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {GeoJSONFeature} Object.
* @override
* @api
*/
writeFeatureObject(feature, opt_options) {
opt_options = this.adaptOptions(opt_options);
const object = /** @type {GeoJSONFeature} */ ({
'type': 'Feature'
});
const id = feature.getId();
if (id !== undefined) {
object.id = id;
}
const geometry = feature.getGeometry();
if (geometry) {
object.geometry = writeGeometry(geometry, opt_options);
} else {
object.geometry = null;
}
const properties = feature.getProperties();
delete properties[feature.getGeometryName()];
if (!isEmpty(properties)) {
object.properties = properties;
} else {
object.properties = null;
}
return object;
}
/**
* Encode an array of features as a GeoJSON object.
*
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {GeoJSONFeatureCollection} GeoJSON Object.
* @override
* @api
*/
writeFeaturesObject(features, opt_options) {
opt_options = this.adaptOptions(opt_options);
const objects = [];
for (let i = 0, ii = features.length; i < ii; ++i) {
objects.push(this.writeFeatureObject(features[i], opt_options));
}
return /** @type {GeoJSONFeatureCollection} */ ({
type: 'FeatureCollection',
features: objects
});
}
/**
* Encode a geometry as a GeoJSON object.
*
* @param {module:ol/geom/Geometry} geometry Geometry.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {GeoJSONGeometry|GeoJSONGeometryCollection} Object.
* @override
* @api
*/
writeGeometryObject(geometry, opt_options) {
return writeGeometry(geometry, this.adaptOptions(opt_options));
}
}
inherits(GeoJSON, JSONFeature); inherits(GeoJSON, JSONFeature);
@@ -354,62 +507,6 @@ GeoJSON.prototype.readFeature;
GeoJSON.prototype.readFeatures; GeoJSON.prototype.readFeatures;
/**
* @inheritDoc
*/
GeoJSON.prototype.readFeatureFromObject = function(object, opt_options) {
/**
* @type {GeoJSONFeature}
*/
let geoJSONFeature = null;
if (object.type === 'Feature') {
geoJSONFeature = /** @type {GeoJSONFeature} */ (object);
} else {
geoJSONFeature = /** @type {GeoJSONFeature} */ ({
type: 'Feature',
geometry: /** @type {GeoJSONGeometry|GeoJSONGeometryCollection} */ (object)
});
}
const geometry = readGeometry(geoJSONFeature.geometry, opt_options);
const feature = new Feature();
if (this.geometryName_) {
feature.setGeometryName(this.geometryName_);
} else if (this.extractGeometryName_ && geoJSONFeature.geometry_name !== undefined) {
feature.setGeometryName(geoJSONFeature.geometry_name);
}
feature.setGeometry(geometry);
if (geoJSONFeature.id !== undefined) {
feature.setId(geoJSONFeature.id);
}
if (geoJSONFeature.properties) {
feature.setProperties(geoJSONFeature.properties);
}
return feature;
};
/**
* @inheritDoc
*/
GeoJSON.prototype.readFeaturesFromObject = function(object, opt_options) {
const geoJSONObject = /** @type {GeoJSONObject} */ (object);
/** @type {Array.<module:ol/Feature>} */
let features = null;
if (geoJSONObject.type === 'FeatureCollection') {
const geoJSONFeatureCollection = /** @type {GeoJSONFeatureCollection} */ (object);
features = [];
const geoJSONFeatures = geoJSONFeatureCollection.features;
for (let i = 0, ii = geoJSONFeatures.length; i < ii; ++i) {
features.push(this.readFeatureFromObject(geoJSONFeatures[i], opt_options));
}
} else {
features = [this.readFeatureFromObject(object, opt_options)];
}
return features;
};
/** /**
* Read a geometry from a GeoJSON source. * Read a geometry from a GeoJSON source.
* *
@@ -422,14 +519,6 @@ GeoJSON.prototype.readFeaturesFromObject = function(object, opt_options) {
GeoJSON.prototype.readGeometry; GeoJSON.prototype.readGeometry;
/**
* @inheritDoc
*/
GeoJSON.prototype.readGeometryFromObject = function(object, opt_options) {
return readGeometry(/** @type {GeoJSONGeometry} */ (object), opt_options);
};
/** /**
* Read the projection from a GeoJSON source. * Read the projection from a GeoJSON source.
* *
@@ -441,28 +530,6 @@ GeoJSON.prototype.readGeometryFromObject = function(object, opt_options) {
GeoJSON.prototype.readProjection; GeoJSON.prototype.readProjection;
/**
* @inheritDoc
*/
GeoJSON.prototype.readProjectionFromObject = function(object) {
const geoJSONObject = /** @type {GeoJSONObject} */ (object);
const crs = geoJSONObject.crs;
let projection;
if (crs) {
if (crs.type == 'name') {
projection = getProjection(crs.properties.name);
} else {
assert(false, 36); // Unknown SRS type
}
} else {
projection = this.dataProjection;
}
return (
/** @type {module:ol/proj/Projection} */ (projection)
);
};
/** /**
* Encode a feature as a GeoJSON Feature string. * Encode a feature as a GeoJSON Feature string.
* *
@@ -476,42 +543,6 @@ GeoJSON.prototype.readProjectionFromObject = function(object) {
GeoJSON.prototype.writeFeature; GeoJSON.prototype.writeFeature;
/**
* Encode a feature as a GeoJSON Feature object.
*
* @param {module:ol/Feature} feature Feature.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {GeoJSONFeature} Object.
* @override
* @api
*/
GeoJSON.prototype.writeFeatureObject = function(feature, opt_options) {
opt_options = this.adaptOptions(opt_options);
const object = /** @type {GeoJSONFeature} */ ({
'type': 'Feature'
});
const id = feature.getId();
if (id !== undefined) {
object.id = id;
}
const geometry = feature.getGeometry();
if (geometry) {
object.geometry = writeGeometry(geometry, opt_options);
} else {
object.geometry = null;
}
const properties = feature.getProperties();
delete properties[feature.getGeometryName()];
if (!isEmpty(properties)) {
object.properties = properties;
} else {
object.properties = null;
}
return object;
};
/** /**
* Encode an array of features as GeoJSON. * Encode an array of features as GeoJSON.
* *
@@ -524,28 +555,6 @@ GeoJSON.prototype.writeFeatureObject = function(feature, opt_options) {
GeoJSON.prototype.writeFeatures; GeoJSON.prototype.writeFeatures;
/**
* Encode an array of features as a GeoJSON object.
*
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {GeoJSONFeatureCollection} GeoJSON Object.
* @override
* @api
*/
GeoJSON.prototype.writeFeaturesObject = function(features, opt_options) {
opt_options = this.adaptOptions(opt_options);
const objects = [];
for (let i = 0, ii = features.length; i < ii; ++i) {
objects.push(this.writeFeatureObject(features[i], opt_options));
}
return /** @type {GeoJSONFeatureCollection} */ ({
type: 'FeatureCollection',
features: objects
});
};
/** /**
* Encode a geometry as a GeoJSON string. * Encode a geometry as a GeoJSON string.
* *
@@ -558,16 +567,4 @@ GeoJSON.prototype.writeFeaturesObject = function(features, opt_options) {
GeoJSON.prototype.writeGeometry; GeoJSON.prototype.writeGeometry;
/**
* Encode a geometry as a GeoJSON object.
*
* @param {module:ol/geom/Geometry} geometry Geometry.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {GeoJSONGeometry|GeoJSONGeometryCollection} Object.
* @override
* @api
*/
GeoJSON.prototype.writeGeometryObject = function(geometry, opt_options) {
return writeGeometry(geometry, this.adaptOptions(opt_options));
};
export default GeoJSON; export default GeoJSON;
+88 -90
View File
@@ -36,7 +36,8 @@ const IGCZ = {
* @param {module:ol/format/IGC~Options=} opt_options Options. * @param {module:ol/format/IGC~Options=} opt_options Options.
* @api * @api
*/ */
const IGC = function(opt_options) { class IGC {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -52,58 +53,12 @@ const IGC = function(opt_options) {
* @type {IGCZ} * @type {IGCZ}
*/ */
this.altitudeMode_ = options.altitudeMode ? options.altitudeMode : IGCZ.NONE; this.altitudeMode_ = options.altitudeMode ? options.altitudeMode : IGCZ.NONE;
}; }
inherits(IGC, TextFeature); /**
/**
* @const
* @type {RegExp}
*/
const B_RECORD_RE =
/^B(\d{2})(\d{2})(\d{2})(\d{2})(\d{5})([NS])(\d{3})(\d{5})([EW])([AV])(\d{5})(\d{5})/;
/**
* @const
* @type {RegExp}
*/
const H_RECORD_RE = /^H.([A-Z]{3}).*?:(.*)/;
/**
* @const
* @type {RegExp}
*/
const HFDTE_RECORD_RE = /^HFDTE(\d{2})(\d{2})(\d{2})/;
/**
* A regular expression matching the newline characters `\r\n`, `\r` and `\n`.
*
* @const
* @type {RegExp}
*/
const NEWLINE_RE = /\r\n|\r|\n/;
/**
* Read the feature from the IGC source.
*
* @function
* @param {Document|Node|Object|string} source Source.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @return {module:ol/Feature} Feature.
* @api
*/
IGC.prototype.readFeature;
/**
* @inheritDoc * @inheritDoc
*/ */
IGC.prototype.readFeatureFromText = function(text, opt_options) { readFeatureFromText(text, opt_options) {
const altitudeMode = this.altitudeMode_; const altitudeMode = this.altitudeMode_;
const lines = text.split(NEWLINE_RE); const lines = text.split(NEWLINE_RE);
/** @type {Object.<string, string>} */ /** @type {Object.<string, string>} */
@@ -173,7 +128,89 @@ IGC.prototype.readFeatureFromText = function(text, opt_options) {
const feature = new Feature(transformWithOptions(lineString, false, opt_options)); const feature = new Feature(transformWithOptions(lineString, false, opt_options));
feature.setProperties(properties); feature.setProperties(properties);
return feature; return feature;
}; }
/**
* @inheritDoc
*/
readFeaturesFromText(text, opt_options) {
const feature = this.readFeatureFromText(text, opt_options);
if (feature) {
return [feature];
} else {
return [];
}
}
/**
* Not implemented.
* @inheritDoc
*/
writeFeatureText(feature, opt_options) {}
/**
* Not implemented.
* @inheritDoc
*/
writeFeaturesText(features, opt_options) {}
/**
* Not implemented.
* @inheritDoc
*/
writeGeometryText(geometry, opt_options) {}
/**
* Not implemented.
* @inheritDoc
*/
readGeometryFromText(text, opt_options) {}
}
inherits(IGC, TextFeature);
/**
* @const
* @type {RegExp}
*/
const B_RECORD_RE =
/^B(\d{2})(\d{2})(\d{2})(\d{2})(\d{5})([NS])(\d{3})(\d{5})([EW])([AV])(\d{5})(\d{5})/;
/**
* @const
* @type {RegExp}
*/
const H_RECORD_RE = /^H.([A-Z]{3}).*?:(.*)/;
/**
* @const
* @type {RegExp}
*/
const HFDTE_RECORD_RE = /^HFDTE(\d{2})(\d{2})(\d{2})/;
/**
* A regular expression matching the newline characters `\r\n`, `\r` and `\n`.
*
* @const
* @type {RegExp}
*/
const NEWLINE_RE = /\r\n|\r|\n/;
/**
* Read the feature from the IGC source.
*
* @function
* @param {Document|Node|Object|string} source Source.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @return {module:ol/Feature} Feature.
* @api
*/
IGC.prototype.readFeature;
/** /**
@@ -189,19 +226,6 @@ IGC.prototype.readFeatureFromText = function(text, opt_options) {
IGC.prototype.readFeatures; IGC.prototype.readFeatures;
/**
* @inheritDoc
*/
IGC.prototype.readFeaturesFromText = function(text, opt_options) {
const feature = this.readFeatureFromText(text, opt_options);
if (feature) {
return [feature];
} else {
return [];
}
};
/** /**
* Read the projection from the IGC source. * Read the projection from the IGC source.
* *
@@ -213,30 +237,4 @@ IGC.prototype.readFeaturesFromText = function(text, opt_options) {
IGC.prototype.readProjection; IGC.prototype.readProjection;
/**
* Not implemented.
* @inheritDoc
*/
IGC.prototype.writeFeatureText = function(feature, opt_options) {};
/**
* Not implemented.
* @inheritDoc
*/
IGC.prototype.writeFeaturesText = function(features, opt_options) {};
/**
* Not implemented.
* @inheritDoc
*/
IGC.prototype.writeGeometryText = function(geometry, opt_options) {};
/**
* Not implemented.
* @inheritDoc
*/
IGC.prototype.readGeometryFromText = function(text, opt_options) {};
export default IGC; export default IGC;
+122 -133
View File
@@ -15,9 +15,129 @@ import FormatType from '../format/FormatType.js';
* @abstract * @abstract
* @extends {module:ol/format/Feature} * @extends {module:ol/format/Feature}
*/ */
const JSONFeature = function() { class JSONFeature {
constructor() {
FeatureFormat.call(this); FeatureFormat.call(this);
}; }
/**
* @inheritDoc
*/
getType() {
return FormatType.JSON;
}
/**
* @inheritDoc
*/
readFeature(source, opt_options) {
return this.readFeatureFromObject(
getObject(source), this.getReadOptions(source, opt_options));
}
/**
* @inheritDoc
*/
readFeatures(source, opt_options) {
return this.readFeaturesFromObject(
getObject(source), this.getReadOptions(source, opt_options));
}
/**
* @abstract
* @param {Object} object Object.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {module:ol/Feature} Feature.
*/
readFeatureFromObject(object, opt_options) {}
/**
* @abstract
* @param {Object} object Object.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {Array.<module:ol/Feature>} Features.
*/
readFeaturesFromObject(object, opt_options) {}
/**
* @inheritDoc
*/
readGeometry(source, opt_options) {
return this.readGeometryFromObject(
getObject(source), this.getReadOptions(source, opt_options));
}
/**
* @abstract
* @param {Object} object Object.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {module:ol/geom/Geometry} Geometry.
*/
readGeometryFromObject(object, opt_options) {}
/**
* @inheritDoc
*/
readProjection(source) {
return this.readProjectionFromObject(getObject(source));
}
/**
* @abstract
* @param {Object} object Object.
* @protected
* @return {module:ol/proj/Projection} Projection.
*/
readProjectionFromObject(object) {}
/**
* @inheritDoc
*/
writeFeature(feature, opt_options) {
return JSON.stringify(this.writeFeatureObject(feature, opt_options));
}
/**
* @abstract
* @param {module:ol/Feature} feature Feature.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {Object} Object.
*/
writeFeatureObject(feature, opt_options) {}
/**
* @inheritDoc
*/
writeFeatures(features, opt_options) {
return JSON.stringify(this.writeFeaturesObject(features, opt_options));
}
/**
* @abstract
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {Object} Object.
*/
writeFeaturesObject(features, opt_options) {}
/**
* @inheritDoc
*/
writeGeometry(geometry, opt_options) {
return JSON.stringify(this.writeGeometryObject(geometry, opt_options));
}
/**
* @abstract
* @param {module:ol/geom/Geometry} geometry Geometry.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {Object} Object.
*/
writeGeometryObject(geometry, opt_options) {}
}
inherits(JSONFeature, FeatureFormat); inherits(JSONFeature, FeatureFormat);
@@ -38,135 +158,4 @@ function getObject(source) {
} }
/**
* @inheritDoc
*/
JSONFeature.prototype.getType = function() {
return FormatType.JSON;
};
/**
* @inheritDoc
*/
JSONFeature.prototype.readFeature = function(source, opt_options) {
return this.readFeatureFromObject(
getObject(source), this.getReadOptions(source, opt_options));
};
/**
* @inheritDoc
*/
JSONFeature.prototype.readFeatures = function(source, opt_options) {
return this.readFeaturesFromObject(
getObject(source), this.getReadOptions(source, opt_options));
};
/**
* @abstract
* @param {Object} object Object.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {module:ol/Feature} Feature.
*/
JSONFeature.prototype.readFeatureFromObject = function(object, opt_options) {};
/**
* @abstract
* @param {Object} object Object.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {Array.<module:ol/Feature>} Features.
*/
JSONFeature.prototype.readFeaturesFromObject = function(object, opt_options) {};
/**
* @inheritDoc
*/
JSONFeature.prototype.readGeometry = function(source, opt_options) {
return this.readGeometryFromObject(
getObject(source), this.getReadOptions(source, opt_options));
};
/**
* @abstract
* @param {Object} object Object.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {module:ol/geom/Geometry} Geometry.
*/
JSONFeature.prototype.readGeometryFromObject = function(object, opt_options) {};
/**
* @inheritDoc
*/
JSONFeature.prototype.readProjection = function(source) {
return this.readProjectionFromObject(getObject(source));
};
/**
* @abstract
* @param {Object} object Object.
* @protected
* @return {module:ol/proj/Projection} Projection.
*/
JSONFeature.prototype.readProjectionFromObject = function(object) {};
/**
* @inheritDoc
*/
JSONFeature.prototype.writeFeature = function(feature, opt_options) {
return JSON.stringify(this.writeFeatureObject(feature, opt_options));
};
/**
* @abstract
* @param {module:ol/Feature} feature Feature.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {Object} Object.
*/
JSONFeature.prototype.writeFeatureObject = function(feature, opt_options) {};
/**
* @inheritDoc
*/
JSONFeature.prototype.writeFeatures = function(features, opt_options) {
return JSON.stringify(this.writeFeaturesObject(features, opt_options));
};
/**
* @abstract
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {Object} Object.
*/
JSONFeature.prototype.writeFeaturesObject = function(features, opt_options) {};
/**
* @inheritDoc
*/
JSONFeature.prototype.writeGeometry = function(geometry, opt_options) {
return JSON.stringify(this.writeGeometryObject(geometry, opt_options));
};
/**
* @abstract
* @param {module:ol/geom/Geometry} geometry Geometry.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @return {Object} Object.
*/
JSONFeature.prototype.writeGeometryObject = function(geometry, opt_options) {};
export default JSONFeature; export default JSONFeature;
+402 -415
View File
@@ -259,7 +259,8 @@ function createStyleDefaults() {
* @param {module:ol/format/KML~Options=} opt_options Options. * @param {module:ol/format/KML~Options=} opt_options Options.
* @api * @api
*/ */
const KML = function(opt_options) { class KML {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -308,7 +309,406 @@ const KML = function(opt_options) {
this.showPointNames_ = options.showPointNames !== undefined ? this.showPointNames_ = options.showPointNames !== undefined ?
options.showPointNames : true; options.showPointNames : true;
}; }
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
* @return {Array.<module:ol/Feature>|undefined} Features.
*/
readDocumentOrFolder_(node, objectStack) {
// FIXME use scope somehow
const parsersNS = makeStructureNS(
NAMESPACE_URIS, {
'Document': makeArrayExtender(this.readDocumentOrFolder_, this),
'Folder': makeArrayExtender(this.readDocumentOrFolder_, this),
'Placemark': makeArrayPusher(this.readPlacemark_, this),
'Style': this.readSharedStyle_.bind(this),
'StyleMap': this.readSharedStyleMap_.bind(this)
});
/** @type {Array.<module:ol/Feature>} */
const features = pushParseAndPop([], parsersNS, node, objectStack, this);
if (features) {
return features;
} else {
return undefined;
}
}
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
* @return {module:ol/Feature|undefined} Feature.
*/
readPlacemark_(node, objectStack) {
const object = pushParseAndPop({'geometry': null},
PLACEMARK_PARSERS, node, objectStack);
if (!object) {
return undefined;
}
const feature = new Feature();
const id = node.getAttribute('id');
if (id !== null) {
feature.setId(id);
}
const options = /** @type {module:ol/format/Feature~ReadOptions} */ (objectStack[0]);
const geometry = object['geometry'];
if (geometry) {
transformWithOptions(geometry, false, options);
}
feature.setGeometry(geometry);
delete object['geometry'];
if (this.extractStyles_) {
const style = object['Style'];
const styleUrl = object['styleUrl'];
const styleFunction = createFeatureStyleFunction(
style, styleUrl, this.defaultStyle_, this.sharedStyles_,
this.showPointNames_);
feature.setStyle(styleFunction);
}
delete object['Style'];
// we do not remove the styleUrl property from the object, so it
// gets stored on feature when setProperties is called
feature.setProperties(object);
return feature;
}
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
*/
readSharedStyle_(node, objectStack) {
const id = node.getAttribute('id');
if (id !== null) {
const style = readStyle(node, objectStack);
if (style) {
let styleUri;
let baseURI = node.baseURI;
if (!baseURI || baseURI == 'about:blank') {
baseURI = window.location.href;
}
if (baseURI) {
const url = new URL('#' + id, baseURI);
styleUri = url.href;
} else {
styleUri = '#' + id;
}
this.sharedStyles_[styleUri] = style;
}
}
}
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
*/
readSharedStyleMap_(node, objectStack) {
const id = node.getAttribute('id');
if (id === null) {
return;
}
const styleMapValue = readStyleMapValue(node, objectStack);
if (!styleMapValue) {
return;
}
let styleUri;
let baseURI = node.baseURI;
if (!baseURI || baseURI == 'about:blank') {
baseURI = window.location.href;
}
if (baseURI) {
const url = new URL('#' + id, baseURI);
styleUri = url.href;
} else {
styleUri = '#' + id;
}
this.sharedStyles_[styleUri] = styleMapValue;
}
/**
* @inheritDoc
*/
readFeatureFromNode(node, opt_options) {
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
return null;
}
const feature = this.readPlacemark_(
node, [this.getReadOptions(node, opt_options)]);
if (feature) {
return feature;
} else {
return null;
}
}
/**
* @inheritDoc
*/
readFeaturesFromNode(node, opt_options) {
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
return [];
}
let features;
const localName = node.localName;
if (localName == 'Document' || localName == 'Folder') {
features = this.readDocumentOrFolder_(
node, [this.getReadOptions(node, opt_options)]);
if (features) {
return features;
} else {
return [];
}
} else if (localName == 'Placemark') {
const feature = this.readPlacemark_(
node, [this.getReadOptions(node, opt_options)]);
if (feature) {
return [feature];
} else {
return [];
}
} else if (localName == 'kml') {
features = [];
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
const fs = this.readFeaturesFromNode(n, opt_options);
if (fs) {
extend(features, fs);
}
}
return features;
} else {
return [];
}
}
/**
* Read the name of the KML.
*
* @param {Document|Node|string} source Source.
* @return {string|undefined} Name.
* @api
*/
readName(source) {
if (isDocument(source)) {
return this.readNameFromDocument(/** @type {Document} */ (source));
} else if (isNode(source)) {
return this.readNameFromNode(/** @type {Node} */ (source));
} else if (typeof source === 'string') {
const doc = parse(source);
return this.readNameFromDocument(doc);
} else {
return undefined;
}
}
/**
* @param {Document} doc Document.
* @return {string|undefined} Name.
*/
readNameFromDocument(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
const name = this.readNameFromNode(n);
if (name) {
return name;
}
}
}
return undefined;
}
/**
* @param {Node} node Node.
* @return {string|undefined} Name.
*/
readNameFromNode(node) {
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
n.localName == 'name') {
return readString(n);
}
}
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
const localName = n.localName;
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
(localName == 'Document' ||
localName == 'Folder' ||
localName == 'Placemark' ||
localName == 'kml')) {
const name = this.readNameFromNode(n);
if (name) {
return name;
}
}
}
return undefined;
}
/**
* Read the network links of the KML.
*
* @param {Document|Node|string} source Source.
* @return {Array.<Object>} Network links.
* @api
*/
readNetworkLinks(source) {
const networkLinks = [];
if (isDocument(source)) {
extend(networkLinks, this.readNetworkLinksFromDocument(
/** @type {Document} */ (source)));
} else if (isNode(source)) {
extend(networkLinks, this.readNetworkLinksFromNode(
/** @type {Node} */ (source)));
} else if (typeof source === 'string') {
const doc = parse(source);
extend(networkLinks, this.readNetworkLinksFromDocument(doc));
}
return networkLinks;
}
/**
* @param {Document} doc Document.
* @return {Array.<Object>} Network links.
*/
readNetworkLinksFromDocument(doc) {
const networkLinks = [];
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
extend(networkLinks, this.readNetworkLinksFromNode(n));
}
}
return networkLinks;
}
/**
* @param {Node} node Node.
* @return {Array.<Object>} Network links.
*/
readNetworkLinksFromNode(node) {
const networkLinks = [];
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
n.localName == 'NetworkLink') {
const obj = pushParseAndPop({}, NETWORK_LINK_PARSERS,
n, []);
networkLinks.push(obj);
}
}
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
const localName = n.localName;
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
(localName == 'Document' ||
localName == 'Folder' ||
localName == 'kml')) {
extend(networkLinks, this.readNetworkLinksFromNode(n));
}
}
return networkLinks;
}
/**
* Read the regions of the KML.
*
* @param {Document|Node|string} source Source.
* @return {Array.<Object>} Regions.
* @api
*/
readRegion(source) {
const regions = [];
if (isDocument(source)) {
extend(regions, this.readRegionFromDocument(
/** @type {Document} */ (source)));
} else if (isNode(source)) {
extend(regions, this.readRegionFromNode(
/** @type {Node} */ (source)));
} else if (typeof source === 'string') {
const doc = parse(source);
extend(regions, this.readRegionFromDocument(doc));
}
return regions;
}
/**
* @param {Document} doc Document.
* @return {Array.<Object>} Region.
*/
readRegionFromDocument(doc) {
const regions = [];
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
extend(regions, this.readRegionFromNode(n));
}
}
return regions;
}
/**
* @param {Node} node Node.
* @return {Array.<Object>} Region.
* @api
*/
readRegionFromNode(node) {
const regions = [];
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
n.localName == 'Region') {
const obj = pushParseAndPop({}, REGION_PARSERS,
n, []);
regions.push(obj);
}
}
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
const localName = n.localName;
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
(localName == 'Document' ||
localName == 'Folder' ||
localName == 'kml')) {
extend(regions, this.readRegionFromNode(n));
}
}
return regions;
}
/**
* Encode an array of features in the KML format as an XML node. GeometryCollections,
* MultiPoints, MultiLineStrings, and MultiPolygons are output as MultiGeometries.
*
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
* @return {Node} Node.
* @override
* @api
*/
writeFeaturesNode(features, opt_options) {
opt_options = this.adaptOptions(opt_options);
const kml = createElementNS(NAMESPACE_URIS[4], 'kml');
const xmlnsUri = 'http://www.w3.org/2000/xmlns/';
kml.setAttributeNS(xmlnsUri, 'xmlns:gx', GX_NAMESPACE_URIS[0]);
kml.setAttributeNS(xmlnsUri, 'xmlns:xsi', XML_SCHEMA_INSTANCE_URI);
kml.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', SCHEMA_LOCATION);
const /** @type {module:ol/xml~NodeStackItem} */ context = {node: kml};
const properties = {};
if (features.length > 1) {
properties['Document'] = features;
} else if (features.length == 1) {
properties['Placemark'] = features[0];
}
const orderedKeys = KML_SEQUENCE[kml.namespaceURI];
const values = makeSequence(properties, orderedKeys);
pushSerializeAndPop(context, KML_SERIALIZERS,
OBJECT_PROPERTY_NODE_FACTORY, values, [opt_options], orderedKeys,
this);
return kml;
}
}
inherits(KML, XMLFeature); inherits(KML, XMLFeature);
@@ -1643,132 +2043,6 @@ const PLACEMARK_PARSERS = makeStructureNS(
)); ));
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
* @return {Array.<module:ol/Feature>|undefined} Features.
*/
KML.prototype.readDocumentOrFolder_ = function(node, objectStack) {
// FIXME use scope somehow
const parsersNS = makeStructureNS(
NAMESPACE_URIS, {
'Document': makeArrayExtender(this.readDocumentOrFolder_, this),
'Folder': makeArrayExtender(this.readDocumentOrFolder_, this),
'Placemark': makeArrayPusher(this.readPlacemark_, this),
'Style': this.readSharedStyle_.bind(this),
'StyleMap': this.readSharedStyleMap_.bind(this)
});
/** @type {Array.<module:ol/Feature>} */
const features = pushParseAndPop([], parsersNS, node, objectStack, this);
if (features) {
return features;
} else {
return undefined;
}
};
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
* @return {module:ol/Feature|undefined} Feature.
*/
KML.prototype.readPlacemark_ = function(node, objectStack) {
const object = pushParseAndPop({'geometry': null},
PLACEMARK_PARSERS, node, objectStack);
if (!object) {
return undefined;
}
const feature = new Feature();
const id = node.getAttribute('id');
if (id !== null) {
feature.setId(id);
}
const options = /** @type {module:ol/format/Feature~ReadOptions} */ (objectStack[0]);
const geometry = object['geometry'];
if (geometry) {
transformWithOptions(geometry, false, options);
}
feature.setGeometry(geometry);
delete object['geometry'];
if (this.extractStyles_) {
const style = object['Style'];
const styleUrl = object['styleUrl'];
const styleFunction = createFeatureStyleFunction(
style, styleUrl, this.defaultStyle_, this.sharedStyles_,
this.showPointNames_);
feature.setStyle(styleFunction);
}
delete object['Style'];
// we do not remove the styleUrl property from the object, so it
// gets stored on feature when setProperties is called
feature.setProperties(object);
return feature;
};
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
*/
KML.prototype.readSharedStyle_ = function(node, objectStack) {
const id = node.getAttribute('id');
if (id !== null) {
const style = readStyle(node, objectStack);
if (style) {
let styleUri;
let baseURI = node.baseURI;
if (!baseURI || baseURI == 'about:blank') {
baseURI = window.location.href;
}
if (baseURI) {
const url = new URL('#' + id, baseURI);
styleUri = url.href;
} else {
styleUri = '#' + id;
}
this.sharedStyles_[styleUri] = style;
}
}
};
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
*/
KML.prototype.readSharedStyleMap_ = function(node, objectStack) {
const id = node.getAttribute('id');
if (id === null) {
return;
}
const styleMapValue = readStyleMapValue(node, objectStack);
if (!styleMapValue) {
return;
}
let styleUri;
let baseURI = node.baseURI;
if (!baseURI || baseURI == 'about:blank') {
baseURI = window.location.href;
}
if (baseURI) {
const url = new URL('#' + id, baseURI);
styleUri = url.href;
} else {
styleUri = '#' + id;
}
this.sharedStyles_[styleUri] = styleMapValue;
};
/** /**
* Read the first feature from a KML source. MultiGeometries are converted into * Read the first feature from a KML source. MultiGeometries are converted into
* GeometryCollections if they are a mix of geometry types, and into MultiPoint/ * GeometryCollections if they are a mix of geometry types, and into MultiPoint/
@@ -1783,23 +2057,6 @@ KML.prototype.readSharedStyleMap_ = function(node, objectStack) {
KML.prototype.readFeature; KML.prototype.readFeature;
/**
* @inheritDoc
*/
KML.prototype.readFeatureFromNode = function(node, opt_options) {
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
return null;
}
const feature = this.readPlacemark_(
node, [this.getReadOptions(node, opt_options)]);
if (feature) {
return feature;
} else {
return null;
}
};
/** /**
* Read all features from a KML source. MultiGeometries are converted into * Read all features from a KML source. MultiGeometries are converted into
* GeometryCollections if they are a mix of geometry types, and into MultiPoint/ * GeometryCollections if they are a mix of geometry types, and into MultiPoint/
@@ -1814,243 +2071,6 @@ KML.prototype.readFeatureFromNode = function(node, opt_options) {
KML.prototype.readFeatures; KML.prototype.readFeatures;
/**
* @inheritDoc
*/
KML.prototype.readFeaturesFromNode = function(node, opt_options) {
if (!includes(NAMESPACE_URIS, node.namespaceURI)) {
return [];
}
let features;
const localName = node.localName;
if (localName == 'Document' || localName == 'Folder') {
features = this.readDocumentOrFolder_(
node, [this.getReadOptions(node, opt_options)]);
if (features) {
return features;
} else {
return [];
}
} else if (localName == 'Placemark') {
const feature = this.readPlacemark_(
node, [this.getReadOptions(node, opt_options)]);
if (feature) {
return [feature];
} else {
return [];
}
} else if (localName == 'kml') {
features = [];
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
const fs = this.readFeaturesFromNode(n, opt_options);
if (fs) {
extend(features, fs);
}
}
return features;
} else {
return [];
}
};
/**
* Read the name of the KML.
*
* @param {Document|Node|string} source Source.
* @return {string|undefined} Name.
* @api
*/
KML.prototype.readName = function(source) {
if (isDocument(source)) {
return this.readNameFromDocument(/** @type {Document} */ (source));
} else if (isNode(source)) {
return this.readNameFromNode(/** @type {Node} */ (source));
} else if (typeof source === 'string') {
const doc = parse(source);
return this.readNameFromDocument(doc);
} else {
return undefined;
}
};
/**
* @param {Document} doc Document.
* @return {string|undefined} Name.
*/
KML.prototype.readNameFromDocument = function(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
const name = this.readNameFromNode(n);
if (name) {
return name;
}
}
}
return undefined;
};
/**
* @param {Node} node Node.
* @return {string|undefined} Name.
*/
KML.prototype.readNameFromNode = function(node) {
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
n.localName == 'name') {
return readString(n);
}
}
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
const localName = n.localName;
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
(localName == 'Document' ||
localName == 'Folder' ||
localName == 'Placemark' ||
localName == 'kml')) {
const name = this.readNameFromNode(n);
if (name) {
return name;
}
}
}
return undefined;
};
/**
* Read the network links of the KML.
*
* @param {Document|Node|string} source Source.
* @return {Array.<Object>} Network links.
* @api
*/
KML.prototype.readNetworkLinks = function(source) {
const networkLinks = [];
if (isDocument(source)) {
extend(networkLinks, this.readNetworkLinksFromDocument(
/** @type {Document} */ (source)));
} else if (isNode(source)) {
extend(networkLinks, this.readNetworkLinksFromNode(
/** @type {Node} */ (source)));
} else if (typeof source === 'string') {
const doc = parse(source);
extend(networkLinks, this.readNetworkLinksFromDocument(doc));
}
return networkLinks;
};
/**
* @param {Document} doc Document.
* @return {Array.<Object>} Network links.
*/
KML.prototype.readNetworkLinksFromDocument = function(doc) {
const networkLinks = [];
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
extend(networkLinks, this.readNetworkLinksFromNode(n));
}
}
return networkLinks;
};
/**
* @param {Node} node Node.
* @return {Array.<Object>} Network links.
*/
KML.prototype.readNetworkLinksFromNode = function(node) {
const networkLinks = [];
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
n.localName == 'NetworkLink') {
const obj = pushParseAndPop({}, NETWORK_LINK_PARSERS,
n, []);
networkLinks.push(obj);
}
}
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
const localName = n.localName;
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
(localName == 'Document' ||
localName == 'Folder' ||
localName == 'kml')) {
extend(networkLinks, this.readNetworkLinksFromNode(n));
}
}
return networkLinks;
};
/**
* Read the regions of the KML.
*
* @param {Document|Node|string} source Source.
* @return {Array.<Object>} Regions.
* @api
*/
KML.prototype.readRegion = function(source) {
const regions = [];
if (isDocument(source)) {
extend(regions, this.readRegionFromDocument(
/** @type {Document} */ (source)));
} else if (isNode(source)) {
extend(regions, this.readRegionFromNode(
/** @type {Node} */ (source)));
} else if (typeof source === 'string') {
const doc = parse(source);
extend(regions, this.readRegionFromDocument(doc));
}
return regions;
};
/**
* @param {Document} doc Document.
* @return {Array.<Object>} Region.
*/
KML.prototype.readRegionFromDocument = function(doc) {
const regions = [];
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
extend(regions, this.readRegionFromNode(n));
}
}
return regions;
};
/**
* @param {Node} node Node.
* @return {Array.<Object>} Region.
* @api
*/
KML.prototype.readRegionFromNode = function(node) {
const regions = [];
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
n.localName == 'Region') {
const obj = pushParseAndPop({}, REGION_PARSERS,
n, []);
regions.push(obj);
}
}
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
const localName = n.localName;
if (includes(NAMESPACE_URIS, n.namespaceURI) &&
(localName == 'Document' ||
localName == 'Folder' ||
localName == 'kml')) {
extend(regions, this.readRegionFromNode(n));
}
}
return regions;
};
/** /**
* Read the projection from a KML source. * Read the projection from a KML source.
* *
@@ -2955,37 +2975,4 @@ const KML_SERIALIZERS = makeStructureNS(
KML.prototype.writeFeatures; KML.prototype.writeFeatures;
/**
* Encode an array of features in the KML format as an XML node. GeometryCollections,
* MultiPoints, MultiLineStrings, and MultiPolygons are output as MultiGeometries.
*
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
* @return {Node} Node.
* @override
* @api
*/
KML.prototype.writeFeaturesNode = function(features, opt_options) {
opt_options = this.adaptOptions(opt_options);
const kml = createElementNS(NAMESPACE_URIS[4], 'kml');
const xmlnsUri = 'http://www.w3.org/2000/xmlns/';
kml.setAttributeNS(xmlnsUri, 'xmlns:gx', GX_NAMESPACE_URIS[0]);
kml.setAttributeNS(xmlnsUri, 'xmlns:xsi', XML_SCHEMA_INSTANCE_URI);
kml.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', SCHEMA_LOCATION);
const /** @type {module:ol/xml~NodeStackItem} */ context = {node: kml};
const properties = {};
if (features.length > 1) {
properties['Document'] = features;
} else if (features.length == 1) {
properties['Placemark'] = features[0];
}
const orderedKeys = KML_SEQUENCE[kml.namespaceURI];
const values = makeSequence(properties, orderedKeys);
pushSerializeAndPop(context, KML_SERIALIZERS,
OBJECT_PROPERTY_NODE_FACTORY, values, [opt_options], orderedKeys,
this);
return kml;
};
export default KML; export default KML;
+224 -232
View File
@@ -47,7 +47,8 @@ import RenderFeature from '../render/Feature.js';
* @param {module:ol/format/MVT~Options=} opt_options Options. * @param {module:ol/format/MVT~Options=} opt_options Options.
* @api * @api
*/ */
const MVT = function(opt_options) { class MVT {
constructor(opt_options) {
FeatureFormat.call(this); FeatureFormat.call(this);
@@ -94,7 +95,228 @@ const MVT = function(opt_options) {
*/ */
this.extent_ = null; this.extent_ = null;
}; }
/**
* Read the raw geometry from the pbf offset stored in a raw feature's geometry
* property.
* @suppress {missingProperties}
* @param {Object} pbf PBF.
* @param {Object} feature Raw feature.
* @param {Array.<number>} flatCoordinates Array to store flat coordinates in.
* @param {Array.<number>} ends Array to store ends in.
* @private
*/
readRawGeometry_(pbf, feature, flatCoordinates, ends) {
pbf.pos = feature.geometry;
const end = pbf.readVarint() + pbf.pos;
let cmd = 1;
let length = 0;
let x = 0;
let y = 0;
let coordsLen = 0;
let currentEnd = 0;
while (pbf.pos < end) {
if (!length) {
const cmdLen = pbf.readVarint();
cmd = cmdLen & 0x7;
length = cmdLen >> 3;
}
length--;
if (cmd === 1 || cmd === 2) {
x += pbf.readSVarint();
y += pbf.readSVarint();
if (cmd === 1) { // moveTo
if (coordsLen > currentEnd) {
ends.push(coordsLen);
currentEnd = coordsLen;
}
}
flatCoordinates.push(x, y);
coordsLen += 2;
} else if (cmd === 7) {
if (coordsLen > currentEnd) {
// close polygon
flatCoordinates.push(
flatCoordinates[currentEnd], flatCoordinates[currentEnd + 1]);
coordsLen += 2;
}
} else {
assert(false, 59); // Invalid command found in the PBF
}
}
if (coordsLen > currentEnd) {
ends.push(coordsLen);
currentEnd = coordsLen;
}
}
/**
* @private
* @param {Object} pbf PBF
* @param {Object} rawFeature Raw Mapbox feature.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @return {module:ol/Feature|module:ol/render/Feature} Feature.
*/
createFeature_(pbf, rawFeature, opt_options) {
const type = rawFeature.type;
if (type === 0) {
return null;
}
let feature;
const id = rawFeature.id;
const values = rawFeature.properties;
values[this.layerName_] = rawFeature.layer.name;
const flatCoordinates = [];
const ends = [];
this.readRawGeometry_(pbf, rawFeature, flatCoordinates, ends);
const geometryType = getGeometryType(type, ends.length);
if (this.featureClass_ === RenderFeature) {
feature = new this.featureClass_(geometryType, flatCoordinates, ends, values, id);
} else {
let geom;
if (geometryType == GeometryType.POLYGON) {
const endss = [];
let offset = 0;
let prevEndIndex = 0;
for (let i = 0, ii = ends.length; i < ii; ++i) {
const end = ends[i];
if (!linearRingIsClockwise(flatCoordinates, offset, end, 2)) {
endss.push(ends.slice(prevEndIndex, i));
prevEndIndex = i;
}
offset = end;
}
if (endss.length > 1) {
geom = new MultiPolygon(flatCoordinates, GeometryLayout.XY, endss);
} else {
geom = new Polygon(flatCoordinates, GeometryLayout.XY, ends);
}
} else {
geom = geometryType === GeometryType.POINT ? new Point(flatCoordinates, GeometryLayout.XY) :
geometryType === GeometryType.LINE_STRING ? new LineString(flatCoordinates, GeometryLayout.XY) :
geometryType === GeometryType.POLYGON ? new Polygon(flatCoordinates, GeometryLayout.XY, ends) :
geometryType === GeometryType.MULTI_POINT ? new MultiPoint(flatCoordinates, GeometryLayout.XY) :
geometryType === GeometryType.MULTI_LINE_STRING ? new MultiLineString(flatCoordinates, GeometryLayout.XY, ends) :
null;
}
feature = new this.featureClass_();
if (this.geometryName_) {
feature.setGeometryName(this.geometryName_);
}
const geometry = transformWithOptions(geom, false, this.adaptOptions(opt_options));
feature.setGeometry(geometry);
feature.setId(id);
feature.setProperties(values);
}
return feature;
}
/**
* @inheritDoc
* @api
*/
getLastExtent() {
return this.extent_;
}
/**
* @inheritDoc
*/
getType() {
return FormatType.ARRAY_BUFFER;
}
/**
* @inheritDoc
* @api
*/
readFeatures(source, opt_options) {
const layers = this.layers_;
const pbf = new PBF(/** @type {ArrayBuffer} */ (source));
const pbfLayers = pbf.readFields(layersPBFReader, {});
/** @type {Array.<module:ol/Feature|module:ol/render/Feature>} */
const features = [];
for (const name in pbfLayers) {
if (layers && layers.indexOf(name) == -1) {
continue;
}
const pbfLayer = pbfLayers[name];
for (let i = 0, ii = pbfLayer.length; i < ii; ++i) {
const rawFeature = readRawFeature(pbf, pbfLayer, i);
features.push(this.createFeature_(pbf, rawFeature));
}
this.extent_ = pbfLayer ? [0, 0, pbfLayer.extent, pbfLayer.extent] : null;
}
return features;
}
/**
* @inheritDoc
* @api
*/
readProjection(source) {
return this.dataProjection;
}
/**
* Sets the layers that features will be read from.
* @param {Array.<string>} layers Layers.
* @api
*/
setLayers(layers) {
this.layers_ = layers;
}
/**
* Not implemented.
* @override
*/
readFeature() {}
/**
* Not implemented.
* @override
*/
readGeometry() {}
/**
* Not implemented.
* @override
*/
writeFeature() {}
/**
* Not implemented.
* @override
*/
writeGeometry() {}
/**
* Not implemented.
* @override
*/
writeFeatures() {}
}
inherits(MVT, FeatureFormat); inherits(MVT, FeatureFormat);
@@ -201,72 +423,6 @@ function readRawFeature(pbf, layer, i) {
} }
/**
* Read the raw geometry from the pbf offset stored in a raw feature's geometry
* property.
* @suppress {missingProperties}
* @param {Object} pbf PBF.
* @param {Object} feature Raw feature.
* @param {Array.<number>} flatCoordinates Array to store flat coordinates in.
* @param {Array.<number>} ends Array to store ends in.
* @private
*/
MVT.prototype.readRawGeometry_ = function(pbf, feature, flatCoordinates, ends) {
pbf.pos = feature.geometry;
const end = pbf.readVarint() + pbf.pos;
let cmd = 1;
let length = 0;
let x = 0;
let y = 0;
let coordsLen = 0;
let currentEnd = 0;
while (pbf.pos < end) {
if (!length) {
const cmdLen = pbf.readVarint();
cmd = cmdLen & 0x7;
length = cmdLen >> 3;
}
length--;
if (cmd === 1 || cmd === 2) {
x += pbf.readSVarint();
y += pbf.readSVarint();
if (cmd === 1) { // moveTo
if (coordsLen > currentEnd) {
ends.push(coordsLen);
currentEnd = coordsLen;
}
}
flatCoordinates.push(x, y);
coordsLen += 2;
} else if (cmd === 7) {
if (coordsLen > currentEnd) {
// close polygon
flatCoordinates.push(
flatCoordinates[currentEnd], flatCoordinates[currentEnd + 1]);
coordsLen += 2;
}
} else {
assert(false, 59); // Invalid command found in the PBF
}
}
if (coordsLen > currentEnd) {
ends.push(coordsLen);
currentEnd = coordsLen;
}
};
/** /**
* @suppress {missingProperties} * @suppress {missingProperties}
* @param {number} type The raw feature's geometry type * @param {number} type The raw feature's geometry type
@@ -292,168 +448,4 @@ function getGeometryType(type, numEnds) {
return geometryType; return geometryType;
} }
/**
* @private
* @param {Object} pbf PBF
* @param {Object} rawFeature Raw Mapbox feature.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @return {module:ol/Feature|module:ol/render/Feature} Feature.
*/
MVT.prototype.createFeature_ = function(pbf, rawFeature, opt_options) {
const type = rawFeature.type;
if (type === 0) {
return null;
}
let feature;
const id = rawFeature.id;
const values = rawFeature.properties;
values[this.layerName_] = rawFeature.layer.name;
const flatCoordinates = [];
const ends = [];
this.readRawGeometry_(pbf, rawFeature, flatCoordinates, ends);
const geometryType = getGeometryType(type, ends.length);
if (this.featureClass_ === RenderFeature) {
feature = new this.featureClass_(geometryType, flatCoordinates, ends, values, id);
} else {
let geom;
if (geometryType == GeometryType.POLYGON) {
const endss = [];
let offset = 0;
let prevEndIndex = 0;
for (let i = 0, ii = ends.length; i < ii; ++i) {
const end = ends[i];
if (!linearRingIsClockwise(flatCoordinates, offset, end, 2)) {
endss.push(ends.slice(prevEndIndex, i));
prevEndIndex = i;
}
offset = end;
}
if (endss.length > 1) {
geom = new MultiPolygon(flatCoordinates, GeometryLayout.XY, endss);
} else {
geom = new Polygon(flatCoordinates, GeometryLayout.XY, ends);
}
} else {
geom = geometryType === GeometryType.POINT ? new Point(flatCoordinates, GeometryLayout.XY) :
geometryType === GeometryType.LINE_STRING ? new LineString(flatCoordinates, GeometryLayout.XY) :
geometryType === GeometryType.POLYGON ? new Polygon(flatCoordinates, GeometryLayout.XY, ends) :
geometryType === GeometryType.MULTI_POINT ? new MultiPoint(flatCoordinates, GeometryLayout.XY) :
geometryType === GeometryType.MULTI_LINE_STRING ? new MultiLineString(flatCoordinates, GeometryLayout.XY, ends) :
null;
}
feature = new this.featureClass_();
if (this.geometryName_) {
feature.setGeometryName(this.geometryName_);
}
const geometry = transformWithOptions(geom, false, this.adaptOptions(opt_options));
feature.setGeometry(geometry);
feature.setId(id);
feature.setProperties(values);
}
return feature;
};
/**
* @inheritDoc
* @api
*/
MVT.prototype.getLastExtent = function() {
return this.extent_;
};
/**
* @inheritDoc
*/
MVT.prototype.getType = function() {
return FormatType.ARRAY_BUFFER;
};
/**
* @inheritDoc
* @api
*/
MVT.prototype.readFeatures = function(source, opt_options) {
const layers = this.layers_;
const pbf = new PBF(/** @type {ArrayBuffer} */ (source));
const pbfLayers = pbf.readFields(layersPBFReader, {});
/** @type {Array.<module:ol/Feature|module:ol/render/Feature>} */
const features = [];
for (const name in pbfLayers) {
if (layers && layers.indexOf(name) == -1) {
continue;
}
const pbfLayer = pbfLayers[name];
for (let i = 0, ii = pbfLayer.length; i < ii; ++i) {
const rawFeature = readRawFeature(pbf, pbfLayer, i);
features.push(this.createFeature_(pbf, rawFeature));
}
this.extent_ = pbfLayer ? [0, 0, pbfLayer.extent, pbfLayer.extent] : null;
}
return features;
};
/**
* @inheritDoc
* @api
*/
MVT.prototype.readProjection = function(source) {
return this.dataProjection;
};
/**
* Sets the layers that features will be read from.
* @param {Array.<string>} layers Layers.
* @api
*/
MVT.prototype.setLayers = function(layers) {
this.layers_ = layers;
};
/**
* Not implemented.
* @override
*/
MVT.prototype.readFeature = function() {};
/**
* Not implemented.
* @override
*/
MVT.prototype.readGeometry = function() {};
/**
* Not implemented.
* @override
*/
MVT.prototype.writeFeature = function() {};
/**
* Not implemented.
* @override
*/
MVT.prototype.writeGeometry = function() {};
/**
* Not implemented.
* @override
*/
MVT.prototype.writeFeatures = function() {};
export default MVT; export default MVT;
+62 -62
View File
@@ -24,14 +24,74 @@ import {pushParseAndPop, makeStructureNS} from '../xml.js';
* @extends {module:ol/format/XMLFeature} * @extends {module:ol/format/XMLFeature}
* @api * @api
*/ */
const OSMXML = function() { class OSMXML {
constructor() {
XMLFeature.call(this); XMLFeature.call(this);
/** /**
* @inheritDoc * @inheritDoc
*/ */
this.dataProjection = getProjection('EPSG:4326'); this.dataProjection = getProjection('EPSG:4326');
}; }
/**
* @inheritDoc
*/
readFeaturesFromNode(node, opt_options) {
const options = this.getReadOptions(node, opt_options);
if (node.localName == 'osm') {
const state = pushParseAndPop({
nodes: {},
ways: [],
features: []
}, PARSERS, node, [options]);
// parse nodes in ways
for (let j = 0; j < state.ways.length; j++) {
const values = /** @type {Object} */ (state.ways[j]);
/** @type {Array.<number>} */
const flatCoordinates = [];
for (let i = 0, ii = values.ndrefs.length; i < ii; i++) {
const point = state.nodes[values.ndrefs[i]];
extend(flatCoordinates, point);
}
let geometry;
if (values.ndrefs[0] == values.ndrefs[values.ndrefs.length - 1]) {
// closed way
geometry = new Polygon(flatCoordinates, GeometryLayout.XY, [flatCoordinates.length]);
} else {
geometry = new LineString(flatCoordinates, GeometryLayout.XY);
}
transformWithOptions(geometry, false, options);
const feature = new Feature(geometry);
feature.setId(values.id);
feature.setProperties(values.tags);
state.features.push(feature);
}
if (state.features) {
return state.features;
}
}
return [];
}
/**
* Not implemented.
* @inheritDoc
*/
writeFeatureNode(feature, opt_options) {}
/**
* Not implemented.
* @inheritDoc
*/
writeFeaturesNode(features, opt_options) {}
/**
* Not implemented.
* @inheritDoc
*/
writeGeometryNode(geometry, opt_options) {}
}
inherits(OSMXML, XMLFeature); inherits(OSMXML, XMLFeature);
@@ -152,47 +212,6 @@ function readTag(node, objectStack) {
OSMXML.prototype.readFeatures; OSMXML.prototype.readFeatures;
/**
* @inheritDoc
*/
OSMXML.prototype.readFeaturesFromNode = function(node, opt_options) {
const options = this.getReadOptions(node, opt_options);
if (node.localName == 'osm') {
const state = pushParseAndPop({
nodes: {},
ways: [],
features: []
}, PARSERS, node, [options]);
// parse nodes in ways
for (let j = 0; j < state.ways.length; j++) {
const values = /** @type {Object} */ (state.ways[j]);
/** @type {Array.<number>} */
const flatCoordinates = [];
for (let i = 0, ii = values.ndrefs.length; i < ii; i++) {
const point = state.nodes[values.ndrefs[i]];
extend(flatCoordinates, point);
}
let geometry;
if (values.ndrefs[0] == values.ndrefs[values.ndrefs.length - 1]) {
// closed way
geometry = new Polygon(flatCoordinates, GeometryLayout.XY, [flatCoordinates.length]);
} else {
geometry = new LineString(flatCoordinates, GeometryLayout.XY);
}
transformWithOptions(geometry, false, options);
const feature = new Feature(geometry);
feature.setId(values.id);
feature.setProperties(values.tags);
state.features.push(feature);
}
if (state.features) {
return state.features;
}
}
return [];
};
/** /**
* Read the projection from an OSM source. * Read the projection from an OSM source.
* *
@@ -204,23 +223,4 @@ OSMXML.prototype.readFeaturesFromNode = function(node, opt_options) {
OSMXML.prototype.readProjection; OSMXML.prototype.readProjection;
/**
* Not implemented.
* @inheritDoc
*/
OSMXML.prototype.writeFeatureNode = function(feature, opt_options) {};
/**
* Not implemented.
* @inheritDoc
*/
OSMXML.prototype.writeFeaturesNode = function(features, opt_options) {};
/**
* Not implemented.
* @inheritDoc
*/
OSMXML.prototype.writeGeometryNode = function(geometry, opt_options) {};
export default OSMXML; export default OSMXML;
+25 -25
View File
@@ -11,9 +11,32 @@ import {makeObjectPropertyPusher, makeObjectPropertySetter, makeStructureNS, pus
* @constructor * @constructor
* @extends {module:ol/format/XML} * @extends {module:ol/format/XML}
*/ */
const OWS = function() { class OWS {
constructor() {
XML.call(this); XML.call(this);
}; }
/**
* @inheritDoc
*/
readFromDocument(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
return this.readFromNode(n);
}
}
return null;
}
/**
* @inheritDoc
*/
readFromNode(node) {
const owsObject = pushParseAndPop({},
PARSERS, node, []);
return owsObject ? owsObject : null;
}
}
inherits(OWS, XML); inherits(OWS, XML);
@@ -187,29 +210,6 @@ const SERVICE_PROVIDER_PARSERS =
}); });
/**
* @inheritDoc
*/
OWS.prototype.readFromDocument = function(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
return this.readFromNode(n);
}
}
return null;
};
/**
* @inheritDoc
*/
OWS.prototype.readFromNode = function(node) {
const owsObject = pushParseAndPop({},
PARSERS, node, []);
return owsObject ? owsObject : null;
};
/** /**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
+70 -72
View File
@@ -32,7 +32,8 @@ import {get as getProjection} from '../proj.js';
* @param {module:ol/format/Polyline~Options=} opt_options Optional configuration object. * @param {module:ol/format/Polyline~Options=} opt_options Optional configuration object.
* @api * @api
*/ */
const Polyline = function(opt_options) { class Polyline {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -55,7 +56,74 @@ const Polyline = function(opt_options) {
*/ */
this.geometryLayout_ = options.geometryLayout ? this.geometryLayout_ = options.geometryLayout ?
options.geometryLayout : GeometryLayout.XY; options.geometryLayout : GeometryLayout.XY;
}; }
/**
* @inheritDoc
*/
readFeatureFromText(text, opt_options) {
const geometry = this.readGeometryFromText(text, opt_options);
return new Feature(geometry);
}
/**
* @inheritDoc
*/
readFeaturesFromText(text, opt_options) {
const feature = this.readFeatureFromText(text, opt_options);
return [feature];
}
/**
* @inheritDoc
*/
readGeometryFromText(text, opt_options) {
const stride = getStrideForLayout(this.geometryLayout_);
const flatCoordinates = decodeDeltas(text, stride, this.factor_);
flipXY(flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
const coordinates = inflateCoordinates(flatCoordinates, 0, flatCoordinates.length, stride);
return (
/** @type {module:ol/geom/Geometry} */ (transformWithOptions(
new LineString(coordinates, this.geometryLayout_),
false,
this.adaptOptions(opt_options)
))
);
}
/**
* @inheritDoc
*/
writeFeatureText(feature, opt_options) {
const geometry = feature.getGeometry();
if (geometry) {
return this.writeGeometryText(geometry, opt_options);
} else {
assert(false, 40); // Expected `feature` to have a geometry
return '';
}
}
/**
* @inheritDoc
*/
writeFeaturesText(features, opt_options) {
return this.writeFeatureText(features[0], opt_options);
}
/**
* @inheritDoc
*/
writeGeometryText(geometry, opt_options) {
geometry = /** @type {module:ol/geom/LineString} */
(transformWithOptions(geometry, true, this.adaptOptions(opt_options)));
const flatCoordinates = geometry.getFlatCoordinates();
const stride = geometry.getStride();
flipXY(flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
return encodeDeltas(flatCoordinates, stride, this.factor_);
}
}
inherits(Polyline, TextFeature); inherits(Polyline, TextFeature);
@@ -277,15 +345,6 @@ export function encodeUnsignedInteger(num) {
Polyline.prototype.readFeature; Polyline.prototype.readFeature;
/**
* @inheritDoc
*/
Polyline.prototype.readFeatureFromText = function(text, opt_options) {
const geometry = this.readGeometryFromText(text, opt_options);
return new Feature(geometry);
};
/** /**
* Read the feature from the source. As Polyline sources contain a single * Read the feature from the source. As Polyline sources contain a single
* feature, this will return the feature in an array. * feature, this will return the feature in an array.
@@ -299,15 +358,6 @@ Polyline.prototype.readFeatureFromText = function(text, opt_options) {
Polyline.prototype.readFeatures; Polyline.prototype.readFeatures;
/**
* @inheritDoc
*/
Polyline.prototype.readFeaturesFromText = function(text, opt_options) {
const feature = this.readFeatureFromText(text, opt_options);
return [feature];
};
/** /**
* Read the geometry from the source. * Read the geometry from the source.
* *
@@ -320,25 +370,6 @@ Polyline.prototype.readFeaturesFromText = function(text, opt_options) {
Polyline.prototype.readGeometry; Polyline.prototype.readGeometry;
/**
* @inheritDoc
*/
Polyline.prototype.readGeometryFromText = function(text, opt_options) {
const stride = getStrideForLayout(this.geometryLayout_);
const flatCoordinates = decodeDeltas(text, stride, this.factor_);
flipXY(flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
const coordinates = inflateCoordinates(flatCoordinates, 0, flatCoordinates.length, stride);
return (
/** @type {module:ol/geom/Geometry} */ (transformWithOptions(
new LineString(coordinates, this.geometryLayout_),
false,
this.adaptOptions(opt_options)
))
);
};
/** /**
* Read the projection from a Polyline source. * Read the projection from a Polyline source.
* *
@@ -350,28 +381,6 @@ Polyline.prototype.readGeometryFromText = function(text, opt_options) {
Polyline.prototype.readProjection; Polyline.prototype.readProjection;
/**
* @inheritDoc
*/
Polyline.prototype.writeFeatureText = function(feature, opt_options) {
const geometry = feature.getGeometry();
if (geometry) {
return this.writeGeometryText(geometry, opt_options);
} else {
assert(false, 40); // Expected `feature` to have a geometry
return '';
}
};
/**
* @inheritDoc
*/
Polyline.prototype.writeFeaturesText = function(features, opt_options) {
return this.writeFeatureText(features[0], opt_options);
};
/** /**
* Write a single geometry in Polyline format. * Write a single geometry in Polyline format.
* *
@@ -384,15 +393,4 @@ Polyline.prototype.writeFeaturesText = function(features, opt_options) {
Polyline.prototype.writeGeometry; Polyline.prototype.writeGeometry;
/**
* @inheritDoc
*/
Polyline.prototype.writeGeometryText = function(geometry, opt_options) {
geometry = /** @type {module:ol/geom/LineString} */
(transformWithOptions(geometry, true, this.adaptOptions(opt_options)));
const flatCoordinates = geometry.getFlatCoordinates();
const stride = geometry.getStride();
flipXY(flatCoordinates, 0, flatCoordinates.length, stride, flatCoordinates);
return encodeDeltas(flatCoordinates, stride, this.factor_);
};
export default Polyline; export default Polyline;
+123 -134
View File
@@ -15,9 +15,130 @@ import FormatType from '../format/FormatType.js';
* @abstract * @abstract
* @extends {module:ol/format/Feature} * @extends {module:ol/format/Feature}
*/ */
const TextFeature = function() { class TextFeature {
constructor() {
FeatureFormat.call(this); FeatureFormat.call(this);
}; }
/**
* @inheritDoc
*/
getType() {
return FormatType.TEXT;
}
/**
* @inheritDoc
*/
readFeature(source, opt_options) {
return this.readFeatureFromText(getText(source), this.adaptOptions(opt_options));
}
/**
* @abstract
* @param {string} text Text.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {module:ol/Feature} Feature.
*/
readFeatureFromText(text, opt_options) {}
/**
* @inheritDoc
*/
readFeatures(source, opt_options) {
return this.readFeaturesFromText(getText(source), this.adaptOptions(opt_options));
}
/**
* @abstract
* @param {string} text Text.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {Array.<module:ol/Feature>} Features.
*/
readFeaturesFromText(text, opt_options) {}
/**
* @inheritDoc
*/
readGeometry(source, opt_options) {
return this.readGeometryFromText(getText(source), this.adaptOptions(opt_options));
}
/**
* @abstract
* @param {string} text Text.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {module:ol/geom/Geometry} Geometry.
*/
readGeometryFromText(text, opt_options) {}
/**
* @inheritDoc
*/
readProjection(source) {
return this.readProjectionFromText(getText(source));
}
/**
* @param {string} text Text.
* @protected
* @return {module:ol/proj/Projection} Projection.
*/
readProjectionFromText(text) {
return this.dataProjection;
}
/**
* @inheritDoc
*/
writeFeature(feature, opt_options) {
return this.writeFeatureText(feature, this.adaptOptions(opt_options));
}
/**
* @abstract
* @param {module:ol/Feature} feature Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @protected
* @return {string} Text.
*/
writeFeatureText(feature, opt_options) {}
/**
* @inheritDoc
*/
writeFeatures(features, opt_options) {
return this.writeFeaturesText(features, this.adaptOptions(opt_options));
}
/**
* @abstract
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @protected
* @return {string} Text.
*/
writeFeaturesText(features, opt_options) {}
/**
* @inheritDoc
*/
writeGeometry(geometry, opt_options) {
return this.writeGeometryText(geometry, this.adaptOptions(opt_options));
}
/**
* @abstract
* @param {module:ol/geom/Geometry} geometry Geometry.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @protected
* @return {string} Text.
*/
writeGeometryText(geometry, opt_options) {}
}
inherits(TextFeature, FeatureFormat); inherits(TextFeature, FeatureFormat);
@@ -35,136 +156,4 @@ function getText(source) {
} }
/**
* @inheritDoc
*/
TextFeature.prototype.getType = function() {
return FormatType.TEXT;
};
/**
* @inheritDoc
*/
TextFeature.prototype.readFeature = function(source, opt_options) {
return this.readFeatureFromText(getText(source), this.adaptOptions(opt_options));
};
/**
* @abstract
* @param {string} text Text.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {module:ol/Feature} Feature.
*/
TextFeature.prototype.readFeatureFromText = function(text, opt_options) {};
/**
* @inheritDoc
*/
TextFeature.prototype.readFeatures = function(source, opt_options) {
return this.readFeaturesFromText(getText(source), this.adaptOptions(opt_options));
};
/**
* @abstract
* @param {string} text Text.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {Array.<module:ol/Feature>} Features.
*/
TextFeature.prototype.readFeaturesFromText = function(text, opt_options) {};
/**
* @inheritDoc
*/
TextFeature.prototype.readGeometry = function(source, opt_options) {
return this.readGeometryFromText(getText(source), this.adaptOptions(opt_options));
};
/**
* @abstract
* @param {string} text Text.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @protected
* @return {module:ol/geom/Geometry} Geometry.
*/
TextFeature.prototype.readGeometryFromText = function(text, opt_options) {};
/**
* @inheritDoc
*/
TextFeature.prototype.readProjection = function(source) {
return this.readProjectionFromText(getText(source));
};
/**
* @param {string} text Text.
* @protected
* @return {module:ol/proj/Projection} Projection.
*/
TextFeature.prototype.readProjectionFromText = function(text) {
return this.dataProjection;
};
/**
* @inheritDoc
*/
TextFeature.prototype.writeFeature = function(feature, opt_options) {
return this.writeFeatureText(feature, this.adaptOptions(opt_options));
};
/**
* @abstract
* @param {module:ol/Feature} feature Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @protected
* @return {string} Text.
*/
TextFeature.prototype.writeFeatureText = function(feature, opt_options) {};
/**
* @inheritDoc
*/
TextFeature.prototype.writeFeatures = function(features, opt_options) {
return this.writeFeaturesText(features, this.adaptOptions(opt_options));
};
/**
* @abstract
* @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @protected
* @return {string} Text.
*/
TextFeature.prototype.writeFeaturesText = function(features, opt_options) {};
/**
* @inheritDoc
*/
TextFeature.prototype.writeGeometry = function(geometry, opt_options) {
return this.writeGeometryText(geometry, this.adaptOptions(opt_options));
};
/**
* @abstract
* @param {module:ol/geom/Geometry} geometry Geometry.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Write options.
* @protected
* @return {string} Text.
*/
TextFeature.prototype.writeGeometryText = function(geometry, opt_options) {};
export default TextFeature; export default TextFeature;
+82 -85
View File
@@ -48,7 +48,8 @@ import {get as getProjection} from '../proj.js';
* @param {module:ol/format/TopoJSON~Options=} opt_options Options. * @param {module:ol/format/TopoJSON~Options=} opt_options Options.
* @api * @api
*/ */
const TopoJSON = function(opt_options) { class TopoJSON {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -73,7 +74,86 @@ const TopoJSON = function(opt_options) {
options.dataProjection ? options.dataProjection ?
options.dataProjection : 'EPSG:4326'); options.dataProjection : 'EPSG:4326');
}; }
/**
* @inheritDoc
*/
readFeaturesFromObject(object, opt_options) {
if (object.type == 'Topology') {
const topoJSONTopology = /** @type {TopoJSONTopology} */ (object);
let transform, scale = null, translate = null;
if (topoJSONTopology.transform) {
transform = topoJSONTopology.transform;
scale = transform.scale;
translate = transform.translate;
}
const arcs = topoJSONTopology.arcs;
if (transform) {
transformArcs(arcs, scale, translate);
}
/** @type {Array.<module:ol/Feature>} */
const features = [];
const topoJSONFeatures = topoJSONTopology.objects;
const property = this.layerName_;
let feature;
for (const objectName in topoJSONFeatures) {
if (this.layers_ && this.layers_.indexOf(objectName) == -1) {
continue;
}
if (topoJSONFeatures[objectName].type === 'GeometryCollection') {
feature = /** @type {TopoJSONGeometryCollection} */ (topoJSONFeatures[objectName]);
features.push.apply(features, readFeaturesFromGeometryCollection(
feature, arcs, scale, translate, property, objectName, opt_options));
} else {
feature = /** @type {TopoJSONGeometry} */ (topoJSONFeatures[objectName]);
features.push(readFeatureFromGeometry(
feature, arcs, scale, translate, property, objectName, opt_options));
}
}
return features;
} else {
return [];
}
}
/**
* @inheritDoc
*/
readProjectionFromObject(object) {
return this.dataProjection;
}
/**
* Not implemented.
* @inheritDoc
*/
writeFeatureObject(feature, opt_options) {}
/**
* Not implemented.
* @inheritDoc
*/
writeFeaturesObject(features, opt_options) {}
/**
* Not implemented.
* @inheritDoc
*/
writeGeometryObject(geometry, opt_options) {}
/**
* Not implemented.
* @override
*/
readGeometryFromObject() {}
/**
* Not implemented.
* @override
*/
readFeatureFromObject() {}
}
inherits(TopoJSON, JSONFeature); inherits(TopoJSON, JSONFeature);
@@ -309,48 +389,6 @@ function readFeatureFromGeometry(object, arcs, scale, translate, property, name,
TopoJSON.prototype.readFeatures; TopoJSON.prototype.readFeatures;
/**
* @inheritDoc
*/
TopoJSON.prototype.readFeaturesFromObject = function(object, opt_options) {
if (object.type == 'Topology') {
const topoJSONTopology = /** @type {TopoJSONTopology} */ (object);
let transform, scale = null, translate = null;
if (topoJSONTopology.transform) {
transform = topoJSONTopology.transform;
scale = transform.scale;
translate = transform.translate;
}
const arcs = topoJSONTopology.arcs;
if (transform) {
transformArcs(arcs, scale, translate);
}
/** @type {Array.<module:ol/Feature>} */
const features = [];
const topoJSONFeatures = topoJSONTopology.objects;
const property = this.layerName_;
let feature;
for (const objectName in topoJSONFeatures) {
if (this.layers_ && this.layers_.indexOf(objectName) == -1) {
continue;
}
if (topoJSONFeatures[objectName].type === 'GeometryCollection') {
feature = /** @type {TopoJSONGeometryCollection} */ (topoJSONFeatures[objectName]);
features.push.apply(features, readFeaturesFromGeometryCollection(
feature, arcs, scale, translate, property, objectName, opt_options));
} else {
feature = /** @type {TopoJSONGeometry} */ (topoJSONFeatures[objectName]);
features.push(readFeatureFromGeometry(
feature, arcs, scale, translate, property, objectName, opt_options));
}
}
return features;
} else {
return [];
}
};
/** /**
* Apply a linear transform to array of arcs. The provided array of arcs is * Apply a linear transform to array of arcs. The provided array of arcs is
* modified in place. * modified in place.
@@ -412,45 +450,4 @@ function transformVertex(vertex, scale, translate) {
TopoJSON.prototype.readProjection; TopoJSON.prototype.readProjection;
/**
* @inheritDoc
*/
TopoJSON.prototype.readProjectionFromObject = function(object) {
return this.dataProjection;
};
/**
* Not implemented.
* @inheritDoc
*/
TopoJSON.prototype.writeFeatureObject = function(feature, opt_options) {};
/**
* Not implemented.
* @inheritDoc
*/
TopoJSON.prototype.writeFeaturesObject = function(features, opt_options) {};
/**
* Not implemented.
* @inheritDoc
*/
TopoJSON.prototype.writeGeometryObject = function(geometry, opt_options) {};
/**
* Not implemented.
* @override
*/
TopoJSON.prototype.readGeometryFromObject = function() {};
/**
* Not implemented.
* @override
*/
TopoJSON.prototype.readFeatureFromObject = function() {};
export default TopoJSON; export default TopoJSON;
+237 -246
View File
@@ -143,7 +143,8 @@ const DEFAULT_VERSION = '1.1.0';
* @extends {module:ol/format/XMLFeature} * @extends {module:ol/format/XMLFeature}
* @api * @api
*/ */
const WFS = function(opt_options) { class WFS {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
/** /**
@@ -173,43 +174,26 @@ const WFS = function(opt_options) {
options.schemaLocation : SCHEMA_LOCATIONS[DEFAULT_VERSION]; options.schemaLocation : SCHEMA_LOCATIONS[DEFAULT_VERSION];
XMLFeature.call(this); XMLFeature.call(this);
}; }
inherits(WFS, XMLFeature); /**
/**
* @return {Array.<string>|string|undefined} featureType * @return {Array.<string>|string|undefined} featureType
*/ */
WFS.prototype.getFeatureType = function() { getFeatureType() {
return this.featureType_; return this.featureType_;
}; }
/**
/**
* @param {Array.<string>|string|undefined} featureType Feature type(s) to parse. * @param {Array.<string>|string|undefined} featureType Feature type(s) to parse.
*/ */
WFS.prototype.setFeatureType = function(featureType) { setFeatureType(featureType) {
this.featureType_ = featureType; this.featureType_ = featureType;
}; }
/**
/**
* Read all features from a WFS FeatureCollection.
*
* @function
* @param {Document|Node|Object|string} source Source.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @return {Array.<module:ol/Feature>} Features.
* @api
*/
WFS.prototype.readFeatures;
/**
* @inheritDoc * @inheritDoc
*/ */
WFS.prototype.readFeaturesFromNode = function(node, opt_options) { readFeaturesFromNode(node, opt_options) {
const context = /** @type {module:ol/xml~NodeStackItem} */ ({ const context = /** @type {module:ol/xml~NodeStackItem} */ ({
'featureType': this.featureType_, 'featureType': this.featureType_,
'featureNS': this.featureNS_ 'featureNS': this.featureNS_
@@ -226,17 +210,16 @@ WFS.prototype.readFeaturesFromNode = function(node, opt_options) {
features = []; features = [];
} }
return features; return features;
}; }
/**
/**
* Read transaction response of the source. * Read transaction response of the source.
* *
* @param {Document|Node|Object|string} source Source. * @param {Document|Node|Object|string} source Source.
* @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response. * @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response.
* @api * @api
*/ */
WFS.prototype.readTransactionResponse = function(source) { readTransactionResponse(source) {
if (isDocument(source)) { if (isDocument(source)) {
return this.readTransactionResponseFromDocument( return this.readTransactionResponseFromDocument(
/** @type {Document} */ (source)); /** @type {Document} */ (source));
@@ -248,10 +231,9 @@ WFS.prototype.readTransactionResponse = function(source) {
} else { } else {
return undefined; return undefined;
} }
}; }
/**
/**
* Read feature collection metadata of the source. * Read feature collection metadata of the source.
* *
* @param {Document|Node|Object|string} source Source. * @param {Document|Node|Object|string} source Source.
@@ -259,7 +241,7 @@ WFS.prototype.readTransactionResponse = function(source) {
* FeatureCollection metadata. * FeatureCollection metadata.
* @api * @api
*/ */
WFS.prototype.readFeatureCollectionMetadata = function(source) { readFeatureCollectionMetadata(source) {
if (isDocument(source)) { if (isDocument(source)) {
return this.readFeatureCollectionMetadataFromDocument( return this.readFeatureCollectionMetadataFromDocument(
/** @type {Document} */ (source)); /** @type {Document} */ (source));
@@ -272,22 +254,237 @@ WFS.prototype.readFeatureCollectionMetadata = function(source) {
} else { } else {
return undefined; return undefined;
} }
}; }
/**
/**
* @param {Document} doc Document. * @param {Document} doc Document.
* @return {module:ol/format/WFS~FeatureCollectionMetadata|undefined} * @return {module:ol/format/WFS~FeatureCollectionMetadata|undefined}
* FeatureCollection metadata. * FeatureCollection metadata.
*/ */
WFS.prototype.readFeatureCollectionMetadataFromDocument = function(doc) { readFeatureCollectionMetadataFromDocument(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) { for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) { if (n.nodeType == Node.ELEMENT_NODE) {
return this.readFeatureCollectionMetadataFromNode(n); return this.readFeatureCollectionMetadataFromNode(n);
} }
} }
return undefined; return undefined;
}; }
/**
* @param {Node} node Node.
* @return {module:ol/format/WFS~FeatureCollectionMetadata|undefined}
* FeatureCollection metadata.
*/
readFeatureCollectionMetadataFromNode(node) {
const result = {};
const value = readNonNegativeIntegerString(
node.getAttribute('numberOfFeatures'));
result['numberOfFeatures'] = value;
return pushParseAndPop(
/** @type {module:ol/format/WFS~FeatureCollectionMetadata} */ (result),
FEATURE_COLLECTION_PARSERS, node, [], this.gmlFormat_);
}
/**
* @param {Document} doc Document.
* @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response.
*/
readTransactionResponseFromDocument(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
return this.readTransactionResponseFromNode(n);
}
}
return undefined;
}
/**
* @param {Node} node Node.
* @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response.
*/
readTransactionResponseFromNode(node) {
return pushParseAndPop(
/** @type {module:ol/format/WFS~TransactionResponse} */({}),
TRANSACTION_RESPONSE_PARSERS, node, []);
}
/**
* Encode format as WFS `GetFeature` and return the Node.
*
* @param {module:ol/format/WFS~WriteGetFeatureOptions} options Options.
* @return {Node} Result.
* @api
*/
writeGetFeature(options) {
const node = createElementNS(WFSNS, 'GetFeature');
node.setAttribute('service', 'WFS');
node.setAttribute('version', '1.1.0');
let filter;
if (options) {
if (options.handle) {
node.setAttribute('handle', options.handle);
}
if (options.outputFormat) {
node.setAttribute('outputFormat', options.outputFormat);
}
if (options.maxFeatures !== undefined) {
node.setAttribute('maxFeatures', options.maxFeatures);
}
if (options.resultType) {
node.setAttribute('resultType', options.resultType);
}
if (options.startIndex !== undefined) {
node.setAttribute('startIndex', options.startIndex);
}
if (options.count !== undefined) {
node.setAttribute('count', options.count);
}
filter = options.filter;
if (options.bbox) {
assert(options.geometryName,
12); // `options.geometryName` must also be provided when `options.bbox` is set
const bbox = bboxFilter(
/** @type {string} */ (options.geometryName), options.bbox, options.srsName);
if (filter) {
// if bbox and filter are both set, combine the two into a single filter
filter = andFilter(filter, bbox);
} else {
filter = bbox;
}
}
}
node.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', this.schemaLocation_);
/** @type {module:ol/xml~NodeStackItem} */
const context = {
node: node,
'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]);
return node;
}
/**
* Encode format as WFS `Transaction` and return the Node.
*
* @param {Array.<module:ol/Feature>} inserts The features to insert.
* @param {Array.<module:ol/Feature>} updates The features to update.
* @param {Array.<module:ol/Feature>} deletes The features to delete.
* @param {module:ol/format/WFS~WriteTransactionOptions} options Write options.
* @return {Node} Result.
* @api
*/
writeTransaction(inserts, updates, deletes, options) {
const objectStack = [];
const node = createElementNS(WFSNS, 'Transaction');
const version = options.version ? options.version : DEFAULT_VERSION;
const gmlVersion = version === '1.0.0' ? 2 : 3;
node.setAttribute('service', 'WFS');
node.setAttribute('version', version);
let baseObj;
/** @type {module:ol/xml~NodeStackItem} */
let obj;
if (options) {
baseObj = options.gmlOptions ? options.gmlOptions : {};
if (options.handle) {
node.setAttribute('handle', options.handle);
}
}
const schemaLocation = SCHEMA_LOCATIONS[version];
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,
'featureType': options.featureType, 'featurePrefix': featurePrefix,
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
assign(obj, baseObj);
pushSerializeAndPop(obj,
TRANSACTION_SERIALIZERS,
makeSimpleNodeFactory('Insert'), inserts,
objectStack);
}
if (updates) {
obj = {node: node, 'featureNS': options.featureNS,
'featureType': options.featureType, 'featurePrefix': featurePrefix,
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
assign(obj, baseObj);
pushSerializeAndPop(obj,
TRANSACTION_SERIALIZERS,
makeSimpleNodeFactory('Update'), updates,
objectStack);
}
if (deletes) {
pushSerializeAndPop({node: node, 'featureNS': options.featureNS,
'featureType': options.featureType, 'featurePrefix': featurePrefix,
'gmlVersion': gmlVersion, 'srsName': options.srsName},
TRANSACTION_SERIALIZERS,
makeSimpleNodeFactory('Delete'), deletes,
objectStack);
}
if (options.nativeElements) {
pushSerializeAndPop({node: node, 'featureNS': options.featureNS,
'featureType': options.featureType, 'featurePrefix': featurePrefix,
'gmlVersion': gmlVersion, 'srsName': options.srsName},
TRANSACTION_SERIALIZERS,
makeSimpleNodeFactory('Native'), options.nativeElements,
objectStack);
}
return node;
}
/**
* @inheritDoc
*/
readProjectionFromDocument(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
return this.readProjectionFromNode(n);
}
}
return null;
}
/**
* @inheritDoc
*/
readProjectionFromNode(node) {
if (node.firstElementChild &&
node.firstElementChild.firstElementChild) {
node = node.firstElementChild.firstElementChild;
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
if (!(n.childNodes.length === 0 ||
(n.childNodes.length === 1 &&
n.firstChild.nodeType === 3))) {
const objectStack = [{}];
this.gmlFormat_.readGeometryElement(n, objectStack);
return getProjection(objectStack.pop().srsName);
}
}
}
return null;
}
}
inherits(WFS, XMLFeature);
/**
* Read all features from a WFS FeatureCollection.
*
* @function
* @param {Document|Node|Object|string} source Source.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Read options.
* @return {Array.<module:ol/Feature>} Features.
* @api
*/
WFS.prototype.readFeatures;
/** /**
@@ -302,22 +499,6 @@ const FEATURE_COLLECTION_PARSERS = {
}; };
/**
* @param {Node} node Node.
* @return {module:ol/format/WFS~FeatureCollectionMetadata|undefined}
* FeatureCollection metadata.
*/
WFS.prototype.readFeatureCollectionMetadataFromNode = function(node) {
const result = {};
const value = readNonNegativeIntegerString(
node.getAttribute('numberOfFeatures'));
result['numberOfFeatures'] = value;
return pushParseAndPop(
/** @type {module:ol/format/WFS~FeatureCollectionMetadata} */ (result),
FEATURE_COLLECTION_PARSERS, node, [], this.gmlFormat_);
};
/** /**
* @const * @const
* @type {Object.<string, Object.<string, module:ol/xml~Parser>>} * @type {Object.<string, Object.<string, module:ol/xml~Parser>>}
@@ -400,31 +581,6 @@ const TRANSACTION_RESPONSE_PARSERS = {
}; };
/**
* @param {Document} doc Document.
* @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response.
*/
WFS.prototype.readTransactionResponseFromDocument = function(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
return this.readTransactionResponseFromNode(n);
}
}
return undefined;
};
/**
* @param {Node} node Node.
* @return {module:ol/format/WFS~TransactionResponse|undefined} Transaction response.
*/
WFS.prototype.readTransactionResponseFromNode = function(node) {
return pushParseAndPop(
/** @type {module:ol/format/WFS~TransactionResponse} */({}),
TRANSACTION_RESPONSE_PARSERS, node, []);
};
/** /**
* @type {Object.<string, Object.<string, module:ol/xml~Serializer>>} * @type {Object.<string, Object.<string, module:ol/xml~Serializer>>}
*/ */
@@ -942,138 +1098,6 @@ function writeGetFeature(node, featureTypes, objectStack) {
} }
/**
* Encode format as WFS `GetFeature` and return the Node.
*
* @param {module:ol/format/WFS~WriteGetFeatureOptions} options Options.
* @return {Node} Result.
* @api
*/
WFS.prototype.writeGetFeature = function(options) {
const node = createElementNS(WFSNS, 'GetFeature');
node.setAttribute('service', 'WFS');
node.setAttribute('version', '1.1.0');
let filter;
if (options) {
if (options.handle) {
node.setAttribute('handle', options.handle);
}
if (options.outputFormat) {
node.setAttribute('outputFormat', options.outputFormat);
}
if (options.maxFeatures !== undefined) {
node.setAttribute('maxFeatures', options.maxFeatures);
}
if (options.resultType) {
node.setAttribute('resultType', options.resultType);
}
if (options.startIndex !== undefined) {
node.setAttribute('startIndex', options.startIndex);
}
if (options.count !== undefined) {
node.setAttribute('count', options.count);
}
filter = options.filter;
if (options.bbox) {
assert(options.geometryName,
12); // `options.geometryName` must also be provided when `options.bbox` is set
const bbox = bboxFilter(
/** @type {string} */ (options.geometryName), options.bbox, options.srsName);
if (filter) {
// if bbox and filter are both set, combine the two into a single filter
filter = andFilter(filter, bbox);
} else {
filter = bbox;
}
}
}
node.setAttributeNS(XML_SCHEMA_INSTANCE_URI, 'xsi:schemaLocation', this.schemaLocation_);
/** @type {module:ol/xml~NodeStackItem} */
const context = {
node: node,
'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]);
return node;
};
/**
* Encode format as WFS `Transaction` and return the Node.
*
* @param {Array.<module:ol/Feature>} inserts The features to insert.
* @param {Array.<module:ol/Feature>} updates The features to update.
* @param {Array.<module:ol/Feature>} deletes The features to delete.
* @param {module:ol/format/WFS~WriteTransactionOptions} options Write options.
* @return {Node} Result.
* @api
*/
WFS.prototype.writeTransaction = function(inserts, updates, deletes, options) {
const objectStack = [];
const node = createElementNS(WFSNS, 'Transaction');
const version = options.version ? options.version : DEFAULT_VERSION;
const gmlVersion = version === '1.0.0' ? 2 : 3;
node.setAttribute('service', 'WFS');
node.setAttribute('version', version);
let baseObj;
/** @type {module:ol/xml~NodeStackItem} */
let obj;
if (options) {
baseObj = options.gmlOptions ? options.gmlOptions : {};
if (options.handle) {
node.setAttribute('handle', options.handle);
}
}
const schemaLocation = SCHEMA_LOCATIONS[version];
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,
'featureType': options.featureType, 'featurePrefix': featurePrefix,
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
assign(obj, baseObj);
pushSerializeAndPop(obj,
TRANSACTION_SERIALIZERS,
makeSimpleNodeFactory('Insert'), inserts,
objectStack);
}
if (updates) {
obj = {node: node, 'featureNS': options.featureNS,
'featureType': options.featureType, 'featurePrefix': featurePrefix,
'gmlVersion': gmlVersion, 'hasZ': options.hasZ, 'srsName': options.srsName};
assign(obj, baseObj);
pushSerializeAndPop(obj,
TRANSACTION_SERIALIZERS,
makeSimpleNodeFactory('Update'), updates,
objectStack);
}
if (deletes) {
pushSerializeAndPop({node: node, 'featureNS': options.featureNS,
'featureType': options.featureType, 'featurePrefix': featurePrefix,
'gmlVersion': gmlVersion, 'srsName': options.srsName},
TRANSACTION_SERIALIZERS,
makeSimpleNodeFactory('Delete'), deletes,
objectStack);
}
if (options.nativeElements) {
pushSerializeAndPop({node: node, 'featureNS': options.featureNS,
'featureType': options.featureType, 'featurePrefix': featurePrefix,
'gmlVersion': gmlVersion, 'srsName': options.srsName},
TRANSACTION_SERIALIZERS,
makeSimpleNodeFactory('Native'), options.nativeElements,
objectStack);
}
return node;
};
/** /**
* Read the projection from a WFS source. * Read the projection from a WFS source.
* *
@@ -1085,37 +1109,4 @@ WFS.prototype.writeTransaction = function(inserts, updates, deletes, options) {
WFS.prototype.readProjection; WFS.prototype.readProjection;
/**
* @inheritDoc
*/
WFS.prototype.readProjectionFromDocument = function(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
return this.readProjectionFromNode(n);
}
}
return null;
};
/**
* @inheritDoc
*/
WFS.prototype.readProjectionFromNode = function(node) {
if (node.firstElementChild &&
node.firstElementChild.firstElementChild) {
node = node.firstElementChild.firstElementChild;
for (let n = node.firstElementChild; n; n = n.nextElementSibling) {
if (!(n.childNodes.length === 0 ||
(n.childNodes.length === 1 &&
n.firstChild.nodeType === 3))) {
const objectStack = [{}];
this.gmlFormat_.readGeometryElement(n, objectStack);
return getProjection(objectStack.pop().srsName);
}
}
}
return null;
};
export default WFS; export default WFS;
+217 -246
View File
@@ -77,7 +77,8 @@ const TokenType = {
* @param {string} wkt WKT string. * @param {string} wkt WKT string.
* @constructor * @constructor
*/ */
const Lexer = function(wkt) { class Lexer {
constructor(wkt) {
/** /**
* @type {string} * @type {string}
@@ -89,56 +90,51 @@ const Lexer = function(wkt) {
* @private * @private
*/ */
this.index_ = -1; this.index_ = -1;
}; }
/**
/**
* @param {string} c Character. * @param {string} c Character.
* @return {boolean} Whether the character is alphabetic. * @return {boolean} Whether the character is alphabetic.
* @private * @private
*/ */
Lexer.prototype.isAlpha_ = function(c) { isAlpha_(c) {
return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'; return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
}; }
/**
/**
* @param {string} c Character. * @param {string} c Character.
* @param {boolean=} opt_decimal Whether the string number * @param {boolean=} opt_decimal Whether the string number
* contains a dot, i.e. is a decimal number. * contains a dot, i.e. is a decimal number.
* @return {boolean} Whether the character is numeric. * @return {boolean} Whether the character is numeric.
* @private * @private
*/ */
Lexer.prototype.isNumeric_ = function(c, opt_decimal) { isNumeric_(c, opt_decimal) {
const decimal = opt_decimal !== undefined ? opt_decimal : false; const decimal = opt_decimal !== undefined ? opt_decimal : false;
return c >= '0' && c <= '9' || c == '.' && !decimal; return c >= '0' && c <= '9' || c == '.' && !decimal;
}; }
/**
/**
* @param {string} c Character. * @param {string} c Character.
* @return {boolean} Whether the character is whitespace. * @return {boolean} Whether the character is whitespace.
* @private * @private
*/ */
Lexer.prototype.isWhiteSpace_ = function(c) { isWhiteSpace_(c) {
return c == ' ' || c == '\t' || c == '\r' || c == '\n'; return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}; }
/**
/**
* @return {string} Next string character. * @return {string} Next string character.
* @private * @private
*/ */
Lexer.prototype.nextChar_ = function() { nextChar_() {
return this.wkt.charAt(++this.index_); return this.wkt.charAt(++this.index_);
}; }
/**
/**
* Fetch and return the next token. * Fetch and return the next token.
* @return {!module:ol/format/WKT~Token} Next string token. * @return {!module:ol/format/WKT~Token} Next string token.
*/ */
Lexer.prototype.nextToken = function() { nextToken() {
const c = this.nextChar_(); const c = this.nextChar_();
const token = {position: this.index_, value: c}; const token = {position: this.index_, value: c};
@@ -163,14 +159,13 @@ Lexer.prototype.nextToken = function() {
} }
return token; return token;
}; }
/**
/**
* @return {number} Numeric token value. * @return {number} Numeric token value.
* @private * @private
*/ */
Lexer.prototype.readNumber_ = function() { readNumber_() {
let c; let c;
const index = this.index_; const index = this.index_;
let decimal = false; let decimal = false;
@@ -192,29 +187,29 @@ Lexer.prototype.readNumber_ = function() {
scientificNotation && (c == '-' || c == '+') scientificNotation && (c == '-' || c == '+')
); );
return parseFloat(this.wkt.substring(index, this.index_--)); return parseFloat(this.wkt.substring(index, this.index_--));
}; }
/**
/**
* @return {string} String token value. * @return {string} String token value.
* @private * @private
*/ */
Lexer.prototype.readText_ = function() { readText_() {
let c; let c;
const index = this.index_; const index = this.index_;
do { do {
c = this.nextChar_(); c = this.nextChar_();
} while (this.isAlpha_(c)); } while (this.isAlpha_(c));
return this.wkt.substring(index, this.index_--).toUpperCase(); return this.wkt.substring(index, this.index_--).toUpperCase();
}; }
}
/** /**
* Class to parse the tokens from the WKT string. * Class to parse the tokens from the WKT string.
* @param {module:ol/format/WKT~Lexer} lexer The lexer. * @param {module:ol/format/WKT~Lexer} lexer The lexer.
* @constructor * @constructor
*/ */
const Parser = function(lexer) { class Parser {
constructor(lexer) {
/** /**
* @type {module:ol/format/WKT~Lexer} * @type {module:ol/format/WKT~Lexer}
@@ -233,59 +228,55 @@ const Parser = function(lexer) {
* @private * @private
*/ */
this.layout_ = GeometryLayout.XY; this.layout_ = GeometryLayout.XY;
}; }
/**
/**
* Fetch the next token form the lexer and replace the active token. * Fetch the next token form the lexer and replace the active token.
* @private * @private
*/ */
Parser.prototype.consume_ = function() { consume_() {
this.token_ = this.lexer_.nextToken(); this.token_ = this.lexer_.nextToken();
}; }
/** /**
* Tests if the given type matches the type of the current token. * Tests if the given type matches the type of the current token.
* @param {module:ol/format/WKT~TokenType} type Token type. * @param {module:ol/format/WKT~TokenType} type Token type.
* @return {boolean} Whether the token matches the given type. * @return {boolean} Whether the token matches the given type.
*/ */
Parser.prototype.isTokenType = function(type) { isTokenType(type) {
const isMatch = this.token_.type == type; const isMatch = this.token_.type == type;
return isMatch; return isMatch;
}; }
/**
/**
* If the given type matches the current token, consume it. * If the given type matches the current token, consume it.
* @param {module:ol/format/WKT~TokenType} type Token type. * @param {module:ol/format/WKT~TokenType} type Token type.
* @return {boolean} Whether the token matches the given type. * @return {boolean} Whether the token matches the given type.
*/ */
Parser.prototype.match = function(type) { match(type) {
const isMatch = this.isTokenType(type); const isMatch = this.isTokenType(type);
if (isMatch) { if (isMatch) {
this.consume_(); this.consume_();
} }
return isMatch; return isMatch;
}; }
/**
/**
* Try to parse the tokens provided by the lexer. * Try to parse the tokens provided by the lexer.
* @return {module:ol/geom/Geometry} The geometry. * @return {module:ol/geom/Geometry} The geometry.
*/ */
Parser.prototype.parse = function() { parse() {
this.consume_(); this.consume_();
const geometry = this.parseGeometry_(); const geometry = this.parseGeometry_();
return geometry; return geometry;
}; }
/**
/**
* Try to parse the dimensional info. * Try to parse the dimensional info.
* @return {module:ol/geom/GeometryLayout} The layout. * @return {module:ol/geom/GeometryLayout} The layout.
* @private * @private
*/ */
Parser.prototype.parseGeometryLayout_ = function() { parseGeometryLayout_() {
let layout = GeometryLayout.XY; let layout = GeometryLayout.XY;
const dimToken = this.token_; const dimToken = this.token_;
if (this.isTokenType(TokenType.TEXT)) { if (this.isTokenType(TokenType.TEXT)) {
@@ -302,14 +293,13 @@ Parser.prototype.parseGeometryLayout_ = function() {
} }
} }
return layout; return layout;
}; }
/**
/**
* @return {!Array.<module:ol/geom/Geometry>} A collection of geometries. * @return {!Array.<module:ol/geom/Geometry>} A collection of geometries.
* @private * @private
*/ */
Parser.prototype.parseGeometryCollectionText_ = function() { parseGeometryCollectionText_() {
if (this.match(TokenType.LEFT_PAREN)) { if (this.match(TokenType.LEFT_PAREN)) {
const geometries = []; const geometries = [];
do { do {
@@ -322,14 +312,13 @@ Parser.prototype.parseGeometryCollectionText_ = function() {
return []; return [];
} }
throw new Error(this.formatErrorMessage_()); throw new Error(this.formatErrorMessage_());
}; }
/**
/**
* @return {Array.<number>} All values in a point. * @return {Array.<number>} All values in a point.
* @private * @private
*/ */
Parser.prototype.parsePointText_ = function() { parsePointText_() {
if (this.match(TokenType.LEFT_PAREN)) { if (this.match(TokenType.LEFT_PAREN)) {
const coordinates = this.parsePoint_(); const coordinates = this.parsePoint_();
if (this.match(TokenType.RIGHT_PAREN)) { if (this.match(TokenType.RIGHT_PAREN)) {
@@ -339,14 +328,13 @@ Parser.prototype.parsePointText_ = function() {
return null; return null;
} }
throw new Error(this.formatErrorMessage_()); throw new Error(this.formatErrorMessage_());
}; }
/**
/**
* @return {!Array.<!Array.<number>>} All points in a linestring. * @return {!Array.<!Array.<number>>} All points in a linestring.
* @private * @private
*/ */
Parser.prototype.parseLineStringText_ = function() { parseLineStringText_() {
if (this.match(TokenType.LEFT_PAREN)) { if (this.match(TokenType.LEFT_PAREN)) {
const coordinates = this.parsePointList_(); const coordinates = this.parsePointList_();
if (this.match(TokenType.RIGHT_PAREN)) { if (this.match(TokenType.RIGHT_PAREN)) {
@@ -356,14 +344,13 @@ Parser.prototype.parseLineStringText_ = function() {
return []; return [];
} }
throw new Error(this.formatErrorMessage_()); throw new Error(this.formatErrorMessage_());
}; }
/**
/**
* @return {!Array.<!Array.<number>>} All points in a polygon. * @return {!Array.<!Array.<number>>} All points in a polygon.
* @private * @private
*/ */
Parser.prototype.parsePolygonText_ = function() { parsePolygonText_() {
if (this.match(TokenType.LEFT_PAREN)) { if (this.match(TokenType.LEFT_PAREN)) {
const coordinates = this.parseLineStringTextList_(); const coordinates = this.parseLineStringTextList_();
if (this.match(TokenType.RIGHT_PAREN)) { if (this.match(TokenType.RIGHT_PAREN)) {
@@ -373,14 +360,13 @@ Parser.prototype.parsePolygonText_ = function() {
return []; return [];
} }
throw new Error(this.formatErrorMessage_()); throw new Error(this.formatErrorMessage_());
}; }
/**
/**
* @return {!Array.<!Array.<number>>} All points in a multipoint. * @return {!Array.<!Array.<number>>} All points in a multipoint.
* @private * @private
*/ */
Parser.prototype.parseMultiPointText_ = function() { parseMultiPointText_() {
if (this.match(TokenType.LEFT_PAREN)) { if (this.match(TokenType.LEFT_PAREN)) {
let coordinates; let coordinates;
if (this.token_.type == TokenType.LEFT_PAREN) { if (this.token_.type == TokenType.LEFT_PAREN) {
@@ -395,15 +381,14 @@ Parser.prototype.parseMultiPointText_ = function() {
return []; return [];
} }
throw new Error(this.formatErrorMessage_()); throw new Error(this.formatErrorMessage_());
}; }
/**
/**
* @return {!Array.<!Array.<number>>} All linestring points * @return {!Array.<!Array.<number>>} All linestring points
* in a multilinestring. * in a multilinestring.
* @private * @private
*/ */
Parser.prototype.parseMultiLineStringText_ = function() { parseMultiLineStringText_() {
if (this.match(TokenType.LEFT_PAREN)) { if (this.match(TokenType.LEFT_PAREN)) {
const coordinates = this.parseLineStringTextList_(); const coordinates = this.parseLineStringTextList_();
if (this.match(TokenType.RIGHT_PAREN)) { if (this.match(TokenType.RIGHT_PAREN)) {
@@ -413,14 +398,13 @@ Parser.prototype.parseMultiLineStringText_ = function() {
return []; return [];
} }
throw new Error(this.formatErrorMessage_()); throw new Error(this.formatErrorMessage_());
}; }
/**
/**
* @return {!Array.<!Array.<number>>} All polygon points in a multipolygon. * @return {!Array.<!Array.<number>>} All polygon points in a multipolygon.
* @private * @private
*/ */
Parser.prototype.parseMultiPolygonText_ = function() { parseMultiPolygonText_() {
if (this.match(TokenType.LEFT_PAREN)) { if (this.match(TokenType.LEFT_PAREN)) {
const coordinates = this.parsePolygonTextList_(); const coordinates = this.parsePolygonTextList_();
if (this.match(TokenType.RIGHT_PAREN)) { if (this.match(TokenType.RIGHT_PAREN)) {
@@ -430,14 +414,13 @@ Parser.prototype.parseMultiPolygonText_ = function() {
return []; return [];
} }
throw new Error(this.formatErrorMessage_()); throw new Error(this.formatErrorMessage_());
}; }
/**
/**
* @return {!Array.<number>} A point. * @return {!Array.<number>} A point.
* @private * @private
*/ */
Parser.prototype.parsePoint_ = function() { parsePoint_() {
const coordinates = []; const coordinates = [];
const dimensions = this.layout_.length; const dimensions = this.layout_.length;
for (let i = 0; i < dimensions; ++i) { for (let i = 0; i < dimensions; ++i) {
@@ -452,85 +435,111 @@ Parser.prototype.parsePoint_ = function() {
return coordinates; return coordinates;
} }
throw new Error(this.formatErrorMessage_()); throw new Error(this.formatErrorMessage_());
}; }
/**
/**
* @return {!Array.<!Array.<number>>} An array of points. * @return {!Array.<!Array.<number>>} An array of points.
* @private * @private
*/ */
Parser.prototype.parsePointList_ = function() { parsePointList_() {
const coordinates = [this.parsePoint_()]; const coordinates = [this.parsePoint_()];
while (this.match(TokenType.COMMA)) { while (this.match(TokenType.COMMA)) {
coordinates.push(this.parsePoint_()); coordinates.push(this.parsePoint_());
} }
return coordinates; return coordinates;
}; }
/**
/**
* @return {!Array.<!Array.<number>>} An array of points. * @return {!Array.<!Array.<number>>} An array of points.
* @private * @private
*/ */
Parser.prototype.parsePointTextList_ = function() { parsePointTextList_() {
const coordinates = [this.parsePointText_()]; const coordinates = [this.parsePointText_()];
while (this.match(TokenType.COMMA)) { while (this.match(TokenType.COMMA)) {
coordinates.push(this.parsePointText_()); coordinates.push(this.parsePointText_());
} }
return coordinates; return coordinates;
}; }
/**
/**
* @return {!Array.<!Array.<number>>} An array of points. * @return {!Array.<!Array.<number>>} An array of points.
* @private * @private
*/ */
Parser.prototype.parseLineStringTextList_ = function() { parseLineStringTextList_() {
const coordinates = [this.parseLineStringText_()]; const coordinates = [this.parseLineStringText_()];
while (this.match(TokenType.COMMA)) { while (this.match(TokenType.COMMA)) {
coordinates.push(this.parseLineStringText_()); coordinates.push(this.parseLineStringText_());
} }
return coordinates; return coordinates;
}; }
/**
/**
* @return {!Array.<!Array.<number>>} An array of points. * @return {!Array.<!Array.<number>>} An array of points.
* @private * @private
*/ */
Parser.prototype.parsePolygonTextList_ = function() { parsePolygonTextList_() {
const coordinates = [this.parsePolygonText_()]; const coordinates = [this.parsePolygonText_()];
while (this.match(TokenType.COMMA)) { while (this.match(TokenType.COMMA)) {
coordinates.push(this.parsePolygonText_()); coordinates.push(this.parsePolygonText_());
} }
return coordinates; return coordinates;
}; }
/**
/**
* @return {boolean} Whether the token implies an empty geometry. * @return {boolean} Whether the token implies an empty geometry.
* @private * @private
*/ */
Parser.prototype.isEmptyGeometry_ = function() { isEmptyGeometry_() {
const isEmpty = this.isTokenType(TokenType.TEXT) && const isEmpty = this.isTokenType(TokenType.TEXT) &&
this.token_.value == EMPTY; this.token_.value == EMPTY;
if (isEmpty) { if (isEmpty) {
this.consume_(); this.consume_();
} }
return isEmpty; return isEmpty;
}; }
/**
/**
* Create an error message for an unexpected token error. * Create an error message for an unexpected token error.
* @return {string} Error message. * @return {string} Error message.
* @private * @private
*/ */
Parser.prototype.formatErrorMessage_ = function() { formatErrorMessage_() {
return 'Unexpected `' + this.token_.value + '` at position ' + return 'Unexpected `' + this.token_.value + '` at position ' +
this.token_.position + ' in `' + this.lexer_.wkt + '`'; this.token_.position + ' in `' + this.lexer_.wkt + '`';
}; }
/**
* @return {!module:ol/geom/Geometry} The geometry.
* @private
*/
parseGeometry_() {
const token = this.token_;
if (this.match(TokenType.TEXT)) {
const geomType = token.value;
this.layout_ = this.parseGeometryLayout_();
if (geomType == GeometryType.GEOMETRY_COLLECTION.toUpperCase()) {
const geometries = this.parseGeometryCollectionText_();
return new GeometryCollection(geometries);
} else {
const parser = GeometryParser[geomType];
const ctor = GeometryConstructor[geomType];
if (!parser || !ctor) {
throw new Error('Invalid geometry type: ' + geomType);
}
let coordinates = parser.call(this);
if (!coordinates) {
if (ctor === GeometryConstructor[GeometryType.POINT]) {
coordinates = [NaN, NaN];
} else {
coordinates = [];
}
}
return new ctor(coordinates, this.layout_);
}
}
throw new Error(this.formatErrorMessage_());
}
}
/** /**
* @classdesc * @classdesc
@@ -542,7 +551,8 @@ Parser.prototype.formatErrorMessage_ = function() {
* @param {module:ol/format/WKT~Options=} opt_options Options. * @param {module:ol/format/WKT~Options=} opt_options Options.
* @api * @api
*/ */
const WKT = function(opt_options) { class WKT {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -556,7 +566,104 @@ const WKT = function(opt_options) {
this.splitCollection_ = options.splitCollection !== undefined ? this.splitCollection_ = options.splitCollection !== undefined ?
options.splitCollection : false; options.splitCollection : false;
}; }
/**
* Parse a WKT string.
* @param {string} wkt WKT string.
* @return {module:ol/geom/Geometry|undefined}
* The geometry created.
* @private
*/
parse_(wkt) {
const lexer = new Lexer(wkt);
const parser = new Parser(lexer);
return parser.parse();
}
/**
* @inheritDoc
*/
readFeatureFromText(text, opt_options) {
const geom = this.readGeometryFromText(text, opt_options);
if (geom) {
const feature = new Feature();
feature.setGeometry(geom);
return feature;
}
return null;
}
/**
* @inheritDoc
*/
readFeaturesFromText(text, opt_options) {
let geometries = [];
const geometry = this.readGeometryFromText(text, opt_options);
if (this.splitCollection_ &&
geometry.getType() == GeometryType.GEOMETRY_COLLECTION) {
geometries = (/** @type {module:ol/geom/GeometryCollection} */ (geometry))
.getGeometriesArray();
} else {
geometries = [geometry];
}
const features = [];
for (let i = 0, ii = geometries.length; i < ii; ++i) {
const feature = new Feature();
feature.setGeometry(geometries[i]);
features.push(feature);
}
return features;
}
/**
* @inheritDoc
*/
readGeometryFromText(text, opt_options) {
const geometry = this.parse_(text);
if (geometry) {
return (
/** @type {module:ol/geom/Geometry} */ (transformWithOptions(geometry, false, opt_options))
);
} else {
return null;
}
}
/**
* @inheritDoc
*/
writeFeatureText(feature, opt_options) {
const geometry = feature.getGeometry();
if (geometry) {
return this.writeGeometryText(geometry, opt_options);
}
return '';
}
/**
* @inheritDoc
*/
writeFeaturesText(features, opt_options) {
if (features.length == 1) {
return this.writeFeatureText(features[0], opt_options);
}
const geometries = [];
for (let i = 0, ii = features.length; i < ii; ++i) {
geometries.push(features[i].getGeometry());
}
const collection = new GeometryCollection(geometries);
return this.writeGeometryText(collection, opt_options);
}
/**
* @inheritDoc
*/
writeGeometryText(geometry, opt_options) {
return encode(/** @type {module:ol/geom/Geometry} */ (
transformWithOptions(geometry, true, opt_options)));
}
}
inherits(WKT, TextFeature); inherits(WKT, TextFeature);
@@ -712,20 +819,6 @@ function encode(geom) {
} }
/**
* Parse a WKT string.
* @param {string} wkt WKT string.
* @return {module:ol/geom/Geometry|undefined}
* The geometry created.
* @private
*/
WKT.prototype.parse_ = function(wkt) {
const lexer = new Lexer(wkt);
const parser = new Parser(lexer);
return parser.parse();
};
/** /**
* Read a feature from a WKT source. * Read a feature from a WKT source.
* *
@@ -738,20 +831,6 @@ WKT.prototype.parse_ = function(wkt) {
WKT.prototype.readFeature; WKT.prototype.readFeature;
/**
* @inheritDoc
*/
WKT.prototype.readFeatureFromText = function(text, opt_options) {
const geom = this.readGeometryFromText(text, opt_options);
if (geom) {
const feature = new Feature();
feature.setGeometry(geom);
return feature;
}
return null;
};
/** /**
* Read all features from a WKT source. * Read all features from a WKT source.
* *
@@ -764,29 +843,6 @@ WKT.prototype.readFeatureFromText = function(text, opt_options) {
WKT.prototype.readFeatures; WKT.prototype.readFeatures;
/**
* @inheritDoc
*/
WKT.prototype.readFeaturesFromText = function(text, opt_options) {
let geometries = [];
const geometry = this.readGeometryFromText(text, opt_options);
if (this.splitCollection_ &&
geometry.getType() == GeometryType.GEOMETRY_COLLECTION) {
geometries = (/** @type {module:ol/geom/GeometryCollection} */ (geometry))
.getGeometriesArray();
} else {
geometries = [geometry];
}
const features = [];
for (let i = 0, ii = geometries.length; i < ii; ++i) {
const feature = new Feature();
feature.setGeometry(geometries[i]);
features.push(feature);
}
return features;
};
/** /**
* Read a single geometry from a WKT source. * Read a single geometry from a WKT source.
* *
@@ -799,21 +855,6 @@ WKT.prototype.readFeaturesFromText = function(text, opt_options) {
WKT.prototype.readGeometry; WKT.prototype.readGeometry;
/**
* @inheritDoc
*/
WKT.prototype.readGeometryFromText = function(text, opt_options) {
const geometry = this.parse_(text);
if (geometry) {
return (
/** @type {module:ol/geom/Geometry} */ (transformWithOptions(geometry, false, opt_options))
);
} else {
return null;
}
};
/** /**
* @enum {function (new:module:ol/geom/Geometry, Array, module:ol/geom/GeometryLayout)} * @enum {function (new:module:ol/geom/Geometry, Array, module:ol/geom/GeometryLayout)}
*/ */
@@ -840,39 +881,6 @@ const GeometryParser = {
}; };
/**
* @return {!module:ol/geom/Geometry} The geometry.
* @private
*/
Parser.prototype.parseGeometry_ = function() {
const token = this.token_;
if (this.match(TokenType.TEXT)) {
const geomType = token.value;
this.layout_ = this.parseGeometryLayout_();
if (geomType == GeometryType.GEOMETRY_COLLECTION.toUpperCase()) {
const geometries = this.parseGeometryCollectionText_();
return new GeometryCollection(geometries);
} else {
const parser = GeometryParser[geomType];
const ctor = GeometryConstructor[geomType];
if (!parser || !ctor) {
throw new Error('Invalid geometry type: ' + geomType);
}
let coordinates = parser.call(this);
if (!coordinates) {
if (ctor === GeometryConstructor[GeometryType.POINT]) {
coordinates = [NaN, NaN];
} else {
coordinates = [];
}
}
return new ctor(coordinates, this.layout_);
}
}
throw new Error(this.formatErrorMessage_());
};
/** /**
* Encode a feature as a WKT string. * Encode a feature as a WKT string.
* *
@@ -885,18 +893,6 @@ Parser.prototype.parseGeometry_ = function() {
WKT.prototype.writeFeature; WKT.prototype.writeFeature;
/**
* @inheritDoc
*/
WKT.prototype.writeFeatureText = function(feature, opt_options) {
const geometry = feature.getGeometry();
if (geometry) {
return this.writeGeometryText(geometry, opt_options);
}
return '';
};
/** /**
* Encode an array of features as a WKT string. * Encode an array of features as a WKT string.
* *
@@ -909,22 +905,6 @@ WKT.prototype.writeFeatureText = function(feature, opt_options) {
WKT.prototype.writeFeatures; WKT.prototype.writeFeatures;
/**
* @inheritDoc
*/
WKT.prototype.writeFeaturesText = function(features, opt_options) {
if (features.length == 1) {
return this.writeFeatureText(features[0], opt_options);
}
const geometries = [];
for (let i = 0, ii = features.length; i < ii; ++i) {
geometries.push(features[i].getGeometry());
}
const collection = new GeometryCollection(geometries);
return this.writeGeometryText(collection, opt_options);
};
/** /**
* Write a single geometry as a WKT string. * Write a single geometry as a WKT string.
* *
@@ -937,13 +917,4 @@ WKT.prototype.writeFeaturesText = function(features, opt_options) {
WKT.prototype.writeGeometry; WKT.prototype.writeGeometry;
/**
* @inheritDoc
*/
WKT.prototype.writeGeometryText = function(geometry, opt_options) {
return encode(/** @type {module:ol/geom/Geometry} */ (
transformWithOptions(geometry, true, opt_options)));
};
export default WKT; export default WKT;
+27 -27
View File
@@ -17,7 +17,8 @@ import {makeArrayPusher, makeObjectPropertyPusher, makeObjectPropertySetter,
* @extends {module:ol/format/XML} * @extends {module:ol/format/XML}
* @api * @api
*/ */
const WMSCapabilities = function() { class WMSCapabilities {
constructor() {
XML.call(this); XML.call(this);
@@ -25,7 +26,31 @@ const WMSCapabilities = function() {
* @type {string|undefined} * @type {string|undefined}
*/ */
this.version = undefined; this.version = undefined;
}; }
/**
* @inheritDoc
*/
readFromDocument(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
return this.readFromNode(n);
}
}
return null;
}
/**
* @inheritDoc
*/
readFromNode(node) {
this.version = node.getAttribute('version').trim();
const wmsCapabilityObject = pushParseAndPop({
'version': this.version
}, PARSERS, node, []);
return wmsCapabilityObject ? wmsCapabilityObject : null;
}
}
inherits(WMSCapabilities, XML); inherits(WMSCapabilities, XML);
@@ -277,31 +302,6 @@ const KEYWORDLIST_PARSERS = makeStructureNS(
WMSCapabilities.prototype.read; WMSCapabilities.prototype.read;
/**
* @inheritDoc
*/
WMSCapabilities.prototype.readFromDocument = function(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
return this.readFromNode(n);
}
}
return null;
};
/**
* @inheritDoc
*/
WMSCapabilities.prototype.readFromNode = function(node) {
this.version = node.getAttribute('version').trim();
const wmsCapabilityObject = pushParseAndPop({
'version': this.version
}, PARSERS, node, []);
return wmsCapabilityObject ? wmsCapabilityObject : null;
};
/** /**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
+58 -61
View File
@@ -25,7 +25,8 @@ import {makeArrayPusher, makeStructureNS, pushParseAndPop} from '../xml.js';
* @param {module:ol/format/WMSGetFeatureInfo~Options=} opt_options Options. * @param {module:ol/format/WMSGetFeatureInfo~Options=} opt_options Options.
* @api * @api
*/ */
const WMSGetFeatureInfo = function(opt_options) { class WMSGetFeatureInfo {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -50,48 +51,29 @@ const WMSGetFeatureInfo = function(opt_options) {
this.layers_ = options.layers ? options.layers : null; this.layers_ = options.layers ? options.layers : null;
XMLFeature.call(this); XMLFeature.call(this);
}; }
inherits(WMSGetFeatureInfo, XMLFeature); /**
/**
* @const
* @type {string}
*/
const featureIdentifier = '_feature';
/**
* @const
* @type {string}
*/
const layerIdentifier = '_layer';
/**
* @return {Array.<string>} layers * @return {Array.<string>} layers
*/ */
WMSGetFeatureInfo.prototype.getLayers = function() { getLayers() {
return this.layers_; return this.layers_;
}; }
/**
/**
* @param {Array.<string>} layers Layers to parse. * @param {Array.<string>} layers Layers to parse.
*/ */
WMSGetFeatureInfo.prototype.setLayers = function(layers) { setLayers(layers) {
this.layers_ = layers; this.layers_ = layers;
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
* @return {Array.<module:ol/Feature>} Features. * @return {Array.<module:ol/Feature>} Features.
* @private * @private
*/ */
WMSGetFeatureInfo.prototype.readFeatures_ = function(node, objectStack) { readFeatures_(node, objectStack) {
node.setAttribute('namespaceURI', this.featureNS_); node.setAttribute('namespaceURI', this.featureNS_);
const localName = node.localName; const localName = node.localName;
/** @type {Array.<module:ol/Feature>} */ /** @type {Array.<module:ol/Feature>} */
@@ -142,7 +124,53 @@ WMSGetFeatureInfo.prototype.readFeatures_ = function(node, objectStack) {
} }
} }
return features; return features;
}; }
/**
* @inheritDoc
*/
readFeaturesFromNode(node, opt_options) {
const options = {};
if (opt_options) {
assign(options, this.getReadOptions(node, opt_options));
}
return this.readFeatures_(node, [options]);
}
/**
* Not implemented.
* @inheritDoc
*/
writeFeatureNode(feature, opt_options) {}
/**
* Not implemented.
* @inheritDoc
*/
writeFeaturesNode(features, opt_options) {}
/**
* Not implemented.
* @inheritDoc
*/
writeGeometryNode(geometry, opt_options) {}
}
inherits(WMSGetFeatureInfo, XMLFeature);
/**
* @const
* @type {string}
*/
const featureIdentifier = '_feature';
/**
* @const
* @type {string}
*/
const layerIdentifier = '_layer';
/** /**
@@ -157,35 +185,4 @@ WMSGetFeatureInfo.prototype.readFeatures_ = function(node, objectStack) {
WMSGetFeatureInfo.prototype.readFeatures; WMSGetFeatureInfo.prototype.readFeatures;
/**
* @inheritDoc
*/
WMSGetFeatureInfo.prototype.readFeaturesFromNode = function(node, opt_options) {
const options = {};
if (opt_options) {
assign(options, this.getReadOptions(node, opt_options));
}
return this.readFeatures_(node, [options]);
};
/**
* Not implemented.
* @inheritDoc
*/
WMSGetFeatureInfo.prototype.writeFeatureNode = function(feature, opt_options) {};
/**
* Not implemented.
* @inheritDoc
*/
WMSGetFeatureInfo.prototype.writeFeaturesNode = function(features, opt_options) {};
/**
* Not implemented.
* @inheritDoc
*/
WMSGetFeatureInfo.prototype.writeGeometryNode = function(geometry, opt_options) {};
export default WMSGetFeatureInfo; export default WMSGetFeatureInfo;
+30 -30
View File
@@ -18,7 +18,8 @@ import {pushParseAndPop, makeStructureNS,
* @extends {module:ol/format/XML} * @extends {module:ol/format/XML}
* @api * @api
*/ */
const WMTSCapabilities = function() { class WMTSCapabilities {
constructor() {
XML.call(this); XML.call(this);
/** /**
@@ -26,7 +27,34 @@ const WMTSCapabilities = function() {
* @private * @private
*/ */
this.owsParser_ = new OWS(); this.owsParser_ = new OWS();
}; }
/**
* @inheritDoc
*/
readFromDocument(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
return this.readFromNode(n);
}
}
return null;
}
/**
* @inheritDoc
*/
readFromNode(node) {
const version = node.getAttribute('version').trim();
let WMTSCapabilityObject = this.owsParser_.readFromNode(node);
if (!WMTSCapabilityObject) {
return null;
}
WMTSCapabilityObject['version'] = version;
WMTSCapabilityObject = pushParseAndPop(WMTSCapabilityObject, PARSERS, node, []);
return WMTSCapabilityObject ? WMTSCapabilityObject : null;
}
}
inherits(WMTSCapabilities, XML); inherits(WMTSCapabilities, XML);
@@ -204,34 +232,6 @@ const TM_PARSERS = makeStructureNS(
WMTSCapabilities.prototype.read; WMTSCapabilities.prototype.read;
/**
* @inheritDoc
*/
WMTSCapabilities.prototype.readFromDocument = function(doc) {
for (let n = doc.firstChild; n; n = n.nextSibling) {
if (n.nodeType == Node.ELEMENT_NODE) {
return this.readFromNode(n);
}
}
return null;
};
/**
* @inheritDoc
*/
WMTSCapabilities.prototype.readFromNode = function(node) {
const version = node.getAttribute('version').trim();
let WMTSCapabilityObject = this.owsParser_.readFromNode(node);
if (!WMTSCapabilityObject) {
return null;
}
WMTSCapabilityObject['version'] = version;
WMTSCapabilityObject = pushParseAndPop(WMTSCapabilityObject, PARSERS, node, []);
return WMTSCapabilityObject ? WMTSCapabilityObject : null;
};
/** /**
* @param {Node} node Node. * @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack. * @param {Array.<*>} objectStack Object stack.
+10 -13
View File
@@ -11,15 +11,12 @@ import {isDocument, isNode, parse} from '../xml.js';
* @abstract * @abstract
* @struct * @struct
*/ */
const XML = function() { class XML {
}; /**
/**
* @param {Document|Node|string} source Source. * @param {Document|Node|string} source Source.
* @return {Object} The parsed result. * @return {Object} The parsed result.
*/ */
XML.prototype.read = function(source) { read(source) {
if (isDocument(source)) { if (isDocument(source)) {
return this.readFromDocument(/** @type {Document} */ (source)); return this.readFromDocument(/** @type {Document} */ (source));
} else if (isNode(source)) { } else if (isNode(source)) {
@@ -30,21 +27,21 @@ XML.prototype.read = function(source) {
} else { } else {
return null; return null;
} }
}; }
/**
/**
* @abstract * @abstract
* @param {Document} doc Document. * @param {Document} doc Document.
* @return {Object} Object * @return {Object} Object
*/ */
XML.prototype.readFromDocument = function(doc) {}; readFromDocument(doc) {}
/**
/**
* @abstract * @abstract
* @param {Node} node Node. * @param {Node} node Node.
* @return {Object} Object * @return {Object} Object
*/ */
XML.prototype.readFromNode = function(node) {}; readFromNode(node) {}
}
export default XML; export default XML;
+64 -79
View File
@@ -17,7 +17,8 @@ import {isDocument, isNode, parse} from '../xml.js';
* @abstract * @abstract
* @extends {module:ol/format/Feature} * @extends {module:ol/format/Feature}
*/ */
const XMLFeature = function() { class XMLFeature {
constructor() {
/** /**
* @type {XMLSerializer} * @type {XMLSerializer}
@@ -26,23 +27,19 @@ const XMLFeature = function() {
this.xmlSerializer_ = new XMLSerializer(); this.xmlSerializer_ = new XMLSerializer();
FeatureFormat.call(this); FeatureFormat.call(this);
}; }
inherits(XMLFeature, FeatureFormat); /**
/**
* @inheritDoc * @inheritDoc
*/ */
XMLFeature.prototype.getType = function() { getType() {
return FormatType.XML; return FormatType.XML;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
XMLFeature.prototype.readFeature = function(source, opt_options) { readFeature(source, opt_options) {
if (isDocument(source)) { if (isDocument(source)) {
return this.readFeatureFromDocument(/** @type {Document} */ (source), opt_options); return this.readFeatureFromDocument(/** @type {Document} */ (source), opt_options);
} else if (isNode(source)) { } else if (isNode(source)) {
@@ -53,38 +50,35 @@ XMLFeature.prototype.readFeature = function(source, opt_options) {
} else { } else {
return null; return null;
} }
}; }
/**
/**
* @param {Document} doc Document. * @param {Document} doc Document.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options. * @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
* @return {module:ol/Feature} Feature. * @return {module:ol/Feature} Feature.
*/ */
XMLFeature.prototype.readFeatureFromDocument = function(doc, opt_options) { readFeatureFromDocument(doc, opt_options) {
const features = this.readFeaturesFromDocument(doc, opt_options); const features = this.readFeaturesFromDocument(doc, opt_options);
if (features.length > 0) { if (features.length > 0) {
return features[0]; return features[0];
} else { } else {
return null; return null;
} }
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options. * @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
* @return {module:ol/Feature} Feature. * @return {module:ol/Feature} Feature.
*/ */
XMLFeature.prototype.readFeatureFromNode = function(node, opt_options) { readFeatureFromNode(node, opt_options) {
return null; // not implemented return null; // not implemented
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
XMLFeature.prototype.readFeatures = function(source, opt_options) { readFeatures(source, opt_options) {
if (isDocument(source)) { if (isDocument(source)) {
return this.readFeaturesFromDocument( return this.readFeaturesFromDocument(
/** @type {Document} */ (source), opt_options); /** @type {Document} */ (source), opt_options);
@@ -96,16 +90,15 @@ XMLFeature.prototype.readFeatures = function(source, opt_options) {
} else { } else {
return []; return [];
} }
}; }
/**
/**
* @param {Document} doc Document. * @param {Document} doc Document.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options. * @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
* @protected * @protected
* @return {Array.<module:ol/Feature>} Features. * @return {Array.<module:ol/Feature>} Features.
*/ */
XMLFeature.prototype.readFeaturesFromDocument = function(doc, opt_options) { readFeaturesFromDocument(doc, opt_options) {
/** @type {Array.<module:ol/Feature>} */ /** @type {Array.<module:ol/Feature>} */
const features = []; const features = [];
for (let n = doc.firstChild; n; n = n.nextSibling) { for (let n = doc.firstChild; n; n = n.nextSibling) {
@@ -114,23 +107,21 @@ XMLFeature.prototype.readFeaturesFromDocument = function(doc, opt_options) {
} }
} }
return features; return features;
}; }
/**
/**
* @abstract * @abstract
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options. * @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
* @protected * @protected
* @return {Array.<module:ol/Feature>} Features. * @return {Array.<module:ol/Feature>} Features.
*/ */
XMLFeature.prototype.readFeaturesFromNode = function(node, opt_options) {}; readFeaturesFromNode(node, opt_options) {}
/**
/**
* @inheritDoc * @inheritDoc
*/ */
XMLFeature.prototype.readGeometry = function(source, opt_options) { readGeometry(source, opt_options) {
if (isDocument(source)) { if (isDocument(source)) {
return this.readGeometryFromDocument( return this.readGeometryFromDocument(
/** @type {Document} */ (source), opt_options); /** @type {Document} */ (source), opt_options);
@@ -142,35 +133,32 @@ XMLFeature.prototype.readGeometry = function(source, opt_options) {
} else { } else {
return null; return null;
} }
}; }
/**
/**
* @param {Document} doc Document. * @param {Document} doc Document.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options. * @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
* @protected * @protected
* @return {module:ol/geom/Geometry} Geometry. * @return {module:ol/geom/Geometry} Geometry.
*/ */
XMLFeature.prototype.readGeometryFromDocument = function(doc, opt_options) { readGeometryFromDocument(doc, opt_options) {
return null; // not implemented return null; // not implemented
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @param {module:ol/format/Feature~ReadOptions=} opt_options Options. * @param {module:ol/format/Feature~ReadOptions=} opt_options Options.
* @protected * @protected
* @return {module:ol/geom/Geometry} Geometry. * @return {module:ol/geom/Geometry} Geometry.
*/ */
XMLFeature.prototype.readGeometryFromNode = function(node, opt_options) { readGeometryFromNode(node, opt_options) {
return null; // not implemented return null; // not implemented
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
XMLFeature.prototype.readProjection = function(source) { readProjection(source) {
if (isDocument(source)) { if (isDocument(source)) {
return this.readProjectionFromDocument(/** @type {Document} */ (source)); return this.readProjectionFromDocument(/** @type {Document} */ (source));
} else if (isNode(source)) { } else if (isNode(source)) {
@@ -181,83 +169,80 @@ XMLFeature.prototype.readProjection = function(source) {
} else { } else {
return null; return null;
} }
}; }
/**
/**
* @param {Document} doc Document. * @param {Document} doc Document.
* @protected * @protected
* @return {module:ol/proj/Projection} Projection. * @return {module:ol/proj/Projection} Projection.
*/ */
XMLFeature.prototype.readProjectionFromDocument = function(doc) { readProjectionFromDocument(doc) {
return this.dataProjection; return this.dataProjection;
}; }
/**
/**
* @param {Node} node Node. * @param {Node} node Node.
* @protected * @protected
* @return {module:ol/proj/Projection} Projection. * @return {module:ol/proj/Projection} Projection.
*/ */
XMLFeature.prototype.readProjectionFromNode = function(node) { readProjectionFromNode(node) {
return this.dataProjection; return this.dataProjection;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
XMLFeature.prototype.writeFeature = function(feature, opt_options) { writeFeature(feature, opt_options) {
const node = this.writeFeatureNode(feature, opt_options); const node = this.writeFeatureNode(feature, opt_options);
return this.xmlSerializer_.serializeToString(node); return this.xmlSerializer_.serializeToString(node);
}; }
/**
/**
* @param {module:ol/Feature} feature Feature. * @param {module:ol/Feature} feature Feature.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options. * @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
* @protected * @protected
* @return {Node} Node. * @return {Node} Node.
*/ */
XMLFeature.prototype.writeFeatureNode = function(feature, opt_options) { writeFeatureNode(feature, opt_options) {
return null; // not implemented return null; // not implemented
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
XMLFeature.prototype.writeFeatures = function(features, opt_options) { writeFeatures(features, opt_options) {
const node = this.writeFeaturesNode(features, opt_options); const node = this.writeFeaturesNode(features, opt_options);
return this.xmlSerializer_.serializeToString(node); return this.xmlSerializer_.serializeToString(node);
}; }
/**
/**
* @param {Array.<module:ol/Feature>} features Features. * @param {Array.<module:ol/Feature>} features Features.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options. * @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
* @return {Node} Node. * @return {Node} Node.
*/ */
XMLFeature.prototype.writeFeaturesNode = function(features, opt_options) { writeFeaturesNode(features, opt_options) {
return null; // not implemented return null; // not implemented
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
XMLFeature.prototype.writeGeometry = function(geometry, opt_options) { writeGeometry(geometry, opt_options) {
const node = this.writeGeometryNode(geometry, opt_options); const node = this.writeGeometryNode(geometry, opt_options);
return this.xmlSerializer_.serializeToString(node); return this.xmlSerializer_.serializeToString(node);
}; }
/**
/**
* @param {module:ol/geom/Geometry} geometry Geometry. * @param {module:ol/geom/Geometry} geometry Geometry.
* @param {module:ol/format/Feature~WriteOptions=} opt_options Options. * @param {module:ol/format/Feature~WriteOptions=} opt_options Options.
* @return {Node} Node. * @return {Node} Node.
*/ */
XMLFeature.prototype.writeGeometryNode = function(geometry, opt_options) { writeGeometryNode(geometry, opt_options) {
return null; // not implemented return null; // not implemented
}; }
}
inherits(XMLFeature, FeatureFormat);
export default XMLFeature; export default XMLFeature;
+7 -5
View File
@@ -13,21 +13,23 @@
* @param {!string} tagName The XML tag name for this filter. * @param {!string} tagName The XML tag name for this filter.
* @struct * @struct
*/ */
const Filter = function(tagName) { class Filter {
constructor(tagName) {
/** /**
* @private * @private
* @type {!string} * @type {!string}
*/ */
this.tagName_ = tagName; this.tagName_ = tagName;
}; }
/** /**
* The XML tag name for a filter. * The XML tag name for a filter.
* @returns {!string} Name. * @returns {!string} Name.
*/ */
Filter.prototype.getTagName = function() { getTagName() {
return this.tagName_; return this.tagName_;
}; }
}
export default Filter; export default Filter;
+46 -58
View File
@@ -20,7 +20,8 @@ import {deflateCoordinate} from '../geom/flat/deflate.js';
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @api * @api
*/ */
const Circle = function(center, opt_radius, opt_layout) { class Circle {
constructor(center, opt_radius, opt_layout) {
SimpleGeometry.call(this); SimpleGeometry.call(this);
if (opt_layout !== undefined && opt_radius === undefined) { if (opt_layout !== undefined && opt_radius === undefined) {
this.setFlatCoordinates(opt_layout, center); this.setFlatCoordinates(opt_layout, center);
@@ -28,26 +29,22 @@ const Circle = function(center, opt_radius, opt_layout) {
const radius = opt_radius ? opt_radius : 0; const radius = opt_radius ? opt_radius : 0;
this.setCenterAndRadius(center, radius, opt_layout); this.setCenterAndRadius(center, radius, opt_layout);
} }
}; }
inherits(Circle, SimpleGeometry); /**
/**
* Make a complete copy of the geometry. * Make a complete copy of the geometry.
* @return {!module:ol/geom/Circle} Clone. * @return {!module:ol/geom/Circle} Clone.
* @override * @override
* @api * @api
*/ */
Circle.prototype.clone = function() { clone() {
return new Circle(this.flatCoordinates.slice(), undefined, this.layout); return new Circle(this.flatCoordinates.slice(), undefined, this.layout);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Circle.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) { closestPointXY(x, y, closestPoint, minSquaredDistance) {
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
const dx = x - flatCoordinates[0]; const dx = x - flatCoordinates[0];
const dy = y - flatCoordinates[1]; const dy = y - flatCoordinates[1];
@@ -70,78 +67,71 @@ Circle.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistanc
} else { } else {
return minSquaredDistance; return minSquaredDistance;
} }
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Circle.prototype.containsXY = function(x, y) { containsXY(x, y) {
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
const dx = x - flatCoordinates[0]; const dx = x - flatCoordinates[0];
const dy = y - flatCoordinates[1]; const dy = y - flatCoordinates[1];
return dx * dx + dy * dy <= this.getRadiusSquared_(); return dx * dx + dy * dy <= this.getRadiusSquared_();
}; }
/**
/**
* Return the center of the circle as {@link module:ol/coordinate~Coordinate coordinate}. * Return the center of the circle as {@link module:ol/coordinate~Coordinate coordinate}.
* @return {module:ol/coordinate~Coordinate} Center. * @return {module:ol/coordinate~Coordinate} Center.
* @api * @api
*/ */
Circle.prototype.getCenter = function() { getCenter() {
return this.flatCoordinates.slice(0, this.stride); return this.flatCoordinates.slice(0, this.stride);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Circle.prototype.computeExtent = function(extent) { computeExtent(extent) {
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
const radius = flatCoordinates[this.stride] - flatCoordinates[0]; const radius = flatCoordinates[this.stride] - flatCoordinates[0];
return createOrUpdate( return createOrUpdate(
flatCoordinates[0] - radius, flatCoordinates[1] - radius, flatCoordinates[0] - radius, flatCoordinates[1] - radius,
flatCoordinates[0] + radius, flatCoordinates[1] + radius, flatCoordinates[0] + radius, flatCoordinates[1] + radius,
extent); extent);
}; }
/**
/**
* Return the radius of the circle. * Return the radius of the circle.
* @return {number} Radius. * @return {number} Radius.
* @api * @api
*/ */
Circle.prototype.getRadius = function() { getRadius() {
return Math.sqrt(this.getRadiusSquared_()); return Math.sqrt(this.getRadiusSquared_());
}; }
/**
/**
* @private * @private
* @return {number} Radius squared. * @return {number} Radius squared.
*/ */
Circle.prototype.getRadiusSquared_ = function() { getRadiusSquared_() {
const dx = this.flatCoordinates[this.stride] - this.flatCoordinates[0]; const dx = this.flatCoordinates[this.stride] - this.flatCoordinates[0];
const dy = this.flatCoordinates[this.stride + 1] - this.flatCoordinates[1]; const dy = this.flatCoordinates[this.stride + 1] - this.flatCoordinates[1];
return dx * dx + dy * dy; return dx * dx + dy * dy;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
Circle.prototype.getType = function() { getType() {
return GeometryType.CIRCLE; return GeometryType.CIRCLE;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
Circle.prototype.intersectsExtent = function(extent) { intersectsExtent(extent) {
const circleExtent = this.getExtent(); const circleExtent = this.getExtent();
if (intersects(extent, circleExtent)) { if (intersects(extent, circleExtent)) {
const center = this.getCenter(); const center = this.getCenter();
@@ -157,15 +147,14 @@ Circle.prototype.intersectsExtent = function(extent) {
} }
return false; return false;
}; }
/**
/**
* Set the center of the circle as {@link module:ol/coordinate~Coordinate coordinate}. * Set the center of the circle as {@link module:ol/coordinate~Coordinate coordinate}.
* @param {module:ol/coordinate~Coordinate} center Center. * @param {module:ol/coordinate~Coordinate} center Center.
* @api * @api
*/ */
Circle.prototype.setCenter = function(center) { setCenter(center) {
const stride = this.stride; const stride = this.stride;
const radius = this.flatCoordinates[stride] - this.flatCoordinates[0]; const radius = this.flatCoordinates[stride] - this.flatCoordinates[0];
const flatCoordinates = center.slice(); const flatCoordinates = center.slice();
@@ -175,10 +164,9 @@ Circle.prototype.setCenter = function(center) {
} }
this.setFlatCoordinates(this.layout, flatCoordinates); this.setFlatCoordinates(this.layout, flatCoordinates);
this.changed(); this.changed();
}; }
/**
/**
* Set the center (as {@link module:ol/coordinate~Coordinate coordinate}) and the radius (as * Set the center (as {@link module:ol/coordinate~Coordinate coordinate}) and the radius (as
* number) of the circle. * number) of the circle.
* @param {!module:ol/coordinate~Coordinate} center Center. * @param {!module:ol/coordinate~Coordinate} center Center.
@@ -186,7 +174,7 @@ Circle.prototype.setCenter = function(center) {
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @api * @api
*/ */
Circle.prototype.setCenterAndRadius = function(center, radius, opt_layout) { setCenterAndRadius(center, radius, opt_layout) {
this.setLayout(opt_layout, center, 0); this.setLayout(opt_layout, center, 0);
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = []; this.flatCoordinates = [];
@@ -201,30 +189,30 @@ Circle.prototype.setCenterAndRadius = function(center, radius, opt_layout) {
} }
flatCoordinates.length = offset; flatCoordinates.length = offset;
this.changed(); this.changed();
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Circle.prototype.getCoordinates = function() {}; getCoordinates() {}
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Circle.prototype.setCoordinates = function(coordinates, opt_layout) {}; setCoordinates(coordinates, opt_layout) {}
/**
/**
* Set the radius of the circle. The radius is in the units of the projection. * Set the radius of the circle. The radius is in the units of the projection.
* @param {number} radius Radius. * @param {number} radius Radius.
* @api * @api
*/ */
Circle.prototype.setRadius = function(radius) { setRadius(radius) {
this.flatCoordinates[this.stride] = this.flatCoordinates[0] + radius; this.flatCoordinates[this.stride] = this.flatCoordinates[0] + radius;
this.changed(); this.changed();
}; }
}
inherits(Circle, SimpleGeometry);
/** /**
+57 -68
View File
@@ -25,7 +25,8 @@ import {create as createTransform, compose as composeTransform} from '../transfo
* @extends {module:ol/Object} * @extends {module:ol/Object}
* @api * @api
*/ */
const Geometry = function() { class Geometry {
constructor() {
BaseObject.call(this); BaseObject.call(this);
@@ -59,26 +60,16 @@ const Geometry = function() {
*/ */
this.simplifiedGeometryRevision = 0; this.simplifiedGeometryRevision = 0;
}; }
inherits(Geometry, BaseObject); /**
/**
* @type {module:ol/transform~Transform}
*/
const tmpTransform = createTransform();
/**
* Make a complete copy of the geometry. * Make a complete copy of the geometry.
* @abstract * @abstract
* @return {!module:ol/geom/Geometry} Clone. * @return {!module:ol/geom/Geometry} Clone.
*/ */
Geometry.prototype.clone = function() {}; clone() {}
/**
/**
* @abstract * @abstract
* @param {number} x X. * @param {number} x X.
* @param {number} y Y. * @param {number} y Y.
@@ -86,10 +77,9 @@ Geometry.prototype.clone = function() {};
* @param {number} minSquaredDistance Minimum squared distance. * @param {number} minSquaredDistance Minimum squared distance.
* @return {number} Minimum squared distance. * @return {number} Minimum squared distance.
*/ */
Geometry.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) {}; closestPointXY(x, y, closestPoint, minSquaredDistance) {}
/**
/**
* Return the closest point of the geometry to the passed point as * Return the closest point of the geometry to the passed point as
* {@link module:ol/coordinate~Coordinate coordinate}. * {@link module:ol/coordinate~Coordinate coordinate}.
* @param {module:ol/coordinate~Coordinate} point Point. * @param {module:ol/coordinate~Coordinate} point Point.
@@ -97,58 +87,46 @@ Geometry.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDista
* @return {module:ol/coordinate~Coordinate} Closest point. * @return {module:ol/coordinate~Coordinate} Closest point.
* @api * @api
*/ */
Geometry.prototype.getClosestPoint = function(point, opt_closestPoint) { getClosestPoint(point, opt_closestPoint) {
const closestPoint = opt_closestPoint ? opt_closestPoint : [NaN, NaN]; const closestPoint = opt_closestPoint ? opt_closestPoint : [NaN, NaN];
this.closestPointXY(point[0], point[1], closestPoint, Infinity); this.closestPointXY(point[0], point[1], closestPoint, Infinity);
return closestPoint; return closestPoint;
}; }
/**
/**
* Returns true if this geometry includes the specified coordinate. If the * Returns true if this geometry includes the specified coordinate. If the
* coordinate is on the boundary of the geometry, returns false. * coordinate is on the boundary of the geometry, returns false.
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate. * @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
* @return {boolean} Contains coordinate. * @return {boolean} Contains coordinate.
* @api * @api
*/ */
Geometry.prototype.intersectsCoordinate = function(coordinate) { intersectsCoordinate(coordinate) {
return this.containsXY(coordinate[0], coordinate[1]); return this.containsXY(coordinate[0], coordinate[1]);
}; }
/**
/**
* @abstract * @abstract
* @param {module:ol/extent~Extent} extent Extent. * @param {module:ol/extent~Extent} extent Extent.
* @protected * @protected
* @return {module:ol/extent~Extent} extent Extent. * @return {module:ol/extent~Extent} extent Extent.
*/ */
Geometry.prototype.computeExtent = function(extent) {}; computeExtent(extent) {}
/**
/**
* @param {number} x X.
* @param {number} y Y.
* @return {boolean} Contains (x, y).
*/
Geometry.prototype.containsXY = FALSE;
/**
* Get the extent of the geometry. * Get the extent of the geometry.
* @param {module:ol/extent~Extent=} opt_extent Extent. * @param {module:ol/extent~Extent=} opt_extent Extent.
* @return {module:ol/extent~Extent} extent Extent. * @return {module:ol/extent~Extent} extent Extent.
* @api * @api
*/ */
Geometry.prototype.getExtent = function(opt_extent) { getExtent(opt_extent) {
if (this.extentRevision_ != this.getRevision()) { if (this.extentRevision_ != this.getRevision()) {
this.extent_ = this.computeExtent(this.extent_); this.extent_ = this.computeExtent(this.extent_);
this.extentRevision_ = this.getRevision(); this.extentRevision_ = this.getRevision();
} }
return returnOrUpdate(this.extent_, opt_extent); return returnOrUpdate(this.extent_, opt_extent);
}; }
/**
/**
* Rotate the geometry around a given coordinate. This modifies the geometry * Rotate the geometry around a given coordinate. This modifies the geometry
* coordinates in place. * coordinates in place.
* @abstract * @abstract
@@ -156,10 +134,9 @@ Geometry.prototype.getExtent = function(opt_extent) {
* @param {module:ol/coordinate~Coordinate} anchor The rotation center. * @param {module:ol/coordinate~Coordinate} anchor The rotation center.
* @api * @api
*/ */
Geometry.prototype.rotate = function(angle, anchor) {}; rotate(angle, anchor) {}
/**
/**
* Scale the geometry (with an optional origin). This modifies the geometry * Scale the geometry (with an optional origin). This modifies the geometry
* coordinates in place. * coordinates in place.
* @abstract * @abstract
@@ -170,10 +147,9 @@ Geometry.prototype.rotate = function(angle, anchor) {};
* of the geometry extent). * of the geometry extent).
* @api * @api
*/ */
Geometry.prototype.scale = function(sx, opt_sy, opt_anchor) {}; scale(sx, opt_sy, opt_anchor) {}
/**
/**
* Create a simplified version of this geometry. For linestrings, this uses * Create a simplified version of this geometry. For linestrings, this uses
* the the {@link * the the {@link
* https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm * https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
@@ -185,12 +161,11 @@ Geometry.prototype.scale = function(sx, opt_sy, opt_anchor) {};
* geometry. * geometry.
* @api * @api
*/ */
Geometry.prototype.simplify = function(tolerance) { simplify(tolerance) {
return this.getSimplifiedGeometry(tolerance * tolerance); return this.getSimplifiedGeometry(tolerance * tolerance);
}; }
/**
/**
* Create a simplified version of this geometry using the Douglas Peucker * Create a simplified version of this geometry using the Douglas Peucker
* algorithm. * algorithm.
* @see https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm * @see https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
@@ -198,18 +173,16 @@ Geometry.prototype.simplify = function(tolerance) {
* @param {number} squaredTolerance Squared tolerance. * @param {number} squaredTolerance Squared tolerance.
* @return {module:ol/geom/Geometry} Simplified geometry. * @return {module:ol/geom/Geometry} Simplified geometry.
*/ */
Geometry.prototype.getSimplifiedGeometry = function(squaredTolerance) {}; getSimplifiedGeometry(squaredTolerance) {}
/**
/**
* Get the type of this geometry. * Get the type of this geometry.
* @abstract * @abstract
* @return {module:ol/geom/GeometryType} Geometry type. * @return {module:ol/geom/GeometryType} Geometry type.
*/ */
Geometry.prototype.getType = function() {}; getType() {}
/**
/**
* Apply a transform function to each coordinate of the geometry. * Apply a transform function to each coordinate of the geometry.
* The geometry is modified in place. * The geometry is modified in place.
* If you do not want the geometry modified in place, first `clone()` it and * If you do not want the geometry modified in place, first `clone()` it and
@@ -217,29 +190,26 @@ Geometry.prototype.getType = function() {};
* @abstract * @abstract
* @param {module:ol/proj~TransformFunction} transformFn Transform. * @param {module:ol/proj~TransformFunction} transformFn Transform.
*/ */
Geometry.prototype.applyTransform = function(transformFn) {}; applyTransform(transformFn) {}
/**
/**
* Test if the geometry and the passed extent intersect. * Test if the geometry and the passed extent intersect.
* @abstract * @abstract
* @param {module:ol/extent~Extent} extent Extent. * @param {module:ol/extent~Extent} extent Extent.
* @return {boolean} `true` if the geometry and the extent intersect. * @return {boolean} `true` if the geometry and the extent intersect.
*/ */
Geometry.prototype.intersectsExtent = function(extent) {}; intersectsExtent(extent) {}
/**
/**
* Translate the geometry. This modifies the geometry coordinates in place. If * Translate the geometry. This modifies the geometry coordinates in place. If
* instead you want a new geometry, first `clone()` this geometry. * instead you want a new geometry, first `clone()` this geometry.
* @abstract * @abstract
* @param {number} deltaX Delta X. * @param {number} deltaX Delta X.
* @param {number} deltaY Delta Y. * @param {number} deltaY Delta Y.
*/ */
Geometry.prototype.translate = function(deltaX, deltaY) {}; translate(deltaX, deltaY) {}
/**
/**
* Transform each coordinate of the geometry from one coordinate reference * Transform each coordinate of the geometry from one coordinate reference
* system to another. The geometry is modified in place. * system to another. The geometry is modified in place.
* For example, a line will be transformed to a line and a circle to a circle. * For example, a line will be transformed to a line and a circle to a circle.
@@ -254,7 +224,7 @@ Geometry.prototype.translate = function(deltaX, deltaY) {};
* modified in place. * modified in place.
* @api * @api
*/ */
Geometry.prototype.transform = function(source, destination) { transform(source, destination) {
source = getProjection(source); source = getProjection(source);
const transformFn = source.getUnits() == Units.TILE_PIXELS ? const transformFn = source.getUnits() == Units.TILE_PIXELS ?
function(inCoordinates, outCoordinates, stride) { function(inCoordinates, outCoordinates, stride) {
@@ -272,5 +242,24 @@ Geometry.prototype.transform = function(source, destination) {
getTransform(source, destination); getTransform(source, destination);
this.applyTransform(transformFn); this.applyTransform(transformFn);
return this; return this;
}; }
}
inherits(Geometry, BaseObject);
/**
* @type {module:ol/transform~Transform}
*/
const tmpTransform = createTransform();
/**
* @param {number} x X.
* @param {number} y Y.
* @return {boolean} Contains (x, y).
*/
Geometry.prototype.containsXY = FALSE;
export default Geometry; export default Geometry;
+78 -93
View File
@@ -18,7 +18,8 @@ import {clear} from '../obj.js';
* @param {Array.<module:ol/geom/Geometry>=} opt_geometries Geometries. * @param {Array.<module:ol/geom/Geometry>=} opt_geometries Geometries.
* @api * @api
*/ */
const GeometryCollection = function(opt_geometries) { class GeometryCollection {
constructor(opt_geometries) {
Geometry.call(this); Geometry.call(this);
@@ -29,28 +30,12 @@ const GeometryCollection = function(opt_geometries) {
this.geometries_ = opt_geometries ? opt_geometries : null; this.geometries_ = opt_geometries ? opt_geometries : null;
this.listenGeometriesChange_(); this.listenGeometriesChange_();
};
inherits(GeometryCollection, Geometry);
/**
* @param {Array.<module:ol/geom/Geometry>} geometries Geometries.
* @return {Array.<module:ol/geom/Geometry>} Cloned geometries.
*/
function cloneGeometries(geometries) {
const clonedGeometries = [];
for (let i = 0, ii = geometries.length; i < ii; ++i) {
clonedGeometries.push(geometries[i].clone());
} }
return clonedGeometries;
}
/**
/**
* @private * @private
*/ */
GeometryCollection.prototype.unlistenGeometriesChange_ = function() { unlistenGeometriesChange_() {
if (!this.geometries_) { if (!this.geometries_) {
return; return;
} }
@@ -59,13 +44,12 @@ GeometryCollection.prototype.unlistenGeometriesChange_ = function() {
this.geometries_[i], EventType.CHANGE, this.geometries_[i], EventType.CHANGE,
this.changed, this); this.changed, this);
} }
}; }
/**
/**
* @private * @private
*/ */
GeometryCollection.prototype.listenGeometriesChange_ = function() { listenGeometriesChange_() {
if (!this.geometries_) { if (!this.geometries_) {
return; return;
} }
@@ -74,26 +58,24 @@ GeometryCollection.prototype.listenGeometriesChange_ = function() {
this.geometries_[i], EventType.CHANGE, this.geometries_[i], EventType.CHANGE,
this.changed, this); this.changed, this);
} }
}; }
/**
/**
* Make a complete copy of the geometry. * Make a complete copy of the geometry.
* @return {!module:ol/geom/GeometryCollection} Clone. * @return {!module:ol/geom/GeometryCollection} Clone.
* @override * @override
* @api * @api
*/ */
GeometryCollection.prototype.clone = function() { clone() {
const geometryCollection = new GeometryCollection(null); const geometryCollection = new GeometryCollection(null);
geometryCollection.setGeometries(this.geometries_); geometryCollection.setGeometries(this.geometries_);
return geometryCollection; return geometryCollection;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
GeometryCollection.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) { closestPointXY(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) { if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance; return minSquaredDistance;
} }
@@ -103,13 +85,12 @@ GeometryCollection.prototype.closestPointXY = function(x, y, closestPoint, minSq
x, y, closestPoint, minSquaredDistance); x, y, closestPoint, minSquaredDistance);
} }
return minSquaredDistance; return minSquaredDistance;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
GeometryCollection.prototype.containsXY = function(x, y) { containsXY(x, y) {
const geometries = this.geometries_; const geometries = this.geometries_;
for (let i = 0, ii = geometries.length; i < ii; ++i) { for (let i = 0, ii = geometries.length; i < ii; ++i) {
if (geometries[i].containsXY(x, y)) { if (geometries[i].containsXY(x, y)) {
@@ -117,44 +98,40 @@ GeometryCollection.prototype.containsXY = function(x, y) {
} }
} }
return false; return false;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
GeometryCollection.prototype.computeExtent = function(extent) { computeExtent(extent) {
createOrUpdateEmpty(extent); createOrUpdateEmpty(extent);
const geometries = this.geometries_; const geometries = this.geometries_;
for (let i = 0, ii = geometries.length; i < ii; ++i) { for (let i = 0, ii = geometries.length; i < ii; ++i) {
extend(extent, geometries[i].getExtent()); extend(extent, geometries[i].getExtent());
} }
return extent; return extent;
}; }
/**
/**
* Return the geometries that make up this geometry collection. * Return the geometries that make up this geometry collection.
* @return {Array.<module:ol/geom/Geometry>} Geometries. * @return {Array.<module:ol/geom/Geometry>} Geometries.
* @api * @api
*/ */
GeometryCollection.prototype.getGeometries = function() { getGeometries() {
return cloneGeometries(this.geometries_); return cloneGeometries(this.geometries_);
}; }
/**
/**
* @return {Array.<module:ol/geom/Geometry>} Geometries. * @return {Array.<module:ol/geom/Geometry>} Geometries.
*/ */
GeometryCollection.prototype.getGeometriesArray = function() { getGeometriesArray() {
return this.geometries_; return this.geometries_;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
GeometryCollection.prototype.getSimplifiedGeometry = function(squaredTolerance) { getSimplifiedGeometry(squaredTolerance) {
if (this.simplifiedGeometryRevision != this.getRevision()) { if (this.simplifiedGeometryRevision != this.getRevision()) {
clear(this.simplifiedGeometryCache); clear(this.simplifiedGeometryCache);
this.simplifiedGeometryMaxMinSquaredTolerance = 0; this.simplifiedGeometryMaxMinSquaredTolerance = 0;
@@ -190,23 +167,21 @@ GeometryCollection.prototype.getSimplifiedGeometry = function(squaredTolerance)
return this; return this;
} }
} }
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
GeometryCollection.prototype.getType = function() { getType() {
return GeometryType.GEOMETRY_COLLECTION; return GeometryType.GEOMETRY_COLLECTION;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
GeometryCollection.prototype.intersectsExtent = function(extent) { intersectsExtent(extent) {
const geometries = this.geometries_; const geometries = this.geometries_;
for (let i = 0, ii = geometries.length; i < ii; ++i) { for (let i = 0, ii = geometries.length; i < ii; ++i) {
if (geometries[i].intersectsExtent(extent)) { if (geometries[i].intersectsExtent(extent)) {
@@ -214,35 +189,32 @@ GeometryCollection.prototype.intersectsExtent = function(extent) {
} }
} }
return false; return false;
}; }
/**
/**
* @return {boolean} Is empty. * @return {boolean} Is empty.
*/ */
GeometryCollection.prototype.isEmpty = function() { isEmpty() {
return this.geometries_.length === 0; return this.geometries_.length === 0;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
GeometryCollection.prototype.rotate = function(angle, anchor) { rotate(angle, anchor) {
const geometries = this.geometries_; const geometries = this.geometries_;
for (let i = 0, ii = geometries.length; i < ii; ++i) { for (let i = 0, ii = geometries.length; i < ii; ++i) {
geometries[i].rotate(angle, anchor); geometries[i].rotate(angle, anchor);
} }
this.changed(); this.changed();
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
GeometryCollection.prototype.scale = function(sx, opt_sy, opt_anchor) { scale(sx, opt_sy, opt_anchor) {
let anchor = opt_anchor; let anchor = opt_anchor;
if (!anchor) { if (!anchor) {
anchor = getCenter(this.getExtent()); anchor = getCenter(this.getExtent());
@@ -252,64 +224,77 @@ GeometryCollection.prototype.scale = function(sx, opt_sy, opt_anchor) {
geometries[i].scale(sx, opt_sy, anchor); geometries[i].scale(sx, opt_sy, anchor);
} }
this.changed(); this.changed();
}; }
/**
/**
* Set the geometries that make up this geometry collection. * Set the geometries that make up this geometry collection.
* @param {Array.<module:ol/geom/Geometry>} geometries Geometries. * @param {Array.<module:ol/geom/Geometry>} geometries Geometries.
* @api * @api
*/ */
GeometryCollection.prototype.setGeometries = function(geometries) { setGeometries(geometries) {
this.setGeometriesArray(cloneGeometries(geometries)); this.setGeometriesArray(cloneGeometries(geometries));
}; }
/**
/**
* @param {Array.<module:ol/geom/Geometry>} geometries Geometries. * @param {Array.<module:ol/geom/Geometry>} geometries Geometries.
*/ */
GeometryCollection.prototype.setGeometriesArray = function(geometries) { setGeometriesArray(geometries) {
this.unlistenGeometriesChange_(); this.unlistenGeometriesChange_();
this.geometries_ = geometries; this.geometries_ = geometries;
this.listenGeometriesChange_(); this.listenGeometriesChange_();
this.changed(); this.changed();
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
GeometryCollection.prototype.applyTransform = function(transformFn) { applyTransform(transformFn) {
const geometries = this.geometries_; const geometries = this.geometries_;
for (let i = 0, ii = geometries.length; i < ii; ++i) { for (let i = 0, ii = geometries.length; i < ii; ++i) {
geometries[i].applyTransform(transformFn); geometries[i].applyTransform(transformFn);
} }
this.changed(); this.changed();
}; }
/**
/**
* Translate the geometry. * Translate the geometry.
* @param {number} deltaX Delta X. * @param {number} deltaX Delta X.
* @param {number} deltaY Delta Y. * @param {number} deltaY Delta Y.
* @override * @override
* @api * @api
*/ */
GeometryCollection.prototype.translate = function(deltaX, deltaY) { translate(deltaX, deltaY) {
const geometries = this.geometries_; const geometries = this.geometries_;
for (let i = 0, ii = geometries.length; i < ii; ++i) { for (let i = 0, ii = geometries.length; i < ii; ++i) {
geometries[i].translate(deltaX, deltaY); geometries[i].translate(deltaX, deltaY);
} }
this.changed(); this.changed();
}; }
/**
* @inheritDoc
*/
disposeInternal() {
this.unlistenGeometriesChange_();
Geometry.prototype.disposeInternal.call(this);
}
}
inherits(GeometryCollection, Geometry);
/** /**
* @inheritDoc * @param {Array.<module:ol/geom/Geometry>} geometries Geometries.
* @return {Array.<module:ol/geom/Geometry>} Cloned geometries.
*/ */
GeometryCollection.prototype.disposeInternal = function() { function cloneGeometries(geometries) {
this.unlistenGeometriesChange_(); const clonedGeometries = [];
Geometry.prototype.disposeInternal.call(this); for (let i = 0, ii = geometries.length; i < ii; ++i) {
}; clonedGeometries.push(geometries[i].clone());
}
return clonedGeometries;
}
export default GeometryCollection; export default GeometryCollection;
+46 -56
View File
@@ -28,7 +28,8 @@ import {douglasPeucker} from '../geom/flat/simplify.js';
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @api * @api
*/ */
const LineString = function(coordinates, opt_layout) { class LineString {
constructor(coordinates, opt_layout) {
SimpleGeometry.call(this); SimpleGeometry.call(this);
@@ -62,41 +63,36 @@ const LineString = function(coordinates, opt_layout) {
this.setCoordinates(coordinates, opt_layout); this.setCoordinates(coordinates, opt_layout);
} }
}; }
inherits(LineString, SimpleGeometry); /**
/**
* Append the passed coordinate to the coordinates of the linestring. * Append the passed coordinate to the coordinates of the linestring.
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate. * @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
* @api * @api
*/ */
LineString.prototype.appendCoordinate = function(coordinate) { appendCoordinate(coordinate) {
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = coordinate.slice(); this.flatCoordinates = coordinate.slice();
} else { } else {
extend(this.flatCoordinates, coordinate); extend(this.flatCoordinates, coordinate);
} }
this.changed(); this.changed();
}; }
/**
/**
* Make a complete copy of the geometry. * Make a complete copy of the geometry.
* @return {!module:ol/geom/LineString} Clone. * @return {!module:ol/geom/LineString} Clone.
* @override * @override
* @api * @api
*/ */
LineString.prototype.clone = function() { clone() {
return new LineString(this.flatCoordinates.slice(), this.layout); return new LineString(this.flatCoordinates.slice(), this.layout);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
LineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) { closestPointXY(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) { if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance; return minSquaredDistance;
} }
@@ -108,10 +104,9 @@ LineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDis
return assignClosestPoint( return assignClosestPoint(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
this.maxDelta_, false, x, y, closestPoint, minSquaredDistance); this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);
}; }
/**
/**
* Iterate over each segment, calling the provided callback. * Iterate over each segment, calling the provided callback.
* If the callback returns a truthy value the function returns that * If the callback returns a truthy value the function returns that
* value immediately. Otherwise the function returns `false`. * value immediately. Otherwise the function returns `false`.
@@ -122,12 +117,11 @@ LineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDis
* @template T,S * @template T,S
* @api * @api
*/ */
LineString.prototype.forEachSegment = function(callback) { forEachSegment(callback) {
return forEachSegment(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, callback); return forEachSegment(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, callback);
}; }
/**
/**
* Returns the coordinate at `m` using linear interpolation, or `null` if no * Returns the coordinate at `m` using linear interpolation, or `null` if no
* such coordinate exists. * such coordinate exists.
* *
@@ -141,7 +135,7 @@ LineString.prototype.forEachSegment = function(callback) {
* @return {module:ol/coordinate~Coordinate} Coordinate. * @return {module:ol/coordinate~Coordinate} Coordinate.
* @api * @api
*/ */
LineString.prototype.getCoordinateAtM = function(m, opt_extrapolate) { getCoordinateAtM(m, opt_extrapolate) {
if (this.layout != GeometryLayout.XYM && if (this.layout != GeometryLayout.XYM &&
this.layout != GeometryLayout.XYZM) { this.layout != GeometryLayout.XYZM) {
return null; return null;
@@ -149,22 +143,20 @@ LineString.prototype.getCoordinateAtM = function(m, opt_extrapolate) {
const extrapolate = opt_extrapolate !== undefined ? opt_extrapolate : false; const extrapolate = opt_extrapolate !== undefined ? opt_extrapolate : false;
return lineStringCoordinateAtM(this.flatCoordinates, 0, return lineStringCoordinateAtM(this.flatCoordinates, 0,
this.flatCoordinates.length, this.stride, m, extrapolate); this.flatCoordinates.length, this.stride, m, extrapolate);
}; }
/**
/**
* Return the coordinates of the linestring. * Return the coordinates of the linestring.
* @return {Array.<module:ol/coordinate~Coordinate>} Coordinates. * @return {Array.<module:ol/coordinate~Coordinate>} Coordinates.
* @override * @override
* @api * @api
*/ */
LineString.prototype.getCoordinates = function() { getCoordinates() {
return inflateCoordinates( return inflateCoordinates(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride); this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
}; }
/**
/**
* Return the coordinate at the provided fraction along the linestring. * Return the coordinate at the provided fraction along the linestring.
* The `fraction` is a number between 0 and 1, where 0 is the start of the * The `fraction` is a number between 0 and 1, where 0 is the start of the
* linestring and 1 is the end. * linestring and 1 is the end.
@@ -174,76 +166,70 @@ LineString.prototype.getCoordinates = function() {
* @return {module:ol/coordinate~Coordinate} Coordinate of the interpolated point. * @return {module:ol/coordinate~Coordinate} Coordinate of the interpolated point.
* @api * @api
*/ */
LineString.prototype.getCoordinateAt = function(fraction, opt_dest) { getCoordinateAt(fraction, opt_dest) {
return interpolatePoint( return interpolatePoint(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
fraction, opt_dest); fraction, opt_dest);
}; }
/**
/**
* Return the length of the linestring on projected plane. * Return the length of the linestring on projected plane.
* @return {number} Length (on projected plane). * @return {number} Length (on projected plane).
* @api * @api
*/ */
LineString.prototype.getLength = function() { getLength() {
return lineStringLength( return lineStringLength(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride); this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
}; }
/**
/**
* @return {Array.<number>} Flat midpoint. * @return {Array.<number>} Flat midpoint.
*/ */
LineString.prototype.getFlatMidpoint = function() { getFlatMidpoint() {
if (this.flatMidpointRevision_ != this.getRevision()) { if (this.flatMidpointRevision_ != this.getRevision()) {
this.flatMidpoint_ = this.getCoordinateAt(0.5, this.flatMidpoint_); this.flatMidpoint_ = this.getCoordinateAt(0.5, this.flatMidpoint_);
this.flatMidpointRevision_ = this.getRevision(); this.flatMidpointRevision_ = this.getRevision();
} }
return this.flatMidpoint_; return this.flatMidpoint_;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
LineString.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) { getSimplifiedGeometryInternal(squaredTolerance) {
const simplifiedFlatCoordinates = []; const simplifiedFlatCoordinates = [];
simplifiedFlatCoordinates.length = douglasPeucker( simplifiedFlatCoordinates.length = douglasPeucker(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
squaredTolerance, simplifiedFlatCoordinates, 0); squaredTolerance, simplifiedFlatCoordinates, 0);
return new LineString(simplifiedFlatCoordinates, GeometryLayout.XY); return new LineString(simplifiedFlatCoordinates, GeometryLayout.XY);
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
LineString.prototype.getType = function() { getType() {
return GeometryType.LINE_STRING; return GeometryType.LINE_STRING;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
LineString.prototype.intersectsExtent = function(extent) { intersectsExtent(extent) {
return intersectsLineString( return intersectsLineString(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
extent); extent);
}; }
/**
/**
* Set the coordinates of the linestring. * Set the coordinates of the linestring.
* @param {!Array.<module:ol/coordinate~Coordinate>} coordinates Coordinates. * @param {!Array.<module:ol/coordinate~Coordinate>} coordinates Coordinates.
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @override * @override
* @api * @api
*/ */
LineString.prototype.setCoordinates = function(coordinates, opt_layout) { setCoordinates(coordinates, opt_layout) {
this.setLayout(opt_layout, coordinates, 1); this.setLayout(opt_layout, coordinates, 1);
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = []; this.flatCoordinates = [];
@@ -251,6 +237,10 @@ LineString.prototype.setCoordinates = function(coordinates, opt_layout) {
this.flatCoordinates.length = deflateCoordinates( this.flatCoordinates.length = deflateCoordinates(
this.flatCoordinates, 0, coordinates, this.stride); this.flatCoordinates, 0, coordinates, this.stride);
this.changed(); this.changed();
}; }
}
inherits(LineString, SimpleGeometry);
export default LineString; export default LineString;
+31 -35
View File
@@ -25,7 +25,8 @@ import {douglasPeucker} from '../geom/flat/simplify.js';
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @api * @api
*/ */
const LinearRing = function(coordinates, opt_layout) { class LinearRing {
constructor(coordinates, opt_layout) {
SimpleGeometry.call(this); SimpleGeometry.call(this);
@@ -47,26 +48,22 @@ const LinearRing = function(coordinates, opt_layout) {
this.setCoordinates(coordinates, opt_layout); this.setCoordinates(coordinates, opt_layout);
} }
}; }
inherits(LinearRing, SimpleGeometry); /**
/**
* Make a complete copy of the geometry. * Make a complete copy of the geometry.
* @return {!module:ol/geom/LinearRing} Clone. * @return {!module:ol/geom/LinearRing} Clone.
* @override * @override
* @api * @api
*/ */
LinearRing.prototype.clone = function() { clone() {
return new LinearRing(this.flatCoordinates.slice(), this.layout); return new LinearRing(this.flatCoordinates.slice(), this.layout);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
LinearRing.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) { closestPointXY(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) { if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance; return minSquaredDistance;
} }
@@ -78,66 +75,60 @@ LinearRing.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDis
return assignClosestPoint( return assignClosestPoint(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
this.maxDelta_, true, x, y, closestPoint, minSquaredDistance); this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
}; }
/**
/**
* Return the area of the linear ring on projected plane. * Return the area of the linear ring on projected plane.
* @return {number} Area (on projected plane). * @return {number} Area (on projected plane).
* @api * @api
*/ */
LinearRing.prototype.getArea = function() { getArea() {
return linearRingArea(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride); return linearRingArea(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
}; }
/**
/**
* Return the coordinates of the linear ring. * Return the coordinates of the linear ring.
* @return {Array.<module:ol/coordinate~Coordinate>} Coordinates. * @return {Array.<module:ol/coordinate~Coordinate>} Coordinates.
* @override * @override
* @api * @api
*/ */
LinearRing.prototype.getCoordinates = function() { getCoordinates() {
return inflateCoordinates( return inflateCoordinates(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride); this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
LinearRing.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) { getSimplifiedGeometryInternal(squaredTolerance) {
const simplifiedFlatCoordinates = []; const simplifiedFlatCoordinates = [];
simplifiedFlatCoordinates.length = douglasPeucker( simplifiedFlatCoordinates.length = douglasPeucker(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, this.flatCoordinates, 0, this.flatCoordinates.length, this.stride,
squaredTolerance, simplifiedFlatCoordinates, 0); squaredTolerance, simplifiedFlatCoordinates, 0);
return new LinearRing(simplifiedFlatCoordinates, GeometryLayout.XY); return new LinearRing(simplifiedFlatCoordinates, GeometryLayout.XY);
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
LinearRing.prototype.getType = function() { getType() {
return GeometryType.LINEAR_RING; return GeometryType.LINEAR_RING;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
LinearRing.prototype.intersectsExtent = function(extent) {}; intersectsExtent(extent) {}
/**
/**
* Set the coordinates of the linear ring. * Set the coordinates of the linear ring.
* @param {!Array.<module:ol/coordinate~Coordinate>} coordinates Coordinates. * @param {!Array.<module:ol/coordinate~Coordinate>} coordinates Coordinates.
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @override * @override
* @api * @api
*/ */
LinearRing.prototype.setCoordinates = function(coordinates, opt_layout) { setCoordinates(coordinates, opt_layout) {
this.setLayout(opt_layout, coordinates, 1); this.setLayout(opt_layout, coordinates, 1);
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = []; this.flatCoordinates = [];
@@ -145,5 +136,10 @@ LinearRing.prototype.setCoordinates = function(coordinates, opt_layout) {
this.flatCoordinates.length = deflateCoordinates( this.flatCoordinates.length = deflateCoordinates(
this.flatCoordinates, 0, coordinates, this.stride); this.flatCoordinates, 0, coordinates, this.stride);
this.changed(); this.changed();
}; }
}
inherits(LinearRing, SimpleGeometry);
export default LinearRing; export default LinearRing;
+47 -56
View File
@@ -28,7 +28,8 @@ import {douglasPeuckerArray} from '../geom/flat/simplify.js';
* @param {Array.<number>} opt_ends Flat coordinate ends for internal use. * @param {Array.<number>} opt_ends Flat coordinate ends for internal use.
* @api * @api
*/ */
const MultiLineString = function(coordinates, opt_layout, opt_ends) { class MultiLineString {
constructor(coordinates, opt_layout, opt_ends) {
SimpleGeometry.call(this); SimpleGeometry.call(this);
@@ -71,17 +72,14 @@ const MultiLineString = function(coordinates, opt_layout, opt_ends) {
this.ends_ = ends; this.ends_ = ends;
} }
}; }
inherits(MultiLineString, SimpleGeometry); /**
/**
* Append the passed linestring to the multilinestring. * Append the passed linestring to the multilinestring.
* @param {module:ol/geom/LineString} lineString LineString. * @param {module:ol/geom/LineString} lineString LineString.
* @api * @api
*/ */
MultiLineString.prototype.appendLineString = function(lineString) { appendLineString(lineString) {
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = lineString.getFlatCoordinates().slice(); this.flatCoordinates = lineString.getFlatCoordinates().slice();
} else { } else {
@@ -89,24 +87,22 @@ MultiLineString.prototype.appendLineString = function(lineString) {
} }
this.ends_.push(this.flatCoordinates.length); this.ends_.push(this.flatCoordinates.length);
this.changed(); this.changed();
}; }
/**
/**
* Make a complete copy of the geometry. * Make a complete copy of the geometry.
* @return {!module:ol/geom/MultiLineString} Clone. * @return {!module:ol/geom/MultiLineString} Clone.
* @override * @override
* @api * @api
*/ */
MultiLineString.prototype.clone = function() { clone() {
return new MultiLineString(this.flatCoordinates.slice(), this.layout, this.ends_.slice()); return new MultiLineString(this.flatCoordinates.slice(), this.layout, this.ends_.slice());
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
MultiLineString.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) { closestPointXY(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) { if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance; return minSquaredDistance;
} }
@@ -118,10 +114,9 @@ MultiLineString.prototype.closestPointXY = function(x, y, closestPoint, minSquar
return assignClosestArrayPoint( return assignClosestArrayPoint(
this.flatCoordinates, 0, this.ends_, this.stride, this.flatCoordinates, 0, this.ends_, this.stride,
this.maxDelta_, false, x, y, closestPoint, minSquaredDistance); this.maxDelta_, false, x, y, closestPoint, minSquaredDistance);
}; }
/**
/**
* Returns the coordinate at `m` using linear interpolation, or `null` if no * Returns the coordinate at `m` using linear interpolation, or `null` if no
* such coordinate exists. * such coordinate exists.
* *
@@ -143,7 +138,7 @@ MultiLineString.prototype.closestPointXY = function(x, y, closestPoint, minSquar
* @return {module:ol/coordinate~Coordinate} Coordinate. * @return {module:ol/coordinate~Coordinate} Coordinate.
* @api * @api
*/ */
MultiLineString.prototype.getCoordinateAtM = function(m, opt_extrapolate, opt_interpolate) { getCoordinateAtM(m, opt_extrapolate, opt_interpolate) {
if ((this.layout != GeometryLayout.XYM && if ((this.layout != GeometryLayout.XYM &&
this.layout != GeometryLayout.XYZM) || this.layout != GeometryLayout.XYZM) ||
this.flatCoordinates.length === 0) { this.flatCoordinates.length === 0) {
@@ -153,50 +148,46 @@ MultiLineString.prototype.getCoordinateAtM = function(m, opt_extrapolate, opt_in
const interpolate = opt_interpolate !== undefined ? opt_interpolate : false; const interpolate = opt_interpolate !== undefined ? opt_interpolate : false;
return lineStringsCoordinateAtM(this.flatCoordinates, 0, return lineStringsCoordinateAtM(this.flatCoordinates, 0,
this.ends_, this.stride, m, extrapolate, interpolate); this.ends_, this.stride, m, extrapolate, interpolate);
}; }
/**
/**
* Return the coordinates of the multilinestring. * Return the coordinates of the multilinestring.
* @return {Array.<Array.<module:ol/coordinate~Coordinate>>} Coordinates. * @return {Array.<Array.<module:ol/coordinate~Coordinate>>} Coordinates.
* @override * @override
* @api * @api
*/ */
MultiLineString.prototype.getCoordinates = function() { getCoordinates() {
return inflateCoordinatesArray( return inflateCoordinatesArray(
this.flatCoordinates, 0, this.ends_, this.stride); this.flatCoordinates, 0, this.ends_, this.stride);
}; }
/**
/**
* @return {Array.<number>} Ends. * @return {Array.<number>} Ends.
*/ */
MultiLineString.prototype.getEnds = function() { getEnds() {
return this.ends_; return this.ends_;
}; }
/**
/**
* Return the linestring at the specified index. * Return the linestring at the specified index.
* @param {number} index Index. * @param {number} index Index.
* @return {module:ol/geom/LineString} LineString. * @return {module:ol/geom/LineString} LineString.
* @api * @api
*/ */
MultiLineString.prototype.getLineString = function(index) { getLineString(index) {
if (index < 0 || this.ends_.length <= index) { if (index < 0 || this.ends_.length <= index) {
return null; return null;
} }
return new LineString(this.flatCoordinates.slice( return new LineString(this.flatCoordinates.slice(
index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]), this.layout); index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]), this.layout);
}; }
/**
/**
* Return the linestrings of this multilinestring. * Return the linestrings of this multilinestring.
* @return {Array.<module:ol/geom/LineString>} LineStrings. * @return {Array.<module:ol/geom/LineString>} LineStrings.
* @api * @api
*/ */
MultiLineString.prototype.getLineStrings = function() { getLineStrings() {
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
const ends = this.ends_; const ends = this.ends_;
const layout = this.layout; const layout = this.layout;
@@ -210,13 +201,12 @@ MultiLineString.prototype.getLineStrings = function() {
offset = end; offset = end;
} }
return lineStrings; return lineStrings;
}; }
/**
/**
* @return {Array.<number>} Flat midpoints. * @return {Array.<number>} Flat midpoints.
*/ */
MultiLineString.prototype.getFlatMidpoints = function() { getFlatMidpoints() {
const midpoints = []; const midpoints = [];
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
let offset = 0; let offset = 0;
@@ -230,49 +220,45 @@ MultiLineString.prototype.getFlatMidpoints = function() {
offset = end; offset = end;
} }
return midpoints; return midpoints;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
MultiLineString.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) { getSimplifiedGeometryInternal(squaredTolerance) {
const simplifiedFlatCoordinates = []; const simplifiedFlatCoordinates = [];
const simplifiedEnds = []; const simplifiedEnds = [];
simplifiedFlatCoordinates.length = douglasPeuckerArray( simplifiedFlatCoordinates.length = douglasPeuckerArray(
this.flatCoordinates, 0, this.ends_, this.stride, squaredTolerance, this.flatCoordinates, 0, this.ends_, this.stride, squaredTolerance,
simplifiedFlatCoordinates, 0, simplifiedEnds); simplifiedFlatCoordinates, 0, simplifiedEnds);
return new MultiLineString(simplifiedFlatCoordinates, GeometryLayout.XY, simplifiedEnds); return new MultiLineString(simplifiedFlatCoordinates, GeometryLayout.XY, simplifiedEnds);
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
MultiLineString.prototype.getType = function() { getType() {
return GeometryType.MULTI_LINE_STRING; return GeometryType.MULTI_LINE_STRING;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
MultiLineString.prototype.intersectsExtent = function(extent) { intersectsExtent(extent) {
return intersectsLineStringArray( return intersectsLineStringArray(
this.flatCoordinates, 0, this.ends_, this.stride, extent); this.flatCoordinates, 0, this.ends_, this.stride, extent);
}; }
/**
/**
* Set the coordinates of the multilinestring. * Set the coordinates of the multilinestring.
* @param {!Array.<Array.<module:ol/coordinate~Coordinate>>} coordinates Coordinates. * @param {!Array.<Array.<module:ol/coordinate~Coordinate>>} coordinates Coordinates.
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @override * @override
* @api * @api
*/ */
MultiLineString.prototype.setCoordinates = function(coordinates, opt_layout) { setCoordinates(coordinates, opt_layout) {
this.setLayout(opt_layout, coordinates, 2); this.setLayout(opt_layout, coordinates, 2);
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = []; this.flatCoordinates = [];
@@ -281,5 +267,10 @@ MultiLineString.prototype.setCoordinates = function(coordinates, opt_layout) {
this.flatCoordinates, 0, coordinates, this.stride, this.ends_); this.flatCoordinates, 0, coordinates, this.stride, this.ends_);
this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1]; this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];
this.changed(); this.changed();
}; }
}
inherits(MultiLineString, SimpleGeometry);
export default MultiLineString; export default MultiLineString;
+35 -40
View File
@@ -23,49 +23,45 @@ import {squaredDistance as squaredDx} from '../math.js';
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @api * @api
*/ */
const MultiPoint = function(coordinates, opt_layout) { class MultiPoint {
constructor(coordinates, opt_layout) {
SimpleGeometry.call(this); SimpleGeometry.call(this);
if (opt_layout && !Array.isArray(coordinates[0])) { if (opt_layout && !Array.isArray(coordinates[0])) {
this.setFlatCoordinates(opt_layout, coordinates); this.setFlatCoordinates(opt_layout, coordinates);
} else { } else {
this.setCoordinates(coordinates, opt_layout); this.setCoordinates(coordinates, opt_layout);
} }
}; }
inherits(MultiPoint, SimpleGeometry); /**
/**
* Append the passed point to this multipoint. * Append the passed point to this multipoint.
* @param {module:ol/geom/Point} point Point. * @param {module:ol/geom/Point} point Point.
* @api * @api
*/ */
MultiPoint.prototype.appendPoint = function(point) { appendPoint(point) {
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = point.getFlatCoordinates().slice(); this.flatCoordinates = point.getFlatCoordinates().slice();
} else { } else {
extend(this.flatCoordinates, point.getFlatCoordinates()); extend(this.flatCoordinates, point.getFlatCoordinates());
} }
this.changed(); this.changed();
}; }
/**
/**
* Make a complete copy of the geometry. * Make a complete copy of the geometry.
* @return {!module:ol/geom/MultiPoint} Clone. * @return {!module:ol/geom/MultiPoint} Clone.
* @override * @override
* @api * @api
*/ */
MultiPoint.prototype.clone = function() { clone() {
const multiPoint = new MultiPoint(this.flatCoordinates.slice(), this.layout); const multiPoint = new MultiPoint(this.flatCoordinates.slice(), this.layout);
return multiPoint; return multiPoint;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
MultiPoint.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) { closestPointXY(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) { if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance; return minSquaredDistance;
} }
@@ -83,43 +79,40 @@ MultiPoint.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDis
} }
} }
return minSquaredDistance; return minSquaredDistance;
}; }
/**
/**
* Return the coordinates of the multipoint. * Return the coordinates of the multipoint.
* @return {Array.<module:ol/coordinate~Coordinate>} Coordinates. * @return {Array.<module:ol/coordinate~Coordinate>} Coordinates.
* @override * @override
* @api * @api
*/ */
MultiPoint.prototype.getCoordinates = function() { getCoordinates() {
return inflateCoordinates( return inflateCoordinates(
this.flatCoordinates, 0, this.flatCoordinates.length, this.stride); this.flatCoordinates, 0, this.flatCoordinates.length, this.stride);
}; }
/**
/**
* Return the point at the specified index. * Return the point at the specified index.
* @param {number} index Index. * @param {number} index Index.
* @return {module:ol/geom/Point} Point. * @return {module:ol/geom/Point} Point.
* @api * @api
*/ */
MultiPoint.prototype.getPoint = function(index) { getPoint(index) {
const n = !this.flatCoordinates ? 0 : this.flatCoordinates.length / this.stride; const n = !this.flatCoordinates ? 0 : this.flatCoordinates.length / this.stride;
if (index < 0 || n <= index) { if (index < 0 || n <= index) {
return null; return null;
} }
return new Point(this.flatCoordinates.slice( return new Point(this.flatCoordinates.slice(
index * this.stride, (index + 1) * this.stride), this.layout); index * this.stride, (index + 1) * this.stride), this.layout);
}; }
/**
/**
* Return the points of this multipoint. * Return the points of this multipoint.
* @return {Array.<module:ol/geom/Point>} Points. * @return {Array.<module:ol/geom/Point>} Points.
* @api * @api
*/ */
MultiPoint.prototype.getPoints = function() { getPoints() {
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
const layout = this.layout; const layout = this.layout;
const stride = this.stride; const stride = this.stride;
@@ -130,23 +123,21 @@ MultiPoint.prototype.getPoints = function() {
points.push(point); points.push(point);
} }
return points; return points;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
MultiPoint.prototype.getType = function() { getType() {
return GeometryType.MULTI_POINT; return GeometryType.MULTI_POINT;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
MultiPoint.prototype.intersectsExtent = function(extent) { intersectsExtent(extent) {
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
const stride = this.stride; const stride = this.stride;
for (let i = 0, ii = flatCoordinates.length; i < ii; i += stride) { for (let i = 0, ii = flatCoordinates.length; i < ii; i += stride) {
@@ -157,17 +148,16 @@ MultiPoint.prototype.intersectsExtent = function(extent) {
} }
} }
return false; return false;
}; }
/**
/**
* Set the coordinates of the multipoint. * Set the coordinates of the multipoint.
* @param {!Array.<module:ol/coordinate~Coordinate>} coordinates Coordinates. * @param {!Array.<module:ol/coordinate~Coordinate>} coordinates Coordinates.
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @override * @override
* @api * @api
*/ */
MultiPoint.prototype.setCoordinates = function(coordinates, opt_layout) { setCoordinates(coordinates, opt_layout) {
this.setLayout(opt_layout, coordinates, 1); this.setLayout(opt_layout, coordinates, 1);
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = []; this.flatCoordinates = [];
@@ -175,5 +165,10 @@ MultiPoint.prototype.setCoordinates = function(coordinates, opt_layout) {
this.flatCoordinates.length = deflateCoordinates( this.flatCoordinates.length = deflateCoordinates(
this.flatCoordinates, 0, coordinates, this.stride); this.flatCoordinates, 0, coordinates, this.stride);
this.changed(); this.changed();
}; }
}
inherits(MultiPoint, SimpleGeometry);
export default MultiPoint; export default MultiPoint;
+54 -68
View File
@@ -34,7 +34,8 @@ import {quantizeMultiArray} from '../geom/flat/simplify.js';
* coordinates. * coordinates.
* @api * @api
*/ */
const MultiPolygon = function(coordinates, opt_layout, opt_endss) { class MultiPolygon {
constructor(coordinates, opt_layout, opt_endss) {
SimpleGeometry.call(this); SimpleGeometry.call(this);
@@ -108,17 +109,14 @@ const MultiPolygon = function(coordinates, opt_layout, opt_endss) {
this.setCoordinates(coordinates, opt_layout); this.setCoordinates(coordinates, opt_layout);
} }
}; }
inherits(MultiPolygon, SimpleGeometry); /**
/**
* Append the passed polygon to this multipolygon. * Append the passed polygon to this multipolygon.
* @param {module:ol/geom/Polygon} polygon Polygon. * @param {module:ol/geom/Polygon} polygon Polygon.
* @api * @api
*/ */
MultiPolygon.prototype.appendPolygon = function(polygon) { appendPolygon(polygon) {
/** @type {Array.<number>} */ /** @type {Array.<number>} */
let ends; let ends;
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
@@ -135,16 +133,15 @@ MultiPolygon.prototype.appendPolygon = function(polygon) {
} }
this.endss_.push(ends); this.endss_.push(ends);
this.changed(); this.changed();
}; }
/**
/**
* Make a complete copy of the geometry. * Make a complete copy of the geometry.
* @return {!module:ol/geom/MultiPolygon} Clone. * @return {!module:ol/geom/MultiPolygon} Clone.
* @override * @override
* @api * @api
*/ */
MultiPolygon.prototype.clone = function() { clone() {
const len = this.endss_.length; const len = this.endss_.length;
const newEndss = new Array(len); const newEndss = new Array(len);
for (let i = 0; i < len; ++i) { for (let i = 0; i < len; ++i) {
@@ -153,13 +150,12 @@ MultiPolygon.prototype.clone = function() {
return new MultiPolygon( return new MultiPolygon(
this.flatCoordinates.slice(), this.layout, newEndss); this.flatCoordinates.slice(), this.layout, newEndss);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
MultiPolygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) { closestPointXY(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) { if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance; return minSquaredDistance;
} }
@@ -171,28 +167,25 @@ MultiPolygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredD
return assignClosestMultiArrayPoint( return assignClosestMultiArrayPoint(
this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride,
this.maxDelta_, true, x, y, closestPoint, minSquaredDistance); this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
MultiPolygon.prototype.containsXY = function(x, y) { containsXY(x, y) {
return linearRingssContainsXY(this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, x, y); return linearRingssContainsXY(this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, x, y);
}; }
/**
/**
* Return the area of the multipolygon on projected plane. * Return the area of the multipolygon on projected plane.
* @return {number} Area (on projected plane). * @return {number} Area (on projected plane).
* @api * @api
*/ */
MultiPolygon.prototype.getArea = function() { getArea() {
return linearRingssArea(this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride); return linearRingssArea(this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride);
}; }
/**
/**
* Get the coordinate array for this geometry. This array has the structure * Get the coordinate array for this geometry. This array has the structure
* of a GeoJSON coordinate array for multi-polygons. * of a GeoJSON coordinate array for multi-polygons.
* *
@@ -206,7 +199,7 @@ MultiPolygon.prototype.getArea = function() {
* @override * @override
* @api * @api
*/ */
MultiPolygon.prototype.getCoordinates = function(opt_right) { getCoordinates(opt_right) {
let flatCoordinates; let flatCoordinates;
if (opt_right !== undefined) { if (opt_right !== undefined) {
flatCoordinates = this.getOrientedFlatCoordinates().slice(); flatCoordinates = this.getOrientedFlatCoordinates().slice();
@@ -218,21 +211,19 @@ MultiPolygon.prototype.getCoordinates = function(opt_right) {
return inflateMultiCoordinatesArray( return inflateMultiCoordinatesArray(
flatCoordinates, 0, this.endss_, this.stride); flatCoordinates, 0, this.endss_, this.stride);
}; }
/**
/**
* @return {Array.<Array.<number>>} Endss. * @return {Array.<Array.<number>>} Endss.
*/ */
MultiPolygon.prototype.getEndss = function() { getEndss() {
return this.endss_; return this.endss_;
}; }
/**
/**
* @return {Array.<number>} Flat interior points. * @return {Array.<number>} Flat interior points.
*/ */
MultiPolygon.prototype.getFlatInteriorPoints = function() { getFlatInteriorPoints() {
if (this.flatInteriorPointsRevision_ != this.getRevision()) { if (this.flatInteriorPointsRevision_ != this.getRevision()) {
const flatCenters = linearRingssCenter( const flatCenters = linearRingssCenter(
this.flatCoordinates, 0, this.endss_, this.stride); this.flatCoordinates, 0, this.endss_, this.stride);
@@ -242,24 +233,22 @@ MultiPolygon.prototype.getFlatInteriorPoints = function() {
this.flatInteriorPointsRevision_ = this.getRevision(); this.flatInteriorPointsRevision_ = this.getRevision();
} }
return this.flatInteriorPoints_; return this.flatInteriorPoints_;
}; }
/**
/**
* Return the interior points as {@link module:ol/geom/MultiPoint multipoint}. * Return the interior points as {@link module:ol/geom/MultiPoint multipoint}.
* @return {module:ol/geom/MultiPoint} Interior points as XYM coordinates, where M is * @return {module:ol/geom/MultiPoint} Interior points as XYM coordinates, where M is
* the length of the horizontal intersection that the point belongs to. * the length of the horizontal intersection that the point belongs to.
* @api * @api
*/ */
MultiPolygon.prototype.getInteriorPoints = function() { getInteriorPoints() {
return new MultiPoint(this.getFlatInteriorPoints().slice(), GeometryLayout.XYM); return new MultiPoint(this.getFlatInteriorPoints().slice(), GeometryLayout.XYM);
}; }
/**
/**
* @return {Array.<number>} Oriented flat coordinates. * @return {Array.<number>} Oriented flat coordinates.
*/ */
MultiPolygon.prototype.getOrientedFlatCoordinates = function() { getOrientedFlatCoordinates() {
if (this.orientedRevision_ != this.getRevision()) { if (this.orientedRevision_ != this.getRevision()) {
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
if (linearRingsAreOriented( if (linearRingsAreOriented(
@@ -274,13 +263,12 @@ MultiPolygon.prototype.getOrientedFlatCoordinates = function() {
this.orientedRevision_ = this.getRevision(); this.orientedRevision_ = this.getRevision();
} }
return this.orientedFlatCoordinates_; return this.orientedFlatCoordinates_;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
MultiPolygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) { getSimplifiedGeometryInternal(squaredTolerance) {
const simplifiedFlatCoordinates = []; const simplifiedFlatCoordinates = [];
const simplifiedEndss = []; const simplifiedEndss = [];
simplifiedFlatCoordinates.length = quantizeMultiArray( simplifiedFlatCoordinates.length = quantizeMultiArray(
@@ -288,16 +276,15 @@ MultiPolygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance
Math.sqrt(squaredTolerance), Math.sqrt(squaredTolerance),
simplifiedFlatCoordinates, 0, simplifiedEndss); simplifiedFlatCoordinates, 0, simplifiedEndss);
return new MultiPolygon(simplifiedFlatCoordinates, GeometryLayout.XY, simplifiedEndss); return new MultiPolygon(simplifiedFlatCoordinates, GeometryLayout.XY, simplifiedEndss);
}; }
/**
/**
* Return the polygon at the specified index. * Return the polygon at the specified index.
* @param {number} index Index. * @param {number} index Index.
* @return {module:ol/geom/Polygon} Polygon. * @return {module:ol/geom/Polygon} Polygon.
* @api * @api
*/ */
MultiPolygon.prototype.getPolygon = function(index) { getPolygon(index) {
if (index < 0 || this.endss_.length <= index) { if (index < 0 || this.endss_.length <= index) {
return null; return null;
} }
@@ -316,15 +303,14 @@ MultiPolygon.prototype.getPolygon = function(index) {
} }
} }
return new Polygon(this.flatCoordinates.slice(offset, end), this.layout, ends); return new Polygon(this.flatCoordinates.slice(offset, end), this.layout, ends);
}; }
/**
/**
* Return the polygons of this multipolygon. * Return the polygons of this multipolygon.
* @return {Array.<module:ol/geom/Polygon>} Polygons. * @return {Array.<module:ol/geom/Polygon>} Polygons.
* @api * @api
*/ */
MultiPolygon.prototype.getPolygons = function() { getPolygons() {
const layout = this.layout; const layout = this.layout;
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
const endss = this.endss_; const endss = this.endss_;
@@ -343,36 +329,33 @@ MultiPolygon.prototype.getPolygons = function() {
offset = end; offset = end;
} }
return polygons; return polygons;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
MultiPolygon.prototype.getType = function() { getType() {
return GeometryType.MULTI_POLYGON; return GeometryType.MULTI_POLYGON;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
MultiPolygon.prototype.intersectsExtent = function(extent) { intersectsExtent(extent) {
return intersectsLinearRingMultiArray( return intersectsLinearRingMultiArray(
this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, extent); this.getOrientedFlatCoordinates(), 0, this.endss_, this.stride, extent);
}; }
/**
/**
* Set the coordinates of the multipolygon. * Set the coordinates of the multipolygon.
* @param {!Array.<Array.<Array.<module:ol/coordinate~Coordinate>>>} coordinates Coordinates. * @param {!Array.<Array.<Array.<module:ol/coordinate~Coordinate>>>} coordinates Coordinates.
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @override * @override
* @api * @api
*/ */
MultiPolygon.prototype.setCoordinates = function(coordinates, opt_layout) { setCoordinates(coordinates, opt_layout) {
this.setLayout(opt_layout, coordinates, 3); this.setLayout(opt_layout, coordinates, 3);
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = []; this.flatCoordinates = [];
@@ -387,7 +370,10 @@ MultiPolygon.prototype.setCoordinates = function(coordinates, opt_layout) {
0 : lastEnds[lastEnds.length - 1]; 0 : lastEnds[lastEnds.length - 1];
} }
this.changed(); this.changed();
}; }
}
inherits(MultiPolygon, SimpleGeometry);
export default MultiPolygon; export default MultiPolygon;
+28 -32
View File
@@ -18,30 +18,27 @@ import {squaredDistance as squaredDx} from '../math.js';
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @api * @api
*/ */
const Point = function(coordinates, opt_layout) { class Point {
constructor(coordinates, opt_layout) {
SimpleGeometry.call(this); SimpleGeometry.call(this);
this.setCoordinates(coordinates, opt_layout); this.setCoordinates(coordinates, opt_layout);
}; }
inherits(Point, SimpleGeometry); /**
/**
* Make a complete copy of the geometry. * Make a complete copy of the geometry.
* @return {!module:ol/geom/Point} Clone. * @return {!module:ol/geom/Point} Clone.
* @override * @override
* @api * @api
*/ */
Point.prototype.clone = function() { clone() {
const point = new Point(this.flatCoordinates.slice(), this.layout); const point = new Point(this.flatCoordinates.slice(), this.layout);
return point; return point;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Point.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) { closestPointXY(x, y, closestPoint, minSquaredDistance) {
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
const squaredDistance = squaredDx(x, y, flatCoordinates[0], flatCoordinates[1]); const squaredDistance = squaredDx(x, y, flatCoordinates[0], flatCoordinates[1]);
if (squaredDistance < minSquaredDistance) { if (squaredDistance < minSquaredDistance) {
@@ -54,51 +51,46 @@ Point.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance
} else { } else {
return minSquaredDistance; return minSquaredDistance;
} }
}; }
/**
/**
* Return the coordinate of the point. * Return the coordinate of the point.
* @return {module:ol/coordinate~Coordinate} Coordinates. * @return {module:ol/coordinate~Coordinate} Coordinates.
* @override * @override
* @api * @api
*/ */
Point.prototype.getCoordinates = function() { getCoordinates() {
return !this.flatCoordinates ? [] : this.flatCoordinates.slice(); return !this.flatCoordinates ? [] : this.flatCoordinates.slice();
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Point.prototype.computeExtent = function(extent) { computeExtent(extent) {
return createOrUpdateFromCoordinate(this.flatCoordinates, extent); return createOrUpdateFromCoordinate(this.flatCoordinates, extent);
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
Point.prototype.getType = function() { getType() {
return GeometryType.POINT; return GeometryType.POINT;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
Point.prototype.intersectsExtent = function(extent) { intersectsExtent(extent) {
return containsXY(extent, this.flatCoordinates[0], this.flatCoordinates[1]); return containsXY(extent, this.flatCoordinates[0], this.flatCoordinates[1]);
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
Point.prototype.setCoordinates = function(coordinates, opt_layout) { setCoordinates(coordinates, opt_layout) {
this.setLayout(opt_layout, coordinates, 0); this.setLayout(opt_layout, coordinates, 0);
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = []; this.flatCoordinates = [];
@@ -106,6 +98,10 @@ Point.prototype.setCoordinates = function(coordinates, opt_layout) {
this.flatCoordinates.length = deflateCoordinate( this.flatCoordinates.length = deflateCoordinate(
this.flatCoordinates, 0, coordinates, this.stride); this.flatCoordinates, 0, coordinates, this.stride);
this.changed(); this.changed();
}; }
}
inherits(Point, SimpleGeometry);
export default Point; export default Point;
+58 -72
View File
@@ -39,7 +39,8 @@ import {modulo} from '../math.js';
* coordinates). * coordinates).
* @api * @api
*/ */
const Polygon = function(coordinates, opt_layout, opt_ends) { class Polygon {
constructor(coordinates, opt_layout, opt_ends) {
SimpleGeometry.call(this); SimpleGeometry.call(this);
@@ -92,17 +93,14 @@ const Polygon = function(coordinates, opt_layout, opt_ends) {
this.setCoordinates(coordinates, opt_layout); this.setCoordinates(coordinates, opt_layout);
} }
}; }
inherits(Polygon, SimpleGeometry); /**
/**
* Append the passed linear ring to this polygon. * Append the passed linear ring to this polygon.
* @param {module:ol/geom/LinearRing} linearRing Linear ring. * @param {module:ol/geom/LinearRing} linearRing Linear ring.
* @api * @api
*/ */
Polygon.prototype.appendLinearRing = function(linearRing) { appendLinearRing(linearRing) {
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = linearRing.getFlatCoordinates().slice(); this.flatCoordinates = linearRing.getFlatCoordinates().slice();
} else { } else {
@@ -110,24 +108,22 @@ Polygon.prototype.appendLinearRing = function(linearRing) {
} }
this.ends_.push(this.flatCoordinates.length); this.ends_.push(this.flatCoordinates.length);
this.changed(); this.changed();
}; }
/**
/**
* Make a complete copy of the geometry. * Make a complete copy of the geometry.
* @return {!module:ol/geom/Polygon} Clone. * @return {!module:ol/geom/Polygon} Clone.
* @override * @override
* @api * @api
*/ */
Polygon.prototype.clone = function() { clone() {
return new Polygon(this.flatCoordinates.slice(), this.layout, this.ends_.slice()); return new Polygon(this.flatCoordinates.slice(), this.layout, this.ends_.slice());
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Polygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistance) { closestPointXY(x, y, closestPoint, minSquaredDistance) {
if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) { if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) {
return minSquaredDistance; return minSquaredDistance;
} }
@@ -139,28 +135,25 @@ Polygon.prototype.closestPointXY = function(x, y, closestPoint, minSquaredDistan
return assignClosestArrayPoint( return assignClosestArrayPoint(
this.flatCoordinates, 0, this.ends_, this.stride, this.flatCoordinates, 0, this.ends_, this.stride,
this.maxDelta_, true, x, y, closestPoint, minSquaredDistance); this.maxDelta_, true, x, y, closestPoint, minSquaredDistance);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Polygon.prototype.containsXY = function(x, y) { containsXY(x, y) {
return linearRingsContainsXY(this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, x, y); return linearRingsContainsXY(this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, x, y);
}; }
/**
/**
* Return the area of the polygon on projected plane. * Return the area of the polygon on projected plane.
* @return {number} Area (on projected plane). * @return {number} Area (on projected plane).
* @api * @api
*/ */
Polygon.prototype.getArea = function() { getArea() {
return linearRingsArea(this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride); return linearRingsArea(this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride);
}; }
/**
/**
* Get the coordinate array for this geometry. This array has the structure * Get the coordinate array for this geometry. This array has the structure
* of a GeoJSON coordinate array for polygons. * of a GeoJSON coordinate array for polygons.
* *
@@ -174,7 +167,7 @@ Polygon.prototype.getArea = function() {
* @override * @override
* @api * @api
*/ */
Polygon.prototype.getCoordinates = function(opt_right) { getCoordinates(opt_right) {
let flatCoordinates; let flatCoordinates;
if (opt_right !== undefined) { if (opt_right !== undefined) {
flatCoordinates = this.getOrientedFlatCoordinates().slice(); flatCoordinates = this.getOrientedFlatCoordinates().slice();
@@ -186,21 +179,19 @@ Polygon.prototype.getCoordinates = function(opt_right) {
return inflateCoordinatesArray( return inflateCoordinatesArray(
flatCoordinates, 0, this.ends_, this.stride); flatCoordinates, 0, this.ends_, this.stride);
}; }
/**
/**
* @return {Array.<number>} Ends. * @return {Array.<number>} Ends.
*/ */
Polygon.prototype.getEnds = function() { getEnds() {
return this.ends_; return this.ends_;
}; }
/**
/**
* @return {Array.<number>} Interior point. * @return {Array.<number>} Interior point.
*/ */
Polygon.prototype.getFlatInteriorPoint = function() { getFlatInteriorPoint() {
if (this.flatInteriorPointRevision_ != this.getRevision()) { if (this.flatInteriorPointRevision_ != this.getRevision()) {
const flatCenter = getCenter(this.getExtent()); const flatCenter = getCenter(this.getExtent());
this.flatInteriorPoint_ = getInteriorPointOfArray( this.flatInteriorPoint_ = getInteriorPointOfArray(
@@ -209,33 +200,30 @@ Polygon.prototype.getFlatInteriorPoint = function() {
this.flatInteriorPointRevision_ = this.getRevision(); this.flatInteriorPointRevision_ = this.getRevision();
} }
return this.flatInteriorPoint_; return this.flatInteriorPoint_;
}; }
/**
/**
* Return an interior point of the polygon. * Return an interior point of the polygon.
* @return {module:ol/geom/Point} Interior point as XYM coordinate, where M is the * @return {module:ol/geom/Point} Interior point as XYM coordinate, where M is the
* length of the horizontal intersection that the point belongs to. * length of the horizontal intersection that the point belongs to.
* @api * @api
*/ */
Polygon.prototype.getInteriorPoint = function() { getInteriorPoint() {
return new Point(this.getFlatInteriorPoint(), GeometryLayout.XYM); return new Point(this.getFlatInteriorPoint(), GeometryLayout.XYM);
}; }
/**
/**
* Return the number of rings of the polygon, this includes the exterior * Return the number of rings of the polygon, this includes the exterior
* ring and any interior rings. * ring and any interior rings.
* *
* @return {number} Number of rings. * @return {number} Number of rings.
* @api * @api
*/ */
Polygon.prototype.getLinearRingCount = function() { getLinearRingCount() {
return this.ends_.length; return this.ends_.length;
}; }
/**
/**
* Return the Nth linear ring of the polygon geometry. Return `null` if the * Return the Nth linear ring of the polygon geometry. Return `null` if the
* given index is out of range. * given index is out of range.
* The exterior linear ring is available at index `0` and the interior rings * The exterior linear ring is available at index `0` and the interior rings
@@ -245,21 +233,20 @@ Polygon.prototype.getLinearRingCount = function() {
* @return {module:ol/geom/LinearRing} Linear ring. * @return {module:ol/geom/LinearRing} Linear ring.
* @api * @api
*/ */
Polygon.prototype.getLinearRing = function(index) { getLinearRing(index) {
if (index < 0 || this.ends_.length <= index) { if (index < 0 || this.ends_.length <= index) {
return null; return null;
} }
return new LinearRing(this.flatCoordinates.slice( return new LinearRing(this.flatCoordinates.slice(
index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]), this.layout); index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]), this.layout);
}; }
/**
/**
* Return the linear rings of the polygon. * Return the linear rings of the polygon.
* @return {Array.<module:ol/geom/LinearRing>} Linear rings. * @return {Array.<module:ol/geom/LinearRing>} Linear rings.
* @api * @api
*/ */
Polygon.prototype.getLinearRings = function() { getLinearRings() {
const layout = this.layout; const layout = this.layout;
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
const ends = this.ends_; const ends = this.ends_;
@@ -272,13 +259,12 @@ Polygon.prototype.getLinearRings = function() {
offset = end; offset = end;
} }
return linearRings; return linearRings;
}; }
/**
/**
* @return {Array.<number>} Oriented flat coordinates. * @return {Array.<number>} Oriented flat coordinates.
*/ */
Polygon.prototype.getOrientedFlatCoordinates = function() { getOrientedFlatCoordinates() {
if (this.orientedRevision_ != this.getRevision()) { if (this.orientedRevision_ != this.getRevision()) {
const flatCoordinates = this.flatCoordinates; const flatCoordinates = this.flatCoordinates;
if (linearRingIsOriented( if (linearRingIsOriented(
@@ -293,13 +279,12 @@ Polygon.prototype.getOrientedFlatCoordinates = function() {
this.orientedRevision_ = this.getRevision(); this.orientedRevision_ = this.getRevision();
} }
return this.orientedFlatCoordinates_; return this.orientedFlatCoordinates_;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Polygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) { getSimplifiedGeometryInternal(squaredTolerance) {
const simplifiedFlatCoordinates = []; const simplifiedFlatCoordinates = [];
const simplifiedEnds = []; const simplifiedEnds = [];
simplifiedFlatCoordinates.length = quantizeArray( simplifiedFlatCoordinates.length = quantizeArray(
@@ -307,36 +292,33 @@ Polygon.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
Math.sqrt(squaredTolerance), Math.sqrt(squaredTolerance),
simplifiedFlatCoordinates, 0, simplifiedEnds); simplifiedFlatCoordinates, 0, simplifiedEnds);
return new Polygon(simplifiedFlatCoordinates, GeometryLayout.XY, simplifiedEnds); return new Polygon(simplifiedFlatCoordinates, GeometryLayout.XY, simplifiedEnds);
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
Polygon.prototype.getType = function() { getType() {
return GeometryType.POLYGON; return GeometryType.POLYGON;
}; }
/**
/**
* @inheritDoc * @inheritDoc
* @api * @api
*/ */
Polygon.prototype.intersectsExtent = function(extent) { intersectsExtent(extent) {
return intersectsLinearRingArray( return intersectsLinearRingArray(
this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, extent); this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, extent);
}; }
/**
/**
* Set the coordinates of the polygon. * Set the coordinates of the polygon.
* @param {!Array.<Array.<module:ol/coordinate~Coordinate>>} coordinates Coordinates. * @param {!Array.<Array.<module:ol/coordinate~Coordinate>>} coordinates Coordinates.
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout. * @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
* @override * @override
* @api * @api
*/ */
Polygon.prototype.setCoordinates = function(coordinates, opt_layout) { setCoordinates(coordinates, opt_layout) {
this.setLayout(opt_layout, coordinates, 2); this.setLayout(opt_layout, coordinates, 2);
if (!this.flatCoordinates) { if (!this.flatCoordinates) {
this.flatCoordinates = []; this.flatCoordinates = [];
@@ -345,7 +327,11 @@ Polygon.prototype.setCoordinates = function(coordinates, opt_layout) {
this.flatCoordinates, 0, coordinates, this.stride, this.ends_); this.flatCoordinates, 0, coordinates, this.stride, this.ends_);
this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1]; this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1];
this.changed(); this.changed();
}; }
}
inherits(Polygon, SimpleGeometry);
export default Polygon; export default Polygon;
+216 -230
View File
@@ -19,7 +19,8 @@ import {clear} from '../obj.js';
* @extends {module:ol/geom/Geometry} * @extends {module:ol/geom/Geometry}
* @api * @api
*/ */
const SimpleGeometry = function() { class SimpleGeometry {
constructor() {
Geometry.call(this); Geometry.call(this);
@@ -41,7 +42,220 @@ const SimpleGeometry = function() {
*/ */
this.flatCoordinates = null; this.flatCoordinates = null;
}; }
/**
* @inheritDoc
*/
computeExtent(extent) {
return createOrUpdateFromFlatCoordinates(this.flatCoordinates,
0, this.flatCoordinates.length, this.stride, extent);
}
/**
* @abstract
* @return {Array} Coordinates.
*/
getCoordinates() {}
/**
* Return the first coordinate of the geometry.
* @return {module:ol/coordinate~Coordinate} First coordinate.
* @api
*/
getFirstCoordinate() {
return this.flatCoordinates.slice(0, this.stride);
}
/**
* @return {Array.<number>} Flat coordinates.
*/
getFlatCoordinates() {
return this.flatCoordinates;
}
/**
* Return the last coordinate of the geometry.
* @return {module:ol/coordinate~Coordinate} Last point.
* @api
*/
getLastCoordinate() {
return this.flatCoordinates.slice(this.flatCoordinates.length - this.stride);
}
/**
* Return the {@link module:ol/geom/GeometryLayout~GeometryLayout layout} of the geometry.
* @return {module:ol/geom/GeometryLayout} Layout.
* @api
*/
getLayout() {
return this.layout;
}
/**
* @inheritDoc
*/
getSimplifiedGeometry(squaredTolerance) {
if (this.simplifiedGeometryRevision != this.getRevision()) {
clear(this.simplifiedGeometryCache);
this.simplifiedGeometryMaxMinSquaredTolerance = 0;
this.simplifiedGeometryRevision = this.getRevision();
}
// If squaredTolerance is negative or if we know that simplification will not
// have any effect then just return this.
if (squaredTolerance < 0 ||
(this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
squaredTolerance <= this.simplifiedGeometryMaxMinSquaredTolerance)) {
return this;
}
const key = squaredTolerance.toString();
if (this.simplifiedGeometryCache.hasOwnProperty(key)) {
return this.simplifiedGeometryCache[key];
} else {
const simplifiedGeometry =
this.getSimplifiedGeometryInternal(squaredTolerance);
const simplifiedFlatCoordinates = simplifiedGeometry.getFlatCoordinates();
if (simplifiedFlatCoordinates.length < this.flatCoordinates.length) {
this.simplifiedGeometryCache[key] = simplifiedGeometry;
return simplifiedGeometry;
} else {
// Simplification did not actually remove any coordinates. We now know
// that any calls to getSimplifiedGeometry with a squaredTolerance less
// than or equal to the current squaredTolerance will also not have any
// effect. This allows us to short circuit simplification (saving CPU
// cycles) and prevents the cache of simplified geometries from filling
// up with useless identical copies of this geometry (saving memory).
this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
return this;
}
}
}
/**
* @param {number} squaredTolerance Squared tolerance.
* @return {module:ol/geom/SimpleGeometry} Simplified geometry.
* @protected
*/
getSimplifiedGeometryInternal(squaredTolerance) {
return this;
}
/**
* @return {number} Stride.
*/
getStride() {
return this.stride;
}
/**
* @param {module:ol/geom/GeometryLayout} layout Layout.
* @param {Array.<number>} flatCoordinates Flat coordinates.
*/
setFlatCoordinates(layout, flatCoordinates) {
this.stride = getStrideForLayout(layout);
this.layout = layout;
this.flatCoordinates = flatCoordinates;
}
/**
* @abstract
* @param {!Array} coordinates Coordinates.
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
*/
setCoordinates(coordinates, opt_layout) {}
/**
* @param {module:ol/geom/GeometryLayout|undefined} layout Layout.
* @param {Array} coordinates Coordinates.
* @param {number} nesting Nesting.
* @protected
*/
setLayout(layout, coordinates, nesting) {
/** @type {number} */
let stride;
if (layout) {
stride = getStrideForLayout(layout);
} else {
for (let i = 0; i < nesting; ++i) {
if (coordinates.length === 0) {
this.layout = GeometryLayout.XY;
this.stride = 2;
return;
} else {
coordinates = /** @type {Array} */ (coordinates[0]);
}
}
stride = coordinates.length;
layout = getLayoutForStride(stride);
}
this.layout = layout;
this.stride = stride;
}
/**
* @inheritDoc
* @api
*/
applyTransform(transformFn) {
if (this.flatCoordinates) {
transformFn(this.flatCoordinates, this.flatCoordinates, this.stride);
this.changed();
}
}
/**
* @inheritDoc
* @api
*/
rotate(angle, anchor) {
const flatCoordinates = this.getFlatCoordinates();
if (flatCoordinates) {
const stride = this.getStride();
rotate(
flatCoordinates, 0, flatCoordinates.length,
stride, angle, anchor, flatCoordinates);
this.changed();
}
}
/**
* @inheritDoc
* @api
*/
scale(sx, opt_sy, opt_anchor) {
let sy = opt_sy;
if (sy === undefined) {
sy = sx;
}
let anchor = opt_anchor;
if (!anchor) {
anchor = getCenter(this.getExtent());
}
const flatCoordinates = this.getFlatCoordinates();
if (flatCoordinates) {
const stride = this.getStride();
scale(
flatCoordinates, 0, flatCoordinates.length,
stride, sx, sy, anchor, flatCoordinates);
this.changed();
}
}
/**
* @inheritDoc
* @api
*/
translate(deltaX, deltaY) {
const flatCoordinates = this.getFlatCoordinates();
if (flatCoordinates) {
const stride = this.getStride();
translate(
flatCoordinates, 0, flatCoordinates.length, stride,
deltaX, deltaY, flatCoordinates);
this.changed();
}
}
}
inherits(SimpleGeometry, Geometry); inherits(SimpleGeometry, Geometry);
@@ -88,234 +302,6 @@ export function getStrideForLayout(layout) {
SimpleGeometry.prototype.containsXY = FALSE; SimpleGeometry.prototype.containsXY = FALSE;
/**
* @inheritDoc
*/
SimpleGeometry.prototype.computeExtent = function(extent) {
return createOrUpdateFromFlatCoordinates(this.flatCoordinates,
0, this.flatCoordinates.length, this.stride, extent);
};
/**
* @abstract
* @return {Array} Coordinates.
*/
SimpleGeometry.prototype.getCoordinates = function() {};
/**
* Return the first coordinate of the geometry.
* @return {module:ol/coordinate~Coordinate} First coordinate.
* @api
*/
SimpleGeometry.prototype.getFirstCoordinate = function() {
return this.flatCoordinates.slice(0, this.stride);
};
/**
* @return {Array.<number>} Flat coordinates.
*/
SimpleGeometry.prototype.getFlatCoordinates = function() {
return this.flatCoordinates;
};
/**
* Return the last coordinate of the geometry.
* @return {module:ol/coordinate~Coordinate} Last point.
* @api
*/
SimpleGeometry.prototype.getLastCoordinate = function() {
return this.flatCoordinates.slice(this.flatCoordinates.length - this.stride);
};
/**
* Return the {@link module:ol/geom/GeometryLayout~GeometryLayout layout} of the geometry.
* @return {module:ol/geom/GeometryLayout} Layout.
* @api
*/
SimpleGeometry.prototype.getLayout = function() {
return this.layout;
};
/**
* @inheritDoc
*/
SimpleGeometry.prototype.getSimplifiedGeometry = function(squaredTolerance) {
if (this.simplifiedGeometryRevision != this.getRevision()) {
clear(this.simplifiedGeometryCache);
this.simplifiedGeometryMaxMinSquaredTolerance = 0;
this.simplifiedGeometryRevision = this.getRevision();
}
// If squaredTolerance is negative or if we know that simplification will not
// have any effect then just return this.
if (squaredTolerance < 0 ||
(this.simplifiedGeometryMaxMinSquaredTolerance !== 0 &&
squaredTolerance <= this.simplifiedGeometryMaxMinSquaredTolerance)) {
return this;
}
const key = squaredTolerance.toString();
if (this.simplifiedGeometryCache.hasOwnProperty(key)) {
return this.simplifiedGeometryCache[key];
} else {
const simplifiedGeometry =
this.getSimplifiedGeometryInternal(squaredTolerance);
const simplifiedFlatCoordinates = simplifiedGeometry.getFlatCoordinates();
if (simplifiedFlatCoordinates.length < this.flatCoordinates.length) {
this.simplifiedGeometryCache[key] = simplifiedGeometry;
return simplifiedGeometry;
} else {
// Simplification did not actually remove any coordinates. We now know
// that any calls to getSimplifiedGeometry with a squaredTolerance less
// than or equal to the current squaredTolerance will also not have any
// effect. This allows us to short circuit simplification (saving CPU
// cycles) and prevents the cache of simplified geometries from filling
// up with useless identical copies of this geometry (saving memory).
this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance;
return this;
}
}
};
/**
* @param {number} squaredTolerance Squared tolerance.
* @return {module:ol/geom/SimpleGeometry} Simplified geometry.
* @protected
*/
SimpleGeometry.prototype.getSimplifiedGeometryInternal = function(squaredTolerance) {
return this;
};
/**
* @return {number} Stride.
*/
SimpleGeometry.prototype.getStride = function() {
return this.stride;
};
/**
* @param {module:ol/geom/GeometryLayout} layout Layout.
* @param {Array.<number>} flatCoordinates Flat coordinates.
*/
SimpleGeometry.prototype.setFlatCoordinates = function(layout, flatCoordinates) {
this.stride = getStrideForLayout(layout);
this.layout = layout;
this.flatCoordinates = flatCoordinates;
};
/**
* @abstract
* @param {!Array} coordinates Coordinates.
* @param {module:ol/geom/GeometryLayout=} opt_layout Layout.
*/
SimpleGeometry.prototype.setCoordinates = function(coordinates, opt_layout) {};
/**
* @param {module:ol/geom/GeometryLayout|undefined} layout Layout.
* @param {Array} coordinates Coordinates.
* @param {number} nesting Nesting.
* @protected
*/
SimpleGeometry.prototype.setLayout = function(layout, coordinates, nesting) {
/** @type {number} */
let stride;
if (layout) {
stride = getStrideForLayout(layout);
} else {
for (let i = 0; i < nesting; ++i) {
if (coordinates.length === 0) {
this.layout = GeometryLayout.XY;
this.stride = 2;
return;
} else {
coordinates = /** @type {Array} */ (coordinates[0]);
}
}
stride = coordinates.length;
layout = getLayoutForStride(stride);
}
this.layout = layout;
this.stride = stride;
};
/**
* @inheritDoc
* @api
*/
SimpleGeometry.prototype.applyTransform = function(transformFn) {
if (this.flatCoordinates) {
transformFn(this.flatCoordinates, this.flatCoordinates, this.stride);
this.changed();
}
};
/**
* @inheritDoc
* @api
*/
SimpleGeometry.prototype.rotate = function(angle, anchor) {
const flatCoordinates = this.getFlatCoordinates();
if (flatCoordinates) {
const stride = this.getStride();
rotate(
flatCoordinates, 0, flatCoordinates.length,
stride, angle, anchor, flatCoordinates);
this.changed();
}
};
/**
* @inheritDoc
* @api
*/
SimpleGeometry.prototype.scale = function(sx, opt_sy, opt_anchor) {
let sy = opt_sy;
if (sy === undefined) {
sy = sx;
}
let anchor = opt_anchor;
if (!anchor) {
anchor = getCenter(this.getExtent());
}
const flatCoordinates = this.getFlatCoordinates();
if (flatCoordinates) {
const stride = this.getStride();
scale(
flatCoordinates, 0, flatCoordinates.length,
stride, sx, sy, anchor, flatCoordinates);
this.changed();
}
};
/**
* @inheritDoc
* @api
*/
SimpleGeometry.prototype.translate = function(deltaX, deltaY) {
const flatCoordinates = this.getFlatCoordinates();
if (flatCoordinates) {
const stride = this.getStride();
translate(
flatCoordinates, 0, flatCoordinates.length, stride,
deltaX, deltaY, flatCoordinates);
this.changed();
}
};
/** /**
* @param {module:ol/geom/SimpleGeometry} simpleGeometry Simple geometry. * @param {module:ol/geom/SimpleGeometry} simpleGeometry Simple geometry.
* @param {module:ol/transform~Transform} transform Transform. * @param {module:ol/transform~Transform} transform Transform.
+48 -52
View File
@@ -89,7 +89,8 @@ inherits(DragAndDropEvent, Event);
* @param {module:ol/interaction/DragAndDrop~Options=} opt_options Options. * @param {module:ol/interaction/DragAndDrop~Options=} opt_options Options.
* @api * @api
*/ */
const DragAndDrop = function(opt_options) { class DragAndDrop {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -129,42 +130,14 @@ const DragAndDrop = function(opt_options) {
*/ */
this.target = options.target ? options.target : null; this.target = options.target ? options.target : null;
};
inherits(DragAndDrop, Interaction);
/**
* @param {DragEvent} event Event.
* @this {module:ol/interaction/DragAndDrop}
*/
function handleDrop(event) {
const files = event.dataTransfer.files;
for (let i = 0, ii = files.length; i < ii; ++i) {
const file = files.item(i);
const reader = new FileReader();
reader.addEventListener(EventType.LOAD, this.handleResult_.bind(this, file));
reader.readAsText(file);
} }
}
/**
/**
* @param {DragEvent} event Event.
*/
function handleStop(event) {
event.stopPropagation();
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
}
/**
* @param {File} file File. * @param {File} file File.
* @param {Event} event Load event. * @param {Event} event Load event.
* @private * @private
*/ */
DragAndDrop.prototype.handleResult_ = function(file, event) { handleResult_(file, event) {
const result = event.target.result; const result = event.target.result;
const map = this.getMap(); const map = this.getMap();
let projection = this.projection_; let projection = this.projection_;
@@ -200,13 +173,12 @@ DragAndDrop.prototype.handleResult_ = function(file, event) {
new DragAndDropEvent( new DragAndDropEvent(
DragAndDropEventType.ADD_FEATURES, file, DragAndDropEventType.ADD_FEATURES, file,
features, projection)); features, projection));
}; }
/**
/**
* @private * @private
*/ */
DragAndDrop.prototype.registerListeners_ = function() { registerListeners_() {
const map = this.getMap(); const map = this.getMap();
if (map) { if (map) {
const dropArea = this.target ? this.target : map.getViewport(); const dropArea = this.target ? this.target : map.getViewport();
@@ -217,59 +189,83 @@ DragAndDrop.prototype.registerListeners_ = function() {
listen(dropArea, EventType.DROP, handleStop, this) listen(dropArea, EventType.DROP, handleStop, this)
]; ];
} }
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
DragAndDrop.prototype.setActive = function(active) { setActive(active) {
Interaction.prototype.setActive.call(this, active); Interaction.prototype.setActive.call(this, active);
if (active) { if (active) {
this.registerListeners_(); this.registerListeners_();
} else { } else {
this.unregisterListeners_(); this.unregisterListeners_();
} }
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
DragAndDrop.prototype.setMap = function(map) { setMap(map) {
this.unregisterListeners_(); this.unregisterListeners_();
Interaction.prototype.setMap.call(this, map); Interaction.prototype.setMap.call(this, map);
if (this.getActive()) { if (this.getActive()) {
this.registerListeners_(); this.registerListeners_();
} }
}; }
/**
/**
* @param {module:ol/format/Feature} format Format. * @param {module:ol/format/Feature} format Format.
* @param {string} text Text. * @param {string} text Text.
* @param {module:ol/format/Feature~ReadOptions} options Read options. * @param {module:ol/format/Feature~ReadOptions} options Read options.
* @private * @private
* @return {Array.<module:ol/Feature>} Features. * @return {Array.<module:ol/Feature>} Features.
*/ */
DragAndDrop.prototype.tryReadFeatures_ = function(format, text, options) { tryReadFeatures_(format, text, options) {
try { try {
return format.readFeatures(text, options); return format.readFeatures(text, options);
} catch (e) { } catch (e) {
return null; return null;
} }
}; }
/**
/**
* @private * @private
*/ */
DragAndDrop.prototype.unregisterListeners_ = function() { unregisterListeners_() {
if (this.dropListenKeys_) { if (this.dropListenKeys_) {
this.dropListenKeys_.forEach(unlistenByKey); this.dropListenKeys_.forEach(unlistenByKey);
this.dropListenKeys_ = null; this.dropListenKeys_ = null;
} }
}; }
}
inherits(DragAndDrop, Interaction);
/**
* @param {DragEvent} event Event.
* @this {module:ol/interaction/DragAndDrop}
*/
function handleDrop(event) {
const files = event.dataTransfer.files;
for (let i = 0, ii = files.length; i < ii; ++i) {
const file = files.item(i);
const reader = new FileReader();
reader.addEventListener(EventType.LOAD, this.handleResult_.bind(this, file));
reader.readAsText(file);
}
}
/**
* @param {DragEvent} event Event.
*/
function handleStop(event) {
event.stopPropagation();
event.preventDefault();
event.dataTransfer.dropEffect = 'copy';
}
export default DragAndDrop; export default DragAndDrop;
+13 -12
View File
@@ -110,7 +110,8 @@ inherits(DragBoxEvent, Event);
* @param {module:ol/interaction/DragBox~Options=} opt_options Options. * @param {module:ol/interaction/DragBox~Options=} opt_options Options.
* @api * @api
*/ */
const DragBox = function(opt_options) { class DragBox {
constructor(opt_options) {
PointerInteraction.call(this, { PointerInteraction.call(this, {
handleDownEvent: handleDownEvent, handleDownEvent: handleDownEvent,
@@ -150,7 +151,17 @@ const DragBox = function(opt_options) {
*/ */
this.boxEndCondition_ = options.boxEndCondition ? this.boxEndCondition_ = options.boxEndCondition ?
options.boxEndCondition : defaultBoxEndCondition; options.boxEndCondition : defaultBoxEndCondition;
}; }
/**
* Returns geometry of last drawn box.
* @return {module:ol/geom/Polygon} Geometry.
* @api
*/
getGeometry() {
return this.box_.getGeometry();
}
}
inherits(DragBox, PointerInteraction); inherits(DragBox, PointerInteraction);
@@ -188,16 +199,6 @@ function handleDragEvent(mapBrowserEvent) {
} }
/**
* Returns geometry of last drawn box.
* @return {module:ol/geom/Polygon} Geometry.
* @api
*/
DragBox.prototype.getGeometry = function() {
return this.box_.getGeometry();
};
/** /**
* To be overridden by child classes. * To be overridden by child classes.
* FIXME: use constructor option instead of relying on overriding. * FIXME: use constructor option instead of relying on overriding.
+11 -8
View File
@@ -35,7 +35,8 @@ import DragBox from '../interaction/DragBox.js';
* @param {module:ol/interaction/DragZoom~Options=} opt_options Options. * @param {module:ol/interaction/DragZoom~Options=} opt_options Options.
* @api * @api
*/ */
const DragZoom = function(opt_options) { class DragZoom {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
const condition = options.condition ? options.condition : shiftKeyOnly; const condition = options.condition ? options.condition : shiftKeyOnly;
@@ -57,15 +58,12 @@ const DragZoom = function(opt_options) {
className: options.className || 'ol-dragzoom' className: options.className || 'ol-dragzoom'
}); });
}; }
inherits(DragZoom, DragBox); /**
/**
* @inheritDoc * @inheritDoc
*/ */
DragZoom.prototype.onBoxEnd = function() { onBoxEnd() {
const map = this.getMap(); const map = this.getMap();
const view = /** @type {!module:ol/View} */ (map.getView()); const view = /** @type {!module:ol/View} */ (map.getView());
@@ -98,5 +96,10 @@ DragZoom.prototype.onBoxEnd = function() {
easing: easeOut easing: easeOut
}); });
}; }
}
inherits(DragZoom, DragBox);
export default DragZoom; export default DragZoom;
+367 -378
View File
@@ -160,7 +160,8 @@ inherits(DrawEvent, Event);
* @param {module:ol/interaction/Draw~Options} options Options. * @param {module:ol/interaction/Draw~Options} options Options.
* @api * @api
*/ */
const Draw = function(options) { class Draw {
constructor(options) {
PointerInteraction.call(this, { PointerInteraction.call(this, {
handleDownEvent: handleDownEvent, handleDownEvent: handleDownEvent,
@@ -430,7 +431,371 @@ const Draw = function(options) {
getChangeEventType(InteractionProperty.ACTIVE), getChangeEventType(InteractionProperty.ACTIVE),
this.updateState_, this); this.updateState_, this);
}; }
/**
* @inheritDoc
*/
setMap(map) {
PointerInteraction.prototype.setMap.call(this, map);
this.updateState_();
}
/**
* Handle move events.
* @param {module:ol/MapBrowserEvent} event A move event.
* @return {boolean} Pass the event to other interactions.
* @private
*/
handlePointerMove_(event) {
if (this.downPx_ &&
((!this.freehand_ && this.shouldHandle_) ||
(this.freehand_ && !this.shouldHandle_))) {
const downPx = this.downPx_;
const clickPx = event.pixel;
const dx = downPx[0] - clickPx[0];
const dy = downPx[1] - clickPx[1];
const squaredDistance = dx * dx + dy * dy;
this.shouldHandle_ = this.freehand_ ?
squaredDistance > this.squaredClickTolerance_ :
squaredDistance <= this.squaredClickTolerance_;
if (!this.shouldHandle_) {
return true;
}
}
if (this.finishCoordinate_) {
this.modifyDrawing_(event);
} else {
this.createOrUpdateSketchPoint_(event);
}
return true;
}
/**
* Determine if an event is within the snapping tolerance of the start coord.
* @param {module:ol/MapBrowserEvent} event Event.
* @return {boolean} The event is within the snapping tolerance of the start.
* @private
*/
atFinish_(event) {
let at = false;
if (this.sketchFeature_) {
let potentiallyDone = false;
let potentiallyFinishCoordinates = [this.finishCoordinate_];
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]];
}
if (potentiallyDone) {
const map = event.map;
for (let i = 0, ii = potentiallyFinishCoordinates.length; i < ii; i++) {
const finishCoordinate = potentiallyFinishCoordinates[i];
const finishPixel = map.getPixelFromCoordinate(finishCoordinate);
const pixel = event.pixel;
const dx = pixel[0] - finishPixel[0];
const dy = pixel[1] - finishPixel[1];
const snapTolerance = this.freehand_ ? 1 : this.snapTolerance_;
at = Math.sqrt(dx * dx + dy * dy) <= snapTolerance;
if (at) {
this.finishCoordinate_ = finishCoordinate;
break;
}
}
}
}
return at;
}
/**
* @param {module:ol/MapBrowserEvent} event Event.
* @private
*/
createOrUpdateSketchPoint_(event) {
const coordinates = event.coordinate.slice();
if (!this.sketchPoint_) {
this.sketchPoint_ = new Feature(new Point(coordinates));
this.updateSketchFeatures_();
} else {
const sketchPointGeom = /** @type {module:ol/geom/Point} */ (this.sketchPoint_.getGeometry());
sketchPointGeom.setCoordinates(coordinates);
}
}
/**
* Start the drawing.
* @param {module:ol/MapBrowserEvent} event Event.
* @private
*/
startDrawing_(event) {
const start = event.coordinate;
this.finishCoordinate_ = start;
if (this.mode_ === Mode.POINT) {
this.sketchCoords_ = start.slice();
} else if (this.mode_ === Mode.POLYGON) {
this.sketchCoords_ = [[start.slice(), start.slice()]];
this.sketchLineCoords_ = this.sketchCoords_[0];
} else {
this.sketchCoords_ = [start.slice(), start.slice()];
}
if (this.sketchLineCoords_) {
this.sketchLine_ = new Feature(
new LineString(this.sketchLineCoords_));
}
const geometry = this.geometryFunction_(this.sketchCoords_);
this.sketchFeature_ = new Feature();
if (this.geometryName_) {
this.sketchFeature_.setGeometryName(this.geometryName_);
}
this.sketchFeature_.setGeometry(geometry);
this.updateSketchFeatures_();
this.dispatchEvent(new DrawEvent(DrawEventType.DRAWSTART, this.sketchFeature_));
}
/**
* Modify the drawing.
* @param {module:ol/MapBrowserEvent} event Event.
* @private
*/
modifyDrawing_(event) {
let coordinate = event.coordinate;
const geometry = /** @type {module:ol/geom/SimpleGeometry} */ (this.sketchFeature_.getGeometry());
let coordinates, last;
if (this.mode_ === Mode.POINT) {
last = this.sketchCoords_;
} else if (this.mode_ === Mode.POLYGON) {
coordinates = this.sketchCoords_[0];
last = coordinates[coordinates.length - 1];
if (this.atFinish_(event)) {
// snap to finish
coordinate = this.finishCoordinate_.slice();
}
} else {
coordinates = this.sketchCoords_;
last = coordinates[coordinates.length - 1];
}
last[0] = coordinate[0];
last[1] = coordinate[1];
this.geometryFunction_(/** @type {!Array.<module:ol/coordinate~Coordinate>} */ (this.sketchCoords_), geometry);
if (this.sketchPoint_) {
const sketchPointGeom = /** @type {module:ol/geom/Point} */ (this.sketchPoint_.getGeometry());
sketchPointGeom.setCoordinates(coordinate);
}
let sketchLineGeom;
if (geometry instanceof Polygon &&
this.mode_ !== Mode.POLYGON) {
if (!this.sketchLine_) {
this.sketchLine_ = new Feature();
}
const ring = geometry.getLinearRing(0);
sketchLineGeom = /** @type {module:ol/geom/LineString} */ (this.sketchLine_.getGeometry());
if (!sketchLineGeom) {
sketchLineGeom = new LineString(ring.getFlatCoordinates(), ring.getLayout());
this.sketchLine_.setGeometry(sketchLineGeom);
} else {
sketchLineGeom.setFlatCoordinates(
ring.getLayout(), ring.getFlatCoordinates());
sketchLineGeom.changed();
}
} else if (this.sketchLineCoords_) {
sketchLineGeom = /** @type {module:ol/geom/LineString} */ (this.sketchLine_.getGeometry());
sketchLineGeom.setCoordinates(this.sketchLineCoords_);
}
this.updateSketchFeatures_();
}
/**
* Add a new coordinate to the drawing.
* @param {module:ol/MapBrowserEvent} event Event.
* @private
*/
addToDrawing_(event) {
const coordinate = event.coordinate;
const geometry = /** @type {module:ol/geom/SimpleGeometry} */ (this.sketchFeature_.getGeometry());
let done;
let coordinates;
if (this.mode_ === Mode.LINE_STRING) {
this.finishCoordinate_ = coordinate.slice();
coordinates = this.sketchCoords_;
if (coordinates.length >= this.maxPoints_) {
if (this.freehand_) {
coordinates.pop();
} else {
done = true;
}
}
coordinates.push(coordinate.slice());
this.geometryFunction_(coordinates, geometry);
} else if (this.mode_ === Mode.POLYGON) {
coordinates = this.sketchCoords_[0];
if (coordinates.length >= this.maxPoints_) {
if (this.freehand_) {
coordinates.pop();
} else {
done = true;
}
}
coordinates.push(coordinate.slice());
if (done) {
this.finishCoordinate_ = coordinates[0];
}
this.geometryFunction_(this.sketchCoords_, geometry);
}
this.updateSketchFeatures_();
if (done) {
this.finishDrawing();
}
}
/**
* Remove last point of the feature currently being drawn.
* @api
*/
removeLastPoint() {
if (!this.sketchFeature_) {
return;
}
const geometry = /** @type {module:ol/geom/SimpleGeometry} */ (this.sketchFeature_.getGeometry());
let coordinates, sketchLineGeom;
if (this.mode_ === Mode.LINE_STRING) {
coordinates = 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.splice(-2, 1);
sketchLineGeom = /** @type {module:ol/geom/LineString} */ (this.sketchLine_.getGeometry());
sketchLineGeom.setCoordinates(coordinates);
this.geometryFunction_(this.sketchCoords_, geometry);
}
if (coordinates.length === 0) {
this.finishCoordinate_ = null;
}
this.updateSketchFeatures_();
}
/**
* Stop drawing and add the sketch feature to the target layer.
* The {@link module:ol/interaction/Draw~DrawEventType.DRAWEND} event is
* dispatched before inserting the feature.
* @api
*/
finishDrawing() {
const sketchFeature = this.abortDrawing_();
if (!sketchFeature) {
return;
}
let coordinates = this.sketchCoords_;
const geometry = /** @type {module:ol/geom/SimpleGeometry} */ (sketchFeature.getGeometry());
if (this.mode_ === Mode.LINE_STRING) {
// remove the redundant last point
coordinates.pop();
this.geometryFunction_(coordinates, geometry);
} else if (this.mode_ === Mode.POLYGON) {
// remove the redundant last point in ring
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]));
} else if (this.type_ === GeometryType.MULTI_LINE_STRING) {
sketchFeature.setGeometry(new MultiLineString([coordinates]));
} else if (this.type_ === GeometryType.MULTI_POLYGON) {
sketchFeature.setGeometry(new MultiPolygon([coordinates]));
}
// First dispatch event to allow full set up of feature
this.dispatchEvent(new DrawEvent(DrawEventType.DRAWEND, sketchFeature));
// Then insert feature
if (this.features_) {
this.features_.push(sketchFeature);
}
if (this.source_) {
this.source_.addFeature(sketchFeature);
}
}
/**
* Stop drawing without adding the sketch feature to the target layer.
* @return {module:ol/Feature} The sketch feature (or null if none).
* @private
*/
abortDrawing_() {
this.finishCoordinate_ = null;
const sketchFeature = this.sketchFeature_;
if (sketchFeature) {
this.sketchFeature_ = null;
this.sketchPoint_ = null;
this.sketchLine_ = null;
this.overlay_.getSource().clear(true);
}
return sketchFeature;
}
/**
* Extend an existing geometry by adding additional points. This only works
* on features with `LineString` geometries, where the interaction will
* extend lines by adding points to the end of the coordinates array.
* @param {!module:ol/Feature} feature Feature to be extended.
* @api
*/
extend(feature) {
const geometry = feature.getGeometry();
const lineString = /** @type {module:ol/geom/LineString} */ (geometry);
this.sketchFeature_ = feature;
this.sketchCoords_ = lineString.getCoordinates();
const last = this.sketchCoords_[this.sketchCoords_.length - 1];
this.finishCoordinate_ = last.slice();
this.sketchCoords_.push(last.slice());
this.updateSketchFeatures_();
this.dispatchEvent(new DrawEvent(DrawEventType.DRAWSTART, this.sketchFeature_));
}
/**
* Redraw the sketch features.
* @private
*/
updateSketchFeatures_() {
const sketchFeatures = [];
if (this.sketchFeature_) {
sketchFeatures.push(this.sketchFeature_);
}
if (this.sketchLine_) {
sketchFeatures.push(this.sketchLine_);
}
if (this.sketchPoint_) {
sketchFeatures.push(this.sketchPoint_);
}
const overlaySource = this.overlay_.getSource();
overlaySource.clear(true);
overlaySource.addFeatures(sketchFeatures);
}
/**
* @private
*/
updateState_() {
const map = this.getMap();
const active = this.getActive();
if (!map || !active) {
this.abortDrawing_();
}
this.overlay_.setMap(active ? map : null);
}
}
inherits(Draw, PointerInteraction); inherits(Draw, PointerInteraction);
@@ -446,15 +811,6 @@ function getDefaultStyleFunction() {
} }
/**
* @inheritDoc
*/
Draw.prototype.setMap = function(map) {
PointerInteraction.prototype.setMap.call(this, map);
this.updateState_();
};
/** /**
* Handles the {@link module:ol/MapBrowserEvent map browser event} and may actually * Handles the {@link module:ol/MapBrowserEvent map browser event} and may actually
* draw or finish the drawing. * draw or finish the drawing.
@@ -581,379 +937,12 @@ function handleUpEvent(event) {
} }
/**
* Handle move events.
* @param {module:ol/MapBrowserEvent} event A move event.
* @return {boolean} Pass the event to other interactions.
* @private
*/
Draw.prototype.handlePointerMove_ = function(event) {
if (this.downPx_ &&
((!this.freehand_ && this.shouldHandle_) ||
(this.freehand_ && !this.shouldHandle_))) {
const downPx = this.downPx_;
const clickPx = event.pixel;
const dx = downPx[0] - clickPx[0];
const dy = downPx[1] - clickPx[1];
const squaredDistance = dx * dx + dy * dy;
this.shouldHandle_ = this.freehand_ ?
squaredDistance > this.squaredClickTolerance_ :
squaredDistance <= this.squaredClickTolerance_;
if (!this.shouldHandle_) {
return true;
}
}
if (this.finishCoordinate_) {
this.modifyDrawing_(event);
} else {
this.createOrUpdateSketchPoint_(event);
}
return true;
};
/**
* Determine if an event is within the snapping tolerance of the start coord.
* @param {module:ol/MapBrowserEvent} event Event.
* @return {boolean} The event is within the snapping tolerance of the start.
* @private
*/
Draw.prototype.atFinish_ = function(event) {
let at = false;
if (this.sketchFeature_) {
let potentiallyDone = false;
let potentiallyFinishCoordinates = [this.finishCoordinate_];
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]];
}
if (potentiallyDone) {
const map = event.map;
for (let i = 0, ii = potentiallyFinishCoordinates.length; i < ii; i++) {
const finishCoordinate = potentiallyFinishCoordinates[i];
const finishPixel = map.getPixelFromCoordinate(finishCoordinate);
const pixel = event.pixel;
const dx = pixel[0] - finishPixel[0];
const dy = pixel[1] - finishPixel[1];
const snapTolerance = this.freehand_ ? 1 : this.snapTolerance_;
at = Math.sqrt(dx * dx + dy * dy) <= snapTolerance;
if (at) {
this.finishCoordinate_ = finishCoordinate;
break;
}
}
}
}
return at;
};
/**
* @param {module:ol/MapBrowserEvent} event Event.
* @private
*/
Draw.prototype.createOrUpdateSketchPoint_ = function(event) {
const coordinates = event.coordinate.slice();
if (!this.sketchPoint_) {
this.sketchPoint_ = new Feature(new Point(coordinates));
this.updateSketchFeatures_();
} else {
const sketchPointGeom = /** @type {module:ol/geom/Point} */ (this.sketchPoint_.getGeometry());
sketchPointGeom.setCoordinates(coordinates);
}
};
/**
* Start the drawing.
* @param {module:ol/MapBrowserEvent} event Event.
* @private
*/
Draw.prototype.startDrawing_ = function(event) {
const start = event.coordinate;
this.finishCoordinate_ = start;
if (this.mode_ === Mode.POINT) {
this.sketchCoords_ = start.slice();
} else if (this.mode_ === Mode.POLYGON) {
this.sketchCoords_ = [[start.slice(), start.slice()]];
this.sketchLineCoords_ = this.sketchCoords_[0];
} else {
this.sketchCoords_ = [start.slice(), start.slice()];
}
if (this.sketchLineCoords_) {
this.sketchLine_ = new Feature(
new LineString(this.sketchLineCoords_));
}
const geometry = this.geometryFunction_(this.sketchCoords_);
this.sketchFeature_ = new Feature();
if (this.geometryName_) {
this.sketchFeature_.setGeometryName(this.geometryName_);
}
this.sketchFeature_.setGeometry(geometry);
this.updateSketchFeatures_();
this.dispatchEvent(new DrawEvent(DrawEventType.DRAWSTART, this.sketchFeature_));
};
/**
* Modify the drawing.
* @param {module:ol/MapBrowserEvent} event Event.
* @private
*/
Draw.prototype.modifyDrawing_ = function(event) {
let coordinate = event.coordinate;
const geometry = /** @type {module:ol/geom/SimpleGeometry} */ (this.sketchFeature_.getGeometry());
let coordinates, last;
if (this.mode_ === Mode.POINT) {
last = this.sketchCoords_;
} else if (this.mode_ === Mode.POLYGON) {
coordinates = this.sketchCoords_[0];
last = coordinates[coordinates.length - 1];
if (this.atFinish_(event)) {
// snap to finish
coordinate = this.finishCoordinate_.slice();
}
} else {
coordinates = this.sketchCoords_;
last = coordinates[coordinates.length - 1];
}
last[0] = coordinate[0];
last[1] = coordinate[1];
this.geometryFunction_(/** @type {!Array.<module:ol/coordinate~Coordinate>} */ (this.sketchCoords_), geometry);
if (this.sketchPoint_) {
const sketchPointGeom = /** @type {module:ol/geom/Point} */ (this.sketchPoint_.getGeometry());
sketchPointGeom.setCoordinates(coordinate);
}
let sketchLineGeom;
if (geometry instanceof Polygon &&
this.mode_ !== Mode.POLYGON) {
if (!this.sketchLine_) {
this.sketchLine_ = new Feature();
}
const ring = geometry.getLinearRing(0);
sketchLineGeom = /** @type {module:ol/geom/LineString} */ (this.sketchLine_.getGeometry());
if (!sketchLineGeom) {
sketchLineGeom = new LineString(ring.getFlatCoordinates(), ring.getLayout());
this.sketchLine_.setGeometry(sketchLineGeom);
} else {
sketchLineGeom.setFlatCoordinates(
ring.getLayout(), ring.getFlatCoordinates());
sketchLineGeom.changed();
}
} else if (this.sketchLineCoords_) {
sketchLineGeom = /** @type {module:ol/geom/LineString} */ (this.sketchLine_.getGeometry());
sketchLineGeom.setCoordinates(this.sketchLineCoords_);
}
this.updateSketchFeatures_();
};
/**
* Add a new coordinate to the drawing.
* @param {module:ol/MapBrowserEvent} event Event.
* @private
*/
Draw.prototype.addToDrawing_ = function(event) {
const coordinate = event.coordinate;
const geometry = /** @type {module:ol/geom/SimpleGeometry} */ (this.sketchFeature_.getGeometry());
let done;
let coordinates;
if (this.mode_ === Mode.LINE_STRING) {
this.finishCoordinate_ = coordinate.slice();
coordinates = this.sketchCoords_;
if (coordinates.length >= this.maxPoints_) {
if (this.freehand_) {
coordinates.pop();
} else {
done = true;
}
}
coordinates.push(coordinate.slice());
this.geometryFunction_(coordinates, geometry);
} else if (this.mode_ === Mode.POLYGON) {
coordinates = this.sketchCoords_[0];
if (coordinates.length >= this.maxPoints_) {
if (this.freehand_) {
coordinates.pop();
} else {
done = true;
}
}
coordinates.push(coordinate.slice());
if (done) {
this.finishCoordinate_ = coordinates[0];
}
this.geometryFunction_(this.sketchCoords_, geometry);
}
this.updateSketchFeatures_();
if (done) {
this.finishDrawing();
}
};
/**
* Remove last point of the feature currently being drawn.
* @api
*/
Draw.prototype.removeLastPoint = function() {
if (!this.sketchFeature_) {
return;
}
const geometry = /** @type {module:ol/geom/SimpleGeometry} */ (this.sketchFeature_.getGeometry());
let coordinates, sketchLineGeom;
if (this.mode_ === Mode.LINE_STRING) {
coordinates = 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.splice(-2, 1);
sketchLineGeom = /** @type {module:ol/geom/LineString} */ (this.sketchLine_.getGeometry());
sketchLineGeom.setCoordinates(coordinates);
this.geometryFunction_(this.sketchCoords_, geometry);
}
if (coordinates.length === 0) {
this.finishCoordinate_ = null;
}
this.updateSketchFeatures_();
};
/**
* Stop drawing and add the sketch feature to the target layer.
* The {@link module:ol/interaction/Draw~DrawEventType.DRAWEND} event is
* dispatched before inserting the feature.
* @api
*/
Draw.prototype.finishDrawing = function() {
const sketchFeature = this.abortDrawing_();
if (!sketchFeature) {
return;
}
let coordinates = this.sketchCoords_;
const geometry = /** @type {module:ol/geom/SimpleGeometry} */ (sketchFeature.getGeometry());
if (this.mode_ === Mode.LINE_STRING) {
// remove the redundant last point
coordinates.pop();
this.geometryFunction_(coordinates, geometry);
} else if (this.mode_ === Mode.POLYGON) {
// remove the redundant last point in ring
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]));
} else if (this.type_ === GeometryType.MULTI_LINE_STRING) {
sketchFeature.setGeometry(new MultiLineString([coordinates]));
} else if (this.type_ === GeometryType.MULTI_POLYGON) {
sketchFeature.setGeometry(new MultiPolygon([coordinates]));
}
// First dispatch event to allow full set up of feature
this.dispatchEvent(new DrawEvent(DrawEventType.DRAWEND, sketchFeature));
// Then insert feature
if (this.features_) {
this.features_.push(sketchFeature);
}
if (this.source_) {
this.source_.addFeature(sketchFeature);
}
};
/**
* Stop drawing without adding the sketch feature to the target layer.
* @return {module:ol/Feature} The sketch feature (or null if none).
* @private
*/
Draw.prototype.abortDrawing_ = function() {
this.finishCoordinate_ = null;
const sketchFeature = this.sketchFeature_;
if (sketchFeature) {
this.sketchFeature_ = null;
this.sketchPoint_ = null;
this.sketchLine_ = null;
this.overlay_.getSource().clear(true);
}
return sketchFeature;
};
/**
* Extend an existing geometry by adding additional points. This only works
* on features with `LineString` geometries, where the interaction will
* extend lines by adding points to the end of the coordinates array.
* @param {!module:ol/Feature} feature Feature to be extended.
* @api
*/
Draw.prototype.extend = function(feature) {
const geometry = feature.getGeometry();
const lineString = /** @type {module:ol/geom/LineString} */ (geometry);
this.sketchFeature_ = feature;
this.sketchCoords_ = lineString.getCoordinates();
const last = this.sketchCoords_[this.sketchCoords_.length - 1];
this.finishCoordinate_ = last.slice();
this.sketchCoords_.push(last.slice());
this.updateSketchFeatures_();
this.dispatchEvent(new DrawEvent(DrawEventType.DRAWSTART, this.sketchFeature_));
};
/** /**
* @inheritDoc * @inheritDoc
*/ */
Draw.prototype.shouldStopEvent = FALSE; Draw.prototype.shouldStopEvent = FALSE;
/**
* Redraw the sketch features.
* @private
*/
Draw.prototype.updateSketchFeatures_ = function() {
const sketchFeatures = [];
if (this.sketchFeature_) {
sketchFeatures.push(this.sketchFeature_);
}
if (this.sketchLine_) {
sketchFeatures.push(this.sketchLine_);
}
if (this.sketchPoint_) {
sketchFeatures.push(this.sketchPoint_);
}
const overlaySource = this.overlay_.getSource();
overlaySource.clear(true);
overlaySource.addFeatures(sketchFeatures);
};
/**
* @private
*/
Draw.prototype.updateState_ = function() {
const map = this.getMap();
const active = this.getActive();
if (!map || !active) {
this.abortDrawing_();
}
this.overlay_.setMap(active ? map : null);
};
/** /**
* Create a `geometryFunction` for `type: 'Circle'` that will create a regular * 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 * polygon with a user specified number of sides and start angle instead of an
+137 -137
View File
@@ -82,7 +82,8 @@ inherits(ExtentInteractionEvent, Event);
* @param {module:ol/interaction/Extent~Options=} opt_options Options. * @param {module:ol/interaction/Extent~Options=} opt_options Options.
* @api * @api
*/ */
const ExtentInteraction = function(opt_options) { class ExtentInteraction {
constructor(opt_options) {
const options = opt_options || {}; const options = opt_options || {};
@@ -173,7 +174,141 @@ const ExtentInteraction = function(opt_options) {
if (opt_options.extent) { if (opt_options.extent) {
this.setExtent(opt_options.extent); this.setExtent(opt_options.extent);
} }
}; }
/**
* @param {module:ol~Pixel} pixel cursor location
* @param {module:ol/PluggableMap} map map
* @returns {module:ol/coordinate~Coordinate|null} snapped vertex on extent
* @private
*/
snapToVertex_(pixel, map) {
const pixelCoordinate = map.getCoordinateFromPixel(pixel);
const sortByDistance = function(a, b) {
return squaredDistanceToSegment(pixelCoordinate, a) -
squaredDistanceToSegment(pixelCoordinate, b);
};
const extent = this.getExtent();
if (extent) {
//convert extents to line segments and find the segment closest to pixelCoordinate
const segments = getSegments(extent);
segments.sort(sortByDistance);
const closestSegment = segments[0];
let vertex = (closestOnSegment(pixelCoordinate,
closestSegment));
const vertexPixel = map.getPixelFromCoordinate(vertex);
//if the distance is within tolerance, snap to the segment
if (coordinateDistance(pixel, vertexPixel) <= this.pixelTolerance_) {
//test if we should further snap to a vertex
const pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
const pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
const squaredDist1 = squaredCoordinateDistance(vertexPixel, pixel1);
const squaredDist2 = squaredCoordinateDistance(vertexPixel, pixel2);
const dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
this.snappedToVertex_ = dist <= this.pixelTolerance_;
if (this.snappedToVertex_) {
vertex = squaredDist1 > squaredDist2 ?
closestSegment[1] : closestSegment[0];
}
return vertex;
}
}
return null;
}
/**
* @param {module:ol/MapBrowserEvent} mapBrowserEvent pointer move event
* @private
*/
handlePointerMove_(mapBrowserEvent) {
const pixel = mapBrowserEvent.pixel;
const map = mapBrowserEvent.map;
let vertex = this.snapToVertex_(pixel, map);
if (!vertex) {
vertex = map.getCoordinateFromPixel(pixel);
}
this.createOrUpdatePointerFeature_(vertex);
}
/**
* @param {module:ol/extent~Extent} extent extent
* @returns {module:ol/Feature} extent as featrue
* @private
*/
createOrUpdateExtentFeature_(extent) {
let extentFeature = this.extentFeature_;
if (!extentFeature) {
if (!extent) {
extentFeature = new Feature({});
} else {
extentFeature = new Feature(polygonFromExtent(extent));
}
this.extentFeature_ = extentFeature;
this.extentOverlay_.getSource().addFeature(extentFeature);
} else {
if (!extent) {
extentFeature.setGeometry(undefined);
} else {
extentFeature.setGeometry(polygonFromExtent(extent));
}
}
return extentFeature;
}
/**
* @param {module:ol/coordinate~Coordinate} vertex location of feature
* @returns {module:ol/Feature} vertex as feature
* @private
*/
createOrUpdatePointerFeature_(vertex) {
let vertexFeature = this.vertexFeature_;
if (!vertexFeature) {
vertexFeature = new Feature(new Point(vertex));
this.vertexFeature_ = vertexFeature;
this.vertexOverlay_.getSource().addFeature(vertexFeature);
} else {
const geometry = /** @type {module:ol/geom/Point} */ (vertexFeature.getGeometry());
geometry.setCoordinates(vertex);
}
return vertexFeature;
}
/**
* @inheritDoc
*/
setMap(map) {
this.extentOverlay_.setMap(map);
this.vertexOverlay_.setMap(map);
PointerInteraction.prototype.setMap.call(this, map);
}
/**
* Returns the current drawn extent in the view projection
*
* @return {module:ol/extent~Extent} Drawn extent in the view projection.
* @api
*/
getExtent() {
return this.extent_;
}
/**
* Manually sets the drawn extent, using the view projection.
*
* @param {module:ol/extent~Extent} extent Extent
* @api
*/
setExtent(extent) {
//Null extent means no bbox
this.extent_ = extent ? extent : null;
this.createOrUpdateExtentFeature_(extent);
this.dispatchEvent(new ExtentInteractionEvent(this.extent_));
}
}
inherits(ExtentInteraction, PointerInteraction); inherits(ExtentInteraction, PointerInteraction);
@@ -350,140 +485,5 @@ function getSegments(extent) {
]; ];
} }
/**
* @param {module:ol~Pixel} pixel cursor location
* @param {module:ol/PluggableMap} map map
* @returns {module:ol/coordinate~Coordinate|null} snapped vertex on extent
* @private
*/
ExtentInteraction.prototype.snapToVertex_ = function(pixel, map) {
const pixelCoordinate = map.getCoordinateFromPixel(pixel);
const sortByDistance = function(a, b) {
return squaredDistanceToSegment(pixelCoordinate, a) -
squaredDistanceToSegment(pixelCoordinate, b);
};
const extent = this.getExtent();
if (extent) {
//convert extents to line segments and find the segment closest to pixelCoordinate
const segments = getSegments(extent);
segments.sort(sortByDistance);
const closestSegment = segments[0];
let vertex = (closestOnSegment(pixelCoordinate,
closestSegment));
const vertexPixel = map.getPixelFromCoordinate(vertex);
//if the distance is within tolerance, snap to the segment
if (coordinateDistance(pixel, vertexPixel) <= this.pixelTolerance_) {
//test if we should further snap to a vertex
const pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
const pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
const squaredDist1 = squaredCoordinateDistance(vertexPixel, pixel1);
const squaredDist2 = squaredCoordinateDistance(vertexPixel, pixel2);
const dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
this.snappedToVertex_ = dist <= this.pixelTolerance_;
if (this.snappedToVertex_) {
vertex = squaredDist1 > squaredDist2 ?
closestSegment[1] : closestSegment[0];
}
return vertex;
}
}
return null;
};
/**
* @param {module:ol/MapBrowserEvent} mapBrowserEvent pointer move event
* @private
*/
ExtentInteraction.prototype.handlePointerMove_ = function(mapBrowserEvent) {
const pixel = mapBrowserEvent.pixel;
const map = mapBrowserEvent.map;
let vertex = this.snapToVertex_(pixel, map);
if (!vertex) {
vertex = map.getCoordinateFromPixel(pixel);
}
this.createOrUpdatePointerFeature_(vertex);
};
/**
* @param {module:ol/extent~Extent} extent extent
* @returns {module:ol/Feature} extent as featrue
* @private
*/
ExtentInteraction.prototype.createOrUpdateExtentFeature_ = function(extent) {
let extentFeature = this.extentFeature_;
if (!extentFeature) {
if (!extent) {
extentFeature = new Feature({});
} else {
extentFeature = new Feature(polygonFromExtent(extent));
}
this.extentFeature_ = extentFeature;
this.extentOverlay_.getSource().addFeature(extentFeature);
} else {
if (!extent) {
extentFeature.setGeometry(undefined);
} else {
extentFeature.setGeometry(polygonFromExtent(extent));
}
}
return extentFeature;
};
/**
* @param {module:ol/coordinate~Coordinate} vertex location of feature
* @returns {module:ol/Feature} vertex as feature
* @private
*/
ExtentInteraction.prototype.createOrUpdatePointerFeature_ = function(vertex) {
let vertexFeature = this.vertexFeature_;
if (!vertexFeature) {
vertexFeature = new Feature(new Point(vertex));
this.vertexFeature_ = vertexFeature;
this.vertexOverlay_.getSource().addFeature(vertexFeature);
} else {
const geometry = /** @type {module:ol/geom/Point} */ (vertexFeature.getGeometry());
geometry.setCoordinates(vertex);
}
return vertexFeature;
};
/**
* @inheritDoc
*/
ExtentInteraction.prototype.setMap = function(map) {
this.extentOverlay_.setMap(map);
this.vertexOverlay_.setMap(map);
PointerInteraction.prototype.setMap.call(this, map);
};
/**
* Returns the current drawn extent in the view projection
*
* @return {module:ol/extent~Extent} Drawn extent in the view projection.
* @api
*/
ExtentInteraction.prototype.getExtent = function() {
return this.extent_;
};
/**
* Manually sets the drawn extent, using the view projection.
*
* @param {module:ol/extent~Extent} extent Extent
* @api
*/
ExtentInteraction.prototype.setExtent = function(extent) {
//Null extent means no bbox
this.extent_ = extent ? extent : null;
this.createOrUpdateExtentFeature_(extent);
this.dispatchEvent(new ExtentInteractionEvent(this.extent_));
};
export default ExtentInteraction; export default ExtentInteraction;
+18 -20
View File
@@ -36,7 +36,8 @@ import {clamp} from '../math.js';
* @extends {module:ol/Object} * @extends {module:ol/Object}
* @api * @api
*/ */
const Interaction = function(options) { class Interaction {
constructor(options) {
BaseObject.call(this); BaseObject.call(this);
@@ -53,52 +54,49 @@ const Interaction = function(options) {
*/ */
this.handleEvent = options.handleEvent; this.handleEvent = options.handleEvent;
}; }
inherits(Interaction, BaseObject); /**
/**
* Return whether the interaction is currently active. * Return whether the interaction is currently active.
* @return {boolean} `true` if the interaction is active, `false` otherwise. * @return {boolean} `true` if the interaction is active, `false` otherwise.
* @observable * @observable
* @api * @api
*/ */
Interaction.prototype.getActive = function() { getActive() {
return /** @type {boolean} */ (this.get(InteractionProperty.ACTIVE)); return /** @type {boolean} */ (this.get(InteractionProperty.ACTIVE));
}; }
/**
/**
* Get the map associated with this interaction. * Get the map associated with this interaction.
* @return {module:ol/PluggableMap} Map. * @return {module:ol/PluggableMap} Map.
* @api * @api
*/ */
Interaction.prototype.getMap = function() { getMap() {
return this.map_; return this.map_;
}; }
/**
/**
* Activate or deactivate the interaction. * Activate or deactivate the interaction.
* @param {boolean} active Active. * @param {boolean} active Active.
* @observable * @observable
* @api * @api
*/ */
Interaction.prototype.setActive = function(active) { setActive(active) {
this.set(InteractionProperty.ACTIVE, active); this.set(InteractionProperty.ACTIVE, active);
}; }
/**
/**
* Remove the interaction from its current map and attach it to the new map. * Remove the interaction from its current map and attach it to the new map.
* Subclasses may set up event handlers to get notified about changes to * Subclasses may set up event handlers to get notified about changes to
* the map here. * the map here.
* @param {module:ol/PluggableMap} map Map. * @param {module:ol/PluggableMap} map Map.
*/ */
Interaction.prototype.setMap = function(map) { setMap(map) {
this.map_ = map; this.map_ = map;
}; }
}
inherits(Interaction, BaseObject);
/** /**
File diff suppressed because it is too large Load Diff
+45 -46
View File
@@ -53,7 +53,8 @@ export const Mode = {
* @param {module:ol/interaction/MouseWheelZoom~Options=} opt_options Options. * @param {module:ol/interaction/MouseWheelZoom~Options=} opt_options Options.
* @api * @api
*/ */
const MouseWheelZoom = function(opt_options) { class MouseWheelZoom {
constructor(opt_options) {
Interaction.call(this, { Interaction.call(this, {
handleEvent: handleEvent handleEvent: handleEvent
@@ -147,7 +148,49 @@ const MouseWheelZoom = function(opt_options) {
*/ */
this.trackpadZoomBuffer_ = 1.5; this.trackpadZoomBuffer_ = 1.5;
}; }
/**
* @private
*/
decrementInteractingHint_() {
this.trackpadTimeoutId_ = undefined;
const view = this.getMap().getView();
view.setHint(ViewHint.INTERACTING, -1);
}
/**
* @private
* @param {module:ol/PluggableMap} map Map.
*/
handleWheelZoom_(map) {
const view = map.getView();
if (view.getAnimating()) {
view.cancelAnimations();
}
const maxDelta = MAX_DELTA;
const delta = clamp(this.delta_, -maxDelta, maxDelta);
zoomByDelta(view, -delta, this.lastAnchor_, this.duration_);
this.mode_ = undefined;
this.delta_ = 0;
this.lastAnchor_ = null;
this.startTime_ = undefined;
this.timeoutId_ = undefined;
}
/**
* Enable or disable using the mouse's location as an anchor when zooming
* @param {boolean} useAnchor true to zoom to the mouse's location, false
* to zoom to the center of the map
* @api
*/
setMouseAnchor(useAnchor) {
this.useAnchor_ = useAnchor;
if (!useAnchor) {
this.lastAnchor_ = null;
}
}
}
inherits(MouseWheelZoom, Interaction); inherits(MouseWheelZoom, Interaction);
@@ -276,48 +319,4 @@ function handleEvent(mapBrowserEvent) {
} }
/**
* @private
*/
MouseWheelZoom.prototype.decrementInteractingHint_ = function() {
this.trackpadTimeoutId_ = undefined;
const view = this.getMap().getView();
view.setHint(ViewHint.INTERACTING, -1);
};
/**
* @private
* @param {module:ol/PluggableMap} map Map.
*/
MouseWheelZoom.prototype.handleWheelZoom_ = function(map) {
const view = map.getView();
if (view.getAnimating()) {
view.cancelAnimations();
}
const maxDelta = MAX_DELTA;
const delta = clamp(this.delta_, -maxDelta, maxDelta);
zoomByDelta(view, -delta, this.lastAnchor_, this.duration_);
this.mode_ = undefined;
this.delta_ = 0;
this.lastAnchor_ = null;
this.startTime_ = undefined;
this.timeoutId_ = undefined;
};
/**
* Enable or disable using the mouse's location as an anchor when zooming
* @param {boolean} useAnchor true to zoom to the mouse's location, false
* to zoom to the center of the map
* @api
*/
MouseWheelZoom.prototype.setMouseAnchor = function(useAnchor) {
this.useAnchor_ = useAnchor;
if (!useAnchor) {
this.lastAnchor_ = null;
}
};
export default MouseWheelZoom; export default MouseWheelZoom;
+43 -42
View File
@@ -77,7 +77,8 @@ const handleMoveEvent = UNDEFINED;
* @extends {module:ol/interaction/Interaction} * @extends {module:ol/interaction/Interaction}
* @api * @api
*/ */
const PointerInteraction = function(opt_options) { class PointerInteraction {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
@@ -131,7 +132,47 @@ const PointerInteraction = function(opt_options) {
*/ */
this.targetPointers = []; this.targetPointers = [];
}; }
/**
* @param {module:ol/MapBrowserPointerEvent} mapBrowserEvent Event.
* @private
*/
updateTrackedPointers_(mapBrowserEvent) {
if (isPointerDraggingEvent(mapBrowserEvent)) {
const event = mapBrowserEvent.pointerEvent;
const id = event.pointerId.toString();
if (mapBrowserEvent.type == MapBrowserEventType.POINTERUP) {
delete this.trackedPointers_[id];
} else if (mapBrowserEvent.type ==
MapBrowserEventType.POINTERDOWN) {
this.trackedPointers_[id] = event;
} else if (id in this.trackedPointers_) {
// update only when there was a pointerdown event for this pointer
this.trackedPointers_[id] = event;
}
this.targetPointers = getValues(this.trackedPointers_);
}
}
/**
* This method is used to determine if "down" events should be propagated to
* other interactions or should be stopped.
*
* The method receives the return code of the "handleDownEvent" function.
*
* By default this function is the "identity" function. It's overridden in
* child classes.
*
* @param {boolean} handled Was the event handled by the interaction?
* @return {boolean} Should the event be stopped?
* @protected
*/
shouldStopEvent(handled) {
return handled;
}
}
inherits(PointerInteraction, Interaction); inherits(PointerInteraction, Interaction);
@@ -165,29 +206,6 @@ function isPointerDraggingEvent(mapBrowserEvent) {
} }
/**
* @param {module:ol/MapBrowserPointerEvent} mapBrowserEvent Event.
* @private
*/
PointerInteraction.prototype.updateTrackedPointers_ = function(mapBrowserEvent) {
if (isPointerDraggingEvent(mapBrowserEvent)) {
const event = mapBrowserEvent.pointerEvent;
const id = event.pointerId.toString();
if (mapBrowserEvent.type == MapBrowserEventType.POINTERUP) {
delete this.trackedPointers_[id];
} else if (mapBrowserEvent.type ==
MapBrowserEventType.POINTERDOWN) {
this.trackedPointers_[id] = event;
} else if (id in this.trackedPointers_) {
// update only when there was a pointerdown event for this pointer
this.trackedPointers_[id] = event;
}
this.targetPointers = getValues(this.trackedPointers_);
}
};
/** /**
* Handles the {@link module:ol/MapBrowserEvent map browser event} and may call into * 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 * other functions, if event sequences like e.g. 'drag' or 'down-up' etc. are
@@ -224,21 +242,4 @@ export function handleEvent(mapBrowserEvent) {
} }
/**
* This method is used to determine if "down" events should be propagated to
* other interactions or should be stopped.
*
* The method receives the return code of the "handleDownEvent" function.
*
* By default this function is the "identity" function. It's overridden in
* child classes.
*
* @param {boolean} handled Was the event handled by the interaction?
* @return {boolean} Should the event be stopped?
* @protected
*/
PointerInteraction.prototype.shouldStopEvent = function(handled) {
return handled;
};
export default PointerInteraction; export default PointerInteraction;
+81 -88
View File
@@ -156,7 +156,8 @@ inherits(SelectEvent, Event);
* @fires SelectEvent * @fires SelectEvent
* @api * @api
*/ */
const Select = function(opt_options) { class Select {
constructor(opt_options) {
Interaction.call(this, { Interaction.call(this, {
handleEvent: handleEvent handleEvent: handleEvent
@@ -259,43 +260,37 @@ const Select = function(opt_options) {
listen(features, CollectionEventType.REMOVE, listen(features, CollectionEventType.REMOVE,
this.removeFeature_, this); this.removeFeature_, this);
}; }
inherits(Select, Interaction); /**
/**
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
* @param {module:ol/layer/Layer} layer Layer. * @param {module:ol/layer/Layer} layer Layer.
* @private * @private
*/ */
Select.prototype.addFeatureLayerAssociation_ = function(feature, layer) { addFeatureLayerAssociation_(feature, layer) {
const key = getUid(feature); const key = getUid(feature);
this.featureLayerAssociation_[key] = layer; this.featureLayerAssociation_[key] = layer;
}; }
/**
/**
* Get the selected features. * Get the selected features.
* @return {module:ol/Collection.<module:ol/Feature>} Features collection. * @return {module:ol/Collection.<module:ol/Feature>} Features collection.
* @api * @api
*/ */
Select.prototype.getFeatures = function() { getFeatures() {
return this.featureOverlay_.getSource().getFeaturesCollection(); return this.featureOverlay_.getSource().getFeaturesCollection();
}; }
/**
/**
* Returns the Hit-detection tolerance. * Returns the Hit-detection tolerance.
* @returns {number} Hit tolerance in pixels. * @returns {number} Hit tolerance in pixels.
* @api * @api
*/ */
Select.prototype.getHitTolerance = function() { getHitTolerance() {
return this.hitTolerance_; return this.hitTolerance_;
}; }
/**
/**
* Returns the associated {@link module:ol/layer/Vector~Vector vectorlayer} of * Returns the associated {@link module:ol/layer/Vector~Vector vectorlayer} of
* the (last) selected feature. Note that this will not work with any * the (last) selected feature. Note that this will not work with any
* programmatic method like pushing features to * programmatic method like pushing features to
@@ -304,12 +299,78 @@ Select.prototype.getHitTolerance = function() {
* @return {module:ol/layer/Vector} Layer. * @return {module:ol/layer/Vector} Layer.
* @api * @api
*/ */
Select.prototype.getLayer = function(feature) { getLayer(feature) {
const key = getUid(feature); const key = getUid(feature);
return ( return (
/** @type {module:ol/layer/Vector} */ (this.featureLayerAssociation_[key]) /** @type {module:ol/layer/Vector} */ (this.featureLayerAssociation_[key])
); );
}; }
/**
* Hit-detection tolerance. Pixels inside the radius around the given position
* will be checked for features. This only works for the canvas renderer and
* not for WebGL.
* @param {number} hitTolerance Hit tolerance in pixels.
* @api
*/
setHitTolerance(hitTolerance) {
this.hitTolerance_ = hitTolerance;
}
/**
* Remove the interaction from its current map, if any, and attach it to a new
* map, if any. Pass `null` to just remove the interaction from the current map.
* @param {module:ol/PluggableMap} map Map.
* @override
* @api
*/
setMap(map) {
const currentMap = this.getMap();
const selectedFeatures =
this.featureOverlay_.getSource().getFeaturesCollection();
if (currentMap) {
selectedFeatures.forEach(currentMap.unskipFeature.bind(currentMap));
}
Interaction.prototype.setMap.call(this, map);
this.featureOverlay_.setMap(map);
if (map) {
selectedFeatures.forEach(map.skipFeature.bind(map));
}
}
/**
* @param {module:ol/Collection~CollectionEvent} evt Event.
* @private
*/
addFeature_(evt) {
const map = this.getMap();
if (map) {
map.skipFeature(/** @type {module:ol/Feature} */ (evt.element));
}
}
/**
* @param {module:ol/Collection~CollectionEvent} evt Event.
* @private
*/
removeFeature_(evt) {
const map = this.getMap();
if (map) {
map.unskipFeature(/** @type {module:ol/Feature} */ (evt.element));
}
}
/**
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
* @private
*/
removeFeatureLayerAssociation_(feature) {
const key = getUid(feature);
delete this.featureLayerAssociation_[key];
}
}
inherits(Select, Interaction);
/** /**
@@ -405,40 +466,6 @@ function handleEvent(mapBrowserEvent) {
} }
/**
* Hit-detection tolerance. Pixels inside the radius around the given position
* will be checked for features. This only works for the canvas renderer and
* not for WebGL.
* @param {number} hitTolerance Hit tolerance in pixels.
* @api
*/
Select.prototype.setHitTolerance = function(hitTolerance) {
this.hitTolerance_ = hitTolerance;
};
/**
* Remove the interaction from its current map, if any, and attach it to a new
* map, if any. Pass `null` to just remove the interaction from the current map.
* @param {module:ol/PluggableMap} map Map.
* @override
* @api
*/
Select.prototype.setMap = function(map) {
const currentMap = this.getMap();
const selectedFeatures =
this.featureOverlay_.getSource().getFeaturesCollection();
if (currentMap) {
selectedFeatures.forEach(currentMap.unskipFeature.bind(currentMap));
}
Interaction.prototype.setMap.call(this, map);
this.featureOverlay_.setMap(map);
if (map) {
selectedFeatures.forEach(map.skipFeature.bind(map));
}
};
/** /**
* @return {module:ol/style/Style~StyleFunction} Styles. * @return {module:ol/style/Style~StyleFunction} Styles.
*/ */
@@ -456,38 +483,4 @@ function getDefaultStyleFunction() {
} }
/**
* @param {module:ol/Collection~CollectionEvent} evt Event.
* @private
*/
Select.prototype.addFeature_ = function(evt) {
const map = this.getMap();
if (map) {
map.skipFeature(/** @type {module:ol/Feature} */ (evt.element));
}
};
/**
* @param {module:ol/Collection~CollectionEvent} evt Event.
* @private
*/
Select.prototype.removeFeature_ = function(evt) {
const map = this.getMap();
if (map) {
map.unskipFeature(/** @type {module:ol/Feature} */ (evt.element));
}
};
/**
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
* @private
*/
Select.prototype.removeFeatureLayerAssociation_ = function(feature) {
const key = getUid(feature);
delete this.featureLayerAssociation_[key];
};
export default Select; export default Select;
+69 -86
View File
@@ -68,7 +68,8 @@ import RBush from '../structs/RBush.js';
* @param {module:ol/interaction/Snap~Options=} opt_options Options. * @param {module:ol/interaction/Snap~Options=} opt_options Options.
* @api * @api
*/ */
const Snap = function(opt_options) { class Snap {
constructor(opt_options) {
PointerInteraction.call(this, { PointerInteraction.call(this, {
handleEvent: handleEvent, handleEvent: handleEvent,
@@ -176,19 +177,16 @@ const Snap = function(opt_options) {
'GeometryCollection': this.writeGeometryCollectionGeometry_, 'GeometryCollection': this.writeGeometryCollectionGeometry_,
'Circle': this.writeCircleGeometry_ 'Circle': this.writeCircleGeometry_
}; };
}; }
inherits(Snap, PointerInteraction); /**
/**
* Add a feature to the collection of features that we may snap to. * Add a feature to the collection of features that we may snap to.
* @param {module:ol/Feature} feature Feature. * @param {module:ol/Feature} feature Feature.
* @param {boolean=} opt_listen Whether to listen to the feature change or not * @param {boolean=} opt_listen Whether to listen to the feature change or not
* Defaults to `true`. * Defaults to `true`.
* @api * @api
*/ */
Snap.prototype.addFeature = function(feature, opt_listen) { addFeature(feature, opt_listen) {
const register = opt_listen !== undefined ? opt_listen : true; const register = opt_listen !== undefined ? opt_listen : true;
const feature_uid = getUid(feature); const feature_uid = getUid(feature);
const geometry = feature.getGeometry(); const geometry = feature.getGeometry();
@@ -206,32 +204,29 @@ Snap.prototype.addFeature = function(feature, opt_listen) {
EventType.CHANGE, EventType.CHANGE,
this.handleFeatureChange_, this); this.handleFeatureChange_, this);
} }
}; }
/**
/**
* @param {module:ol/Feature} feature Feature. * @param {module:ol/Feature} feature Feature.
* @private * @private
*/ */
Snap.prototype.forEachFeatureAdd_ = function(feature) { forEachFeatureAdd_(feature) {
this.addFeature(feature); this.addFeature(feature);
}; }
/**
/**
* @param {module:ol/Feature} feature Feature. * @param {module:ol/Feature} feature Feature.
* @private * @private
*/ */
Snap.prototype.forEachFeatureRemove_ = function(feature) { forEachFeatureRemove_(feature) {
this.removeFeature(feature); this.removeFeature(feature);
}; }
/**
/**
* @return {module:ol/Collection.<module:ol/Feature>|Array.<module:ol/Feature>} Features. * @return {module:ol/Collection.<module:ol/Feature>|Array.<module:ol/Feature>} Features.
* @private * @private
*/ */
Snap.prototype.getFeatures_ = function() { getFeatures_() {
let features; let features;
if (this.features_) { if (this.features_) {
features = this.features_; features = this.features_;
@@ -241,14 +236,13 @@ Snap.prototype.getFeatures_ = function() {
return ( return (
/** @type {!Array.<module:ol/Feature>|!module:ol/Collection.<module:ol/Feature>} */ (features) /** @type {!Array.<module:ol/Feature>|!module:ol/Collection.<module:ol/Feature>} */ (features)
); );
}; }
/**
/**
* @param {module:ol/source/Vector|module:ol/Collection~CollectionEvent} evt Event. * @param {module:ol/source/Vector|module:ol/Collection~CollectionEvent} evt Event.
* @private * @private
*/ */
Snap.prototype.handleFeatureAdd_ = function(evt) { handleFeatureAdd_(evt) {
let feature; let feature;
if (evt instanceof VectorSourceEvent) { if (evt instanceof VectorSourceEvent) {
feature = evt.feature; feature = evt.feature;
@@ -256,14 +250,13 @@ Snap.prototype.handleFeatureAdd_ = function(evt) {
feature = evt.element; feature = evt.element;
} }
this.addFeature(/** @type {module:ol/Feature} */ (feature)); this.addFeature(/** @type {module:ol/Feature} */ (feature));
}; }
/**
/**
* @param {module:ol/source/Vector|module:ol/Collection~CollectionEvent} evt Event. * @param {module:ol/source/Vector|module:ol/Collection~CollectionEvent} evt Event.
* @private * @private
*/ */
Snap.prototype.handleFeatureRemove_ = function(evt) { handleFeatureRemove_(evt) {
let feature; let feature;
if (evt instanceof VectorSourceEvent) { if (evt instanceof VectorSourceEvent) {
feature = evt.feature; feature = evt.feature;
@@ -271,14 +264,13 @@ Snap.prototype.handleFeatureRemove_ = function(evt) {
feature = evt.element; feature = evt.element;
} }
this.removeFeature(/** @type {module:ol/Feature} */ (feature)); this.removeFeature(/** @type {module:ol/Feature} */ (feature));
}; }
/**
/**
* @param {module:ol/events/Event} evt Event. * @param {module:ol/events/Event} evt Event.
* @private * @private
*/ */
Snap.prototype.handleFeatureChange_ = function(evt) { handleFeatureChange_(evt) {
const feature = /** @type {module:ol/Feature} */ (evt.target); const feature = /** @type {module:ol/Feature} */ (evt.target);
if (this.handlingDownUpSequence) { if (this.handlingDownUpSequence) {
const uid = getUid(feature); const uid = getUid(feature);
@@ -288,17 +280,16 @@ Snap.prototype.handleFeatureChange_ = function(evt) {
} else { } else {
this.updateFeature_(feature); this.updateFeature_(feature);
} }
}; }
/**
/**
* Remove a feature from the collection of features that we may snap to. * Remove a feature from the collection of features that we may snap to.
* @param {module:ol/Feature} feature Feature * @param {module:ol/Feature} feature Feature
* @param {boolean=} opt_unlisten Whether to unlisten to the feature change * @param {boolean=} opt_unlisten Whether to unlisten to the feature change
* or not. Defaults to `true`. * or not. Defaults to `true`.
* @api * @api
*/ */
Snap.prototype.removeFeature = function(feature, opt_unlisten) { removeFeature(feature, opt_unlisten) {
const unregister = opt_unlisten !== undefined ? opt_unlisten : true; const unregister = opt_unlisten !== undefined ? opt_unlisten : true;
const feature_uid = getUid(feature); const feature_uid = getUid(feature);
const extent = this.indexedFeaturesExtents_[feature_uid]; const extent = this.indexedFeaturesExtents_[feature_uid];
@@ -319,13 +310,12 @@ Snap.prototype.removeFeature = function(feature, opt_unlisten) {
unlistenByKey(this.featureChangeListenerKeys_[feature_uid]); unlistenByKey(this.featureChangeListenerKeys_[feature_uid]);
delete this.featureChangeListenerKeys_[feature_uid]; delete this.featureChangeListenerKeys_[feature_uid];
} }
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Snap.prototype.setMap = function(map) { setMap(map) {
const currentMap = this.getMap(); const currentMap = this.getMap();
const keys = this.featuresListenerKeys_; const keys = this.featuresListenerKeys_;
const features = this.getFeatures_(); const features = this.getFeatures_();
@@ -355,22 +345,15 @@ Snap.prototype.setMap = function(map) {
} }
features.forEach(this.forEachFeatureAdd_.bind(this)); features.forEach(this.forEachFeatureAdd_.bind(this));
} }
}; }
/**
/**
* @inheritDoc
*/
Snap.prototype.shouldStopEvent = FALSE;
/**
* @param {module:ol~Pixel} pixel Pixel * @param {module:ol~Pixel} pixel Pixel
* @param {module:ol/coordinate~Coordinate} pixelCoordinate Coordinate * @param {module:ol/coordinate~Coordinate} pixelCoordinate Coordinate
* @param {module:ol/PluggableMap} map Map. * @param {module:ol/PluggableMap} map Map.
* @return {module:ol/interaction/Snap~Result} Snap result * @return {module:ol/interaction/Snap~Result} Snap result
*/ */
Snap.prototype.snapTo = function(pixel, pixelCoordinate, map) { snapTo(pixel, pixelCoordinate, map) {
const lowerLeft = map.getCoordinateFromPixel( const lowerLeft = map.getCoordinateFromPixel(
[pixel[0] - this.pixelTolerance_, pixel[1] + this.pixelTolerance_]); [pixel[0] - this.pixelTolerance_, pixel[1] + this.pixelTolerance_]);
@@ -446,25 +429,23 @@ Snap.prototype.snapTo = function(pixel, pixelCoordinate, map) {
vertexPixel: vertexPixel vertexPixel: vertexPixel
}) })
); );
}; }
/**
/**
* @param {module:ol/Feature} feature Feature * @param {module:ol/Feature} feature Feature
* @private * @private
*/ */
Snap.prototype.updateFeature_ = function(feature) { updateFeature_(feature) {
this.removeFeature(feature, false); this.removeFeature(feature, false);
this.addFeature(feature, false); this.addFeature(feature, false);
}; }
/**
/**
* @param {module:ol/Feature} feature Feature * @param {module:ol/Feature} feature Feature
* @param {module:ol/geom/Circle} geometry Geometry. * @param {module:ol/geom/Circle} geometry Geometry.
* @private * @private
*/ */
Snap.prototype.writeCircleGeometry_ = function(feature, geometry) { writeCircleGeometry_(feature, geometry) {
const polygon = fromCircle(geometry); const polygon = fromCircle(geometry);
const coordinates = polygon.getCoordinates()[0]; const coordinates = polygon.getCoordinates()[0];
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) { for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
@@ -475,15 +456,14 @@ Snap.prototype.writeCircleGeometry_ = function(feature, geometry) {
}); });
this.rBush_.insert(boundingExtent(segment), segmentData); this.rBush_.insert(boundingExtent(segment), segmentData);
} }
}; }
/**
/**
* @param {module:ol/Feature} feature Feature * @param {module:ol/Feature} feature Feature
* @param {module:ol/geom/GeometryCollection} geometry Geometry. * @param {module:ol/geom/GeometryCollection} geometry Geometry.
* @private * @private
*/ */
Snap.prototype.writeGeometryCollectionGeometry_ = function(feature, geometry) { writeGeometryCollectionGeometry_(feature, geometry) {
const geometries = geometry.getGeometriesArray(); const geometries = geometry.getGeometriesArray();
for (let i = 0; i < geometries.length; ++i) { for (let i = 0; i < geometries.length; ++i) {
const segmentWriter = this.SEGMENT_WRITERS_[geometries[i].getType()]; const segmentWriter = this.SEGMENT_WRITERS_[geometries[i].getType()];
@@ -491,15 +471,14 @@ Snap.prototype.writeGeometryCollectionGeometry_ = function(feature, geometry) {
segmentWriter.call(this, feature, geometries[i]); segmentWriter.call(this, feature, geometries[i]);
} }
} }
}; }
/**
/**
* @param {module:ol/Feature} feature Feature * @param {module:ol/Feature} feature Feature
* @param {module:ol/geom/LineString} geometry Geometry. * @param {module:ol/geom/LineString} geometry Geometry.
* @private * @private
*/ */
Snap.prototype.writeLineStringGeometry_ = function(feature, geometry) { writeLineStringGeometry_(feature, geometry) {
const coordinates = geometry.getCoordinates(); const coordinates = geometry.getCoordinates();
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) { for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
const segment = coordinates.slice(i, i + 2); const segment = coordinates.slice(i, i + 2);
@@ -509,15 +488,14 @@ Snap.prototype.writeLineStringGeometry_ = function(feature, geometry) {
}); });
this.rBush_.insert(boundingExtent(segment), segmentData); this.rBush_.insert(boundingExtent(segment), segmentData);
} }
}; }
/**
/**
* @param {module:ol/Feature} feature Feature * @param {module:ol/Feature} feature Feature
* @param {module:ol/geom/MultiLineString} geometry Geometry. * @param {module:ol/geom/MultiLineString} geometry Geometry.
* @private * @private
*/ */
Snap.prototype.writeMultiLineStringGeometry_ = function(feature, geometry) { writeMultiLineStringGeometry_(feature, geometry) {
const lines = geometry.getCoordinates(); const lines = geometry.getCoordinates();
for (let j = 0, jj = lines.length; j < jj; ++j) { for (let j = 0, jj = lines.length; j < jj; ++j) {
const coordinates = lines[j]; const coordinates = lines[j];
@@ -530,15 +508,14 @@ Snap.prototype.writeMultiLineStringGeometry_ = function(feature, geometry) {
this.rBush_.insert(boundingExtent(segment), segmentData); this.rBush_.insert(boundingExtent(segment), segmentData);
} }
} }
}; }
/**
/**
* @param {module:ol/Feature} feature Feature * @param {module:ol/Feature} feature Feature
* @param {module:ol/geom/MultiPoint} geometry Geometry. * @param {module:ol/geom/MultiPoint} geometry Geometry.
* @private * @private
*/ */
Snap.prototype.writeMultiPointGeometry_ = function(feature, geometry) { writeMultiPointGeometry_(feature, geometry) {
const points = geometry.getCoordinates(); const points = geometry.getCoordinates();
for (let i = 0, ii = points.length; i < ii; ++i) { for (let i = 0, ii = points.length; i < ii; ++i) {
const coordinates = points[i]; const coordinates = points[i];
@@ -548,15 +525,14 @@ Snap.prototype.writeMultiPointGeometry_ = function(feature, geometry) {
}); });
this.rBush_.insert(geometry.getExtent(), segmentData); this.rBush_.insert(geometry.getExtent(), segmentData);
} }
}; }
/**
/**
* @param {module:ol/Feature} feature Feature * @param {module:ol/Feature} feature Feature
* @param {module:ol/geom/MultiPolygon} geometry Geometry. * @param {module:ol/geom/MultiPolygon} geometry Geometry.
* @private * @private
*/ */
Snap.prototype.writeMultiPolygonGeometry_ = function(feature, geometry) { writeMultiPolygonGeometry_(feature, geometry) {
const polygons = geometry.getCoordinates(); const polygons = geometry.getCoordinates();
for (let k = 0, kk = polygons.length; k < kk; ++k) { for (let k = 0, kk = polygons.length; k < kk; ++k) {
const rings = polygons[k]; const rings = polygons[k];
@@ -572,30 +548,28 @@ Snap.prototype.writeMultiPolygonGeometry_ = function(feature, geometry) {
} }
} }
} }
}; }
/**
/**
* @param {module:ol/Feature} feature Feature * @param {module:ol/Feature} feature Feature
* @param {module:ol/geom/Point} geometry Geometry. * @param {module:ol/geom/Point} geometry Geometry.
* @private * @private
*/ */
Snap.prototype.writePointGeometry_ = function(feature, geometry) { writePointGeometry_(feature, geometry) {
const coordinates = geometry.getCoordinates(); const coordinates = geometry.getCoordinates();
const segmentData = /** @type {module:ol/interaction/Snap~SegmentData} */ ({ const segmentData = /** @type {module:ol/interaction/Snap~SegmentData} */ ({
feature: feature, feature: feature,
segment: [coordinates, coordinates] segment: [coordinates, coordinates]
}); });
this.rBush_.insert(geometry.getExtent(), segmentData); this.rBush_.insert(geometry.getExtent(), segmentData);
}; }
/**
/**
* @param {module:ol/Feature} feature Feature * @param {module:ol/Feature} feature Feature
* @param {module:ol/geom/Polygon} geometry Geometry. * @param {module:ol/geom/Polygon} geometry Geometry.
* @private * @private
*/ */
Snap.prototype.writePolygonGeometry_ = function(feature, geometry) { writePolygonGeometry_(feature, geometry) {
const rings = geometry.getCoordinates(); const rings = geometry.getCoordinates();
for (let j = 0, jj = rings.length; j < jj; ++j) { for (let j = 0, jj = rings.length; j < jj; ++j) {
const coordinates = rings[j]; const coordinates = rings[j];
@@ -608,7 +582,16 @@ Snap.prototype.writePolygonGeometry_ = function(feature, geometry) {
this.rBush_.insert(boundingExtent(segment), segmentData); this.rBush_.insert(boundingExtent(segment), segmentData);
} }
} }
}; }
}
inherits(Snap, PointerInteraction);
/**
* @inheritDoc
*/
Snap.prototype.shouldStopEvent = FALSE;
/** /**
+77 -81
View File
@@ -96,7 +96,8 @@ inherits(TranslateEvent, Event);
* @param {module:ol/interaction/Translate~Options=} opt_options Options. * @param {module:ol/interaction/Translate~Options=} opt_options Options.
* @api * @api
*/ */
const Translate = function(opt_options) { class Translate {
constructor(opt_options) {
PointerInteraction.call(this, { PointerInteraction.call(this, {
handleDownEvent: handleDownEvent, handleDownEvent: handleDownEvent,
handleDragEvent: handleDragEvent, handleDragEvent: handleDragEvent,
@@ -157,7 +158,81 @@ const Translate = function(opt_options) {
getChangeEventType(InteractionProperty.ACTIVE), getChangeEventType(InteractionProperty.ACTIVE),
this.handleActiveChanged_, this); this.handleActiveChanged_, this);
}; }
/**
* Tests to see if the given coordinates intersects any of our selected
* features.
* @param {module:ol~Pixel} pixel Pixel coordinate to test for intersection.
* @param {module:ol/PluggableMap} map Map to test the intersection on.
* @return {module:ol/Feature} Returns the feature found at the specified pixel
* coordinates.
* @private
*/
featuresAtPixel_(pixel, map) {
return map.forEachFeatureAtPixel(pixel,
function(feature) {
if (!this.features_ || includes(this.features_.getArray(), feature)) {
return feature;
}
}.bind(this), {
layerFilter: this.layerFilter_,
hitTolerance: this.hitTolerance_
});
}
/**
* Returns the Hit-detection tolerance.
* @returns {number} Hit tolerance in pixels.
* @api
*/
getHitTolerance() {
return this.hitTolerance_;
}
/**
* Hit-detection tolerance. Pixels inside the radius around the given position
* will be checked for features. This only works for the canvas renderer and
* not for WebGL.
* @param {number} hitTolerance Hit tolerance in pixels.
* @api
*/
setHitTolerance(hitTolerance) {
this.hitTolerance_ = hitTolerance;
}
/**
* @inheritDoc
*/
setMap(map) {
const oldMap = this.getMap();
PointerInteraction.prototype.setMap.call(this, map);
this.updateState_(oldMap);
}
/**
* @private
*/
handleActiveChanged_() {
this.updateState_(null);
}
/**
* @param {module:ol/PluggableMap} oldMap Old map.
* @private
*/
updateState_(oldMap) {
let map = this.getMap();
const active = this.getActive();
if (!map || !active) {
map = map || oldMap;
if (map) {
const elem = map.getViewport();
elem.classList.remove('ol-grab', 'ol-grabbing');
}
}
}
}
inherits(Translate, PointerInteraction); inherits(Translate, PointerInteraction);
@@ -252,83 +327,4 @@ function handleMoveEvent(event) {
} }
/**
* Tests to see if the given coordinates intersects any of our selected
* features.
* @param {module:ol~Pixel} pixel Pixel coordinate to test for intersection.
* @param {module:ol/PluggableMap} map Map to test the intersection on.
* @return {module:ol/Feature} Returns the feature found at the specified pixel
* coordinates.
* @private
*/
Translate.prototype.featuresAtPixel_ = function(pixel, map) {
return map.forEachFeatureAtPixel(pixel,
function(feature) {
if (!this.features_ || includes(this.features_.getArray(), feature)) {
return feature;
}
}.bind(this), {
layerFilter: this.layerFilter_,
hitTolerance: this.hitTolerance_
});
};
/**
* Returns the Hit-detection tolerance.
* @returns {number} Hit tolerance in pixels.
* @api
*/
Translate.prototype.getHitTolerance = function() {
return this.hitTolerance_;
};
/**
* Hit-detection tolerance. Pixels inside the radius around the given position
* will be checked for features. This only works for the canvas renderer and
* not for WebGL.
* @param {number} hitTolerance Hit tolerance in pixels.
* @api
*/
Translate.prototype.setHitTolerance = function(hitTolerance) {
this.hitTolerance_ = hitTolerance;
};
/**
* @inheritDoc
*/
Translate.prototype.setMap = function(map) {
const oldMap = this.getMap();
PointerInteraction.prototype.setMap.call(this, map);
this.updateState_(oldMap);
};
/**
* @private
*/
Translate.prototype.handleActiveChanged_ = function() {
this.updateState_(null);
};
/**
* @param {module:ol/PluggableMap} oldMap Old map.
* @private
*/
Translate.prototype.updateState_ = function(oldMap) {
let map = this.getMap();
const active = this.getActive();
if (!map || !active) {
map = map || oldMap;
if (map) {
const elem = map.getViewport();
elem.classList.remove('ol-grab', 'ol-grabbing');
}
}
};
export default Translate; export default Translate;
+56 -69
View File
@@ -37,7 +37,8 @@ import {assign} from '../obj.js';
* @param {module:ol/layer/Base~Options} options Layer options. * @param {module:ol/layer/Base~Options} options Layer options.
* @api * @api
*/ */
const BaseLayer = function(options) { class BaseLayer {
constructor(options) {
BaseObject.call(this); BaseObject.call(this);
@@ -74,24 +75,20 @@ const BaseLayer = function(options) {
*/ */
this.type; this.type;
}; }
inherits(BaseLayer, BaseObject); /**
/**
* Get the layer type (used when creating a layer renderer). * Get the layer type (used when creating a layer renderer).
* @return {module:ol/LayerType} The layer type. * @return {module:ol/LayerType} The layer type.
*/ */
BaseLayer.prototype.getType = function() { getType() {
return this.type; return this.type;
}; }
/**
/**
* @return {module:ol/layer/Layer~State} Layer state. * @return {module:ol/layer/Layer~State} Layer state.
*/ */
BaseLayer.prototype.getLayerState = function() { getLayerState() {
this.state_.opacity = clamp(this.getOpacity(), 0, 1); this.state_.opacity = clamp(this.getOpacity(), 0, 1);
this.state_.sourceState = this.getSourceState(); this.state_.sourceState = this.getSourceState();
this.state_.visible = this.getVisible(); this.state_.visible = this.getVisible();
@@ -101,168 +98,158 @@ BaseLayer.prototype.getLayerState = function() {
this.state_.minResolution = Math.max(this.getMinResolution(), 0); this.state_.minResolution = Math.max(this.getMinResolution(), 0);
return this.state_; return this.state_;
}; }
/**
/**
* @abstract * @abstract
* @param {Array.<module:ol/layer/Layer>=} opt_array Array of layers (to be * @param {Array.<module:ol/layer/Layer>=} opt_array Array of layers (to be
* modified in place). * modified in place).
* @return {Array.<module:ol/layer/Layer>} Array of layers. * @return {Array.<module:ol/layer/Layer>} Array of layers.
*/ */
BaseLayer.prototype.getLayersArray = function(opt_array) {}; getLayersArray(opt_array) {}
/**
/**
* @abstract * @abstract
* @param {Array.<module:ol/layer/Layer~State>=} opt_states Optional list of layer * @param {Array.<module:ol/layer/Layer~State>=} opt_states Optional list of layer
* states (to be modified in place). * states (to be modified in place).
* @return {Array.<module:ol/layer/Layer~State>} List of layer states. * @return {Array.<module:ol/layer/Layer~State>} List of layer states.
*/ */
BaseLayer.prototype.getLayerStatesArray = function(opt_states) {}; getLayerStatesArray(opt_states) {}
/**
/**
* Return the {@link module:ol/extent~Extent extent} of the layer or `undefined` if it * Return the {@link module:ol/extent~Extent extent} of the layer or `undefined` if it
* will be visible regardless of extent. * will be visible regardless of extent.
* @return {module:ol/extent~Extent|undefined} The layer extent. * @return {module:ol/extent~Extent|undefined} The layer extent.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.getExtent = function() { getExtent() {
return ( return (
/** @type {module:ol/extent~Extent|undefined} */ (this.get(LayerProperty.EXTENT)) /** @type {module:ol/extent~Extent|undefined} */ (this.get(LayerProperty.EXTENT))
); );
}; }
/**
/**
* Return the maximum resolution of the layer. * Return the maximum resolution of the layer.
* @return {number} The maximum resolution of the layer. * @return {number} The maximum resolution of the layer.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.getMaxResolution = function() { getMaxResolution() {
return /** @type {number} */ (this.get(LayerProperty.MAX_RESOLUTION)); return /** @type {number} */ (this.get(LayerProperty.MAX_RESOLUTION));
}; }
/**
/**
* Return the minimum resolution of the layer. * Return the minimum resolution of the layer.
* @return {number} The minimum resolution of the layer. * @return {number} The minimum resolution of the layer.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.getMinResolution = function() { getMinResolution() {
return /** @type {number} */ (this.get(LayerProperty.MIN_RESOLUTION)); return /** @type {number} */ (this.get(LayerProperty.MIN_RESOLUTION));
}; }
/**
/**
* Return the opacity of the layer (between 0 and 1). * Return the opacity of the layer (between 0 and 1).
* @return {number} The opacity of the layer. * @return {number} The opacity of the layer.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.getOpacity = function() { getOpacity() {
return /** @type {number} */ (this.get(LayerProperty.OPACITY)); return /** @type {number} */ (this.get(LayerProperty.OPACITY));
}; }
/**
/**
* @abstract * @abstract
* @return {module:ol/source/State} Source state. * @return {module:ol/source/State} Source state.
*/ */
BaseLayer.prototype.getSourceState = function() {}; getSourceState() {}
/**
/**
* Return the visibility of the layer (`true` or `false`). * Return the visibility of the layer (`true` or `false`).
* @return {boolean} The visibility of the layer. * @return {boolean} The visibility of the layer.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.getVisible = function() { getVisible() {
return /** @type {boolean} */ (this.get(LayerProperty.VISIBLE)); return /** @type {boolean} */ (this.get(LayerProperty.VISIBLE));
}; }
/**
/**
* Return the Z-index of the layer, which is used to order layers before * Return the Z-index of the layer, which is used to order layers before
* rendering. The default Z-index is 0. * rendering. The default Z-index is 0.
* @return {number} The Z-index of the layer. * @return {number} The Z-index of the layer.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.getZIndex = function() { getZIndex() {
return /** @type {number} */ (this.get(LayerProperty.Z_INDEX)); return /** @type {number} */ (this.get(LayerProperty.Z_INDEX));
}; }
/**
/**
* Set the extent at which the layer is visible. If `undefined`, the layer * Set the extent at which the layer is visible. If `undefined`, the layer
* will be visible at all extents. * will be visible at all extents.
* @param {module:ol/extent~Extent|undefined} extent The extent of the layer. * @param {module:ol/extent~Extent|undefined} extent The extent of the layer.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.setExtent = function(extent) { setExtent(extent) {
this.set(LayerProperty.EXTENT, extent); this.set(LayerProperty.EXTENT, extent);
}; }
/**
/**
* Set the maximum resolution at which the layer is visible. * Set the maximum resolution at which the layer is visible.
* @param {number} maxResolution The maximum resolution of the layer. * @param {number} maxResolution The maximum resolution of the layer.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.setMaxResolution = function(maxResolution) { setMaxResolution(maxResolution) {
this.set(LayerProperty.MAX_RESOLUTION, maxResolution); this.set(LayerProperty.MAX_RESOLUTION, maxResolution);
}; }
/**
/**
* Set the minimum resolution at which the layer is visible. * Set the minimum resolution at which the layer is visible.
* @param {number} minResolution The minimum resolution of the layer. * @param {number} minResolution The minimum resolution of the layer.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.setMinResolution = function(minResolution) { setMinResolution(minResolution) {
this.set(LayerProperty.MIN_RESOLUTION, minResolution); this.set(LayerProperty.MIN_RESOLUTION, minResolution);
}; }
/**
/**
* Set the opacity of the layer, allowed values range from 0 to 1. * Set the opacity of the layer, allowed values range from 0 to 1.
* @param {number} opacity The opacity of the layer. * @param {number} opacity The opacity of the layer.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.setOpacity = function(opacity) { setOpacity(opacity) {
this.set(LayerProperty.OPACITY, opacity); this.set(LayerProperty.OPACITY, opacity);
}; }
/**
/**
* Set the visibility of the layer (`true` or `false`). * Set the visibility of the layer (`true` or `false`).
* @param {boolean} visible The visibility of the layer. * @param {boolean} visible The visibility of the layer.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.setVisible = function(visible) { setVisible(visible) {
this.set(LayerProperty.VISIBLE, visible); this.set(LayerProperty.VISIBLE, visible);
}; }
/**
/**
* Set Z-index of the layer, which is used to order layers before rendering. * Set Z-index of the layer, which is used to order layers before rendering.
* The default Z-index is 0. * The default Z-index is 0.
* @param {number} zindex The z-index of the layer. * @param {number} zindex The z-index of the layer.
* @observable * @observable
* @api * @api
*/ */
BaseLayer.prototype.setZIndex = function(zindex) { setZIndex(zindex) {
this.set(LayerProperty.Z_INDEX, zindex); this.set(LayerProperty.Z_INDEX, zindex);
}; }
}
inherits(BaseLayer, BaseObject);
export default BaseLayer; export default BaseLayer;
+34 -40
View File
@@ -51,7 +51,8 @@ const Property = {
* @param {module:ol/layer/Group~Options=} opt_options Layer options. * @param {module:ol/layer/Group~Options=} opt_options Layer options.
* @api * @api
*/ */
const LayerGroup = function(opt_options) { class LayerGroup {
constructor(opt_options) {
const options = opt_options || {}; const options = opt_options || {};
const baseOptions = /** @type {module:ol/layer/Group~Options} */ (assign({}, options)); const baseOptions = /** @type {module:ol/layer/Group~Options} */ (assign({}, options));
@@ -91,24 +92,20 @@ const LayerGroup = function(opt_options) {
this.setLayers(layers); this.setLayers(layers);
}; }
inherits(LayerGroup, BaseLayer); /**
/**
* @private * @private
*/ */
LayerGroup.prototype.handleLayerChange_ = function() { handleLayerChange_() {
this.changed(); this.changed();
}; }
/**
/**
* @param {module:ol/events/Event} event Event. * @param {module:ol/events/Event} event Event.
* @private * @private
*/ */
LayerGroup.prototype.handleLayersChanged_ = function(event) { handleLayersChanged_(event) {
this.layersListenerKeys_.forEach(unlistenByKey); this.layersListenerKeys_.forEach(unlistenByKey);
this.layersListenerKeys_.length = 0; this.layersListenerKeys_.length = 0;
@@ -133,14 +130,13 @@ LayerGroup.prototype.handleLayersChanged_ = function(event) {
} }
this.changed(); this.changed();
}; }
/**
/**
* @param {module:ol/Collection~CollectionEvent} collectionEvent CollectionEvent. * @param {module:ol/Collection~CollectionEvent} collectionEvent CollectionEvent.
* @private * @private
*/ */
LayerGroup.prototype.handleLayersAdd_ = function(collectionEvent) { handleLayersAdd_(collectionEvent) {
const layer = /** @type {module:ol/layer/Base} */ (collectionEvent.element); const layer = /** @type {module:ol/layer/Base} */ (collectionEvent.element);
const key = getUid(layer).toString(); const key = getUid(layer).toString();
this.listenerKeys_[key] = [ this.listenerKeys_[key] = [
@@ -148,23 +144,21 @@ LayerGroup.prototype.handleLayersAdd_ = function(collectionEvent) {
listen(layer, EventType.CHANGE, this.handleLayerChange_, this) listen(layer, EventType.CHANGE, this.handleLayerChange_, this)
]; ];
this.changed(); this.changed();
}; }
/**
/**
* @param {module:ol/Collection~CollectionEvent} collectionEvent CollectionEvent. * @param {module:ol/Collection~CollectionEvent} collectionEvent CollectionEvent.
* @private * @private
*/ */
LayerGroup.prototype.handleLayersRemove_ = function(collectionEvent) { handleLayersRemove_(collectionEvent) {
const layer = /** @type {module:ol/layer/Base} */ (collectionEvent.element); const layer = /** @type {module:ol/layer/Base} */ (collectionEvent.element);
const key = getUid(layer).toString(); const key = getUid(layer).toString();
this.listenerKeys_[key].forEach(unlistenByKey); this.listenerKeys_[key].forEach(unlistenByKey);
delete this.listenerKeys_[key]; delete this.listenerKeys_[key];
this.changed(); this.changed();
}; }
/**
/**
* Returns the {@link module:ol/Collection collection} of {@link module:ol/layer/Layer~Layer layers} * Returns the {@link module:ol/Collection collection} of {@link module:ol/layer/Layer~Layer layers}
* in this group. * in this group.
* @return {!module:ol/Collection.<module:ol/layer/Base>} Collection of * @return {!module:ol/Collection.<module:ol/layer/Base>} Collection of
@@ -172,14 +166,13 @@ LayerGroup.prototype.handleLayersRemove_ = function(collectionEvent) {
* @observable * @observable
* @api * @api
*/ */
LayerGroup.prototype.getLayers = function() { getLayers() {
return ( return (
/** @type {!module:ol/Collection.<module:ol/layer/Base>} */ (this.get(Property.LAYERS)) /** @type {!module:ol/Collection.<module:ol/layer/Base>} */ (this.get(Property.LAYERS))
); );
}; }
/**
/**
* Set the {@link module:ol/Collection collection} of {@link module:ol/layer/Layer~Layer layers} * Set the {@link module:ol/Collection collection} of {@link module:ol/layer/Layer~Layer layers}
* in this group. * in this group.
* @param {!module:ol/Collection.<module:ol/layer/Base>} layers Collection of * @param {!module:ol/Collection.<module:ol/layer/Base>} layers Collection of
@@ -187,27 +180,25 @@ LayerGroup.prototype.getLayers = function() {
* @observable * @observable
* @api * @api
*/ */
LayerGroup.prototype.setLayers = function(layers) { setLayers(layers) {
this.set(Property.LAYERS, layers); this.set(Property.LAYERS, layers);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
LayerGroup.prototype.getLayersArray = function(opt_array) { getLayersArray(opt_array) {
const array = opt_array !== undefined ? opt_array : []; const array = opt_array !== undefined ? opt_array : [];
this.getLayers().forEach(function(layer) { this.getLayers().forEach(function(layer) {
layer.getLayersArray(array); layer.getLayersArray(array);
}); });
return array; return array;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
LayerGroup.prototype.getLayerStatesArray = function(opt_states) { getLayerStatesArray(opt_states) {
const states = opt_states !== undefined ? opt_states : []; const states = opt_states !== undefined ? opt_states : [];
const pos = states.length; const pos = states.length;
@@ -235,14 +226,17 @@ LayerGroup.prototype.getLayerStatesArray = function(opt_states) {
} }
return states; return states;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
LayerGroup.prototype.getSourceState = function() { getSourceState() {
return SourceState.READY; return SourceState.READY;
}; }
}
inherits(LayerGroup, BaseLayer);
export default LayerGroup; export default LayerGroup;
+120 -127
View File
@@ -73,7 +73,8 @@ const DEFAULT_GRADIENT = ['#00f', '#0ff', '#0f0', '#ff0', '#f00'];
* @param {module:ol/layer/Heatmap~Options=} opt_options Options. * @param {module:ol/layer/Heatmap~Options=} opt_options Options.
* @api * @api
*/ */
const Heatmap = function(opt_options) { class Heatmap {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
const baseOptions = assign({}, options); const baseOptions = assign({}, options);
@@ -163,7 +164,124 @@ const Heatmap = function(opt_options) {
this.setRenderOrder(null); this.setRenderOrder(null);
listen(this, RenderEventType.RENDER, this.handleRender_, this); listen(this, RenderEventType.RENDER, this.handleRender_, this);
}; }
/**
* @return {string} Data URL for a circle.
* @private
*/
createCircle_() {
const radius = this.getRadius();
const blur = this.getBlur();
const halfSize = radius + blur + 1;
const size = 2 * halfSize;
const context = createCanvasContext2D(size, size);
context.shadowOffsetX = context.shadowOffsetY = this.shadow_;
context.shadowBlur = blur;
context.shadowColor = '#000';
context.beginPath();
const center = halfSize - this.shadow_;
context.arc(center, center, radius, 0, Math.PI * 2, true);
context.fill();
return context.canvas.toDataURL();
}
/**
* Return the blur size in pixels.
* @return {number} Blur size in pixels.
* @api
* @observable
*/
getBlur() {
return /** @type {number} */ (this.get(Property.BLUR));
}
/**
* Return the gradient colors as array of strings.
* @return {Array.<string>} Colors.
* @api
* @observable
*/
getGradient() {
return /** @type {Array.<string>} */ (this.get(Property.GRADIENT));
}
/**
* Return the size of the radius in pixels.
* @return {number} Radius size in pixel.
* @api
* @observable
*/
getRadius() {
return /** @type {number} */ (this.get(Property.RADIUS));
}
/**
* @private
*/
handleGradientChanged_() {
this.gradient_ = createGradient(this.getGradient());
}
/**
* @private
*/
handleStyleChanged_() {
this.circleImage_ = this.createCircle_();
this.styleCache_ = new Array(256);
this.changed();
}
/**
* @param {module:ol/render/Event} event Post compose event
* @private
*/
handleRender_(event) {
const context = event.context;
const canvas = context.canvas;
const image = context.getImageData(0, 0, canvas.width, canvas.height);
const view8 = image.data;
for (let i = 0, ii = view8.length; i < ii; i += 4) {
const alpha = view8[i + 3] * 4;
if (alpha) {
view8[i] = this.gradient_[alpha];
view8[i + 1] = this.gradient_[alpha + 1];
view8[i + 2] = this.gradient_[alpha + 2];
}
}
context.putImageData(image, 0, 0);
}
/**
* Set the blur size in pixels.
* @param {number} blur Blur size in pixels.
* @api
* @observable
*/
setBlur(blur) {
this.set(Property.BLUR, blur);
}
/**
* Set the gradient colors as array of strings.
* @param {Array.<string>} colors Gradient.
* @api
* @observable
*/
setGradient(colors) {
this.set(Property.GRADIENT, colors);
}
/**
* Set the size of the radius in pixels.
* @param {number} radius Radius size in pixel.
* @api
* @observable
*/
setRadius(radius) {
this.set(Property.RADIUS, radius);
}
}
inherits(Heatmap, VectorLayer); inherits(Heatmap, VectorLayer);
@@ -191,129 +309,4 @@ const createGradient = function(colors) {
}; };
/**
* @return {string} Data URL for a circle.
* @private
*/
Heatmap.prototype.createCircle_ = function() {
const radius = this.getRadius();
const blur = this.getBlur();
const halfSize = radius + blur + 1;
const size = 2 * halfSize;
const context = createCanvasContext2D(size, size);
context.shadowOffsetX = context.shadowOffsetY = this.shadow_;
context.shadowBlur = blur;
context.shadowColor = '#000';
context.beginPath();
const center = halfSize - this.shadow_;
context.arc(center, center, radius, 0, Math.PI * 2, true);
context.fill();
return context.canvas.toDataURL();
};
/**
* Return the blur size in pixels.
* @return {number} Blur size in pixels.
* @api
* @observable
*/
Heatmap.prototype.getBlur = function() {
return /** @type {number} */ (this.get(Property.BLUR));
};
/**
* Return the gradient colors as array of strings.
* @return {Array.<string>} Colors.
* @api
* @observable
*/
Heatmap.prototype.getGradient = function() {
return /** @type {Array.<string>} */ (this.get(Property.GRADIENT));
};
/**
* Return the size of the radius in pixels.
* @return {number} Radius size in pixel.
* @api
* @observable
*/
Heatmap.prototype.getRadius = function() {
return /** @type {number} */ (this.get(Property.RADIUS));
};
/**
* @private
*/
Heatmap.prototype.handleGradientChanged_ = function() {
this.gradient_ = createGradient(this.getGradient());
};
/**
* @private
*/
Heatmap.prototype.handleStyleChanged_ = function() {
this.circleImage_ = this.createCircle_();
this.styleCache_ = new Array(256);
this.changed();
};
/**
* @param {module:ol/render/Event} event Post compose event
* @private
*/
Heatmap.prototype.handleRender_ = function(event) {
const context = event.context;
const canvas = context.canvas;
const image = context.getImageData(0, 0, canvas.width, canvas.height);
const view8 = image.data;
for (let i = 0, ii = view8.length; i < ii; i += 4) {
const alpha = view8[i + 3] * 4;
if (alpha) {
view8[i] = this.gradient_[alpha];
view8[i + 1] = this.gradient_[alpha + 1];
view8[i + 2] = this.gradient_[alpha + 2];
}
}
context.putImageData(image, 0, 0);
};
/**
* Set the blur size in pixels.
* @param {number} blur Blur size in pixels.
* @api
* @observable
*/
Heatmap.prototype.setBlur = function(blur) {
this.set(Property.BLUR, blur);
};
/**
* Set the gradient colors as array of strings.
* @param {Array.<string>} colors Gradient.
* @api
* @observable
*/
Heatmap.prototype.setGradient = function(colors) {
this.set(Property.GRADIENT, colors);
};
/**
* Set the size of the radius in pixels.
* @param {number} radius Radius size in pixel.
* @api
* @observable
*/
Heatmap.prototype.setRadius = function(radius) {
this.set(Property.RADIUS, radius);
};
export default Heatmap; export default Heatmap;
+46 -50
View File
@@ -66,7 +66,8 @@ import SourceState from '../source/State.js';
* @param {module:ol/layer/Layer~Options} options Layer options. * @param {module:ol/layer/Layer~Options} options Layer options.
* @api * @api
*/ */
const Layer = function(options) { class Layer {
constructor(options) {
const baseOptions = assign({}, options); const baseOptions = assign({}, options);
delete baseOptions.source; delete baseOptions.source;
@@ -101,80 +102,58 @@ const Layer = function(options) {
const source = options.source ? options.source : null; const source = options.source ? options.source : null;
this.setSource(source); this.setSource(source);
}; }
inherits(Layer, BaseLayer); /**
/**
* Return `true` if the layer is visible, and if the passed resolution is
* between the layer's minResolution and maxResolution. The comparison is
* inclusive for `minResolution` and exclusive for `maxResolution`.
* @param {module:ol/layer/Layer~State} layerState Layer state.
* @param {number} resolution Resolution.
* @return {boolean} The layer is visible at the given resolution.
*/
export function visibleAtResolution(layerState, resolution) {
return layerState.visible && resolution >= layerState.minResolution &&
resolution < layerState.maxResolution;
}
/**
* @inheritDoc * @inheritDoc
*/ */
Layer.prototype.getLayersArray = function(opt_array) { getLayersArray(opt_array) {
const array = opt_array ? opt_array : []; const array = opt_array ? opt_array : [];
array.push(this); array.push(this);
return array; return array;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Layer.prototype.getLayerStatesArray = function(opt_states) { getLayerStatesArray(opt_states) {
const states = opt_states ? opt_states : []; const states = opt_states ? opt_states : [];
states.push(this.getLayerState()); states.push(this.getLayerState());
return states; return states;
}; }
/**
/**
* Get the layer source. * Get the layer source.
* @return {module:ol/source/Source} The layer source (or `null` if not yet set). * @return {module:ol/source/Source} The layer source (or `null` if not yet set).
* @observable * @observable
* @api * @api
*/ */
Layer.prototype.getSource = function() { getSource() {
const source = this.get(LayerProperty.SOURCE); const source = this.get(LayerProperty.SOURCE);
return ( return (
/** @type {module:ol/source/Source} */ (source) || null /** @type {module:ol/source/Source} */ (source) || null
); );
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
Layer.prototype.getSourceState = function() { getSourceState() {
const source = this.getSource(); const source = this.getSource();
return !source ? SourceState.UNDEFINED : source.getState(); return !source ? SourceState.UNDEFINED : source.getState();
}; }
/**
/**
* @private * @private
*/ */
Layer.prototype.handleSourceChange_ = function() { handleSourceChange_() {
this.changed(); this.changed();
}; }
/**
/**
* @private * @private
*/ */
Layer.prototype.handleSourcePropertyChange_ = function() { handleSourcePropertyChange_() {
if (this.sourceChangeKey_) { if (this.sourceChangeKey_) {
unlistenByKey(this.sourceChangeKey_); unlistenByKey(this.sourceChangeKey_);
this.sourceChangeKey_ = null; this.sourceChangeKey_ = null;
@@ -185,10 +164,9 @@ Layer.prototype.handleSourcePropertyChange_ = function() {
EventType.CHANGE, this.handleSourceChange_, this); EventType.CHANGE, this.handleSourceChange_, this);
} }
this.changed(); this.changed();
}; }
/**
/**
* Sets the layer to be rendered on top of other layers on a map. The map will * Sets the layer to be rendered on top of other layers on a map. The map will
* not manage this layer in its layers collection, and the callback in * not manage this layer in its layers collection, and the callback in
* {@link module:ol/Map#forEachLayerAtPixel} will receive `null` as layer. This * {@link module:ol/Map#forEachLayerAtPixel} will receive `null` as layer. This
@@ -200,7 +178,7 @@ Layer.prototype.handleSourcePropertyChange_ = function() {
* @param {module:ol/PluggableMap} map Map. * @param {module:ol/PluggableMap} map Map.
* @api * @api
*/ */
Layer.prototype.setMap = function(map) { setMap(map) {
if (this.mapPrecomposeKey_) { if (this.mapPrecomposeKey_) {
unlistenByKey(this.mapPrecomposeKey_); unlistenByKey(this.mapPrecomposeKey_);
this.mapPrecomposeKey_ = null; this.mapPrecomposeKey_ = null;
@@ -223,16 +201,34 @@ Layer.prototype.setMap = function(map) {
this.mapRenderKey_ = listen(this, EventType.CHANGE, map.render, map); this.mapRenderKey_ = listen(this, EventType.CHANGE, map.render, map);
this.changed(); this.changed();
} }
}; }
/**
/**
* Set the layer source. * Set the layer source.
* @param {module:ol/source/Source} source The layer source. * @param {module:ol/source/Source} source The layer source.
* @observable * @observable
* @api * @api
*/ */
Layer.prototype.setSource = function(source) { setSource(source) {
this.set(LayerProperty.SOURCE, source); this.set(LayerProperty.SOURCE, source);
}; }
}
inherits(Layer, BaseLayer);
/**
* Return `true` if the layer is visible, and if the passed resolution is
* between the layer's minResolution and maxResolution. The comparison is
* inclusive for `minResolution` and exclusive for `maxResolution`.
* @param {module:ol/layer/Layer~State} layerState Layer state.
* @param {number} resolution Resolution.
* @return {boolean} The layer is visible at the given resolution.
*/
export function visibleAtResolution(layerState, resolution) {
return layerState.visible && resolution >= layerState.minResolution &&
resolution < layerState.maxResolution;
}
export default Layer; export default Layer;
+39 -39
View File
@@ -45,7 +45,8 @@ import {assign} from '../obj.js';
* @param {module:ol/layer/Tile~Options=} opt_options Tile layer options. * @param {module:ol/layer/Tile~Options=} opt_options Tile layer options.
* @api * @api
*/ */
const TileLayer = function(opt_options) { class TileLayer {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
const baseOptions = assign({}, options); const baseOptions = assign({}, options);
@@ -65,20 +66,50 @@ const TileLayer = function(opt_options) {
*/ */
this.type = LayerType.TILE; this.type = LayerType.TILE;
}; }
inherits(TileLayer, Layer); /**
/**
* Return the level as number to which we will preload tiles up to. * Return the level as number to which we will preload tiles up to.
* @return {number} The level to preload tiles up to. * @return {number} The level to preload tiles up to.
* @observable * @observable
* @api * @api
*/ */
TileLayer.prototype.getPreload = function() { getPreload() {
return /** @type {number} */ (this.get(TileProperty.PRELOAD)); return /** @type {number} */ (this.get(TileProperty.PRELOAD));
}; }
/**
* Set the level as number to which we will preload tiles up to.
* @param {number} preload The level to preload tiles up to.
* @observable
* @api
*/
setPreload(preload) {
this.set(TileProperty.PRELOAD, preload);
}
/**
* Whether we use interim tiles on error.
* @return {boolean} Use interim tiles on error.
* @observable
* @api
*/
getUseInterimTilesOnError() {
return /** @type {boolean} */ (this.get(TileProperty.USE_INTERIM_TILES_ON_ERROR));
}
/**
* Set whether we use interim tiles on error.
* @param {boolean} useInterimTilesOnError Use interim tiles on error.
* @observable
* @api
*/
setUseInterimTilesOnError(useInterimTilesOnError) {
this.set(TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);
}
}
inherits(TileLayer, Layer);
/** /**
@@ -90,35 +121,4 @@ TileLayer.prototype.getPreload = function() {
TileLayer.prototype.getSource; TileLayer.prototype.getSource;
/**
* Set the level as number to which we will preload tiles up to.
* @param {number} preload The level to preload tiles up to.
* @observable
* @api
*/
TileLayer.prototype.setPreload = function(preload) {
this.set(TileProperty.PRELOAD, preload);
};
/**
* Whether we use interim tiles on error.
* @return {boolean} Use interim tiles on error.
* @observable
* @api
*/
TileLayer.prototype.getUseInterimTilesOnError = function() {
return /** @type {boolean} */ (this.get(TileProperty.USE_INTERIM_TILES_ON_ERROR));
};
/**
* Set whether we use interim tiles on error.
* @param {boolean} useInterimTilesOnError Use interim tiles on error.
* @observable
* @api
*/
TileLayer.prototype.setUseInterimTilesOnError = function(useInterimTilesOnError) {
this.set(TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);
};
export default TileLayer; export default TileLayer;
+87 -96
View File
@@ -91,7 +91,8 @@ const Property = {
* @param {module:ol/layer/Vector~Options=} opt_options Options. * @param {module:ol/layer/Vector~Options=} opt_options Options.
* @api * @api
*/ */
const VectorLayer = function(opt_options) { class VectorLayer {
constructor(opt_options) {
const options = opt_options ? const options = opt_options ?
opt_options : /** @type {module:ol/layer/Vector~Options} */ ({}); opt_options : /** @type {module:ol/layer/Vector~Options} */ ({});
@@ -159,44 +160,110 @@ const VectorLayer = function(opt_options) {
*/ */
this.type = LayerType.VECTOR; this.type = LayerType.VECTOR;
}; }
inherits(VectorLayer, Layer); /**
/**
* @return {boolean} Declutter. * @return {boolean} Declutter.
*/ */
VectorLayer.prototype.getDeclutter = function() { getDeclutter() {
return this.declutter_; return this.declutter_;
}; }
/**
/**
* @param {boolean} declutter Declutter. * @param {boolean} declutter Declutter.
*/ */
VectorLayer.prototype.setDeclutter = function(declutter) { setDeclutter(declutter) {
this.declutter_ = declutter; this.declutter_ = declutter;
}; }
/**
/**
* @return {number|undefined} Render buffer. * @return {number|undefined} Render buffer.
*/ */
VectorLayer.prototype.getRenderBuffer = function() { getRenderBuffer() {
return this.renderBuffer_; return this.renderBuffer_;
}; }
/**
/**
* @return {function(module:ol/Feature, module:ol/Feature): number|null|undefined} Render * @return {function(module:ol/Feature, module:ol/Feature): number|null|undefined} Render
* order. * order.
*/ */
VectorLayer.prototype.getRenderOrder = function() { getRenderOrder() {
return ( return (
/** @type {module:ol/render~OrderFunction|null|undefined} */ (this.get(Property.RENDER_ORDER)) /** @type {module:ol/render~OrderFunction|null|undefined} */ (this.get(Property.RENDER_ORDER))
); );
}; }
/**
* Get the style for features. This returns whatever was passed to the `style`
* option at construction or to the `setStyle` method.
* @return {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction}
* Layer style.
* @api
*/
getStyle() {
return this.style_;
}
/**
* Get the style function.
* @return {module:ol/style/Style~StyleFunction|undefined} Layer style function.
* @api
*/
getStyleFunction() {
return this.styleFunction_;
}
/**
* @return {boolean} Whether the rendered layer should be updated while
* animating.
*/
getUpdateWhileAnimating() {
return this.updateWhileAnimating_;
}
/**
* @return {boolean} Whether the rendered layer should be updated while
* interacting.
*/
getUpdateWhileInteracting() {
return this.updateWhileInteracting_;
}
/**
* @param {module:ol/render~OrderFunction|null|undefined} renderOrder
* Render order.
*/
setRenderOrder(renderOrder) {
this.set(Property.RENDER_ORDER, renderOrder);
}
/**
* Set the style for features. This can be a single style object, an array
* of styles, or a function that takes a feature and resolution and returns
* an array of styles. If it is `undefined` the default style is used. If
* it is `null` the layer has no style (a `null` style), so only features
* that have their own styles will be rendered in the layer. See
* {@link module:ol/style} for information on the default style.
* @param {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction|null|undefined}
* style Layer style.
* @api
*/
setStyle(style) {
this.style_ = style !== undefined ? style : createDefaultStyle;
this.styleFunction_ = style === null ?
undefined : toStyleFunction(this.style_);
this.changed();
}
/**
* @return {module:ol/layer/VectorRenderType|string} The render mode.
*/
getRenderMode() {
return this.renderMode_;
}
}
inherits(VectorLayer, Layer);
/** /**
@@ -208,80 +275,4 @@ VectorLayer.prototype.getRenderOrder = function() {
VectorLayer.prototype.getSource; VectorLayer.prototype.getSource;
/**
* Get the style for features. This returns whatever was passed to the `style`
* option at construction or to the `setStyle` method.
* @return {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction}
* Layer style.
* @api
*/
VectorLayer.prototype.getStyle = function() {
return this.style_;
};
/**
* Get the style function.
* @return {module:ol/style/Style~StyleFunction|undefined} Layer style function.
* @api
*/
VectorLayer.prototype.getStyleFunction = function() {
return this.styleFunction_;
};
/**
* @return {boolean} Whether the rendered layer should be updated while
* animating.
*/
VectorLayer.prototype.getUpdateWhileAnimating = function() {
return this.updateWhileAnimating_;
};
/**
* @return {boolean} Whether the rendered layer should be updated while
* interacting.
*/
VectorLayer.prototype.getUpdateWhileInteracting = function() {
return this.updateWhileInteracting_;
};
/**
* @param {module:ol/render~OrderFunction|null|undefined} renderOrder
* Render order.
*/
VectorLayer.prototype.setRenderOrder = function(renderOrder) {
this.set(Property.RENDER_ORDER, renderOrder);
};
/**
* Set the style for features. This can be a single style object, an array
* of styles, or a function that takes a feature and resolution and returns
* an array of styles. If it is `undefined` the default style is used. If
* it is `null` the layer has no style (a `null` style), so only features
* that have their own styles will be rendered in the layer. See
* {@link module:ol/style} for information on the default style.
* @param {module:ol/style/Style|Array.<module:ol/style/Style>|module:ol/style/Style~StyleFunction|null|undefined}
* style Layer style.
* @api
*/
VectorLayer.prototype.setStyle = function(style) {
this.style_ = style !== undefined ? style : createDefaultStyle;
this.styleFunction_ = style === null ?
undefined : toStyleFunction(this.style_);
this.changed();
};
/**
* @return {module:ol/layer/VectorRenderType|string} The render mode.
*/
VectorLayer.prototype.getRenderMode = function() {
return this.renderMode_;
};
export default VectorLayer; export default VectorLayer;
+18 -20
View File
@@ -99,7 +99,8 @@ export const RenderType = {
* @param {module:ol/layer/VectorTile~Options=} opt_options Options. * @param {module:ol/layer/VectorTile~Options=} opt_options Options.
* @api * @api
*/ */
const VectorTileLayer = function(opt_options) { class VectorTileLayer {
constructor(opt_options) {
const options = opt_options ? opt_options : {}; const options = opt_options ? opt_options : {};
let renderMode = options.renderMode || VectorTileRenderType.HYBRID; let renderMode = options.renderMode || VectorTileRenderType.HYBRID;
@@ -130,53 +131,50 @@ const VectorTileLayer = function(opt_options) {
*/ */
this.type = LayerType.VECTOR_TILE; this.type = LayerType.VECTOR_TILE;
}; }
inherits(VectorTileLayer, VectorLayer); /**
/**
* Return the level as number to which we will preload tiles up to. * Return the level as number to which we will preload tiles up to.
* @return {number} The level to preload tiles up to. * @return {number} The level to preload tiles up to.
* @observable * @observable
* @api * @api
*/ */
VectorTileLayer.prototype.getPreload = function() { getPreload() {
return /** @type {number} */ (this.get(TileProperty.PRELOAD)); return /** @type {number} */ (this.get(TileProperty.PRELOAD));
}; }
/**
/**
* Whether we use interim tiles on error. * Whether we use interim tiles on error.
* @return {boolean} Use interim tiles on error. * @return {boolean} Use interim tiles on error.
* @observable * @observable
* @api * @api
*/ */
VectorTileLayer.prototype.getUseInterimTilesOnError = function() { getUseInterimTilesOnError() {
return /** @type {boolean} */ (this.get(TileProperty.USE_INTERIM_TILES_ON_ERROR)); return /** @type {boolean} */ (this.get(TileProperty.USE_INTERIM_TILES_ON_ERROR));
}; }
/**
/**
* Set the level as number to which we will preload tiles up to. * Set the level as number to which we will preload tiles up to.
* @param {number} preload The level to preload tiles up to. * @param {number} preload The level to preload tiles up to.
* @observable * @observable
* @api * @api
*/ */
VectorTileLayer.prototype.setPreload = function(preload) { setPreload(preload) {
this.set(TileProperty.PRELOAD, preload); this.set(TileProperty.PRELOAD, preload);
}; }
/**
/**
* Set whether we use interim tiles on error. * Set whether we use interim tiles on error.
* @param {boolean} useInterimTilesOnError Use interim tiles on error. * @param {boolean} useInterimTilesOnError Use interim tiles on error.
* @observable * @observable
* @api * @api
*/ */
VectorTileLayer.prototype.setUseInterimTilesOnError = function(useInterimTilesOnError) { setUseInterimTilesOnError(useInterimTilesOnError) {
this.set(TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError); this.set(TileProperty.USE_INTERIM_TILES_ON_ERROR, useInterimTilesOnError);
}; }
}
inherits(VectorTileLayer, VectorLayer);
/** /**
+11 -10
View File
@@ -6,7 +6,8 @@
* @param {!Object.<string, function(Event)>} mapping Event mapping. * @param {!Object.<string, function(Event)>} mapping Event mapping.
* @constructor * @constructor
*/ */
const EventSource = function(dispatcher, mapping) { class EventSource {
constructor(dispatcher, mapping) {
/** /**
* @type {module:ol/pointer/PointerEventHandler} * @type {module:ol/pointer/PointerEventHandler}
*/ */
@@ -18,24 +19,24 @@ const EventSource = function(dispatcher, mapping) {
* @type {!Object.<string, function(Event)>} * @type {!Object.<string, function(Event)>}
*/ */
this.mapping_ = mapping; this.mapping_ = mapping;
}; }
/**
/**
* List of events supported by this source. * List of events supported by this source.
* @return {Array.<string>} Event names * @return {Array.<string>} Event names
*/ */
EventSource.prototype.getEvents = function() { getEvents() {
return Object.keys(this.mapping_); return Object.keys(this.mapping_);
}; }
/**
/**
* Returns the handler that should handle a given event type. * Returns the handler that should handle a given event type.
* @param {string} eventType The event type. * @param {string} eventType The event type.
* @return {function(Event)} Handler * @return {function(Event)} Handler
*/ */
EventSource.prototype.getHandlerForEvent = function(eventType) { getHandlerForEvent(eventType) {
return this.mapping_[eventType]; return this.mapping_[eventType];
}; }
}
export default EventSource; export default EventSource;
+118 -122
View File
@@ -39,7 +39,8 @@ import EventSource from '../pointer/EventSource.js';
* @constructor * @constructor
* @extends {module:ol/pointer/EventSource} * @extends {module:ol/pointer/EventSource}
*/ */
const MouseSource = function(dispatcher) { class MouseSource {
constructor(dispatcher) {
const mapping = { const mapping = {
'mousedown': this.mousedown, 'mousedown': this.mousedown,
'mousemove': this.mousemove, 'mousemove': this.mousemove,
@@ -60,32 +61,9 @@ const MouseSource = function(dispatcher) {
* @type {Array.<module:ol~Pixel>} * @type {Array.<module:ol~Pixel>}
*/ */
this.lastTouches = []; this.lastTouches = [];
}; }
inherits(MouseSource, EventSource); /**
/**
* @type {number}
*/
export const POINTER_ID = 1;
/**
* @type {string}
*/
export const POINTER_TYPE = 'mouse';
/**
* Radius around touchend that swallows mouse events.
*
* @type {number}
*/
const DEDUP_DIST = 25;
/**
* Detect if a mouse event was simulated from a touch by * Detect if a mouse event was simulated from a touch by
* checking if previously there was a touch event at the * checking if previously there was a touch event at the
* same position. * same position.
@@ -109,7 +87,7 @@ const DEDUP_DIST = 25;
* @param {MouseEvent} inEvent The in event. * @param {MouseEvent} inEvent The in event.
* @return {boolean} True, if the event was generated by a touch. * @return {boolean} True, if the event was generated by a touch.
*/ */
MouseSource.prototype.isEventSimulatedFromTouch_ = function(inEvent) { isEventSimulatedFromTouch_(inEvent) {
const lts = this.lastTouches; const lts = this.lastTouches;
const x = inEvent.clientX; const x = inEvent.clientX;
const y = inEvent.clientY; const y = inEvent.clientY;
@@ -122,7 +100,119 @@ MouseSource.prototype.isEventSimulatedFromTouch_ = function(inEvent) {
} }
} }
return false; return false;
}; }
/**
* Handler for `mousedown`.
*
* @param {MouseEvent} inEvent The in event.
*/
mousedown(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
// TODO(dfreedman) workaround for some elements not sending mouseup
// http://crbug/149091
if (POINTER_ID.toString() in this.pointerMap) {
this.cancel(inEvent);
}
const e = prepareEvent(inEvent, this.dispatcher);
this.pointerMap[POINTER_ID.toString()] = inEvent;
this.dispatcher.down(e, inEvent);
}
}
/**
* Handler for `mousemove`.
*
* @param {MouseEvent} inEvent The in event.
*/
mousemove(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
const e = prepareEvent(inEvent, this.dispatcher);
this.dispatcher.move(e, inEvent);
}
}
/**
* Handler for `mouseup`.
*
* @param {MouseEvent} inEvent The in event.
*/
mouseup(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
const p = this.pointerMap[POINTER_ID.toString()];
if (p && p.button === inEvent.button) {
const e = prepareEvent(inEvent, this.dispatcher);
this.dispatcher.up(e, inEvent);
this.cleanupMouse();
}
}
}
/**
* Handler for `mouseover`.
*
* @param {MouseEvent} inEvent The in event.
*/
mouseover(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
const e = prepareEvent(inEvent, this.dispatcher);
this.dispatcher.enterOver(e, inEvent);
}
}
/**
* Handler for `mouseout`.
*
* @param {MouseEvent} inEvent The in event.
*/
mouseout(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
const e = prepareEvent(inEvent, this.dispatcher);
this.dispatcher.leaveOut(e, inEvent);
}
}
/**
* Dispatches a `pointercancel` event.
*
* @param {Event} inEvent The in event.
*/
cancel(inEvent) {
const e = prepareEvent(inEvent, this.dispatcher);
this.dispatcher.cancel(e, inEvent);
this.cleanupMouse();
}
/**
* Remove the mouse from the list of active pointers.
*/
cleanupMouse() {
delete this.pointerMap[POINTER_ID.toString()];
}
}
inherits(MouseSource, EventSource);
/**
* @type {number}
*/
export const POINTER_ID = 1;
/**
* @type {string}
*/
export const POINTER_TYPE = 'mouse';
/**
* Radius around touchend that swallows mouse events.
*
* @type {number}
*/
const DEDUP_DIST = 25;
/** /**
@@ -151,98 +241,4 @@ function prepareEvent(inEvent, dispatcher) {
} }
/**
* Handler for `mousedown`.
*
* @param {MouseEvent} inEvent The in event.
*/
MouseSource.prototype.mousedown = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
// TODO(dfreedman) workaround for some elements not sending mouseup
// http://crbug/149091
if (POINTER_ID.toString() in this.pointerMap) {
this.cancel(inEvent);
}
const e = prepareEvent(inEvent, this.dispatcher);
this.pointerMap[POINTER_ID.toString()] = inEvent;
this.dispatcher.down(e, inEvent);
}
};
/**
* Handler for `mousemove`.
*
* @param {MouseEvent} inEvent The in event.
*/
MouseSource.prototype.mousemove = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
const e = prepareEvent(inEvent, this.dispatcher);
this.dispatcher.move(e, inEvent);
}
};
/**
* Handler for `mouseup`.
*
* @param {MouseEvent} inEvent The in event.
*/
MouseSource.prototype.mouseup = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
const p = this.pointerMap[POINTER_ID.toString()];
if (p && p.button === inEvent.button) {
const e = prepareEvent(inEvent, this.dispatcher);
this.dispatcher.up(e, inEvent);
this.cleanupMouse();
}
}
};
/**
* Handler for `mouseover`.
*
* @param {MouseEvent} inEvent The in event.
*/
MouseSource.prototype.mouseover = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
const e = prepareEvent(inEvent, this.dispatcher);
this.dispatcher.enterOver(e, inEvent);
}
};
/**
* Handler for `mouseout`.
*
* @param {MouseEvent} inEvent The in event.
*/
MouseSource.prototype.mouseout = function(inEvent) {
if (!this.isEventSimulatedFromTouch_(inEvent)) {
const e = prepareEvent(inEvent, this.dispatcher);
this.dispatcher.leaveOut(e, inEvent);
}
};
/**
* Dispatches a `pointercancel` event.
*
* @param {Event} inEvent The in event.
*/
MouseSource.prototype.cancel = function(inEvent) {
const e = prepareEvent(inEvent, this.dispatcher);
this.dispatcher.cancel(e, inEvent);
this.cleanupMouse();
};
/**
* Remove the mouse from the list of active pointers.
*/
MouseSource.prototype.cleanupMouse = function() {
delete this.pointerMap[POINTER_ID.toString()];
};
export default MouseSource; export default MouseSource;
+113 -119
View File
@@ -39,7 +39,8 @@ import EventSource from '../pointer/EventSource.js';
* @constructor * @constructor
* @extends {module:ol/pointer/EventSource} * @extends {module:ol/pointer/EventSource}
*/ */
const MsSource = function(dispatcher) { class MsSource {
constructor(dispatcher) {
const mapping = { const mapping = {
'MSPointerDown': this.msPointerDown, 'MSPointerDown': this.msPointerDown,
'MSPointerMove': this.msPointerMove, 'MSPointerMove': this.msPointerMove,
@@ -57,7 +58,117 @@ const MsSource = function(dispatcher) {
* @type {!Object.<string, MSPointerEvent|Object>} * @type {!Object.<string, MSPointerEvent|Object>}
*/ */
this.pointerMap = dispatcher.pointerMap; this.pointerMap = dispatcher.pointerMap;
}; }
/**
* Creates a copy of the original event that will be used
* for the fake pointer event.
*
* @private
* @param {MSPointerEvent} inEvent The in event.
* @return {Object} The copied event.
*/
prepareEvent_(inEvent) {
let e = inEvent;
if (typeof inEvent.pointerType === 'number') {
e = this.dispatcher.cloneEvent(inEvent, inEvent);
e.pointerType = POINTER_TYPES[inEvent.pointerType];
}
return e;
}
/**
* Remove this pointer from the list of active pointers.
* @param {number} pointerId Pointer identifier.
*/
cleanup(pointerId) {
delete this.pointerMap[pointerId.toString()];
}
/**
* Handler for `msPointerDown`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
msPointerDown(inEvent) {
this.pointerMap[inEvent.pointerId.toString()] = inEvent;
const e = this.prepareEvent_(inEvent);
this.dispatcher.down(e, inEvent);
}
/**
* Handler for `msPointerMove`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
msPointerMove(inEvent) {
const e = this.prepareEvent_(inEvent);
this.dispatcher.move(e, inEvent);
}
/**
* Handler for `msPointerUp`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
msPointerUp(inEvent) {
const e = this.prepareEvent_(inEvent);
this.dispatcher.up(e, inEvent);
this.cleanup(inEvent.pointerId);
}
/**
* Handler for `msPointerOut`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
msPointerOut(inEvent) {
const e = this.prepareEvent_(inEvent);
this.dispatcher.leaveOut(e, inEvent);
}
/**
* Handler for `msPointerOver`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
msPointerOver(inEvent) {
const e = this.prepareEvent_(inEvent);
this.dispatcher.enterOver(e, inEvent);
}
/**
* Handler for `msPointerCancel`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
msPointerCancel(inEvent) {
const e = this.prepareEvent_(inEvent);
this.dispatcher.cancel(e, inEvent);
this.cleanup(inEvent.pointerId);
}
/**
* Handler for `msLostPointerCapture`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
msLostPointerCapture(inEvent) {
const e = this.dispatcher.makeEvent('lostpointercapture', inEvent, inEvent);
this.dispatcher.dispatchEvent(e);
}
/**
* Handler for `msGotPointerCapture`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
msGotPointerCapture(inEvent) {
const e = this.dispatcher.makeEvent('gotpointercapture', inEvent, inEvent);
this.dispatcher.dispatchEvent(e);
}
}
inherits(MsSource, EventSource); inherits(MsSource, EventSource);
@@ -74,121 +185,4 @@ const POINTER_TYPES = [
]; ];
/**
* Creates a copy of the original event that will be used
* for the fake pointer event.
*
* @private
* @param {MSPointerEvent} inEvent The in event.
* @return {Object} The copied event.
*/
MsSource.prototype.prepareEvent_ = function(inEvent) {
let e = inEvent;
if (typeof inEvent.pointerType === 'number') {
e = this.dispatcher.cloneEvent(inEvent, inEvent);
e.pointerType = POINTER_TYPES[inEvent.pointerType];
}
return e;
};
/**
* Remove this pointer from the list of active pointers.
* @param {number} pointerId Pointer identifier.
*/
MsSource.prototype.cleanup = function(pointerId) {
delete this.pointerMap[pointerId.toString()];
};
/**
* Handler for `msPointerDown`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
MsSource.prototype.msPointerDown = function(inEvent) {
this.pointerMap[inEvent.pointerId.toString()] = inEvent;
const e = this.prepareEvent_(inEvent);
this.dispatcher.down(e, inEvent);
};
/**
* Handler for `msPointerMove`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
MsSource.prototype.msPointerMove = function(inEvent) {
const e = this.prepareEvent_(inEvent);
this.dispatcher.move(e, inEvent);
};
/**
* Handler for `msPointerUp`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
MsSource.prototype.msPointerUp = function(inEvent) {
const e = this.prepareEvent_(inEvent);
this.dispatcher.up(e, inEvent);
this.cleanup(inEvent.pointerId);
};
/**
* Handler for `msPointerOut`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
MsSource.prototype.msPointerOut = function(inEvent) {
const e = this.prepareEvent_(inEvent);
this.dispatcher.leaveOut(e, inEvent);
};
/**
* Handler for `msPointerOver`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
MsSource.prototype.msPointerOver = function(inEvent) {
const e = this.prepareEvent_(inEvent);
this.dispatcher.enterOver(e, inEvent);
};
/**
* Handler for `msPointerCancel`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
MsSource.prototype.msPointerCancel = function(inEvent) {
const e = this.prepareEvent_(inEvent);
this.dispatcher.cancel(e, inEvent);
this.cleanup(inEvent.pointerId);
};
/**
* Handler for `msLostPointerCapture`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
MsSource.prototype.msLostPointerCapture = function(inEvent) {
const e = this.dispatcher.makeEvent('lostpointercapture', inEvent, inEvent);
this.dispatcher.dispatchEvent(e);
};
/**
* Handler for `msGotPointerCapture`.
*
* @param {MSPointerEvent} inEvent The in event.
*/
MsSource.prototype.msGotPointerCapture = function(inEvent) {
const e = this.dispatcher.makeEvent('gotpointercapture', inEvent, inEvent);
this.dispatcher.dispatchEvent(e);
};
export default MsSource; export default MsSource;
+32 -36
View File
@@ -39,7 +39,8 @@ import EventSource from '../pointer/EventSource.js';
* @constructor * @constructor
* @extends {module:ol/pointer/EventSource} * @extends {module:ol/pointer/EventSource}
*/ */
const NativeSource = function(dispatcher) { class NativeSource {
constructor(dispatcher) {
const mapping = { const mapping = {
'pointerdown': this.pointerDown, 'pointerdown': this.pointerDown,
'pointermove': this.pointerMove, 'pointermove': this.pointerMove,
@@ -51,87 +52,82 @@ const NativeSource = function(dispatcher) {
'lostpointercapture': this.lostPointerCapture 'lostpointercapture': this.lostPointerCapture
}; };
EventSource.call(this, dispatcher, mapping); EventSource.call(this, dispatcher, mapping);
}; }
inherits(NativeSource, EventSource); /**
/**
* Handler for `pointerdown`. * Handler for `pointerdown`.
* *
* @param {Event} inEvent The in event. * @param {Event} inEvent The in event.
*/ */
NativeSource.prototype.pointerDown = function(inEvent) { pointerDown(inEvent) {
this.dispatcher.fireNativeEvent(inEvent); this.dispatcher.fireNativeEvent(inEvent);
}; }
/**
/**
* Handler for `pointermove`. * Handler for `pointermove`.
* *
* @param {Event} inEvent The in event. * @param {Event} inEvent The in event.
*/ */
NativeSource.prototype.pointerMove = function(inEvent) { pointerMove(inEvent) {
this.dispatcher.fireNativeEvent(inEvent); this.dispatcher.fireNativeEvent(inEvent);
}; }
/**
/**
* Handler for `pointerup`. * Handler for `pointerup`.
* *
* @param {Event} inEvent The in event. * @param {Event} inEvent The in event.
*/ */
NativeSource.prototype.pointerUp = function(inEvent) { pointerUp(inEvent) {
this.dispatcher.fireNativeEvent(inEvent); this.dispatcher.fireNativeEvent(inEvent);
}; }
/**
/**
* Handler for `pointerout`. * Handler for `pointerout`.
* *
* @param {Event} inEvent The in event. * @param {Event} inEvent The in event.
*/ */
NativeSource.prototype.pointerOut = function(inEvent) { pointerOut(inEvent) {
this.dispatcher.fireNativeEvent(inEvent); this.dispatcher.fireNativeEvent(inEvent);
}; }
/**
/**
* Handler for `pointerover`. * Handler for `pointerover`.
* *
* @param {Event} inEvent The in event. * @param {Event} inEvent The in event.
*/ */
NativeSource.prototype.pointerOver = function(inEvent) { pointerOver(inEvent) {
this.dispatcher.fireNativeEvent(inEvent); this.dispatcher.fireNativeEvent(inEvent);
}; }
/**
/**
* Handler for `pointercancel`. * Handler for `pointercancel`.
* *
* @param {Event} inEvent The in event. * @param {Event} inEvent The in event.
*/ */
NativeSource.prototype.pointerCancel = function(inEvent) { pointerCancel(inEvent) {
this.dispatcher.fireNativeEvent(inEvent); this.dispatcher.fireNativeEvent(inEvent);
}; }
/**
/**
* Handler for `lostpointercapture`. * Handler for `lostpointercapture`.
* *
* @param {Event} inEvent The in event. * @param {Event} inEvent The in event.
*/ */
NativeSource.prototype.lostPointerCapture = function(inEvent) { lostPointerCapture(inEvent) {
this.dispatcher.fireNativeEvent(inEvent); this.dispatcher.fireNativeEvent(inEvent);
}; }
/**
/**
* Handler for `gotpointercapture`. * Handler for `gotpointercapture`.
* *
* @param {Event} inEvent The in event. * @param {Event} inEvent The in event.
*/ */
NativeSource.prototype.gotPointerCapture = function(inEvent) { gotPointerCapture(inEvent) {
this.dispatcher.fireNativeEvent(inEvent); this.dispatcher.fireNativeEvent(inEvent);
}; }
}
inherits(NativeSource, EventSource);
export default NativeSource; export default NativeSource;
+19 -19
View File
@@ -47,7 +47,8 @@ import Event from '../events/Event.js';
* @param {Object.<string, ?>=} opt_eventDict An optional dictionary of * @param {Object.<string, ?>=} opt_eventDict An optional dictionary of
* initial event properties. * initial event properties.
*/ */
const PointerEvent = function(type, originalEvent, opt_eventDict) { class PointerEvent {
constructor(type, originalEvent, opt_eventDict) {
Event.call(this, type); Event.call(this, type);
/** /**
@@ -190,24 +191,14 @@ const PointerEvent = function(type, originalEvent, opt_eventDict) {
originalEvent.preventDefault(); originalEvent.preventDefault();
}; };
} }
}; }
inherits(PointerEvent, Event); /**
/**
* Is the `buttons` property supported?
* @type {boolean}
*/
let HAS_BUTTONS = false;
/**
* @private * @private
* @param {Object.<string, ?>} eventDict The event dictionary. * @param {Object.<string, ?>} eventDict The event dictionary.
* @return {number} Button indicator. * @return {number} Button indicator.
*/ */
PointerEvent.prototype.getButtons_ = function(eventDict) { getButtons_(eventDict) {
// According to the w3c spec, // According to the w3c spec,
// http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button // http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button
// MouseEvent.button == 0 can mean either no mouse button depressed, or the // MouseEvent.button == 0 can mean either no mouse button depressed, or the
@@ -241,16 +232,15 @@ PointerEvent.prototype.getButtons_ = function(eventDict) {
} }
} }
return buttons; return buttons;
}; }
/**
/**
* @private * @private
* @param {Object.<string, ?>} eventDict The event dictionary. * @param {Object.<string, ?>} eventDict The event dictionary.
* @param {number} buttons Button indicator. * @param {number} buttons Button indicator.
* @return {number} The pressure. * @return {number} The pressure.
*/ */
PointerEvent.prototype.getPressure_ = function(eventDict, buttons) { getPressure_(eventDict, buttons) {
// Spec requires that pointers without pressure specified use 0.5 for down // Spec requires that pointers without pressure specified use 0.5 for down
// state and 0 for up state. // state and 0 for up state.
let pressure = 0; let pressure = 0;
@@ -260,7 +250,17 @@ PointerEvent.prototype.getPressure_ = function(eventDict, buttons) {
pressure = buttons ? 0.5 : 0; pressure = buttons ? 0.5 : 0;
} }
return pressure; return pressure;
}; }
}
inherits(PointerEvent, Event);
/**
* Is the `buttons` property supported?
* @type {boolean}
*/
let HAS_BUTTONS = false;
/** /**
+299 -321
View File
@@ -47,7 +47,8 @@ import TouchSource from '../pointer/TouchSource.js';
* @extends {module:ol/events/EventTarget} * @extends {module:ol/events/EventTarget}
* @param {Element|HTMLDocument} element Viewport element. * @param {Element|HTMLDocument} element Viewport element.
*/ */
const PointerEventHandler = function(element) { class PointerEventHandler {
constructor(element) {
EventTarget.call(this); EventTarget.call(this);
/** /**
@@ -76,7 +77,303 @@ const PointerEventHandler = function(element) {
this.eventSourceList_ = []; this.eventSourceList_ = [];
this.registerSources(); this.registerSources();
}; }
/**
* Set up the event sources (mouse, touch and native pointers)
* that generate pointer events.
*/
registerSources() {
if (POINTER) {
this.registerSource('native', new NativeSource(this));
} else if (MSPOINTER) {
this.registerSource('ms', new MsSource(this));
} else {
const mouseSource = new MouseSource(this);
this.registerSource('mouse', mouseSource);
if (TOUCH) {
this.registerSource('touch', new TouchSource(this, mouseSource));
}
}
// register events on the viewport element
this.register_();
}
/**
* Add a new event source that will generate pointer events.
*
* @param {string} name A name for the event source
* @param {module:ol/pointer/EventSource} source The source event.
*/
registerSource(name, source) {
const s = source;
const newEvents = s.getEvents();
if (newEvents) {
newEvents.forEach(function(e) {
const handler = s.getHandlerForEvent(e);
if (handler) {
this.eventMap_[e] = handler.bind(s);
}
}.bind(this));
this.eventSourceList_.push(s);
}
}
/**
* Set up the events for all registered event sources.
* @private
*/
register_() {
const l = this.eventSourceList_.length;
for (let i = 0; i < l; i++) {
const eventSource = this.eventSourceList_[i];
this.addEvents_(eventSource.getEvents());
}
}
/**
* Remove all registered events.
* @private
*/
unregister_() {
const l = this.eventSourceList_.length;
for (let i = 0; i < l; i++) {
const eventSource = this.eventSourceList_[i];
this.removeEvents_(eventSource.getEvents());
}
}
/**
* Calls the right handler for a new event.
* @private
* @param {Event} inEvent Browser event.
*/
eventHandler_(inEvent) {
const type = inEvent.type;
const handler = this.eventMap_[type];
if (handler) {
handler(inEvent);
}
}
/**
* Setup listeners for the given events.
* @private
* @param {Array.<string>} events List of events.
*/
addEvents_(events) {
events.forEach(function(eventName) {
listen(this.element_, eventName, this.eventHandler_, this);
}.bind(this));
}
/**
* Unregister listeners for the given events.
* @private
* @param {Array.<string>} events List of events.
*/
removeEvents_(events) {
events.forEach(function(e) {
unlisten(this.element_, e, this.eventHandler_, this);
}.bind(this));
}
/**
* Returns a snapshot of inEvent, with writable properties.
*
* @param {Event} event Browser event.
* @param {Event|Touch} inEvent An event that contains
* properties to copy.
* @return {Object} An object containing shallow copies of
* `inEvent`'s properties.
*/
cloneEvent(event, inEvent) {
const eventCopy = {};
for (let i = 0, ii = CLONE_PROPS.length; i < ii; i++) {
const p = CLONE_PROPS[i][0];
eventCopy[p] = event[p] || inEvent[p] || CLONE_PROPS[i][1];
}
return eventCopy;
}
// EVENTS
/**
* Triggers a 'pointerdown' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
down(data, event) {
this.fireEvent(PointerEventType.POINTERDOWN, data, event);
}
/**
* Triggers a 'pointermove' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
move(data, event) {
this.fireEvent(PointerEventType.POINTERMOVE, data, event);
}
/**
* Triggers a 'pointerup' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
up(data, event) {
this.fireEvent(PointerEventType.POINTERUP, data, event);
}
/**
* Triggers a 'pointerenter' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
enter(data, event) {
data.bubbles = false;
this.fireEvent(PointerEventType.POINTERENTER, data, event);
}
/**
* Triggers a 'pointerleave' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
leave(data, event) {
data.bubbles = false;
this.fireEvent(PointerEventType.POINTERLEAVE, data, event);
}
/**
* Triggers a 'pointerover' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
over(data, event) {
data.bubbles = true;
this.fireEvent(PointerEventType.POINTEROVER, data, event);
}
/**
* Triggers a 'pointerout' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
out(data, event) {
data.bubbles = true;
this.fireEvent(PointerEventType.POINTEROUT, data, event);
}
/**
* Triggers a 'pointercancel' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
cancel(data, event) {
this.fireEvent(PointerEventType.POINTERCANCEL, data, event);
}
/**
* Triggers a combination of 'pointerout' and 'pointerleave' events.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
leaveOut(data, event) {
this.out(data, event);
if (!this.contains_(data.target, data.relatedTarget)) {
this.leave(data, event);
}
}
/**
* Triggers a combination of 'pointerover' and 'pointerevents' events.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
enterOver(data, event) {
this.over(data, event);
if (!this.contains_(data.target, data.relatedTarget)) {
this.enter(data, event);
}
}
/**
* @private
* @param {Element} container The container element.
* @param {Element} contained The contained element.
* @return {boolean} Returns true if the container element
* contains the other element.
*/
contains_(container, contained) {
if (!container || !contained) {
return false;
}
return container.contains(contained);
}
// EVENT CREATION AND TRACKING
/**
* Creates a new Event of type `inType`, based on the information in
* `data`.
*
* @param {string} inType A string representing the type of event to create.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
* @return {module:ol/pointer/PointerEvent} A PointerEvent of type `inType`.
*/
makeEvent(inType, data, event) {
return new PointerEvent(inType, event, data);
}
/**
* Make and dispatch an event in one call.
* @param {string} inType A string representing the type of event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
fireEvent(inType, data, event) {
const e = this.makeEvent(inType, data, event);
this.dispatchEvent(e);
}
/**
* Creates a pointer event from a native pointer event
* and dispatches this event.
* @param {Event} event A platform event with a target.
*/
fireNativeEvent(event) {
const e = this.makeEvent(event.type, event, event);
this.dispatchEvent(e);
}
/**
* Wrap a native mouse event into a pointer event.
* This proxy method is required for the legacy IE support.
* @param {string} eventType The pointer event type.
* @param {Event} event The event.
* @return {module:ol/pointer/PointerEvent} The wrapped event.
*/
wrapMouseEvent(eventType, event) {
const pointerEvent = this.makeEvent(
eventType, MouseSource.prepareEvent(event, this), event);
return pointerEvent;
}
/**
* @inheritDoc
*/
disposeInternal() {
this.unregister_();
EventTarget.prototype.disposeInternal.call(this);
}
}
inherits(PointerEventHandler, EventTarget); inherits(PointerEventHandler, EventTarget);
@@ -120,323 +417,4 @@ const CLONE_PROPS = [
]; ];
/**
* Set up the event sources (mouse, touch and native pointers)
* that generate pointer events.
*/
PointerEventHandler.prototype.registerSources = function() {
if (POINTER) {
this.registerSource('native', new NativeSource(this));
} else if (MSPOINTER) {
this.registerSource('ms', new MsSource(this));
} else {
const mouseSource = new MouseSource(this);
this.registerSource('mouse', mouseSource);
if (TOUCH) {
this.registerSource('touch', new TouchSource(this, mouseSource));
}
}
// register events on the viewport element
this.register_();
};
/**
* Add a new event source that will generate pointer events.
*
* @param {string} name A name for the event source
* @param {module:ol/pointer/EventSource} source The source event.
*/
PointerEventHandler.prototype.registerSource = function(name, source) {
const s = source;
const newEvents = s.getEvents();
if (newEvents) {
newEvents.forEach(function(e) {
const handler = s.getHandlerForEvent(e);
if (handler) {
this.eventMap_[e] = handler.bind(s);
}
}.bind(this));
this.eventSourceList_.push(s);
}
};
/**
* Set up the events for all registered event sources.
* @private
*/
PointerEventHandler.prototype.register_ = function() {
const l = this.eventSourceList_.length;
for (let i = 0; i < l; i++) {
const eventSource = this.eventSourceList_[i];
this.addEvents_(eventSource.getEvents());
}
};
/**
* Remove all registered events.
* @private
*/
PointerEventHandler.prototype.unregister_ = function() {
const l = this.eventSourceList_.length;
for (let i = 0; i < l; i++) {
const eventSource = this.eventSourceList_[i];
this.removeEvents_(eventSource.getEvents());
}
};
/**
* Calls the right handler for a new event.
* @private
* @param {Event} inEvent Browser event.
*/
PointerEventHandler.prototype.eventHandler_ = function(inEvent) {
const type = inEvent.type;
const handler = this.eventMap_[type];
if (handler) {
handler(inEvent);
}
};
/**
* Setup listeners for the given events.
* @private
* @param {Array.<string>} events List of events.
*/
PointerEventHandler.prototype.addEvents_ = function(events) {
events.forEach(function(eventName) {
listen(this.element_, eventName, this.eventHandler_, this);
}.bind(this));
};
/**
* Unregister listeners for the given events.
* @private
* @param {Array.<string>} events List of events.
*/
PointerEventHandler.prototype.removeEvents_ = function(events) {
events.forEach(function(e) {
unlisten(this.element_, e, this.eventHandler_, this);
}.bind(this));
};
/**
* Returns a snapshot of inEvent, with writable properties.
*
* @param {Event} event Browser event.
* @param {Event|Touch} inEvent An event that contains
* properties to copy.
* @return {Object} An object containing shallow copies of
* `inEvent`'s properties.
*/
PointerEventHandler.prototype.cloneEvent = function(event, inEvent) {
const eventCopy = {};
for (let i = 0, ii = CLONE_PROPS.length; i < ii; i++) {
const p = CLONE_PROPS[i][0];
eventCopy[p] = event[p] || inEvent[p] || CLONE_PROPS[i][1];
}
return eventCopy;
};
// EVENTS
/**
* Triggers a 'pointerdown' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
PointerEventHandler.prototype.down = function(data, event) {
this.fireEvent(PointerEventType.POINTERDOWN, data, event);
};
/**
* Triggers a 'pointermove' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
PointerEventHandler.prototype.move = function(data, event) {
this.fireEvent(PointerEventType.POINTERMOVE, data, event);
};
/**
* Triggers a 'pointerup' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
PointerEventHandler.prototype.up = function(data, event) {
this.fireEvent(PointerEventType.POINTERUP, data, event);
};
/**
* Triggers a 'pointerenter' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
PointerEventHandler.prototype.enter = function(data, event) {
data.bubbles = false;
this.fireEvent(PointerEventType.POINTERENTER, data, event);
};
/**
* Triggers a 'pointerleave' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
PointerEventHandler.prototype.leave = function(data, event) {
data.bubbles = false;
this.fireEvent(PointerEventType.POINTERLEAVE, data, event);
};
/**
* Triggers a 'pointerover' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
PointerEventHandler.prototype.over = function(data, event) {
data.bubbles = true;
this.fireEvent(PointerEventType.POINTEROVER, data, event);
};
/**
* Triggers a 'pointerout' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
PointerEventHandler.prototype.out = function(data, event) {
data.bubbles = true;
this.fireEvent(PointerEventType.POINTEROUT, data, event);
};
/**
* Triggers a 'pointercancel' event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
PointerEventHandler.prototype.cancel = function(data, event) {
this.fireEvent(PointerEventType.POINTERCANCEL, data, event);
};
/**
* Triggers a combination of 'pointerout' and 'pointerleave' events.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
PointerEventHandler.prototype.leaveOut = function(data, event) {
this.out(data, event);
if (!this.contains_(data.target, data.relatedTarget)) {
this.leave(data, event);
}
};
/**
* Triggers a combination of 'pointerover' and 'pointerevents' events.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
PointerEventHandler.prototype.enterOver = function(data, event) {
this.over(data, event);
if (!this.contains_(data.target, data.relatedTarget)) {
this.enter(data, event);
}
};
/**
* @private
* @param {Element} container The container element.
* @param {Element} contained The contained element.
* @return {boolean} Returns true if the container element
* contains the other element.
*/
PointerEventHandler.prototype.contains_ = function(container, contained) {
if (!container || !contained) {
return false;
}
return container.contains(contained);
};
// EVENT CREATION AND TRACKING
/**
* Creates a new Event of type `inType`, based on the information in
* `data`.
*
* @param {string} inType A string representing the type of event to create.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
* @return {module:ol/pointer/PointerEvent} A PointerEvent of type `inType`.
*/
PointerEventHandler.prototype.makeEvent = function(inType, data, event) {
return new PointerEvent(inType, event, data);
};
/**
* Make and dispatch an event in one call.
* @param {string} inType A string representing the type of event.
* @param {Object} data Pointer event data.
* @param {Event} event The event.
*/
PointerEventHandler.prototype.fireEvent = function(inType, data, event) {
const e = this.makeEvent(inType, data, event);
this.dispatchEvent(e);
};
/**
* Creates a pointer event from a native pointer event
* and dispatches this event.
* @param {Event} event A platform event with a target.
*/
PointerEventHandler.prototype.fireNativeEvent = function(event) {
const e = this.makeEvent(event.type, event, event);
this.dispatchEvent(e);
};
/**
* Wrap a native mouse event into a pointer event.
* This proxy method is required for the legacy IE support.
* @param {string} eventType The pointer event type.
* @param {Event} event The event.
* @return {module:ol/pointer/PointerEvent} The wrapped event.
*/
PointerEventHandler.prototype.wrapMouseEvent = function(eventType, event) {
const pointerEvent = this.makeEvent(
eventType, MouseSource.prepareEvent(event, this), event);
return pointerEvent;
};
/**
* @inheritDoc
*/
PointerEventHandler.prototype.disposeInternal = function() {
this.unregister_();
EventTarget.prototype.disposeInternal.call(this);
};
export default PointerEventHandler; export default PointerEventHandler;
+79 -95
View File
@@ -43,7 +43,8 @@ import {POINTER_ID} from '../pointer/MouseSource.js';
* @param {module:ol/pointer/MouseSource} mouseSource Mouse source. * @param {module:ol/pointer/MouseSource} mouseSource Mouse source.
* @extends {module:ol/pointer/EventSource} * @extends {module:ol/pointer/EventSource}
*/ */
const TouchSource = function(dispatcher, mouseSource) { class TouchSource {
constructor(dispatcher, mouseSource) {
const mapping = { const mapping = {
'touchstart': this.touchstart, 'touchstart': this.touchstart,
'touchmove': this.touchmove, 'touchmove': this.touchmove,
@@ -89,94 +90,74 @@ const TouchSource = function(dispatcher, mouseSource) {
* @type {number} * @type {number}
*/ */
this.dedupTimeout_ = 2500; this.dedupTimeout_ = 2500;
}; }
inherits(TouchSource, EventSource); /**
/**
* @type {number}
*/
const CLICK_COUNT_TIMEOUT = 200;
/**
* @type {string}
*/
const POINTER_TYPE = 'touch';
/**
* @private * @private
* @param {Touch} inTouch The in touch. * @param {Touch} inTouch The in touch.
* @return {boolean} True, if this is the primary touch. * @return {boolean} True, if this is the primary touch.
*/ */
TouchSource.prototype.isPrimaryTouch_ = function(inTouch) { isPrimaryTouch_(inTouch) {
return this.firstTouchId_ === inTouch.identifier; return this.firstTouchId_ === inTouch.identifier;
}; }
/**
/**
* Set primary touch if there are no pointers, or the only pointer is the mouse. * Set primary touch if there are no pointers, or the only pointer is the mouse.
* @param {Touch} inTouch The in touch. * @param {Touch} inTouch The in touch.
* @private * @private
*/ */
TouchSource.prototype.setPrimaryTouch_ = function(inTouch) { setPrimaryTouch_(inTouch) {
const count = Object.keys(this.pointerMap).length; const count = Object.keys(this.pointerMap).length;
if (count === 0 || (count === 1 && POINTER_ID.toString() in this.pointerMap)) { if (count === 0 || (count === 1 && POINTER_ID.toString() in this.pointerMap)) {
this.firstTouchId_ = inTouch.identifier; this.firstTouchId_ = inTouch.identifier;
this.cancelResetClickCount_(); this.cancelResetClickCount_();
} }
}; }
/**
/**
* @private * @private
* @param {PointerEvent} inPointer The in pointer object. * @param {PointerEvent} inPointer The in pointer object.
*/ */
TouchSource.prototype.removePrimaryPointer_ = function(inPointer) { removePrimaryPointer_(inPointer) {
if (inPointer.isPrimary) { if (inPointer.isPrimary) {
this.firstTouchId_ = undefined; this.firstTouchId_ = undefined;
this.resetClickCount_(); this.resetClickCount_();
} }
}; }
/**
/**
* @private * @private
*/ */
TouchSource.prototype.resetClickCount_ = function() { resetClickCount_() {
this.resetId_ = setTimeout( this.resetId_ = setTimeout(
this.resetClickCountHandler_.bind(this), this.resetClickCountHandler_.bind(this),
CLICK_COUNT_TIMEOUT); CLICK_COUNT_TIMEOUT);
}; }
/**
/**
* @private * @private
*/ */
TouchSource.prototype.resetClickCountHandler_ = function() { resetClickCountHandler_() {
this.clickCount_ = 0; this.clickCount_ = 0;
this.resetId_ = undefined; this.resetId_ = undefined;
}; }
/**
/**
* @private * @private
*/ */
TouchSource.prototype.cancelResetClickCount_ = function() { cancelResetClickCount_() {
if (this.resetId_ !== undefined) { if (this.resetId_ !== undefined) {
clearTimeout(this.resetId_); clearTimeout(this.resetId_);
} }
}; }
/**
/**
* @private * @private
* @param {TouchEvent} browserEvent Browser event * @param {TouchEvent} browserEvent Browser event
* @param {Touch} inTouch Touch event * @param {Touch} inTouch Touch event
* @return {PointerEvent} A pointer object. * @return {PointerEvent} A pointer object.
*/ */
TouchSource.prototype.touchToPointer_ = function(browserEvent, inTouch) { touchToPointer_(browserEvent, inTouch) {
const e = this.dispatcher.cloneEvent(browserEvent, inTouch); const e = this.dispatcher.cloneEvent(browserEvent, inTouch);
// Spec specifies that pointerId 1 is reserved for Mouse. // Spec specifies that pointerId 1 is reserved for Mouse.
// Touch identifiers can start at 0. // Touch identifiers can start at 0.
@@ -203,15 +184,14 @@ TouchSource.prototype.touchToPointer_ = function(browserEvent, inTouch) {
e.screenY = inTouch.screenY; e.screenY = inTouch.screenY;
return e; return e;
}; }
/**
/**
* @private * @private
* @param {TouchEvent} inEvent Touch event * @param {TouchEvent} inEvent Touch event
* @param {function(TouchEvent, PointerEvent)} inFunction In function. * @param {function(TouchEvent, PointerEvent)} inFunction In function.
*/ */
TouchSource.prototype.processTouches_ = function(inEvent, inFunction) { processTouches_(inEvent, inFunction) {
const touches = Array.prototype.slice.call(inEvent.changedTouches); const touches = Array.prototype.slice.call(inEvent.changedTouches);
const count = touches.length; const count = touches.length;
function preventDefault() { function preventDefault() {
@@ -223,16 +203,15 @@ TouchSource.prototype.processTouches_ = function(inEvent, inFunction) {
pointer.preventDefault = preventDefault; pointer.preventDefault = preventDefault;
inFunction.call(this, inEvent, pointer); inFunction.call(this, inEvent, pointer);
} }
}; }
/**
/**
* @private * @private
* @param {TouchList} touchList The touch list. * @param {TouchList} touchList The touch list.
* @param {number} searchId Search identifier. * @param {number} searchId Search identifier.
* @return {boolean} True, if the `Touch` with the given id is in the list. * @return {boolean} True, if the `Touch` with the given id is in the list.
*/ */
TouchSource.prototype.findTouch_ = function(touchList, searchId) { findTouch_(touchList, searchId) {
const l = touchList.length; const l = touchList.length;
for (let i = 0; i < l; i++) { for (let i = 0; i < l; i++) {
const touch = touchList[i]; const touch = touchList[i];
@@ -241,10 +220,9 @@ TouchSource.prototype.findTouch_ = function(touchList, searchId) {
} }
} }
return false; return false;
}; }
/**
/**
* In some instances, a touchstart can happen without a touchend. This * In some instances, a touchstart can happen without a touchend. This
* leaves the pointermap in a broken state. * leaves the pointermap in a broken state.
* Therefore, on every touchstart, we remove the touches that did not fire a * Therefore, on every touchstart, we remove the touches that did not fire a
@@ -255,7 +233,7 @@ TouchSource.prototype.findTouch_ = function(touchList, searchId) {
* @private * @private
* @param {TouchEvent} inEvent The in event. * @param {TouchEvent} inEvent The in event.
*/ */
TouchSource.prototype.vacuumTouches_ = function(inEvent) { vacuumTouches_(inEvent) {
const touchList = inEvent.touches; const touchList = inEvent.touches;
// pointerMap.getCount() should be < touchList.length here, // pointerMap.getCount() should be < touchList.length here,
// as the touchstart has not been processed yet. // as the touchstart has not been processed yet.
@@ -277,30 +255,28 @@ TouchSource.prototype.vacuumTouches_ = function(inEvent) {
this.cancelOut_(inEvent, d[i]); this.cancelOut_(inEvent, d[i]);
} }
} }
}; }
/**
/**
* Handler for `touchstart`, triggers `pointerover`, * Handler for `touchstart`, triggers `pointerover`,
* `pointerenter` and `pointerdown` events. * `pointerenter` and `pointerdown` events.
* *
* @param {TouchEvent} inEvent The in event. * @param {TouchEvent} inEvent The in event.
*/ */
TouchSource.prototype.touchstart = function(inEvent) { touchstart(inEvent) {
this.vacuumTouches_(inEvent); this.vacuumTouches_(inEvent);
this.setPrimaryTouch_(inEvent.changedTouches[0]); this.setPrimaryTouch_(inEvent.changedTouches[0]);
this.dedupSynthMouse_(inEvent); this.dedupSynthMouse_(inEvent);
this.clickCount_++; this.clickCount_++;
this.processTouches_(inEvent, this.overDown_); this.processTouches_(inEvent, this.overDown_);
}; }
/**
/**
* @private * @private
* @param {TouchEvent} browserEvent The event. * @param {TouchEvent} browserEvent The event.
* @param {PointerEvent} inPointer The in pointer object. * @param {PointerEvent} inPointer The in pointer object.
*/ */
TouchSource.prototype.overDown_ = function(browserEvent, inPointer) { overDown_(browserEvent, inPointer) {
this.pointerMap[inPointer.pointerId] = { this.pointerMap[inPointer.pointerId] = {
target: inPointer.target, target: inPointer.target,
out: inPointer, out: inPointer,
@@ -309,26 +285,24 @@ TouchSource.prototype.overDown_ = function(browserEvent, inPointer) {
this.dispatcher.over(inPointer, browserEvent); this.dispatcher.over(inPointer, browserEvent);
this.dispatcher.enter(inPointer, browserEvent); this.dispatcher.enter(inPointer, browserEvent);
this.dispatcher.down(inPointer, browserEvent); this.dispatcher.down(inPointer, browserEvent);
}; }
/**
/**
* Handler for `touchmove`. * Handler for `touchmove`.
* *
* @param {TouchEvent} inEvent The in event. * @param {TouchEvent} inEvent The in event.
*/ */
TouchSource.prototype.touchmove = function(inEvent) { touchmove(inEvent) {
inEvent.preventDefault(); inEvent.preventDefault();
this.processTouches_(inEvent, this.moveOverOut_); this.processTouches_(inEvent, this.moveOverOut_);
}; }
/**
/**
* @private * @private
* @param {TouchEvent} browserEvent The event. * @param {TouchEvent} browserEvent The event.
* @param {PointerEvent} inPointer The in pointer. * @param {PointerEvent} inPointer The in pointer.
*/ */
TouchSource.prototype.moveOverOut_ = function(browserEvent, inPointer) { moveOverOut_(browserEvent, inPointer) {
const event = inPointer; const event = inPointer;
const pointer = this.pointerMap[event.pointerId]; const pointer = this.pointerMap[event.pointerId];
// a finger drifted off the screen, ignore it // a finger drifted off the screen, ignore it
@@ -355,75 +329,69 @@ TouchSource.prototype.moveOverOut_ = function(browserEvent, inPointer) {
} }
pointer.out = event; pointer.out = event;
pointer.outTarget = event.target; pointer.outTarget = event.target;
}; }
/**
/**
* Handler for `touchend`, triggers `pointerup`, * Handler for `touchend`, triggers `pointerup`,
* `pointerout` and `pointerleave` events. * `pointerout` and `pointerleave` events.
* *
* @param {TouchEvent} inEvent The event. * @param {TouchEvent} inEvent The event.
*/ */
TouchSource.prototype.touchend = function(inEvent) { touchend(inEvent) {
this.dedupSynthMouse_(inEvent); this.dedupSynthMouse_(inEvent);
this.processTouches_(inEvent, this.upOut_); this.processTouches_(inEvent, this.upOut_);
}; }
/**
/**
* @private * @private
* @param {TouchEvent} browserEvent An event. * @param {TouchEvent} browserEvent An event.
* @param {PointerEvent} inPointer The inPointer object. * @param {PointerEvent} inPointer The inPointer object.
*/ */
TouchSource.prototype.upOut_ = function(browserEvent, inPointer) { upOut_(browserEvent, inPointer) {
this.dispatcher.up(inPointer, browserEvent); this.dispatcher.up(inPointer, browserEvent);
this.dispatcher.out(inPointer, browserEvent); this.dispatcher.out(inPointer, browserEvent);
this.dispatcher.leave(inPointer, browserEvent); this.dispatcher.leave(inPointer, browserEvent);
this.cleanUpPointer_(inPointer); this.cleanUpPointer_(inPointer);
}; }
/**
/**
* Handler for `touchcancel`, triggers `pointercancel`, * Handler for `touchcancel`, triggers `pointercancel`,
* `pointerout` and `pointerleave` events. * `pointerout` and `pointerleave` events.
* *
* @param {TouchEvent} inEvent The in event. * @param {TouchEvent} inEvent The in event.
*/ */
TouchSource.prototype.touchcancel = function(inEvent) { touchcancel(inEvent) {
this.processTouches_(inEvent, this.cancelOut_); this.processTouches_(inEvent, this.cancelOut_);
}; }
/**
/**
* @private * @private
* @param {TouchEvent} browserEvent The event. * @param {TouchEvent} browserEvent The event.
* @param {PointerEvent} inPointer The in pointer. * @param {PointerEvent} inPointer The in pointer.
*/ */
TouchSource.prototype.cancelOut_ = function(browserEvent, inPointer) { cancelOut_(browserEvent, inPointer) {
this.dispatcher.cancel(inPointer, browserEvent); this.dispatcher.cancel(inPointer, browserEvent);
this.dispatcher.out(inPointer, browserEvent); this.dispatcher.out(inPointer, browserEvent);
this.dispatcher.leave(inPointer, browserEvent); this.dispatcher.leave(inPointer, browserEvent);
this.cleanUpPointer_(inPointer); this.cleanUpPointer_(inPointer);
}; }
/**
/**
* @private * @private
* @param {PointerEvent} inPointer The inPointer object. * @param {PointerEvent} inPointer The inPointer object.
*/ */
TouchSource.prototype.cleanUpPointer_ = function(inPointer) { cleanUpPointer_(inPointer) {
delete this.pointerMap[inPointer.pointerId]; delete this.pointerMap[inPointer.pointerId];
this.removePrimaryPointer_(inPointer); this.removePrimaryPointer_(inPointer);
}; }
/**
/**
* Prevent synth mouse events from creating pointer events. * Prevent synth mouse events from creating pointer events.
* *
* @private * @private
* @param {TouchEvent} inEvent The in event. * @param {TouchEvent} inEvent The in event.
*/ */
TouchSource.prototype.dedupSynthMouse_ = function(inEvent) { dedupSynthMouse_(inEvent) {
const lts = this.mouseSource.lastTouches; const lts = this.mouseSource.lastTouches;
const t = inEvent.changedTouches[0]; const t = inEvent.changedTouches[0];
// only the primary finger will synth mouse events // only the primary finger will synth mouse events
@@ -437,5 +405,21 @@ TouchSource.prototype.dedupSynthMouse_ = function(inEvent) {
remove(lts, lt); remove(lts, lt);
}, this.dedupTimeout_); }, this.dedupTimeout_);
} }
}; }
}
inherits(TouchSource, EventSource);
/**
* @type {number}
*/
const CLICK_COUNT_TIMEOUT = 200;
/**
* @type {string}
*/
const POINTER_TYPE = 'touch';
export default TouchSource; export default TouchSource;
+54 -66
View File
@@ -54,7 +54,8 @@ import {METERS_PER_UNIT} from '../proj/Units.js';
* @struct * @struct
* @api * @api
*/ */
const Projection = function(options) { class Projection {
constructor(options) {
/** /**
* @private * @private
* @type {string} * @type {string}
@@ -125,70 +126,63 @@ const Projection = function(options) {
* @type {number|undefined} * @type {number|undefined}
*/ */
this.metersPerUnit_ = options.metersPerUnit; this.metersPerUnit_ = options.metersPerUnit;
}; }
/**
/**
* @return {boolean} The projection is suitable for wrapping the x-axis * @return {boolean} The projection is suitable for wrapping the x-axis
*/ */
Projection.prototype.canWrapX = function() { canWrapX() {
return this.canWrapX_; return this.canWrapX_;
}; }
/**
/**
* Get the code for this projection, e.g. 'EPSG:4326'. * Get the code for this projection, e.g. 'EPSG:4326'.
* @return {string} Code. * @return {string} Code.
* @api * @api
*/ */
Projection.prototype.getCode = function() { getCode() {
return this.code_; return this.code_;
}; }
/**
/**
* Get the validity extent for this projection. * Get the validity extent for this projection.
* @return {module:ol/extent~Extent} Extent. * @return {module:ol/extent~Extent} Extent.
* @api * @api
*/ */
Projection.prototype.getExtent = function() { getExtent() {
return this.extent_; return this.extent_;
}; }
/**
/**
* Get the units of this projection. * Get the units of this projection.
* @return {module:ol/proj/Units} Units. * @return {module:ol/proj/Units} Units.
* @api * @api
*/ */
Projection.prototype.getUnits = function() { getUnits() {
return this.units_; return this.units_;
}; }
/**
/**
* Get the amount of meters per unit of this projection. If the projection is * Get the amount of meters per unit of this projection. If the projection is
* not configured with `metersPerUnit` or a units identifier, the return is * not configured with `metersPerUnit` or a units identifier, the return is
* `undefined`. * `undefined`.
* @return {number|undefined} Meters. * @return {number|undefined} Meters.
* @api * @api
*/ */
Projection.prototype.getMetersPerUnit = function() { getMetersPerUnit() {
return this.metersPerUnit_ || METERS_PER_UNIT[this.units_]; return this.metersPerUnit_ || METERS_PER_UNIT[this.units_];
}; }
/**
/**
* Get the world extent for this projection. * Get the world extent for this projection.
* @return {module:ol/extent~Extent} Extent. * @return {module:ol/extent~Extent} Extent.
* @api * @api
*/ */
Projection.prototype.getWorldExtent = function() { getWorldExtent() {
return this.worldExtent_; return this.worldExtent_;
}; }
/**
/**
* Get the axis orientation of this projection. * Get the axis orientation of this projection.
* Example values are: * Example values are:
* enu - the default easting, northing, elevation. * enu - the default easting, northing, elevation.
@@ -199,87 +193,81 @@ Projection.prototype.getWorldExtent = function() {
* @return {string} Axis orientation. * @return {string} Axis orientation.
* @api * @api
*/ */
Projection.prototype.getAxisOrientation = function() { getAxisOrientation() {
return this.axisOrientation_; return this.axisOrientation_;
}; }
/**
/**
* Is this projection a global projection which spans the whole world? * Is this projection a global projection which spans the whole world?
* @return {boolean} Whether the projection is global. * @return {boolean} Whether the projection is global.
* @api * @api
*/ */
Projection.prototype.isGlobal = function() { isGlobal() {
return this.global_; return this.global_;
}; }
/**
/** * Set if the projection is a global projection which spans the whole world
* Set if the projection is a global projection which spans the whole world * @param {boolean} global Whether the projection is global.
* @param {boolean} global Whether the projection is global. * @api
* @api */
*/ setGlobal(global) {
Projection.prototype.setGlobal = function(global) {
this.global_ = global; this.global_ = global;
this.canWrapX_ = !!(global && this.extent_); this.canWrapX_ = !!(global && this.extent_);
}; }
/**
/**
* @return {module:ol/tilegrid/TileGrid} The default tile grid. * @return {module:ol/tilegrid/TileGrid} The default tile grid.
*/ */
Projection.prototype.getDefaultTileGrid = function() { getDefaultTileGrid() {
return this.defaultTileGrid_; return this.defaultTileGrid_;
}; }
/**
/**
* @param {module:ol/tilegrid/TileGrid} tileGrid The default tile grid. * @param {module:ol/tilegrid/TileGrid} tileGrid The default tile grid.
*/ */
Projection.prototype.setDefaultTileGrid = function(tileGrid) { setDefaultTileGrid(tileGrid) {
this.defaultTileGrid_ = tileGrid; this.defaultTileGrid_ = tileGrid;
}; }
/**
/**
* Set the validity extent for this projection. * Set the validity extent for this projection.
* @param {module:ol/extent~Extent} extent Extent. * @param {module:ol/extent~Extent} extent Extent.
* @api * @api
*/ */
Projection.prototype.setExtent = function(extent) { setExtent(extent) {
this.extent_ = extent; this.extent_ = extent;
this.canWrapX_ = !!(this.global_ && extent); this.canWrapX_ = !!(this.global_ && extent);
}; }
/**
/**
* Set the world extent for this projection. * Set the world extent for this projection.
* @param {module:ol/extent~Extent} worldExtent World extent * @param {module:ol/extent~Extent} worldExtent World extent
* [minlon, minlat, maxlon, maxlat]. * [minlon, minlat, maxlon, maxlat].
* @api * @api
*/ */
Projection.prototype.setWorldExtent = function(worldExtent) { setWorldExtent(worldExtent) {
this.worldExtent_ = worldExtent; this.worldExtent_ = worldExtent;
}; }
/**
/**
* Set the getPointResolution function (see {@link module:ol/proj~getPointResolution} * Set the getPointResolution function (see {@link module:ol/proj~getPointResolution}
* for this projection. * for this projection.
* @param {function(number, module:ol/coordinate~Coordinate):number} func Function * @param {function(number, module:ol/coordinate~Coordinate):number} func Function
* @api * @api
*/ */
Projection.prototype.setGetPointResolution = function(func) { setGetPointResolution(func) {
this.getPointResolutionFunc_ = func; this.getPointResolutionFunc_ = func;
}; }
/**
/**
* Get the custom point resolution function for this projection (if set). * Get the custom point resolution function for this projection (if set).
* @return {function(number, module:ol/coordinate~Coordinate):number|undefined} The custom point * @return {function(number, module:ol/coordinate~Coordinate):number|undefined} The custom point
* resolution function (if set). * resolution function (if set).
*/ */
Projection.prototype.getPointResolutionFunc = function() { getPointResolutionFunc() {
return this.getPointResolutionFunc_; return this.getPointResolutionFunc_;
}; }
}
export default Projection; export default Projection;
+26 -28
View File
@@ -12,7 +12,8 @@ import Polygon from '../geom/Polygon.js';
* @extends {module:ol/Disposable} * @extends {module:ol/Disposable}
* @param {string} className CSS class name. * @param {string} className CSS class name.
*/ */
const RenderBox = function(className) { class RenderBox {
constructor(className) {
/** /**
* @type {module:ol/geom/Polygon} * @type {module:ol/geom/Polygon}
@@ -46,23 +47,19 @@ const RenderBox = function(className) {
*/ */
this.endPixel_ = null; this.endPixel_ = null;
}; }
inherits(RenderBox, Disposable); /**
/**
* @inheritDoc * @inheritDoc
*/ */
RenderBox.prototype.disposeInternal = function() { disposeInternal() {
this.setMap(null); this.setMap(null);
}; }
/**
/**
* @private * @private
*/ */
RenderBox.prototype.render_ = function() { render_() {
const startPixel = this.startPixel_; const startPixel = this.startPixel_;
const endPixel = this.endPixel_; const endPixel = this.endPixel_;
const px = 'px'; const px = 'px';
@@ -71,13 +68,12 @@ RenderBox.prototype.render_ = function() {
style.top = Math.min(startPixel[1], endPixel[1]) + px; style.top = Math.min(startPixel[1], endPixel[1]) + px;
style.width = Math.abs(endPixel[0] - startPixel[0]) + px; style.width = Math.abs(endPixel[0] - startPixel[0]) + px;
style.height = Math.abs(endPixel[1] - startPixel[1]) + px; style.height = Math.abs(endPixel[1] - startPixel[1]) + px;
}; }
/**
/**
* @param {module:ol/PluggableMap} map Map. * @param {module:ol/PluggableMap} map Map.
*/ */
RenderBox.prototype.setMap = function(map) { setMap(map) {
if (this.map_) { if (this.map_) {
this.map_.getOverlayContainer().removeChild(this.element_); this.map_.getOverlayContainer().removeChild(this.element_);
const style = this.element_.style; const style = this.element_.style;
@@ -87,25 +83,23 @@ RenderBox.prototype.setMap = function(map) {
if (this.map_) { if (this.map_) {
this.map_.getOverlayContainer().appendChild(this.element_); this.map_.getOverlayContainer().appendChild(this.element_);
} }
}; }
/**
/**
* @param {module:ol~Pixel} startPixel Start pixel. * @param {module:ol~Pixel} startPixel Start pixel.
* @param {module:ol~Pixel} endPixel End pixel. * @param {module:ol~Pixel} endPixel End pixel.
*/ */
RenderBox.prototype.setPixels = function(startPixel, endPixel) { setPixels(startPixel, endPixel) {
this.startPixel_ = startPixel; this.startPixel_ = startPixel;
this.endPixel_ = endPixel; this.endPixel_ = endPixel;
this.createOrUpdateGeometry(); this.createOrUpdateGeometry();
this.render_(); this.render_();
}; }
/**
/**
* Creates or updates the cached geometry. * Creates or updates the cached geometry.
*/ */
RenderBox.prototype.createOrUpdateGeometry = function() { createOrUpdateGeometry() {
const startPixel = this.startPixel_; const startPixel = this.startPixel_;
const endPixel = this.endPixel_; const endPixel = this.endPixel_;
const pixels = [ const pixels = [
@@ -122,13 +116,17 @@ RenderBox.prototype.createOrUpdateGeometry = function() {
} else { } else {
this.geometry_.setCoordinates([coordinates]); this.geometry_.setCoordinates([coordinates]);
} }
}; }
/**
/**
* @return {module:ol/geom/Polygon} Geometry. * @return {module:ol/geom/Polygon} Geometry.
*/ */
RenderBox.prototype.getGeometry = function() { getGeometry() {
return this.geometry_; return this.geometry_;
}; }
}
inherits(RenderBox, Disposable);
export default RenderBox; export default RenderBox;
+97 -104
View File
@@ -25,7 +25,8 @@ import {create as createTransform, compose as composeTransform} from '../transfo
* @param {Object.<string, *>} properties Properties. * @param {Object.<string, *>} properties Properties.
* @param {number|string|undefined} id Feature id. * @param {number|string|undefined} id Feature id.
*/ */
const RenderFeature = function(type, flatCoordinates, ends, properties, id) { class RenderFeature {
constructor(type, flatCoordinates, ends, properties, id) {
/** /**
* @private * @private
* @type {module:ol/extent~Extent|undefined} * @type {module:ol/extent~Extent|undefined}
@@ -74,41 +75,24 @@ const RenderFeature = function(type, flatCoordinates, ends, properties, id) {
*/ */
this.properties_ = properties; this.properties_ = properties;
}; }
/**
/**
* @type {module:ol/transform~Transform}
*/
const tmpTransform = createTransform();
/**
* Get a feature property by its key. * Get a feature property by its key.
* @param {string} key Key * @param {string} key Key
* @return {*} Value for the requested key. * @return {*} Value for the requested key.
* @api * @api
*/ */
RenderFeature.prototype.get = function(key) { get(key) {
return this.properties_[key]; return this.properties_[key];
}; }
/**
/**
* @return {Array.<number>|Array.<Array.<number>>} Ends or endss.
*/
RenderFeature.prototype.getEnds =
RenderFeature.prototype.getEndss = function() {
return this.ends_;
};
/**
* Get the extent of this feature's geometry. * Get the extent of this feature's geometry.
* @return {module:ol/extent~Extent} Extent. * @return {module:ol/extent~Extent} Extent.
* @api * @api
*/ */
RenderFeature.prototype.getExtent = function() { getExtent() {
if (!this.extent_) { if (!this.extent_) {
this.extent_ = this.type_ === GeometryType.POINT ? this.extent_ = this.type_ === GeometryType.POINT ?
createOrUpdateFromCoordinate(this.flatCoordinates_) : createOrUpdateFromCoordinate(this.flatCoordinates_) :
@@ -117,26 +101,24 @@ RenderFeature.prototype.getExtent = function() {
} }
return this.extent_; return this.extent_;
}; }
/**
/**
* @return {Array.<number>} Flat interior points. * @return {Array.<number>} Flat interior points.
*/ */
RenderFeature.prototype.getFlatInteriorPoint = function() { getFlatInteriorPoint() {
if (!this.flatInteriorPoints_) { if (!this.flatInteriorPoints_) {
const flatCenter = getCenter(this.getExtent()); const flatCenter = getCenter(this.getExtent());
this.flatInteriorPoints_ = getInteriorPointOfArray( this.flatInteriorPoints_ = getInteriorPointOfArray(
this.flatCoordinates_, 0, this.ends_, 2, flatCenter, 0); this.flatCoordinates_, 0, this.ends_, 2, flatCenter, 0);
} }
return this.flatInteriorPoints_; return this.flatInteriorPoints_;
}; }
/**
/**
* @return {Array.<number>} Flat interior points. * @return {Array.<number>} Flat interior points.
*/ */
RenderFeature.prototype.getFlatInteriorPoints = function() { getFlatInteriorPoints() {
if (!this.flatInteriorPoints_) { if (!this.flatInteriorPoints_) {
const flatCenters = linearRingssCenter( const flatCenters = linearRingssCenter(
this.flatCoordinates_, 0, this.ends_, 2); this.flatCoordinates_, 0, this.ends_, 2);
@@ -144,25 +126,23 @@ RenderFeature.prototype.getFlatInteriorPoints = function() {
this.flatCoordinates_, 0, this.ends_, 2, flatCenters); this.flatCoordinates_, 0, this.ends_, 2, flatCenters);
} }
return this.flatInteriorPoints_; return this.flatInteriorPoints_;
}; }
/**
/**
* @return {Array.<number>} Flat midpoint. * @return {Array.<number>} Flat midpoint.
*/ */
RenderFeature.prototype.getFlatMidpoint = function() { getFlatMidpoint() {
if (!this.flatMidpoints_) { if (!this.flatMidpoints_) {
this.flatMidpoints_ = interpolatePoint( this.flatMidpoints_ = interpolatePoint(
this.flatCoordinates_, 0, this.flatCoordinates_.length, 2, 0.5); this.flatCoordinates_, 0, this.flatCoordinates_.length, 2, 0.5);
} }
return this.flatMidpoints_; return this.flatMidpoints_;
}; }
/**
/**
* @return {Array.<number>} Flat midpoints. * @return {Array.<number>} Flat midpoints.
*/ */
RenderFeature.prototype.getFlatMidpoints = function() { getFlatMidpoints() {
if (!this.flatMidpoints_) { if (!this.flatMidpoints_) {
this.flatMidpoints_ = []; this.flatMidpoints_ = [];
const flatCoordinates = this.flatCoordinates_; const flatCoordinates = this.flatCoordinates_;
@@ -177,24 +157,94 @@ RenderFeature.prototype.getFlatMidpoints = function() {
} }
} }
return this.flatMidpoints_; return this.flatMidpoints_;
}; }
/** /**
* Get the feature identifier. This is a stable identifier for the feature and * Get the feature identifier. This is a stable identifier for the feature and
* is set when reading data from a remote source. * is set when reading data from a remote source.
* @return {number|string|undefined} Id. * @return {number|string|undefined} Id.
* @api * @api
*/ */
RenderFeature.prototype.getId = function() { getId() {
return this.id_; return this.id_;
}; }
/**
* @return {Array.<number>} Flat coordinates.
*/
getOrientedFlatCoordinates() {
return this.flatCoordinates_;
}
/**
* For API compatibility with {@link module:ol/Feature~Feature}, this method is useful when
* determining the geometry type in style function (see {@link #getType}).
* @return {module:ol/render/Feature} Feature.
* @api
*/
getGeometry() {
return this;
}
/**
* Get the feature properties.
* @return {Object.<string, *>} Feature properties.
* @api
*/
getProperties() {
return this.properties_;
}
/**
* @return {number} Stride.
*/
getStride() {
return 2;
}
/**
* Get the type of this feature's geometry.
* @return {module:ol/geom/GeometryType} Geometry type.
* @api
*/
getType() {
return this.type_;
}
/**
* Transform geometry coordinates from tile pixel space to projected.
* The SRS of the source and destination are expected to be the same.
*
* @param {module:ol/proj~ProjectionLike} source The current projection
* @param {module:ol/proj~ProjectionLike} destination The desired projection.
*/
transform(source, destination) {
source = getProjection(source);
const pixelExtent = source.getExtent();
const projectedExtent = source.getWorldExtent();
const scale = getHeight(projectedExtent) / getHeight(pixelExtent);
composeTransform(tmpTransform,
projectedExtent[0], projectedExtent[3],
scale, -scale, 0,
0, 0);
transform2D(this.flatCoordinates_, 0, this.flatCoordinates_.length, 2,
tmpTransform, this.flatCoordinates_);
}
}
/** /**
* @return {Array.<number>} Flat coordinates. * @type {module:ol/transform~Transform}
*/ */
RenderFeature.prototype.getOrientedFlatCoordinates = function() { const tmpTransform = createTransform();
return this.flatCoordinates_;
/**
* @return {Array.<number>|Array.<Array.<number>>} Ends or endss.
*/
RenderFeature.prototype.getEnds =
RenderFeature.prototype.getEndss = function() {
return this.ends_;
}; };
@@ -205,27 +255,6 @@ RenderFeature.prototype.getFlatCoordinates =
RenderFeature.prototype.getOrientedFlatCoordinates; RenderFeature.prototype.getOrientedFlatCoordinates;
/**
* For API compatibility with {@link module:ol/Feature~Feature}, this method is useful when
* determining the geometry type in style function (see {@link #getType}).
* @return {module:ol/render/Feature} Feature.
* @api
*/
RenderFeature.prototype.getGeometry = function() {
return this;
};
/**
* Get the feature properties.
* @return {Object.<string, *>} Feature properties.
* @api
*/
RenderFeature.prototype.getProperties = function() {
return this.properties_;
};
/** /**
* Get the feature for working with its geometry. * Get the feature for working with its geometry.
* @return {module:ol/render/Feature} Feature. * @return {module:ol/render/Feature} Feature.
@@ -234,46 +263,10 @@ RenderFeature.prototype.getSimplifiedGeometry =
RenderFeature.prototype.getGeometry; RenderFeature.prototype.getGeometry;
/**
* @return {number} Stride.
*/
RenderFeature.prototype.getStride = function() {
return 2;
};
/** /**
* @return {undefined} * @return {undefined}
*/ */
RenderFeature.prototype.getStyleFunction = UNDEFINED; RenderFeature.prototype.getStyleFunction = UNDEFINED;
/**
* Get the type of this feature's geometry.
* @return {module:ol/geom/GeometryType} Geometry type.
* @api
*/
RenderFeature.prototype.getType = function() {
return this.type_;
};
/**
* Transform geometry coordinates from tile pixel space to projected.
* The SRS of the source and destination are expected to be the same.
*
* @param {module:ol/proj~ProjectionLike} source The current projection
* @param {module:ol/proj~ProjectionLike} destination The desired projection.
*/
RenderFeature.prototype.transform = function(source, destination) {
source = getProjection(source);
const pixelExtent = source.getExtent();
const projectedExtent = source.getWorldExtent();
const scale = getHeight(projectedExtent) / getHeight(pixelExtent);
composeTransform(tmpTransform,
projectedExtent[0], projectedExtent[3],
scale, -scale, 0,
0, 0);
transform2D(this.flatCoordinates_, 0, this.flatCoordinates_.length, 2,
tmpTransform, this.flatCoordinates_);
};
export default RenderFeature; export default RenderFeature;
+7 -8
View File
@@ -6,21 +6,20 @@
* @constructor * @constructor
* @abstract * @abstract
*/ */
const ReplayGroup = function() {}; class ReplayGroup {
/**
/**
* @abstract * @abstract
* @param {number|undefined} zIndex Z index. * @param {number|undefined} zIndex Z index.
* @param {module:ol/render/ReplayType} replayType Replay type. * @param {module:ol/render/ReplayType} replayType Replay type.
* @return {module:ol/render/VectorContext} Replay. * @return {module:ol/render/VectorContext} Replay.
*/ */
ReplayGroup.prototype.getReplay = function(zIndex, replayType) {}; getReplay(zIndex, replayType) {}
/**
/**
* @abstract * @abstract
* @return {boolean} Is empty. * @return {boolean} Is empty.
*/ */
ReplayGroup.prototype.isEmpty = function() {}; isEmpty() {}
}
export default ReplayGroup; export default ReplayGroup;
+35 -51
View File
@@ -9,124 +9,108 @@
* @struct * @struct
* @api * @api
*/ */
const VectorContext = function() { class VectorContext {
}; /**
/**
* Render a geometry with a custom renderer. * Render a geometry with a custom renderer.
* *
* @param {module:ol/geom/SimpleGeometry} geometry Geometry. * @param {module:ol/geom/SimpleGeometry} geometry Geometry.
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
* @param {Function} renderer Renderer. * @param {Function} renderer Renderer.
*/ */
VectorContext.prototype.drawCustom = function(geometry, feature, renderer) {}; drawCustom(geometry, feature, renderer) {}
/**
/**
* Render a geometry. * Render a geometry.
* *
* @param {module:ol/geom/Geometry} geometry The geometry to render. * @param {module:ol/geom/Geometry} geometry The geometry to render.
*/ */
VectorContext.prototype.drawGeometry = function(geometry) {}; drawGeometry(geometry) {}
/**
/**
* Set the rendering style. * Set the rendering style.
* *
* @param {module:ol/style/Style} style The rendering style. * @param {module:ol/style/Style} style The rendering style.
*/ */
VectorContext.prototype.setStyle = function(style) {}; setStyle(style) {}
/**
/**
* @param {module:ol/geom/Circle} circleGeometry Circle geometry. * @param {module:ol/geom/Circle} circleGeometry Circle geometry.
* @param {module:ol/Feature} feature Feature. * @param {module:ol/Feature} feature Feature.
*/ */
VectorContext.prototype.drawCircle = function(circleGeometry, feature) {}; drawCircle(circleGeometry, feature) {}
/**
/**
* @param {module:ol/Feature} feature Feature. * @param {module:ol/Feature} feature Feature.
* @param {module:ol/style/Style} style Style. * @param {module:ol/style/Style} style Style.
*/ */
VectorContext.prototype.drawFeature = function(feature, style) {}; drawFeature(feature, style) {}
/**
/**
* @param {module:ol/geom/GeometryCollection} geometryCollectionGeometry Geometry * @param {module:ol/geom/GeometryCollection} geometryCollectionGeometry Geometry
* collection. * collection.
* @param {module:ol/Feature} feature Feature. * @param {module:ol/Feature} feature Feature.
*/ */
VectorContext.prototype.drawGeometryCollection = function(geometryCollectionGeometry, feature) {}; drawGeometryCollection(geometryCollectionGeometry, feature) {}
/**
/**
* @param {module:ol/geom/LineString|module:ol/render/Feature} lineStringGeometry Line string geometry. * @param {module:ol/geom/LineString|module:ol/render/Feature} lineStringGeometry Line string geometry.
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
*/ */
VectorContext.prototype.drawLineString = function(lineStringGeometry, feature) {}; drawLineString(lineStringGeometry, feature) {}
/**
/**
* @param {module:ol/geom/MultiLineString|module:ol/render/Feature} multiLineStringGeometry MultiLineString geometry. * @param {module:ol/geom/MultiLineString|module:ol/render/Feature} multiLineStringGeometry MultiLineString geometry.
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
*/ */
VectorContext.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) {}; drawMultiLineString(multiLineStringGeometry, feature) {}
/**
/**
* @param {module:ol/geom/MultiPoint|module:ol/render/Feature} multiPointGeometry MultiPoint geometry. * @param {module:ol/geom/MultiPoint|module:ol/render/Feature} multiPointGeometry MultiPoint geometry.
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
*/ */
VectorContext.prototype.drawMultiPoint = function(multiPointGeometry, feature) {}; drawMultiPoint(multiPointGeometry, feature) {}
/**
/**
* @param {module:ol/geom/MultiPolygon} multiPolygonGeometry MultiPolygon geometry. * @param {module:ol/geom/MultiPolygon} multiPolygonGeometry MultiPolygon geometry.
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
*/ */
VectorContext.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) {}; drawMultiPolygon(multiPolygonGeometry, feature) {}
/**
/**
* @param {module:ol/geom/Point|module:ol/render/Feature} pointGeometry Point geometry. * @param {module:ol/geom/Point|module:ol/render/Feature} pointGeometry Point geometry.
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
*/ */
VectorContext.prototype.drawPoint = function(pointGeometry, feature) {}; drawPoint(pointGeometry, feature) {}
/**
/**
* @param {module:ol/geom/Polygon|module:ol/render/Feature} polygonGeometry Polygon geometry. * @param {module:ol/geom/Polygon|module:ol/render/Feature} polygonGeometry Polygon geometry.
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
*/ */
VectorContext.prototype.drawPolygon = function(polygonGeometry, feature) {}; drawPolygon(polygonGeometry, feature) {}
/**
/**
* @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry. * @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry.
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
*/ */
VectorContext.prototype.drawText = function(geometry, feature) {}; drawText(geometry, feature) {}
/**
/**
* @param {module:ol/style/Fill} fillStyle Fill style. * @param {module:ol/style/Fill} fillStyle Fill style.
* @param {module:ol/style/Stroke} strokeStyle Stroke style. * @param {module:ol/style/Stroke} strokeStyle Stroke style.
*/ */
VectorContext.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {}; setFillStrokeStyle(fillStyle, strokeStyle) {}
/**
/**
* @param {module:ol/style/Image} imageStyle Image style. * @param {module:ol/style/Image} imageStyle Image style.
* @param {module:ol/render/canvas~DeclutterGroup=} opt_declutterGroup Declutter. * @param {module:ol/render/canvas~DeclutterGroup=} opt_declutterGroup Declutter.
*/ */
VectorContext.prototype.setImageStyle = function(imageStyle, opt_declutterGroup) {}; setImageStyle(imageStyle, opt_declutterGroup) {}
/**
/**
* @param {module:ol/style/Text} textStyle Text style. * @param {module:ol/style/Text} textStyle Text style.
* @param {module:ol/render/canvas~DeclutterGroup=} opt_declutterGroup Declutter. * @param {module:ol/render/canvas~DeclutterGroup=} opt_declutterGroup Declutter.
*/ */
VectorContext.prototype.setTextStyle = function(textStyle, opt_declutterGroup) {}; setTextStyle(textStyle, opt_declutterGroup) {}
}
export default VectorContext; export default VectorContext;
+23 -25
View File
@@ -16,8 +16,8 @@ import CanvasReplay from '../canvas/Replay.js';
* @param {?} declutterTree Declutter tree. * @param {?} declutterTree Declutter tree.
* @struct * @struct
*/ */
const CanvasImageReplay = function( class CanvasImageReplay {
tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) { constructor(tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
CanvasReplay.call(this, CanvasReplay.call(this,
tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree); tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree);
@@ -105,12 +105,9 @@ const CanvasImageReplay = function(
*/ */
this.width_ = undefined; this.width_ = undefined;
}; }
inherits(CanvasImageReplay, CanvasReplay); /**
/**
* @param {Array.<number>} flatCoordinates Flat coordinates. * @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset. * @param {number} offset Offset.
* @param {number} end End. * @param {number} end End.
@@ -118,15 +115,14 @@ inherits(CanvasImageReplay, CanvasReplay);
* @private * @private
* @return {number} My end. * @return {number} My end.
*/ */
CanvasImageReplay.prototype.drawCoordinates_ = function(flatCoordinates, offset, end, stride) { drawCoordinates_(flatCoordinates, offset, end, stride) {
return this.appendFlatCoordinates(flatCoordinates, offset, end, stride, false, false); return this.appendFlatCoordinates(flatCoordinates, offset, end, stride, false, false);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasImageReplay.prototype.drawPoint = function(pointGeometry, feature) { drawPoint(pointGeometry, feature) {
if (!this.image_) { if (!this.image_) {
return; return;
} }
@@ -150,13 +146,12 @@ CanvasImageReplay.prototype.drawPoint = function(pointGeometry, feature) {
this.scale_, this.snapToPixel_, this.width_ this.scale_, this.snapToPixel_, this.width_
]); ]);
this.endGeometry(pointGeometry, feature); this.endGeometry(pointGeometry, feature);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasImageReplay.prototype.drawMultiPoint = function(multiPointGeometry, feature) { drawMultiPoint(multiPointGeometry, feature) {
if (!this.image_) { if (!this.image_) {
return; return;
} }
@@ -181,13 +176,12 @@ CanvasImageReplay.prototype.drawMultiPoint = function(multiPointGeometry, featur
this.scale_, this.snapToPixel_, this.width_ this.scale_, this.snapToPixel_, this.width_
]); ]);
this.endGeometry(multiPointGeometry, feature); this.endGeometry(multiPointGeometry, feature);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasImageReplay.prototype.finish = function() { finish() {
this.reverseHitDetectionInstructions(); this.reverseHitDetectionInstructions();
// FIXME this doesn't really protect us against further calls to draw*Geometry // FIXME this doesn't really protect us against further calls to draw*Geometry
this.anchorX_ = undefined; this.anchorX_ = undefined;
@@ -203,13 +197,12 @@ CanvasImageReplay.prototype.finish = function() {
this.rotation_ = undefined; this.rotation_ = undefined;
this.snapToPixel_ = undefined; this.snapToPixel_ = undefined;
this.width_ = undefined; this.width_ = undefined;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasImageReplay.prototype.setImageStyle = function(imageStyle, declutterGroup) { setImageStyle(imageStyle, declutterGroup) {
const anchor = imageStyle.getAnchor(); const anchor = imageStyle.getAnchor();
const size = imageStyle.getSize(); const size = imageStyle.getSize();
const hitDetectionImage = imageStyle.getHitDetectionImage(1); const hitDetectionImage = imageStyle.getHitDetectionImage(1);
@@ -229,5 +222,10 @@ CanvasImageReplay.prototype.setImageStyle = function(imageStyle, declutterGroup)
this.scale_ = imageStyle.getScale(); this.scale_ = imageStyle.getScale();
this.snapToPixel_ = imageStyle.getSnapToPixel(); this.snapToPixel_ = imageStyle.getSnapToPixel();
this.width_ = size[0]; this.width_ = size[0];
}; }
}
inherits(CanvasImageReplay, CanvasReplay);
export default CanvasImageReplay; export default CanvasImageReplay;
+71 -88
View File
@@ -35,7 +35,8 @@ import {create as createTransform, compose as composeTransform} from '../../tran
* @param {number} viewRotation View rotation. * @param {number} viewRotation View rotation.
* @struct * @struct
*/ */
const CanvasImmediateRenderer = function(context, pixelRatio, extent, transform, viewRotation) { class CanvasImmediateRenderer {
constructor(context, pixelRatio, extent, transform, viewRotation) {
VectorContext.call(this); VectorContext.call(this);
/** /**
@@ -236,19 +237,16 @@ const CanvasImmediateRenderer = function(context, pixelRatio, extent, transform,
*/ */
this.tmpLocalTransform_ = createTransform(); this.tmpLocalTransform_ = createTransform();
}; }
inherits(CanvasImmediateRenderer, VectorContext); /**
/**
* @param {Array.<number>} flatCoordinates Flat coordinates. * @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset. * @param {number} offset Offset.
* @param {number} end End. * @param {number} end End.
* @param {number} stride Stride. * @param {number} stride Stride.
* @private * @private
*/ */
CanvasImmediateRenderer.prototype.drawImages_ = function(flatCoordinates, offset, end, stride) { drawImages_(flatCoordinates, offset, end, stride) {
if (!this.image_) { if (!this.image_) {
return; return;
} }
@@ -292,17 +290,16 @@ CanvasImmediateRenderer.prototype.drawImages_ = function(flatCoordinates, offset
if (this.imageOpacity_ != 1) { if (this.imageOpacity_ != 1) {
context.globalAlpha = alpha; context.globalAlpha = alpha;
} }
}; }
/**
/**
* @param {Array.<number>} flatCoordinates Flat coordinates. * @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset. * @param {number} offset Offset.
* @param {number} end End. * @param {number} end End.
* @param {number} stride Stride. * @param {number} stride Stride.
* @private * @private
*/ */
CanvasImmediateRenderer.prototype.drawText_ = function(flatCoordinates, offset, end, stride) { drawText_(flatCoordinates, offset, end, stride) {
if (!this.textState_ || this.text_ === '') { if (!this.textState_ || this.text_ === '') {
return; return;
} }
@@ -342,10 +339,9 @@ CanvasImmediateRenderer.prototype.drawText_ = function(flatCoordinates, offset,
if (rotation !== 0 || this.textScale_ != 1) { if (rotation !== 0 || this.textScale_ != 1) {
context.setTransform(1, 0, 0, 1, 0, 0); context.setTransform(1, 0, 0, 1, 0, 0);
} }
}; }
/**
/**
* @param {Array.<number>} flatCoordinates Flat coordinates. * @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset. * @param {number} offset Offset.
* @param {number} end End. * @param {number} end End.
@@ -354,7 +350,7 @@ CanvasImmediateRenderer.prototype.drawText_ = function(flatCoordinates, offset,
* @private * @private
* @return {number} end End. * @return {number} end End.
*/ */
CanvasImmediateRenderer.prototype.moveToLineTo_ = function(flatCoordinates, offset, end, stride, close) { moveToLineTo_(flatCoordinates, offset, end, stride, close) {
const context = this.context_; const context = this.context_;
const pixelCoordinates = transform2D( const pixelCoordinates = transform2D(
flatCoordinates, offset, end, stride, this.transform_, flatCoordinates, offset, end, stride, this.transform_,
@@ -371,10 +367,9 @@ CanvasImmediateRenderer.prototype.moveToLineTo_ = function(flatCoordinates, offs
context.closePath(); context.closePath();
} }
return end; return end;
}; }
/**
/**
* @param {Array.<number>} flatCoordinates Flat coordinates. * @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset. * @param {number} offset Offset.
* @param {Array.<number>} ends Ends. * @param {Array.<number>} ends Ends.
@@ -382,15 +377,14 @@ CanvasImmediateRenderer.prototype.moveToLineTo_ = function(flatCoordinates, offs
* @private * @private
* @return {number} End. * @return {number} End.
*/ */
CanvasImmediateRenderer.prototype.drawRings_ = function(flatCoordinates, offset, ends, stride) { drawRings_(flatCoordinates, offset, ends, stride) {
for (let i = 0, ii = ends.length; i < ii; ++i) { for (let i = 0, ii = ends.length; i < ii; ++i) {
offset = this.moveToLineTo_(flatCoordinates, offset, ends[i], stride, true); offset = this.moveToLineTo_(flatCoordinates, offset, ends[i], stride, true);
} }
return offset; return offset;
}; }
/**
/**
* Render a circle geometry into the canvas. Rendering is immediate and uses * Render a circle geometry into the canvas. Rendering is immediate and uses
* the current fill and stroke styles. * the current fill and stroke styles.
* *
@@ -398,7 +392,7 @@ CanvasImmediateRenderer.prototype.drawRings_ = function(flatCoordinates, offset,
* @override * @override
* @api * @api
*/ */
CanvasImmediateRenderer.prototype.drawCircle = function(geometry) { drawCircle(geometry) {
if (!intersects(this.extent_, geometry.getExtent())) { if (!intersects(this.extent_, geometry.getExtent())) {
return; return;
} }
@@ -428,10 +422,9 @@ CanvasImmediateRenderer.prototype.drawCircle = function(geometry) {
if (this.text_ !== '') { if (this.text_ !== '') {
this.drawText_(geometry.getCenter(), 0, 2, 2); this.drawText_(geometry.getCenter(), 0, 2, 2);
} }
}; }
/**
/**
* Set the rendering style. Note that since this is an immediate rendering API, * Set the rendering style. Note that since this is an immediate rendering API,
* any `zIndex` on the provided style will be ignored. * any `zIndex` on the provided style will be ignored.
* *
@@ -439,14 +432,13 @@ CanvasImmediateRenderer.prototype.drawCircle = function(geometry) {
* @override * @override
* @api * @api
*/ */
CanvasImmediateRenderer.prototype.setStyle = function(style) { setStyle(style) {
this.setFillStrokeStyle(style.getFill(), style.getStroke()); this.setFillStrokeStyle(style.getFill(), style.getStroke());
this.setImageStyle(style.getImage()); this.setImageStyle(style.getImage());
this.setTextStyle(style.getText()); this.setTextStyle(style.getText());
}; }
/**
/**
* Render a geometry into the canvas. Call * Render a geometry into the canvas. Call
* {@link module:ol/render/canvas/Immediate#setStyle} first to set the rendering style. * {@link module:ol/render/canvas/Immediate#setStyle} first to set the rendering style.
* *
@@ -454,7 +446,7 @@ CanvasImmediateRenderer.prototype.setStyle = function(style) {
* @override * @override
* @api * @api
*/ */
CanvasImmediateRenderer.prototype.drawGeometry = function(geometry) { drawGeometry(geometry) {
const type = geometry.getType(); const type = geometry.getType();
switch (type) { switch (type) {
case GeometryType.POINT: case GeometryType.POINT:
@@ -483,10 +475,9 @@ CanvasImmediateRenderer.prototype.drawGeometry = function(geometry) {
break; break;
default: default:
} }
}; }
/**
/**
* Render a feature into the canvas. Note that any `zIndex` on the provided * Render a feature into the canvas. Note that any `zIndex` on the provided
* style will be ignored - features are rendered immediately in the order that * style will be ignored - features are rendered immediately in the order that
* this method is called. If you need `zIndex` support, you should be using an * this method is called. If you need `zIndex` support, you should be using an
@@ -497,39 +488,37 @@ CanvasImmediateRenderer.prototype.drawGeometry = function(geometry) {
* @override * @override
* @api * @api
*/ */
CanvasImmediateRenderer.prototype.drawFeature = function(feature, style) { drawFeature(feature, style) {
const geometry = style.getGeometryFunction()(feature); const geometry = style.getGeometryFunction()(feature);
if (!geometry || !intersects(this.extent_, geometry.getExtent())) { if (!geometry || !intersects(this.extent_, geometry.getExtent())) {
return; return;
} }
this.setStyle(style); this.setStyle(style);
this.drawGeometry(geometry); this.drawGeometry(geometry);
}; }
/**
/**
* Render a GeometryCollection to the canvas. Rendering is immediate and * Render a GeometryCollection to the canvas. Rendering is immediate and
* uses the current styles appropriate for each geometry in the collection. * uses the current styles appropriate for each geometry in the collection.
* *
* @param {module:ol/geom/GeometryCollection} geometry Geometry collection. * @param {module:ol/geom/GeometryCollection} geometry Geometry collection.
* @override * @override
*/ */
CanvasImmediateRenderer.prototype.drawGeometryCollection = function(geometry) { drawGeometryCollection(geometry) {
const geometries = geometry.getGeometriesArray(); const geometries = geometry.getGeometriesArray();
for (let i = 0, ii = geometries.length; i < ii; ++i) { for (let i = 0, ii = geometries.length; i < ii; ++i) {
this.drawGeometry(geometries[i]); this.drawGeometry(geometries[i]);
} }
}; }
/**
/**
* Render a Point geometry into the canvas. Rendering is immediate and uses * Render a Point geometry into the canvas. Rendering is immediate and uses
* the current style. * the current style.
* *
* @param {module:ol/geom/Point|module:ol/render/Feature} geometry Point geometry. * @param {module:ol/geom/Point|module:ol/render/Feature} geometry Point geometry.
* @override * @override
*/ */
CanvasImmediateRenderer.prototype.drawPoint = function(geometry) { drawPoint(geometry) {
const flatCoordinates = geometry.getFlatCoordinates(); const flatCoordinates = geometry.getFlatCoordinates();
const stride = geometry.getStride(); const stride = geometry.getStride();
if (this.image_) { if (this.image_) {
@@ -538,17 +527,16 @@ CanvasImmediateRenderer.prototype.drawPoint = function(geometry) {
if (this.text_ !== '') { if (this.text_ !== '') {
this.drawText_(flatCoordinates, 0, flatCoordinates.length, stride); this.drawText_(flatCoordinates, 0, flatCoordinates.length, stride);
} }
}; }
/**
/**
* Render a MultiPoint geometry into the canvas. Rendering is immediate and * Render a MultiPoint geometry into the canvas. Rendering is immediate and
* uses the current style. * uses the current style.
* *
* @param {module:ol/geom/MultiPoint|module:ol/render/Feature} geometry MultiPoint geometry. * @param {module:ol/geom/MultiPoint|module:ol/render/Feature} geometry MultiPoint geometry.
* @override * @override
*/ */
CanvasImmediateRenderer.prototype.drawMultiPoint = function(geometry) { drawMultiPoint(geometry) {
const flatCoordinates = geometry.getFlatCoordinates(); const flatCoordinates = geometry.getFlatCoordinates();
const stride = geometry.getStride(); const stride = geometry.getStride();
if (this.image_) { if (this.image_) {
@@ -557,17 +545,16 @@ CanvasImmediateRenderer.prototype.drawMultiPoint = function(geometry) {
if (this.text_ !== '') { if (this.text_ !== '') {
this.drawText_(flatCoordinates, 0, flatCoordinates.length, stride); this.drawText_(flatCoordinates, 0, flatCoordinates.length, stride);
} }
}; }
/**
/**
* Render a LineString into the canvas. Rendering is immediate and uses * Render a LineString into the canvas. Rendering is immediate and uses
* the current style. * the current style.
* *
* @param {module:ol/geom/LineString|module:ol/render/Feature} geometry LineString geometry. * @param {module:ol/geom/LineString|module:ol/render/Feature} geometry LineString geometry.
* @override * @override
*/ */
CanvasImmediateRenderer.prototype.drawLineString = function(geometry) { drawLineString(geometry) {
if (!intersects(this.extent_, geometry.getExtent())) { if (!intersects(this.extent_, geometry.getExtent())) {
return; return;
} }
@@ -584,17 +571,16 @@ CanvasImmediateRenderer.prototype.drawLineString = function(geometry) {
const flatMidpoint = geometry.getFlatMidpoint(); const flatMidpoint = geometry.getFlatMidpoint();
this.drawText_(flatMidpoint, 0, 2, 2); this.drawText_(flatMidpoint, 0, 2, 2);
} }
}; }
/**
/**
* Render a MultiLineString geometry into the canvas. Rendering is immediate * Render a MultiLineString geometry into the canvas. Rendering is immediate
* and uses the current style. * and uses the current style.
* *
* @param {module:ol/geom/MultiLineString|module:ol/render/Feature} geometry MultiLineString geometry. * @param {module:ol/geom/MultiLineString|module:ol/render/Feature} geometry MultiLineString geometry.
* @override * @override
*/ */
CanvasImmediateRenderer.prototype.drawMultiLineString = function(geometry) { drawMultiLineString(geometry) {
const geometryExtent = geometry.getExtent(); const geometryExtent = geometry.getExtent();
if (!intersects(this.extent_, geometryExtent)) { if (!intersects(this.extent_, geometryExtent)) {
return; return;
@@ -616,17 +602,16 @@ CanvasImmediateRenderer.prototype.drawMultiLineString = function(geometry) {
const flatMidpoints = geometry.getFlatMidpoints(); const flatMidpoints = geometry.getFlatMidpoints();
this.drawText_(flatMidpoints, 0, flatMidpoints.length, 2); this.drawText_(flatMidpoints, 0, flatMidpoints.length, 2);
} }
}; }
/**
/**
* Render a Polygon geometry into the canvas. Rendering is immediate and uses * Render a Polygon geometry into the canvas. Rendering is immediate and uses
* the current style. * the current style.
* *
* @param {module:ol/geom/Polygon|module:ol/render/Feature} geometry Polygon geometry. * @param {module:ol/geom/Polygon|module:ol/render/Feature} geometry Polygon geometry.
* @override * @override
*/ */
CanvasImmediateRenderer.prototype.drawPolygon = function(geometry) { drawPolygon(geometry) {
if (!intersects(this.extent_, geometry.getExtent())) { if (!intersects(this.extent_, geometry.getExtent())) {
return; return;
} }
@@ -652,16 +637,15 @@ CanvasImmediateRenderer.prototype.drawPolygon = function(geometry) {
const flatInteriorPoint = geometry.getFlatInteriorPoint(); const flatInteriorPoint = geometry.getFlatInteriorPoint();
this.drawText_(flatInteriorPoint, 0, 2, 2); this.drawText_(flatInteriorPoint, 0, 2, 2);
} }
}; }
/**
/**
* Render MultiPolygon geometry into the canvas. Rendering is immediate and * Render MultiPolygon geometry into the canvas. Rendering is immediate and
* uses the current style. * uses the current style.
* @param {module:ol/geom/MultiPolygon} geometry MultiPolygon geometry. * @param {module:ol/geom/MultiPolygon} geometry MultiPolygon geometry.
* @override * @override
*/ */
CanvasImmediateRenderer.prototype.drawMultiPolygon = function(geometry) { drawMultiPolygon(geometry) {
if (!intersects(this.extent_, geometry.getExtent())) { if (!intersects(this.extent_, geometry.getExtent())) {
return; return;
} }
@@ -693,14 +677,13 @@ CanvasImmediateRenderer.prototype.drawMultiPolygon = function(geometry) {
const flatInteriorPoints = geometry.getFlatInteriorPoints(); const flatInteriorPoints = geometry.getFlatInteriorPoints();
this.drawText_(flatInteriorPoints, 0, flatInteriorPoints.length, 2); this.drawText_(flatInteriorPoints, 0, flatInteriorPoints.length, 2);
} }
}; }
/**
/**
* @param {module:ol/render/canvas~FillState} fillState Fill state. * @param {module:ol/render/canvas~FillState} fillState Fill state.
* @private * @private
*/ */
CanvasImmediateRenderer.prototype.setContextFillState_ = function(fillState) { setContextFillState_(fillState) {
const context = this.context_; const context = this.context_;
const contextFillState = this.contextFillState_; const contextFillState = this.contextFillState_;
if (!contextFillState) { if (!contextFillState) {
@@ -713,14 +696,13 @@ CanvasImmediateRenderer.prototype.setContextFillState_ = function(fillState) {
contextFillState.fillStyle = context.fillStyle = fillState.fillStyle; contextFillState.fillStyle = context.fillStyle = fillState.fillStyle;
} }
} }
}; }
/**
/**
* @param {module:ol/render/canvas~StrokeState} strokeState Stroke state. * @param {module:ol/render/canvas~StrokeState} strokeState Stroke state.
* @private * @private
*/ */
CanvasImmediateRenderer.prototype.setContextStrokeState_ = function(strokeState) { setContextStrokeState_(strokeState) {
const context = this.context_; const context = this.context_;
const contextStrokeState = this.contextStrokeState_; const contextStrokeState = this.contextStrokeState_;
if (!contextStrokeState) { if (!contextStrokeState) {
@@ -770,14 +752,13 @@ CanvasImmediateRenderer.prototype.setContextStrokeState_ = function(strokeState)
strokeState.strokeStyle; strokeState.strokeStyle;
} }
} }
}; }
/**
/**
* @param {module:ol/render/canvas~TextState} textState Text state. * @param {module:ol/render/canvas~TextState} textState Text state.
* @private * @private
*/ */
CanvasImmediateRenderer.prototype.setContextTextState_ = function(textState) { setContextTextState_(textState) {
const context = this.context_; const context = this.context_;
const contextTextState = this.contextTextState_; const contextTextState = this.contextTextState_;
const textAlign = textState.textAlign ? const textAlign = textState.textAlign ?
@@ -803,10 +784,9 @@ CanvasImmediateRenderer.prototype.setContextTextState_ = function(textState) {
textState.textBaseline; textState.textBaseline;
} }
} }
}; }
/**
/**
* Set the fill and stroke style for subsequent draw operations. To clear * Set the fill and stroke style for subsequent draw operations. To clear
* either fill or stroke styles, pass null for the appropriate parameter. * either fill or stroke styles, pass null for the appropriate parameter.
* *
@@ -814,7 +794,7 @@ CanvasImmediateRenderer.prototype.setContextTextState_ = function(textState) {
* @param {module:ol/style/Stroke} strokeStyle Stroke style. * @param {module:ol/style/Stroke} strokeStyle Stroke style.
* @override * @override
*/ */
CanvasImmediateRenderer.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) { setFillStrokeStyle(fillStyle, strokeStyle) {
if (!fillStyle) { if (!fillStyle) {
this.fillState_ = null; this.fillState_ = null;
} else { } else {
@@ -851,17 +831,16 @@ CanvasImmediateRenderer.prototype.setFillStrokeStyle = function(fillStyle, strok
strokeStyleColor : defaultStrokeStyle) strokeStyleColor : defaultStrokeStyle)
}; };
} }
}; }
/**
/**
* Set the image style for subsequent draw operations. Pass null to remove * Set the image style for subsequent draw operations. Pass null to remove
* the image style. * the image style.
* *
* @param {module:ol/style/Image} imageStyle Image style. * @param {module:ol/style/Image} imageStyle Image style.
* @override * @override
*/ */
CanvasImmediateRenderer.prototype.setImageStyle = function(imageStyle) { setImageStyle(imageStyle) {
if (!imageStyle) { if (!imageStyle) {
this.image_ = null; this.image_ = null;
} else { } else {
@@ -883,17 +862,16 @@ CanvasImmediateRenderer.prototype.setImageStyle = function(imageStyle) {
this.imageSnapToPixel_ = imageStyle.getSnapToPixel(); this.imageSnapToPixel_ = imageStyle.getSnapToPixel();
this.imageWidth_ = imageSize[0]; this.imageWidth_ = imageSize[0];
} }
}; }
/**
/**
* Set the text style for subsequent draw operations. Pass null to * Set the text style for subsequent draw operations. Pass null to
* remove the text style. * remove the text style.
* *
* @param {module:ol/style/Text} textStyle Text style. * @param {module:ol/style/Text} textStyle Text style.
* @override * @override
*/ */
CanvasImmediateRenderer.prototype.setTextStyle = function(textStyle) { setTextStyle(textStyle) {
if (!textStyle) { if (!textStyle) {
this.text_ = ''; this.text_ = '';
} else { } else {
@@ -962,5 +940,10 @@ CanvasImmediateRenderer.prototype.setTextStyle = function(textStyle) {
this.textScale_ = this.pixelRatio_ * (textScale !== undefined ? this.textScale_ = this.pixelRatio_ * (textScale !== undefined ?
textScale : 1); textScale : 1);
} }
}; }
}
inherits(CanvasImmediateRenderer, VectorContext);
export default CanvasImmediateRenderer; export default CanvasImmediateRenderer;
+23 -25
View File
@@ -16,16 +16,13 @@ import CanvasReplay from '../canvas/Replay.js';
* @param {?} declutterTree Declutter tree. * @param {?} declutterTree Declutter tree.
* @struct * @struct
*/ */
const CanvasLineStringReplay = function( class CanvasLineStringReplay {
tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) { constructor(tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
CanvasReplay.call(this, CanvasReplay.call(this,
tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree); tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree);
}; }
inherits(CanvasLineStringReplay, CanvasReplay); /**
/**
* @param {Array.<number>} flatCoordinates Flat coordinates. * @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset. * @param {number} offset Offset.
* @param {number} end End. * @param {number} end End.
@@ -33,7 +30,7 @@ inherits(CanvasLineStringReplay, CanvasReplay);
* @private * @private
* @return {number} end. * @return {number} end.
*/ */
CanvasLineStringReplay.prototype.drawFlatCoordinates_ = function(flatCoordinates, offset, end, stride) { drawFlatCoordinates_(flatCoordinates, offset, end, stride) {
const myBegin = this.coordinates.length; const myBegin = this.coordinates.length;
const myEnd = this.appendFlatCoordinates( const myEnd = this.appendFlatCoordinates(
flatCoordinates, offset, end, stride, false, false); flatCoordinates, offset, end, stride, false, false);
@@ -41,13 +38,12 @@ CanvasLineStringReplay.prototype.drawFlatCoordinates_ = function(flatCoordinates
this.instructions.push(moveToLineToInstruction); this.instructions.push(moveToLineToInstruction);
this.hitDetectionInstructions.push(moveToLineToInstruction); this.hitDetectionInstructions.push(moveToLineToInstruction);
return end; return end;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasLineStringReplay.prototype.drawLineString = function(lineStringGeometry, feature) { drawLineString(lineStringGeometry, feature) {
const state = this.state; const state = this.state;
const strokeStyle = state.strokeStyle; const strokeStyle = state.strokeStyle;
const lineWidth = state.lineWidth; const lineWidth = state.lineWidth;
@@ -66,13 +62,12 @@ CanvasLineStringReplay.prototype.drawLineString = function(lineStringGeometry, f
this.drawFlatCoordinates_(flatCoordinates, 0, flatCoordinates.length, stride); this.drawFlatCoordinates_(flatCoordinates, 0, flatCoordinates.length, stride);
this.hitDetectionInstructions.push(strokeInstruction); this.hitDetectionInstructions.push(strokeInstruction);
this.endGeometry(lineStringGeometry, feature); this.endGeometry(lineStringGeometry, feature);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasLineStringReplay.prototype.drawMultiLineString = function(multiLineStringGeometry, feature) { drawMultiLineString(multiLineStringGeometry, feature) {
const state = this.state; const state = this.state;
const strokeStyle = state.strokeStyle; const strokeStyle = state.strokeStyle;
const lineWidth = state.lineWidth; const lineWidth = state.lineWidth;
@@ -95,26 +90,24 @@ CanvasLineStringReplay.prototype.drawMultiLineString = function(multiLineStringG
} }
this.hitDetectionInstructions.push(strokeInstruction); this.hitDetectionInstructions.push(strokeInstruction);
this.endGeometry(multiLineStringGeometry, feature); this.endGeometry(multiLineStringGeometry, feature);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasLineStringReplay.prototype.finish = function() { finish() {
const state = this.state; const state = this.state;
if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) { if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {
this.instructions.push(strokeInstruction); this.instructions.push(strokeInstruction);
} }
this.reverseHitDetectionInstructions(); this.reverseHitDetectionInstructions();
this.state = null; this.state = null;
}; }
/**
/**
* @inheritDoc. * @inheritDoc.
*/ */
CanvasLineStringReplay.prototype.applyStroke = function(state) { applyStroke(state) {
if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) { if (state.lastStroke != undefined && state.lastStroke != this.coordinates.length) {
this.instructions.push(strokeInstruction); this.instructions.push(strokeInstruction);
state.lastStroke = this.coordinates.length; state.lastStroke = this.coordinates.length;
@@ -122,5 +115,10 @@ CanvasLineStringReplay.prototype.applyStroke = function(state) {
state.lastStroke = 0; state.lastStroke = 0;
CanvasReplay.prototype.applyStroke.call(this, state); CanvasReplay.prototype.applyStroke.call(this, state);
this.instructions.push(beginPathInstruction); this.instructions.push(beginPathInstruction);
}; }
}
inherits(CanvasLineStringReplay, CanvasReplay);
export default CanvasLineStringReplay; export default CanvasLineStringReplay;
+26 -29
View File
@@ -22,16 +22,13 @@ import CanvasReplay from '../canvas/Replay.js';
* @param {?} declutterTree Declutter tree. * @param {?} declutterTree Declutter tree.
* @struct * @struct
*/ */
const CanvasPolygonReplay = function( class CanvasPolygonReplay {
tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) { constructor(tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
CanvasReplay.call(this, CanvasReplay.call(this,
tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree); tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree);
}; }
inherits(CanvasPolygonReplay, CanvasReplay); /**
/**
* @param {Array.<number>} flatCoordinates Flat coordinates. * @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset. * @param {number} offset Offset.
* @param {Array.<number>} ends Ends. * @param {Array.<number>} ends Ends.
@@ -39,7 +36,7 @@ inherits(CanvasPolygonReplay, CanvasReplay);
* @private * @private
* @return {number} End. * @return {number} End.
*/ */
CanvasPolygonReplay.prototype.drawFlatCoordinatess_ = function(flatCoordinates, offset, ends, stride) { drawFlatCoordinatess_(flatCoordinates, offset, ends, stride) {
const state = this.state; const state = this.state;
const fill = state.fillStyle !== undefined; const fill = state.fillStyle !== undefined;
const stroke = state.strokeStyle != undefined; const stroke = state.strokeStyle != undefined;
@@ -70,13 +67,12 @@ CanvasPolygonReplay.prototype.drawFlatCoordinatess_ = function(flatCoordinates,
this.hitDetectionInstructions.push(strokeInstruction); this.hitDetectionInstructions.push(strokeInstruction);
} }
return offset; return offset;
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasPolygonReplay.prototype.drawCircle = function(circleGeometry, feature) { drawCircle(circleGeometry, feature) {
const state = this.state; const state = this.state;
const fillStyle = state.fillStyle; const fillStyle = state.fillStyle;
const strokeStyle = state.strokeStyle; const strokeStyle = state.strokeStyle;
@@ -115,13 +111,12 @@ CanvasPolygonReplay.prototype.drawCircle = function(circleGeometry, feature) {
this.hitDetectionInstructions.push(strokeInstruction); this.hitDetectionInstructions.push(strokeInstruction);
} }
this.endGeometry(circleGeometry, feature); this.endGeometry(circleGeometry, feature);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasPolygonReplay.prototype.drawPolygon = function(polygonGeometry, feature) { drawPolygon(polygonGeometry, feature) {
const state = this.state; const state = this.state;
const fillStyle = state.fillStyle; const fillStyle = state.fillStyle;
const strokeStyle = state.strokeStyle; const strokeStyle = state.strokeStyle;
@@ -148,13 +143,12 @@ CanvasPolygonReplay.prototype.drawPolygon = function(polygonGeometry, feature) {
const stride = polygonGeometry.getStride(); const stride = polygonGeometry.getStride();
this.drawFlatCoordinatess_(flatCoordinates, 0, ends, stride); this.drawFlatCoordinatess_(flatCoordinates, 0, ends, stride);
this.endGeometry(polygonGeometry, feature); this.endGeometry(polygonGeometry, feature);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasPolygonReplay.prototype.drawMultiPolygon = function(multiPolygonGeometry, feature) { drawMultiPolygon(multiPolygonGeometry, feature) {
const state = this.state; const state = this.state;
const fillStyle = state.fillStyle; const fillStyle = state.fillStyle;
const strokeStyle = state.strokeStyle; const strokeStyle = state.strokeStyle;
@@ -184,13 +178,12 @@ CanvasPolygonReplay.prototype.drawMultiPolygon = function(multiPolygonGeometry,
offset = this.drawFlatCoordinatess_(flatCoordinates, offset, endss[i], stride); offset = this.drawFlatCoordinatess_(flatCoordinates, offset, endss[i], stride);
} }
this.endGeometry(multiPolygonGeometry, feature); this.endGeometry(multiPolygonGeometry, feature);
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasPolygonReplay.prototype.finish = function() { finish() {
this.reverseHitDetectionInstructions(); this.reverseHitDetectionInstructions();
this.state = null; this.state = null;
// We want to preserve topology when drawing polygons. Polygons are // We want to preserve topology when drawing polygons. Polygons are
@@ -204,14 +197,13 @@ CanvasPolygonReplay.prototype.finish = function() {
coordinates[i] = snap(coordinates[i], tolerance); coordinates[i] = snap(coordinates[i], tolerance);
} }
} }
}; }
/**
/**
* @private * @private
* @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry. * @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry.
*/ */
CanvasPolygonReplay.prototype.setFillStrokeStyles_ = function(geometry) { setFillStrokeStyles_(geometry) {
const state = this.state; const state = this.state;
const fillStyle = state.fillStyle; const fillStyle = state.fillStyle;
if (fillStyle !== undefined) { if (fillStyle !== undefined) {
@@ -220,5 +212,10 @@ CanvasPolygonReplay.prototype.setFillStrokeStyles_ = function(geometry) {
if (state.strokeStyle !== undefined) { if (state.strokeStyle !== undefined) {
this.updateStrokeStyle(state, this.applyStroke); this.updateStrokeStyle(state, this.applyStroke);
} }
}; }
}
inherits(CanvasPolygonReplay, CanvasReplay);
export default CanvasPolygonReplay; export default CanvasPolygonReplay;
+125 -117
View File
@@ -39,7 +39,8 @@ import {
* @param {?} declutterTree Declutter tree. * @param {?} declutterTree Declutter tree.
* @struct * @struct
*/ */
const CanvasReplay = function(tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) { class CanvasReplay {
constructor(tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree) {
VectorContext.call(this); VectorContext.call(this);
/** /**
@@ -157,23 +158,9 @@ const CanvasReplay = function(tolerance, maxExtent, resolution, pixelRatio, over
*/ */
this.viewRotation_ = 0; this.viewRotation_ = 0;
}; }
inherits(CanvasReplay, VectorContext); /**
/**
* @type {module:ol/extent~Extent}
*/
const tmpExtent = createEmpty();
/**
* @type {!module:ol/transform~Transform}
*/
const tmpTransform = createTransform();
/**
* @param {CanvasRenderingContext2D} context Context. * @param {CanvasRenderingContext2D} context Context.
* @param {module:ol/coordinate~Coordinate} p1 1st point of the background box. * @param {module:ol/coordinate~Coordinate} p1 1st point of the background box.
* @param {module:ol/coordinate~Coordinate} p2 2nd point of the background box. * @param {module:ol/coordinate~Coordinate} p2 2nd point of the background box.
@@ -182,8 +169,7 @@ const tmpTransform = createTransform();
* @param {Array.<*>} fillInstruction Fill instruction. * @param {Array.<*>} fillInstruction Fill instruction.
* @param {Array.<*>} strokeInstruction Stroke instruction. * @param {Array.<*>} strokeInstruction Stroke instruction.
*/ */
CanvasReplay.prototype.replayTextBackground_ = function(context, p1, p2, p3, p4, replayTextBackground_(context, p1, p2, p3, p4, fillInstruction, strokeInstruction) {
fillInstruction, strokeInstruction) {
context.beginPath(); context.beginPath();
context.moveTo.apply(context, p1); context.moveTo.apply(context, p1);
context.lineTo.apply(context, p2); context.lineTo.apply(context, p2);
@@ -198,10 +184,9 @@ CanvasReplay.prototype.replayTextBackground_ = function(context, p1, p2, p3, p4,
this.setStrokeStyle_(context, /** @type {Array.<*>} */ (strokeInstruction)); this.setStrokeStyle_(context, /** @type {Array.<*>} */ (strokeInstruction));
context.stroke(); context.stroke();
} }
}; }
/**
/**
* @param {CanvasRenderingContext2D} context Context. * @param {CanvasRenderingContext2D} context Context.
* @param {number} x X. * @param {number} x X.
* @param {number} y Y. * @param {number} y Y.
@@ -221,9 +206,26 @@ CanvasReplay.prototype.replayTextBackground_ = function(context, p1, p2, p3, p4,
* @param {Array.<*>} fillInstruction Fill instruction. * @param {Array.<*>} fillInstruction Fill instruction.
* @param {Array.<*>} strokeInstruction Stroke instruction. * @param {Array.<*>} strokeInstruction Stroke instruction.
*/ */
CanvasReplay.prototype.replayImage_ = function(context, x, y, image, replayImage_(
anchorX, anchorY, declutterGroup, height, opacity, originX, originY, context,
rotation, scale, snapToPixel, width, padding, fillInstruction, strokeInstruction) { x,
y,
image,
anchorX,
anchorY,
declutterGroup,
height,
opacity,
originX,
originY,
rotation,
scale,
snapToPixel,
width,
padding,
fillInstruction,
strokeInstruction
) {
const fillStroke = fillInstruction || strokeInstruction; const fillStroke = fillInstruction || strokeInstruction;
anchorX *= scale; anchorX *= scale;
anchorY *= scale; anchorY *= scale;
@@ -297,23 +299,21 @@ CanvasReplay.prototype.replayImage_ = function(context, x, y, image,
} }
drawImage(context, transform, opacity, image, originX, originY, w, h, x, y, scale); drawImage(context, transform, opacity, image, originX, originY, w, h, x, y, scale);
} }
}; }
/**
/**
* @protected * @protected
* @param {Array.<number>} dashArray Dash array. * @param {Array.<number>} dashArray Dash array.
* @return {Array.<number>} Dash array with pixel ratio applied * @return {Array.<number>} Dash array with pixel ratio applied
*/ */
CanvasReplay.prototype.applyPixelRatio = function(dashArray) { applyPixelRatio(dashArray) {
const pixelRatio = this.pixelRatio; const pixelRatio = this.pixelRatio;
return pixelRatio == 1 ? dashArray : dashArray.map(function(dash) { return pixelRatio == 1 ? dashArray : dashArray.map(function(dash) {
return dash * pixelRatio; return dash * pixelRatio;
}); });
}; }
/**
/**
* @param {Array.<number>} flatCoordinates Flat coordinates. * @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset. * @param {number} offset Offset.
* @param {number} end End. * @param {number} end End.
@@ -323,7 +323,7 @@ CanvasReplay.prototype.applyPixelRatio = function(dashArray) {
* @protected * @protected
* @return {number} My end. * @return {number} My end.
*/ */
CanvasReplay.prototype.appendFlatCoordinates = function(flatCoordinates, offset, end, stride, closed, skipFirst) { appendFlatCoordinates(flatCoordinates, offset, end, stride, closed, skipFirst) {
let myEnd = this.coordinates.length; let myEnd = this.coordinates.length;
const extent = this.getBufferedMaxExtent(); const extent = this.getBufferedMaxExtent();
@@ -365,10 +365,9 @@ CanvasReplay.prototype.appendFlatCoordinates = function(flatCoordinates, offset,
this.coordinates[myEnd++] = lastCoord[1]; this.coordinates[myEnd++] = lastCoord[1];
} }
return myEnd; return myEnd;
}; }
/**
/**
* @param {Array.<number>} flatCoordinates Flat coordinates. * @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset. * @param {number} offset Offset.
* @param {Array.<number>} ends Ends. * @param {Array.<number>} ends Ends.
@@ -376,7 +375,7 @@ CanvasReplay.prototype.appendFlatCoordinates = function(flatCoordinates, offset,
* @param {Array.<number>} replayEnds Replay ends. * @param {Array.<number>} replayEnds Replay ends.
* @return {number} Offset. * @return {number} Offset.
*/ */
CanvasReplay.prototype.drawCustomCoordinates_ = function(flatCoordinates, offset, ends, stride, replayEnds) { drawCustomCoordinates_(flatCoordinates, offset, ends, stride, replayEnds) {
for (let i = 0, ii = ends.length; i < ii; ++i) { for (let i = 0, ii = ends.length; i < ii; ++i) {
const end = ends[i]; const end = ends[i];
const replayEnd = this.appendFlatCoordinates(flatCoordinates, offset, end, stride, false, false); const replayEnd = this.appendFlatCoordinates(flatCoordinates, offset, end, stride, false, false);
@@ -384,13 +383,12 @@ CanvasReplay.prototype.drawCustomCoordinates_ = function(flatCoordinates, offset
offset = end; offset = end;
} }
return offset; return offset;
}; }
/**
/**
* @inheritDoc. * @inheritDoc.
*/ */
CanvasReplay.prototype.drawCustom = function(geometry, feature, renderer) { drawCustom(geometry, feature, renderer) {
this.beginGeometry(geometry, feature); this.beginGeometry(geometry, feature);
const type = geometry.getType(); const type = geometry.getType();
const stride = geometry.getStride(); const stride = geometry.getStride();
@@ -434,27 +432,25 @@ CanvasReplay.prototype.drawCustom = function(geometry, feature, renderer) {
replayBegin, replayEnd, geometry, renderer]); replayBegin, replayEnd, geometry, renderer]);
} }
this.endGeometry(geometry, feature); this.endGeometry(geometry, feature);
}; }
/**
/**
* @protected * @protected
* @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry. * @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry.
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
*/ */
CanvasReplay.prototype.beginGeometry = function(geometry, feature) { beginGeometry(geometry, feature) {
this.beginGeometryInstruction1_ = [CanvasInstruction.BEGIN_GEOMETRY, feature, 0]; this.beginGeometryInstruction1_ = [CanvasInstruction.BEGIN_GEOMETRY, feature, 0];
this.instructions.push(this.beginGeometryInstruction1_); this.instructions.push(this.beginGeometryInstruction1_);
this.beginGeometryInstruction2_ = [CanvasInstruction.BEGIN_GEOMETRY, feature, 0]; this.beginGeometryInstruction2_ = [CanvasInstruction.BEGIN_GEOMETRY, feature, 0];
this.hitDetectionInstructions.push(this.beginGeometryInstruction2_); this.hitDetectionInstructions.push(this.beginGeometryInstruction2_);
}; }
/**
/**
* @private * @private
* @param {CanvasRenderingContext2D} context Context. * @param {CanvasRenderingContext2D} context Context.
*/ */
CanvasReplay.prototype.fill_ = function(context) { fill_(context) {
if (this.alignFill_) { if (this.alignFill_) {
const origin = applyTransform(this.renderedTransform_, [0, 0]); const origin = applyTransform(this.renderedTransform_, [0, 0]);
const repeatSize = 512 * this.pixelRatio; const repeatSize = 512 * this.pixelRatio;
@@ -465,15 +461,14 @@ CanvasReplay.prototype.fill_ = function(context) {
if (this.alignFill_) { if (this.alignFill_) {
context.setTransform.apply(context, resetTransform); context.setTransform.apply(context, resetTransform);
} }
}; }
/**
/**
* @private * @private
* @param {CanvasRenderingContext2D} context Context. * @param {CanvasRenderingContext2D} context Context.
* @param {Array.<*>} instruction Instruction. * @param {Array.<*>} instruction Instruction.
*/ */
CanvasReplay.prototype.setStrokeStyle_ = function(context, instruction) { setStrokeStyle_(context, instruction) {
context.strokeStyle = /** @type {module:ol/colorlike~ColorLike} */ (instruction[1]); context.strokeStyle = /** @type {module:ol/colorlike~ColorLike} */ (instruction[1]);
context.lineWidth = /** @type {number} */ (instruction[2]); context.lineWidth = /** @type {number} */ (instruction[2]);
context.lineCap = /** @type {string} */ (instruction[3]); context.lineCap = /** @type {string} */ (instruction[3]);
@@ -483,14 +478,13 @@ CanvasReplay.prototype.setStrokeStyle_ = function(context, instruction) {
context.lineDashOffset = /** @type {number} */ (instruction[7]); context.lineDashOffset = /** @type {number} */ (instruction[7]);
context.setLineDash(/** @type {Array.<number>} */ (instruction[6])); context.setLineDash(/** @type {Array.<number>} */ (instruction[6]));
} }
}; }
/**
/**
* @param {module:ol/render/canvas~DeclutterGroup} declutterGroup Declutter group. * @param {module:ol/render/canvas~DeclutterGroup} declutterGroup Declutter group.
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
*/ */
CanvasReplay.prototype.renderDeclutter_ = function(declutterGroup, feature) { renderDeclutter_(declutterGroup, feature) {
if (declutterGroup && declutterGroup.length > 5) { if (declutterGroup && declutterGroup.length > 5) {
const groupCount = declutterGroup[4]; const groupCount = declutterGroup[4];
if (groupCount == 1 || groupCount == declutterGroup.length - 5) { if (groupCount == 1 || groupCount == declutterGroup.length - 5) {
@@ -520,10 +514,9 @@ CanvasReplay.prototype.renderDeclutter_ = function(declutterGroup, feature) {
createOrUpdateEmpty(declutterGroup); createOrUpdateEmpty(declutterGroup);
} }
} }
}; }
/**
/**
* @private * @private
* @param {CanvasRenderingContext2D} context Context. * @param {CanvasRenderingContext2D} context Context.
* @param {module:ol/transform~Transform} transform Transform. * @param {module:ol/transform~Transform} transform Transform.
@@ -537,9 +530,14 @@ CanvasReplay.prototype.renderDeclutter_ = function(declutterGroup, feature) {
* @return {T|undefined} Callback result. * @return {T|undefined} Callback result.
* @template T * @template T
*/ */
CanvasReplay.prototype.replay_ = function( replay_(
context, transform, skippedFeaturesHash, context,
instructions, featureCallback, opt_hitExtent) { transform,
skippedFeaturesHash,
instructions,
featureCallback,
opt_hitExtent
) {
/** @type {Array.<number>} */ /** @type {Array.<number>} */
let pixelCoordinates; let pixelCoordinates;
if (this.pixelCoordinates_ && equals(transform, this.renderedTransform_)) { if (this.pixelCoordinates_ && equals(transform, this.renderedTransform_)) {
@@ -838,25 +836,22 @@ CanvasReplay.prototype.replay_ = function(
context.stroke(); context.stroke();
} }
return undefined; return undefined;
}; }
/**
/**
* @param {CanvasRenderingContext2D} context Context. * @param {CanvasRenderingContext2D} context Context.
* @param {module:ol/transform~Transform} transform Transform. * @param {module:ol/transform~Transform} transform Transform.
* @param {number} viewRotation View rotation. * @param {number} viewRotation View rotation.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features * @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
* to skip. * to skip.
*/ */
CanvasReplay.prototype.replay = function( replay(context, transform, viewRotation, skippedFeaturesHash) {
context, transform, viewRotation, skippedFeaturesHash) {
this.viewRotation_ = viewRotation; this.viewRotation_ = viewRotation;
this.replay_(context, transform, this.replay_(context, transform,
skippedFeaturesHash, this.instructions, undefined, undefined); skippedFeaturesHash, this.instructions, undefined, undefined);
}; }
/**
/**
* @param {CanvasRenderingContext2D} context Context. * @param {CanvasRenderingContext2D} context Context.
* @param {module:ol/transform~Transform} transform Transform. * @param {module:ol/transform~Transform} transform Transform.
* @param {number} viewRotation View rotation. * @param {number} viewRotation View rotation.
@@ -869,19 +864,23 @@ CanvasReplay.prototype.replay = function(
* @return {T|undefined} Callback result. * @return {T|undefined} Callback result.
* @template T * @template T
*/ */
CanvasReplay.prototype.replayHitDetection = function( replayHitDetection(
context, transform, viewRotation, skippedFeaturesHash, context,
opt_featureCallback, opt_hitExtent) { transform,
viewRotation,
skippedFeaturesHash,
opt_featureCallback,
opt_hitExtent
) {
this.viewRotation_ = viewRotation; this.viewRotation_ = viewRotation;
return this.replay_(context, transform, skippedFeaturesHash, return this.replay_(context, transform, skippedFeaturesHash,
this.hitDetectionInstructions, opt_featureCallback, opt_hitExtent); this.hitDetectionInstructions, opt_featureCallback, opt_hitExtent);
}; }
/**
/**
* Reverse the hit detection instructions. * Reverse the hit detection instructions.
*/ */
CanvasReplay.prototype.reverseHitDetectionInstructions = function() { reverseHitDetectionInstructions() {
const hitDetectionInstructions = this.hitDetectionInstructions; const hitDetectionInstructions = this.hitDetectionInstructions;
// step 1 - reverse array // step 1 - reverse array
hitDetectionInstructions.reverse(); hitDetectionInstructions.reverse();
@@ -902,13 +901,12 @@ CanvasReplay.prototype.reverseHitDetectionInstructions = function() {
begin = -1; begin = -1;
} }
} }
}; }
/**
/**
* @inheritDoc * @inheritDoc
*/ */
CanvasReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) { setFillStrokeStyle(fillStyle, strokeStyle) {
const state = this.state; const state = this.state;
if (fillStyle) { if (fillStyle) {
const fillStyleColor = fillStyle.getColor(); const fillStyleColor = fillStyle.getColor();
@@ -954,15 +952,14 @@ CanvasReplay.prototype.setFillStrokeStyle = function(fillStyle, strokeStyle) {
state.lineWidth = undefined; state.lineWidth = undefined;
state.miterLimit = undefined; state.miterLimit = undefined;
} }
}; }
/**
/**
* @param {module:ol/render/canvas~FillStrokeState} state State. * @param {module:ol/render/canvas~FillStrokeState} state State.
* @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry. * @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry.
* @return {Array.<*>} Fill instruction. * @return {Array.<*>} Fill instruction.
*/ */
CanvasReplay.prototype.createFill = function(state, geometry) { createFill(state, geometry) {
const fillStyle = state.fillStyle; const fillStyle = state.fillStyle;
const fillInstruction = [CanvasInstruction.SET_FILL_STYLE, fillStyle]; const fillInstruction = [CanvasInstruction.SET_FILL_STYLE, fillStyle];
if (typeof fillStyle !== 'string') { if (typeof fillStyle !== 'string') {
@@ -970,37 +967,34 @@ CanvasReplay.prototype.createFill = function(state, geometry) {
fillInstruction.push(true); fillInstruction.push(true);
} }
return fillInstruction; return fillInstruction;
}; }
/**
/**
* @param {module:ol/render/canvas~FillStrokeState} state State. * @param {module:ol/render/canvas~FillStrokeState} state State.
*/ */
CanvasReplay.prototype.applyStroke = function(state) { applyStroke(state) {
this.instructions.push(this.createStroke(state)); this.instructions.push(this.createStroke(state));
}; }
/**
/**
* @param {module:ol/render/canvas~FillStrokeState} state State. * @param {module:ol/render/canvas~FillStrokeState} state State.
* @return {Array.<*>} Stroke instruction. * @return {Array.<*>} Stroke instruction.
*/ */
CanvasReplay.prototype.createStroke = function(state) { createStroke(state) {
return [ return [
CanvasInstruction.SET_STROKE_STYLE, CanvasInstruction.SET_STROKE_STYLE,
state.strokeStyle, state.lineWidth * this.pixelRatio, state.lineCap, state.strokeStyle, state.lineWidth * this.pixelRatio, state.lineCap,
state.lineJoin, state.miterLimit, state.lineJoin, state.miterLimit,
this.applyPixelRatio(state.lineDash), state.lineDashOffset * this.pixelRatio this.applyPixelRatio(state.lineDash), state.lineDashOffset * this.pixelRatio
]; ];
}; }
/**
/**
* @param {module:ol/render/canvas~FillStrokeState} state State. * @param {module:ol/render/canvas~FillStrokeState} state State.
* @param {function(this:module:ol/render/canvas/Replay, module:ol/render/canvas~FillStrokeState, (module:ol/geom/Geometry|module:ol/render/Feature)):Array.<*>} createFill Create fill. * @param {function(this:module:ol/render/canvas/Replay, module:ol/render/canvas~FillStrokeState, (module:ol/geom/Geometry|module:ol/render/Feature)):Array.<*>} createFill Create fill.
* @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry. * @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry.
*/ */
CanvasReplay.prototype.updateFillStyle = function(state, createFill, geometry) { updateFillStyle(state, createFill, geometry) {
const fillStyle = state.fillStyle; const fillStyle = state.fillStyle;
if (typeof fillStyle !== 'string' || state.currentFillStyle != fillStyle) { if (typeof fillStyle !== 'string' || state.currentFillStyle != fillStyle) {
if (fillStyle !== undefined) { if (fillStyle !== undefined) {
@@ -1008,14 +1002,13 @@ CanvasReplay.prototype.updateFillStyle = function(state, createFill, geometry) {
} }
state.currentFillStyle = fillStyle; state.currentFillStyle = fillStyle;
} }
}; }
/**
/**
* @param {module:ol/render/canvas~FillStrokeState} state State. * @param {module:ol/render/canvas~FillStrokeState} state State.
* @param {function(this:module:ol/render/canvas/Replay, module:ol/render/canvas~FillStrokeState)} applyStroke Apply stroke. * @param {function(this:module:ol/render/canvas/Replay, module:ol/render/canvas~FillStrokeState)} applyStroke Apply stroke.
*/ */
CanvasReplay.prototype.updateStrokeStyle = function(state, applyStroke) { updateStrokeStyle(state, applyStroke) {
const strokeStyle = state.strokeStyle; const strokeStyle = state.strokeStyle;
const lineCap = state.lineCap; const lineCap = state.lineCap;
const lineDash = state.lineDash; const lineDash = state.lineDash;
@@ -1041,14 +1034,13 @@ CanvasReplay.prototype.updateStrokeStyle = function(state, applyStroke) {
state.currentLineWidth = lineWidth; state.currentLineWidth = lineWidth;
state.currentMiterLimit = miterLimit; state.currentMiterLimit = miterLimit;
} }
}; }
/**
/**
* @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry. * @param {module:ol/geom/Geometry|module:ol/render/Feature} geometry Geometry.
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature. * @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
*/ */
CanvasReplay.prototype.endGeometry = function(geometry, feature) { endGeometry(geometry, feature) {
this.beginGeometryInstruction1_[2] = this.instructions.length; this.beginGeometryInstruction1_[2] = this.instructions.length;
this.beginGeometryInstruction1_ = null; this.beginGeometryInstruction1_ = null;
this.beginGeometryInstruction2_[2] = this.hitDetectionInstructions.length; this.beginGeometryInstruction2_[2] = this.hitDetectionInstructions.length;
@@ -1056,23 +1048,16 @@ CanvasReplay.prototype.endGeometry = function(geometry, feature) {
const endGeometryInstruction = [CanvasInstruction.END_GEOMETRY, feature]; const endGeometryInstruction = [CanvasInstruction.END_GEOMETRY, feature];
this.instructions.push(endGeometryInstruction); this.instructions.push(endGeometryInstruction);
this.hitDetectionInstructions.push(endGeometryInstruction); this.hitDetectionInstructions.push(endGeometryInstruction);
}; }
/**
/**
* FIXME empty description for jsdoc
*/
CanvasReplay.prototype.finish = UNDEFINED;
/**
* Get the buffered rendering extent. Rendering will be clipped to the extent * Get the buffered rendering extent. Rendering will be clipped to the extent
* provided to the constructor. To account for symbolizers that may intersect * provided to the constructor. To account for symbolizers that may intersect
* this extent, we calculate a buffered extent (e.g. based on stroke width). * this extent, we calculate a buffered extent (e.g. based on stroke width).
* @return {module:ol/extent~Extent} The buffered rendering extent. * @return {module:ol/extent~Extent} The buffered rendering extent.
* @protected * @protected
*/ */
CanvasReplay.prototype.getBufferedMaxExtent = function() { getBufferedMaxExtent() {
if (!this.bufferedMaxExtent_) { if (!this.bufferedMaxExtent_) {
this.bufferedMaxExtent_ = clone(this.maxExtent); this.bufferedMaxExtent_ = clone(this.maxExtent);
if (this.maxLineWidth > 0) { if (this.maxLineWidth > 0) {
@@ -1081,5 +1066,28 @@ CanvasReplay.prototype.getBufferedMaxExtent = function() {
} }
} }
return this.bufferedMaxExtent_; return this.bufferedMaxExtent_;
}; }
}
inherits(CanvasReplay, VectorContext);
/**
* @type {module:ol/extent~Extent}
*/
const tmpExtent = createEmpty();
/**
* @type {!module:ol/transform~Transform}
*/
const tmpTransform = createTransform();
/**
* FIXME empty description for jsdoc
*/
CanvasReplay.prototype.finish = UNDEFINED;
export default CanvasReplay; export default CanvasReplay;
+293 -280
View File
@@ -46,8 +46,16 @@ const BATCH_CONSTRUCTORS = {
* @param {number=} opt_renderBuffer Optional rendering buffer. * @param {number=} opt_renderBuffer Optional rendering buffer.
* @struct * @struct
*/ */
const CanvasReplayGroup = function( class CanvasReplayGroup {
tolerance, maxExtent, resolution, pixelRatio, overlaps, declutterTree, opt_renderBuffer) { constructor(
tolerance,
maxExtent,
resolution,
pixelRatio,
overlaps,
declutterTree,
opt_renderBuffer
) {
ReplayGroup.call(this); ReplayGroup.call(this);
/** /**
@@ -115,7 +123,289 @@ const CanvasReplayGroup = function(
* @type {module:ol/transform~Transform} * @type {module:ol/transform~Transform}
*/ */
this.hitDetectionTransform_ = createTransform(); this.hitDetectionTransform_ = createTransform();
}; }
/**
* @param {boolean} group Group with previous replay.
* @return {module:ol/render/canvas~DeclutterGroup} Declutter instruction group.
*/
addDeclutter(group) {
let declutter = null;
if (this.declutterTree_) {
if (group) {
declutter = this.declutterGroup_;
/** @type {number} */ (declutter[4])++;
} else {
declutter = this.declutterGroup_ = createEmpty();
declutter.push(1);
}
}
return declutter;
}
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {module:ol/transform~Transform} transform Transform.
*/
clip(context, transform) {
const flatClipCoords = this.getClipCoords(transform);
context.beginPath();
context.moveTo(flatClipCoords[0], flatClipCoords[1]);
context.lineTo(flatClipCoords[2], flatClipCoords[3]);
context.lineTo(flatClipCoords[4], flatClipCoords[5]);
context.lineTo(flatClipCoords[6], flatClipCoords[7]);
context.clip();
}
/**
* @param {Array.<module:ol/render/ReplayType>} replays Replays.
* @return {boolean} Has replays of the provided types.
*/
hasReplays(replays) {
for (const zIndex in this.replaysByZIndex_) {
const candidates = this.replaysByZIndex_[zIndex];
for (let i = 0, ii = replays.length; i < ii; ++i) {
if (replays[i] in candidates) {
return true;
}
}
}
return false;
}
/**
* FIXME empty description for jsdoc
*/
finish() {
for (const zKey in this.replaysByZIndex_) {
const replays = this.replaysByZIndex_[zKey];
for (const replayKey in replays) {
replays[replayKey].finish();
}
}
}
/**
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
* @param {number} resolution Resolution.
* @param {number} rotation Rotation.
* @param {number} hitTolerance Hit tolerance in pixels.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features to skip.
* @param {function((module:ol/Feature|module:ol/render/Feature)): T} callback Feature callback.
* @param {Object.<string, module:ol/render/canvas~DeclutterGroup>} declutterReplays Declutter replays.
* @return {T|undefined} Callback result.
* @template T
*/
forEachFeatureAtCoordinate(
coordinate,
resolution,
rotation,
hitTolerance,
skippedFeaturesHash,
callback,
declutterReplays
) {
hitTolerance = Math.round(hitTolerance);
const contextSize = hitTolerance * 2 + 1;
const transform = composeTransform(this.hitDetectionTransform_,
hitTolerance + 0.5, hitTolerance + 0.5,
1 / resolution, -1 / resolution,
-rotation,
-coordinate[0], -coordinate[1]);
const context = this.hitDetectionContext_;
if (context.canvas.width !== contextSize || context.canvas.height !== contextSize) {
context.canvas.width = contextSize;
context.canvas.height = contextSize;
} else {
context.clearRect(0, 0, contextSize, contextSize);
}
/**
* @type {module:ol/extent~Extent}
*/
let hitExtent;
if (this.renderBuffer_ !== undefined) {
hitExtent = createEmpty();
extendCoordinate(hitExtent, coordinate);
buffer(hitExtent, resolution * (this.renderBuffer_ + hitTolerance), hitExtent);
}
const mask = getCircleArray(hitTolerance);
let declutteredFeatures;
if (this.declutterTree_) {
declutteredFeatures = this.declutterTree_.all().map(function(entry) {
return entry.value;
});
}
let replayType;
/**
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
* @return {?} Callback result.
*/
function featureCallback(feature) {
const imageData = context.getImageData(0, 0, contextSize, contextSize).data;
for (let i = 0; i < contextSize; i++) {
for (let j = 0; j < contextSize; j++) {
if (mask[i][j]) {
if (imageData[(j * contextSize + i) * 4 + 3] > 0) {
let result;
if (!(declutteredFeatures && (replayType == ReplayType.IMAGE || replayType == ReplayType.TEXT)) ||
declutteredFeatures.indexOf(feature) !== -1) {
result = callback(feature);
}
if (result) {
return result;
} else {
context.clearRect(0, 0, contextSize, contextSize);
return undefined;
}
}
}
}
}
}
/** @type {Array.<number>} */
const zs = Object.keys(this.replaysByZIndex_).map(Number);
zs.sort(numberSafeCompareFunction);
let i, j, replays, replay, result;
for (i = zs.length - 1; i >= 0; --i) {
const zIndexKey = zs[i].toString();
replays = this.replaysByZIndex_[zIndexKey];
for (j = ORDER.length - 1; j >= 0; --j) {
replayType = ORDER[j];
replay = replays[replayType];
if (replay !== undefined) {
if (declutterReplays &&
(replayType == ReplayType.IMAGE || replayType == ReplayType.TEXT)) {
const declutter = declutterReplays[zIndexKey];
if (!declutter) {
declutterReplays[zIndexKey] = [replay, transform.slice(0)];
} else {
declutter.push(replay, transform.slice(0));
}
} else {
result = replay.replayHitDetection(context, transform, rotation,
skippedFeaturesHash, featureCallback, hitExtent);
if (result) {
return result;
}
}
}
}
}
return undefined;
}
/**
* @param {module:ol/transform~Transform} transform Transform.
* @return {Array.<number>} Clip coordinates.
*/
getClipCoords(transform) {
const maxExtent = this.maxExtent_;
const minX = maxExtent[0];
const minY = maxExtent[1];
const maxX = maxExtent[2];
const maxY = maxExtent[3];
const flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY];
transform2D(
flatClipCoords, 0, 8, 2, transform, flatClipCoords);
return flatClipCoords;
}
/**
* @inheritDoc
*/
getReplay(zIndex, replayType) {
const zIndexKey = zIndex !== undefined ? zIndex.toString() : '0';
let replays = this.replaysByZIndex_[zIndexKey];
if (replays === undefined) {
replays = {};
this.replaysByZIndex_[zIndexKey] = replays;
}
let replay = replays[replayType];
if (replay === undefined) {
const Constructor = BATCH_CONSTRUCTORS[replayType];
replay = new Constructor(this.tolerance_, this.maxExtent_,
this.resolution_, this.pixelRatio_, this.overlaps_, this.declutterTree_);
replays[replayType] = replay;
}
return replay;
}
/**
* @return {Object.<string, Object.<module:ol/render/ReplayType, module:ol/render/canvas/Replay>>} Replays.
*/
getReplays() {
return this.replaysByZIndex_;
}
/**
* @inheritDoc
*/
isEmpty() {
return isEmpty(this.replaysByZIndex_);
}
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {module:ol/transform~Transform} transform Transform.
* @param {number} viewRotation View rotation.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features to skip.
* @param {Array.<module:ol/render/ReplayType>=} opt_replayTypes Ordered replay types to replay.
* Default is {@link module:ol/render/replay~ORDER}
* @param {Object.<string, module:ol/render/canvas~DeclutterGroup>=} opt_declutterReplays Declutter replays.
*/
replay(
context,
transform,
viewRotation,
skippedFeaturesHash,
opt_replayTypes,
opt_declutterReplays
) {
/** @type {Array.<number>} */
const zs = Object.keys(this.replaysByZIndex_).map(Number);
zs.sort(numberSafeCompareFunction);
// setup clipping so that the parts of over-simplified geometries are not
// visible outside the current extent when panning
context.save();
this.clip(context, transform);
const replayTypes = opt_replayTypes ? opt_replayTypes : ORDER;
let i, ii, j, jj, replays, replay;
for (i = 0, ii = zs.length; i < ii; ++i) {
const zIndexKey = zs[i].toString();
replays = this.replaysByZIndex_[zIndexKey];
for (j = 0, jj = replayTypes.length; j < jj; ++j) {
const replayType = replayTypes[j];
replay = replays[replayType];
if (replay !== undefined) {
if (opt_declutterReplays &&
(replayType == ReplayType.IMAGE || replayType == ReplayType.TEXT)) {
const declutter = opt_declutterReplays[zIndexKey];
if (!declutter) {
opt_declutterReplays[zIndexKey] = [replay, transform.slice(0)];
} else {
declutter.push(replay, transform.slice(0));
}
} else {
replay.replay(context, transform, viewRotation, skippedFeaturesHash);
}
}
}
}
context.restore();
}
}
inherits(CanvasReplayGroup, ReplayGroup); inherits(CanvasReplayGroup, ReplayGroup);
@@ -217,281 +507,4 @@ export function replayDeclutter(declutterReplays, context, rotation) {
} }
/**
* @param {boolean} group Group with previous replay.
* @return {module:ol/render/canvas~DeclutterGroup} Declutter instruction group.
*/
CanvasReplayGroup.prototype.addDeclutter = function(group) {
let declutter = null;
if (this.declutterTree_) {
if (group) {
declutter = this.declutterGroup_;
/** @type {number} */ (declutter[4])++;
} else {
declutter = this.declutterGroup_ = createEmpty();
declutter.push(1);
}
}
return declutter;
};
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {module:ol/transform~Transform} transform Transform.
*/
CanvasReplayGroup.prototype.clip = function(context, transform) {
const flatClipCoords = this.getClipCoords(transform);
context.beginPath();
context.moveTo(flatClipCoords[0], flatClipCoords[1]);
context.lineTo(flatClipCoords[2], flatClipCoords[3]);
context.lineTo(flatClipCoords[4], flatClipCoords[5]);
context.lineTo(flatClipCoords[6], flatClipCoords[7]);
context.clip();
};
/**
* @param {Array.<module:ol/render/ReplayType>} replays Replays.
* @return {boolean} Has replays of the provided types.
*/
CanvasReplayGroup.prototype.hasReplays = function(replays) {
for (const zIndex in this.replaysByZIndex_) {
const candidates = this.replaysByZIndex_[zIndex];
for (let i = 0, ii = replays.length; i < ii; ++i) {
if (replays[i] in candidates) {
return true;
}
}
}
return false;
};
/**
* FIXME empty description for jsdoc
*/
CanvasReplayGroup.prototype.finish = function() {
for (const zKey in this.replaysByZIndex_) {
const replays = this.replaysByZIndex_[zKey];
for (const replayKey in replays) {
replays[replayKey].finish();
}
}
};
/**
* @param {module:ol/coordinate~Coordinate} coordinate Coordinate.
* @param {number} resolution Resolution.
* @param {number} rotation Rotation.
* @param {number} hitTolerance Hit tolerance in pixels.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features to skip.
* @param {function((module:ol/Feature|module:ol/render/Feature)): T} callback Feature callback.
* @param {Object.<string, module:ol/render/canvas~DeclutterGroup>} declutterReplays Declutter replays.
* @return {T|undefined} Callback result.
* @template T
*/
CanvasReplayGroup.prototype.forEachFeatureAtCoordinate = function(
coordinate, resolution, rotation, hitTolerance, skippedFeaturesHash, callback, declutterReplays) {
hitTolerance = Math.round(hitTolerance);
const contextSize = hitTolerance * 2 + 1;
const transform = composeTransform(this.hitDetectionTransform_,
hitTolerance + 0.5, hitTolerance + 0.5,
1 / resolution, -1 / resolution,
-rotation,
-coordinate[0], -coordinate[1]);
const context = this.hitDetectionContext_;
if (context.canvas.width !== contextSize || context.canvas.height !== contextSize) {
context.canvas.width = contextSize;
context.canvas.height = contextSize;
} else {
context.clearRect(0, 0, contextSize, contextSize);
}
/**
* @type {module:ol/extent~Extent}
*/
let hitExtent;
if (this.renderBuffer_ !== undefined) {
hitExtent = createEmpty();
extendCoordinate(hitExtent, coordinate);
buffer(hitExtent, resolution * (this.renderBuffer_ + hitTolerance), hitExtent);
}
const mask = getCircleArray(hitTolerance);
let declutteredFeatures;
if (this.declutterTree_) {
declutteredFeatures = this.declutterTree_.all().map(function(entry) {
return entry.value;
});
}
let replayType;
/**
* @param {module:ol/Feature|module:ol/render/Feature} feature Feature.
* @return {?} Callback result.
*/
function featureCallback(feature) {
const imageData = context.getImageData(0, 0, contextSize, contextSize).data;
for (let i = 0; i < contextSize; i++) {
for (let j = 0; j < contextSize; j++) {
if (mask[i][j]) {
if (imageData[(j * contextSize + i) * 4 + 3] > 0) {
let result;
if (!(declutteredFeatures && (replayType == ReplayType.IMAGE || replayType == ReplayType.TEXT)) ||
declutteredFeatures.indexOf(feature) !== -1) {
result = callback(feature);
}
if (result) {
return result;
} else {
context.clearRect(0, 0, contextSize, contextSize);
return undefined;
}
}
}
}
}
}
/** @type {Array.<number>} */
const zs = Object.keys(this.replaysByZIndex_).map(Number);
zs.sort(numberSafeCompareFunction);
let i, j, replays, replay, result;
for (i = zs.length - 1; i >= 0; --i) {
const zIndexKey = zs[i].toString();
replays = this.replaysByZIndex_[zIndexKey];
for (j = ORDER.length - 1; j >= 0; --j) {
replayType = ORDER[j];
replay = replays[replayType];
if (replay !== undefined) {
if (declutterReplays &&
(replayType == ReplayType.IMAGE || replayType == ReplayType.TEXT)) {
const declutter = declutterReplays[zIndexKey];
if (!declutter) {
declutterReplays[zIndexKey] = [replay, transform.slice(0)];
} else {
declutter.push(replay, transform.slice(0));
}
} else {
result = replay.replayHitDetection(context, transform, rotation,
skippedFeaturesHash, featureCallback, hitExtent);
if (result) {
return result;
}
}
}
}
}
return undefined;
};
/**
* @param {module:ol/transform~Transform} transform Transform.
* @return {Array.<number>} Clip coordinates.
*/
CanvasReplayGroup.prototype.getClipCoords = function(transform) {
const maxExtent = this.maxExtent_;
const minX = maxExtent[0];
const minY = maxExtent[1];
const maxX = maxExtent[2];
const maxY = maxExtent[3];
const flatClipCoords = [minX, minY, minX, maxY, maxX, maxY, maxX, minY];
transform2D(
flatClipCoords, 0, 8, 2, transform, flatClipCoords);
return flatClipCoords;
};
/**
* @inheritDoc
*/
CanvasReplayGroup.prototype.getReplay = function(zIndex, replayType) {
const zIndexKey = zIndex !== undefined ? zIndex.toString() : '0';
let replays = this.replaysByZIndex_[zIndexKey];
if (replays === undefined) {
replays = {};
this.replaysByZIndex_[zIndexKey] = replays;
}
let replay = replays[replayType];
if (replay === undefined) {
const Constructor = BATCH_CONSTRUCTORS[replayType];
replay = new Constructor(this.tolerance_, this.maxExtent_,
this.resolution_, this.pixelRatio_, this.overlaps_, this.declutterTree_);
replays[replayType] = replay;
}
return replay;
};
/**
* @return {Object.<string, Object.<module:ol/render/ReplayType, module:ol/render/canvas/Replay>>} Replays.
*/
CanvasReplayGroup.prototype.getReplays = function() {
return this.replaysByZIndex_;
};
/**
* @inheritDoc
*/
CanvasReplayGroup.prototype.isEmpty = function() {
return isEmpty(this.replaysByZIndex_);
};
/**
* @param {CanvasRenderingContext2D} context Context.
* @param {module:ol/transform~Transform} transform Transform.
* @param {number} viewRotation View rotation.
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features to skip.
* @param {Array.<module:ol/render/ReplayType>=} opt_replayTypes Ordered replay types to replay.
* Default is {@link module:ol/render/replay~ORDER}
* @param {Object.<string, module:ol/render/canvas~DeclutterGroup>=} opt_declutterReplays Declutter replays.
*/
CanvasReplayGroup.prototype.replay = function(context,
transform, viewRotation, skippedFeaturesHash, opt_replayTypes, opt_declutterReplays) {
/** @type {Array.<number>} */
const zs = Object.keys(this.replaysByZIndex_).map(Number);
zs.sort(numberSafeCompareFunction);
// setup clipping so that the parts of over-simplified geometries are not
// visible outside the current extent when panning
context.save();
this.clip(context, transform);
const replayTypes = opt_replayTypes ? opt_replayTypes : ORDER;
let i, ii, j, jj, replays, replay;
for (i = 0, ii = zs.length; i < ii; ++i) {
const zIndexKey = zs[i].toString();
replays = this.replaysByZIndex_[zIndexKey];
for (j = 0, jj = replayTypes.length; j < jj; ++j) {
const replayType = replayTypes[j];
replay = replays[replayType];
if (replay !== undefined) {
if (opt_declutterReplays &&
(replayType == ReplayType.IMAGE || replayType == ReplayType.TEXT)) {
const declutter = opt_declutterReplays[zIndexKey];
if (!declutter) {
opt_declutterReplays[zIndexKey] = [replay, transform.slice(0)];
} else {
declutter.push(replay, transform.slice(0));
}
} else {
replay.replay(context, transform, viewRotation, skippedFeaturesHash);
}
}
}
}
context.restore();
};
export default CanvasReplayGroup; export default CanvasReplayGroup;

Some files were not shown because too many files have changed in this diff Show More