goog.provide('ol.Feature'); goog.provide('ol.feature'); goog.require('goog.asserts'); goog.require('goog.events'); goog.require('goog.events.EventType'); goog.require('goog.functions'); goog.require('ol.Object'); goog.require('ol.geom.Geometry'); goog.require('ol.style.Style'); /** * @classdesc * A vector object for geographic features with a geometry and other * attribute properties, similar to the features in vector file formats like * GeoJSON. * * Features can be styled individually with `setStyle`; otherwise they use the * style of their vector layer or feature overlay. * * Note that attribute properties are set as {@link ol.Object} properties on * the feature object, so they are observable, and have get/set accessors. * * Typically, a feature has a single geometry property. You can set the * geometry using the `setGeometry` method and get it with `getGeometry`. * It is possible to store more than one geometry on a feature using attribute * properties. By default, the geometry used for rendering is identified by * the property name `geometry`. If you want to use another geometry property * for rendering, use the `setGeometryName` method to change the attribute * property associated with the geometry for the feature. For example: * * ```js * var feature = new ol.Feature({ * geometry: new ol.geom.Polygon(polyCoords), * labelPoint: new ol.geom.Point(labelCoords), * name: 'My Polygon' * }); * * // get the polygon geometry * var poly = feature.getGeometry(); * * // Render the feature as a point using the coordinates from labelPoint * feature.setGeometryName('labelPoint'); * * // get the point geometry * var point = feature.getGeometry(); * ``` * * @constructor * @extends {ol.Object} * @fires change Triggered when the id, the geometry or the style of the * feature changes. * @param {ol.geom.Geometry|Object.=} opt_geometryOrProperties * You may pass a Geometry object directly, or an object literal * containing properties. If you pass an object literal, you may * include a Geometry associated with a `geometry` key. * @api stable */ ol.Feature = function(opt_geometryOrProperties) { goog.base(this); /** * @private * @type {number|string|undefined} */ this.id_ = undefined; /** * @type {string} * @private */ this.geometryName_ = 'geometry'; /** * User provided style. * @private * @type {ol.style.Style|Array.| * ol.feature.FeatureStyleFunction} */ this.style_ = null; /** * @private * @type {ol.feature.FeatureStyleFunction|undefined} */ this.styleFunction_ = undefined; /** * @private * @type {goog.events.Key} */ this.geometryChangeKey_ = null; goog.events.listen( this, ol.Object.getChangeEventType(this.geometryName_), this.handleGeometryChanged_, false, this); if (goog.isDef(opt_geometryOrProperties)) { if (opt_geometryOrProperties instanceof ol.geom.Geometry || goog.isNull(opt_geometryOrProperties)) { var geometry = /** @type {ol.geom.Geometry} */ (opt_geometryOrProperties); this.setGeometry(geometry); } else { goog.asserts.assert(goog.isObject(opt_geometryOrProperties)); var properties = /** @type {Object.} */ (opt_geometryOrProperties); this.setProperties(properties); } } }; goog.inherits(ol.Feature, ol.Object); /** * Clone this feature. If the original feature has a geometry it * is also cloned. The feature id is not set in the clone. * @return {ol.Feature} The clone. * @api stable */ ol.Feature.prototype.clone = function() { var clone = new ol.Feature(this.getProperties()); clone.setGeometryName(this.getGeometryName()); var geometry = this.getGeometry(); if (goog.isDefAndNotNull(geometry)) { clone.setGeometry(geometry.clone()); } var style = this.getStyle(); if (!goog.isNull(style)) { clone.setStyle(style); } return clone; }; /** * @return {ol.geom.Geometry|undefined} Returns the Geometry associated * with this feature using the current geometry name property. By * default, this is `geometry` but it may be changed by calling * `setGeometryName`. * @api stable * @observable */ ol.Feature.prototype.getGeometry = function() { return /** @type {ol.geom.Geometry|undefined} */ ( this.get(this.geometryName_)); }; goog.exportProperty( ol.Feature.prototype, 'getGeometry', ol.Feature.prototype.getGeometry); /** * @return {number|string|undefined} Id. * @api stable */ ol.Feature.prototype.getId = function() { return this.id_; }; /** * @return {string} Get the property name associated with the geometry for * this feature. By default, this is `geometry` but it may be changed by * calling `setGeometryName`. * @api stable */ ol.Feature.prototype.getGeometryName = function() { return this.geometryName_; }; /** * @return {ol.style.Style|Array.| * ol.feature.FeatureStyleFunction} Return the style as set by `setStyle` * in the same format that it was provided in. If `setStyle` has not been * called, or if it was called with `null`, then `getStyle()` will return * `null`. * @api stable */ ol.Feature.prototype.getStyle = function() { return this.style_; }; /** * @return {ol.feature.FeatureStyleFunction|undefined} Return a function * representing the current style of this feature. * @api stable */ ol.Feature.prototype.getStyleFunction = function() { return this.styleFunction_; }; /** * @private */ ol.Feature.prototype.handleGeometryChange_ = function() { this.changed(); }; /** * @private */ ol.Feature.prototype.handleGeometryChanged_ = function() { if (!goog.isNull(this.geometryChangeKey_)) { goog.events.unlistenByKey(this.geometryChangeKey_); this.geometryChangeKey_ = null; } var geometry = this.getGeometry(); if (goog.isDefAndNotNull(geometry)) { this.geometryChangeKey_ = goog.events.listen(geometry, goog.events.EventType.CHANGE, this.handleGeometryChange_, false, this); this.changed(); } }; /** * @param {ol.geom.Geometry|undefined} geometry Set the geometry for this * feature. This will update the property associated with the current * geometry property name. By default, this is `geometry` but it can be * changed by calling `setGeometryName`. * @api stable * @observable */ ol.Feature.prototype.setGeometry = function(geometry) { this.set(this.geometryName_, geometry); }; goog.exportProperty( ol.Feature.prototype, 'setGeometry', ol.Feature.prototype.setGeometry); /** * Set the style for the feature. This can be a single style object, an array * of styles, or a function that takes a resolution and returns an array of * styles. If it is `null` the feature has no style (a `null` style). * @param {ol.style.Style|Array.| * ol.feature.FeatureStyleFunction} style Style for this feature. * @api stable */ ol.Feature.prototype.setStyle = function(style) { this.style_ = style; this.styleFunction_ = goog.isNull(style) ? undefined : ol.feature.createFeatureStyleFunction(style); this.changed(); }; /** * @param {number|string|undefined} id Set a unique id for this feature. * The id may be used to retrieve a feature from a vector source with the * {@link ol.source.Vector#getFeatureById} method. * @api stable */ ol.Feature.prototype.setId = function(id) { this.id_ = id; this.changed(); }; /** * @param {string} name Set the property name from which this feature's * geometry will be fetched when calling `getGeometry`. * @api stable */ ol.Feature.prototype.setGeometryName = function(name) { goog.events.unlisten( this, ol.Object.getChangeEventType(this.geometryName_), this.handleGeometryChanged_, false, this); this.geometryName_ = name; goog.events.listen( this, ol.Object.getChangeEventType(this.geometryName_), this.handleGeometryChanged_, false, this); this.handleGeometryChanged_(); }; /** * A function that takes a `{number}` representing the view's resolution. It * returns an Array of {@link ol.style.Style}. This way individual features * can be styled. The this keyword inside the function references the * {@link ol.Feature} to be styled. * * @typedef {function(this: ol.Feature, number): Array.} * @api stable */ ol.feature.FeatureStyleFunction; /** * Convert the provided object into a feature style function. Functions passed * through unchanged. Arrays of ol.style.Style or single style objects wrapped * in a new feature style function. * @param {ol.feature.FeatureStyleFunction|!Array.| * !ol.style.Style} obj A feature style function, a single style, or an * array of styles. * @return {ol.feature.FeatureStyleFunction} A style function. */ ol.feature.createFeatureStyleFunction = function(obj) { /** * @type {ol.feature.FeatureStyleFunction} */ var styleFunction; if (goog.isFunction(obj)) { styleFunction = /** @type {ol.feature.FeatureStyleFunction} */ (obj); } else { /** * @type {Array.} */ var styles; if (goog.isArray(obj)) { styles = obj; } else { goog.asserts.assertInstanceof(obj, ol.style.Style); styles = [obj]; } styleFunction = goog.functions.constant(styles); } return styleFunction; };