418 lines
10 KiB
JavaScript
418 lines
10 KiB
JavaScript
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.geom.GeometryType');
|
|
goog.require('ol.style.Circle');
|
|
goog.require('ol.style.Fill');
|
|
goog.require('ol.style.Stroke');
|
|
goog.require('ol.style.Style');
|
|
|
|
|
|
|
|
/**
|
|
* @classdesc
|
|
* A vector object for geographical features with a geometry and other
|
|
* attribute properties, similar to the features in vector file formats like
|
|
* GeoJSON.
|
|
* Features can be styled individually or use the style of their vector layer.
|
|
*
|
|
* @constructor
|
|
* @extends {ol.Object}
|
|
* @fires change Triggered when the geometry or style of the feature changes.
|
|
* @param {ol.geom.Geometry|Object.<string, *>=} opt_geometryOrValues
|
|
* Values or geometry.
|
|
* @todo api
|
|
*/
|
|
ol.Feature = function(opt_geometryOrValues) {
|
|
|
|
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.style.Style>|
|
|
* 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_geometryOrValues)) {
|
|
if (opt_geometryOrValues instanceof ol.geom.Geometry ||
|
|
goog.isNull(opt_geometryOrValues)) {
|
|
var geometry = /** @type {ol.geom.Geometry} */ (opt_geometryOrValues);
|
|
this.setGeometry(geometry);
|
|
} else {
|
|
goog.asserts.assert(goog.isObject(opt_geometryOrValues));
|
|
var values = /** @type {Object.<string, *>} */ (opt_geometryOrValues);
|
|
this.setValues(values);
|
|
}
|
|
}
|
|
};
|
|
goog.inherits(ol.Feature, ol.Object);
|
|
|
|
|
|
/**
|
|
* @return {ol.geom.Geometry|undefined} Geometry.
|
|
* @todo api
|
|
*/
|
|
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.
|
|
* @todo api
|
|
*/
|
|
ol.Feature.prototype.getId = function() {
|
|
return this.id_;
|
|
};
|
|
|
|
|
|
/**
|
|
* @return {string} Geometry property name.
|
|
* @todo api
|
|
*/
|
|
ol.Feature.prototype.getGeometryName = function() {
|
|
return this.geometryName_;
|
|
};
|
|
|
|
|
|
/**
|
|
* @return {ol.style.Style|Array.<ol.style.Style>|
|
|
* ol.feature.FeatureStyleFunction} User provided style.
|
|
* @todo api
|
|
*/
|
|
ol.Feature.prototype.getStyle = function() {
|
|
return this.style_;
|
|
};
|
|
|
|
|
|
/**
|
|
* @return {ol.feature.FeatureStyleFunction|undefined} Style function.
|
|
* @todo api
|
|
*/
|
|
ol.Feature.prototype.getStyleFunction = function() {
|
|
return this.styleFunction_;
|
|
};
|
|
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
ol.Feature.prototype.handleGeometryChange_ = function() {
|
|
this.dispatchChangeEvent();
|
|
};
|
|
|
|
|
|
/**
|
|
* @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.dispatchChangeEvent();
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @param {ol.geom.Geometry|undefined} geometry Geometry.
|
|
* @todo api
|
|
*/
|
|
ol.Feature.prototype.setGeometry = function(geometry) {
|
|
this.set(this.geometryName_, geometry);
|
|
};
|
|
goog.exportProperty(
|
|
ol.Feature.prototype,
|
|
'setGeometry',
|
|
ol.Feature.prototype.setGeometry);
|
|
|
|
|
|
/**
|
|
* @param {ol.style.Style|Array.<ol.style.Style>|
|
|
* ol.feature.FeatureStyleFunction} style Feature style.
|
|
* @todo api
|
|
*/
|
|
ol.Feature.prototype.setStyle = function(style) {
|
|
this.style_ = style;
|
|
this.styleFunction_ = ol.feature.createFeatureStyleFunction(style);
|
|
this.dispatchChangeEvent();
|
|
};
|
|
|
|
|
|
/**
|
|
* @param {number|string|undefined} id Id.
|
|
* @todo api
|
|
*/
|
|
ol.Feature.prototype.setId = function(id) {
|
|
this.id_ = id;
|
|
this.dispatchChangeEvent();
|
|
};
|
|
|
|
|
|
/**
|
|
* @param {string} name Geometry property name.
|
|
* @todo api
|
|
*/
|
|
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.<ol.style.Style>}
|
|
* @todo api
|
|
*/
|
|
ol.feature.FeatureStyleFunction;
|
|
|
|
|
|
/**
|
|
* Default style function for features.
|
|
* @param {number} resolution Resolution.
|
|
* @return {Array.<ol.style.Style>} Style.
|
|
* @this {ol.Feature}
|
|
*/
|
|
ol.feature.defaultFeatureStyleFunction = function(resolution) {
|
|
var fill = new ol.style.Fill({
|
|
color: 'rgba(255,255,255,0.4)'
|
|
});
|
|
var stroke = new ol.style.Stroke({
|
|
color: '#3399CC',
|
|
width: 1.25
|
|
});
|
|
var styles = [
|
|
new ol.style.Style({
|
|
image: new ol.style.Circle({
|
|
fill: fill,
|
|
stroke: stroke,
|
|
radius: 5
|
|
}),
|
|
fill: fill,
|
|
stroke: stroke
|
|
})
|
|
];
|
|
|
|
// now that we've run it the first time,
|
|
// replace the function with a constant version
|
|
ol.feature.defaultFeatureStyleFunction =
|
|
/** @type {function(this:ol.Feature):Array.<ol.style.Style>} */(
|
|
function(resolution) {
|
|
return styles;
|
|
});
|
|
|
|
return styles;
|
|
};
|
|
|
|
|
|
/**
|
|
* A function that takes an {@link ol.Feature} and a `{number}` representing
|
|
* the view's resolution. The function should return an array of
|
|
* {@link ol.style.Style}. This way e.g. a vector layer can be styled.
|
|
*
|
|
* @typedef {function(ol.Feature, number): Array.<ol.style.Style>}
|
|
* @todo api
|
|
*/
|
|
ol.feature.StyleFunction;
|
|
|
|
|
|
/**
|
|
* @param {ol.Feature} feature Feature.
|
|
* @param {number} resolution Resolution.
|
|
* @return {Array.<ol.style.Style>} Style.
|
|
*/
|
|
ol.feature.defaultStyleFunction = function(feature, resolution) {
|
|
var featureStyleFunction = feature.getStyleFunction();
|
|
if (!goog.isDef(featureStyleFunction)) {
|
|
featureStyleFunction = ol.feature.defaultFeatureStyleFunction;
|
|
}
|
|
return featureStyleFunction.call(feature, resolution);
|
|
};
|
|
|
|
|
|
/**
|
|
* 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>|
|
|
* 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.<ol.style.Style>}
|
|
*/
|
|
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;
|
|
};
|
|
|
|
|
|
/**
|
|
* Convert the provided object into a style function. Functions passed through
|
|
* unchanged. Arrays of ol.style.Style or single style objects wrapped in a
|
|
* new style function.
|
|
* @param {ol.feature.StyleFunction|Array.<ol.style.Style>|ol.style.Style} obj
|
|
* A style function, a single style, or an array of styles.
|
|
* @return {ol.feature.StyleFunction} A style function.
|
|
*/
|
|
ol.feature.createStyleFunction = function(obj) {
|
|
/**
|
|
* @type {ol.feature.StyleFunction}
|
|
*/
|
|
var styleFunction;
|
|
|
|
if (goog.isFunction(obj)) {
|
|
styleFunction = /** @type {ol.feature.StyleFunction} */ (obj);
|
|
} else {
|
|
/**
|
|
* @type {Array.<ol.style.Style>}
|
|
*/
|
|
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;
|
|
};
|
|
|
|
|
|
/**
|
|
* Default styles for editing features.
|
|
* @return {Object.<ol.geom.GeometryType, Array.<ol.style.Style>>} Styles
|
|
*/
|
|
ol.feature.createDefaultEditingStyles = function() {
|
|
/** @type {Object.<ol.geom.GeometryType, Array.<ol.style.Style>>} */
|
|
var styles = {};
|
|
var white = [255, 255, 255, 1];
|
|
var blue = [0, 153, 255, 1];
|
|
var width = 3;
|
|
styles[ol.geom.GeometryType.POLYGON] = [
|
|
new ol.style.Style({
|
|
fill: new ol.style.Fill({
|
|
color: [255, 255, 255, 0.5]
|
|
})
|
|
})
|
|
];
|
|
styles[ol.geom.GeometryType.MULTI_POLYGON] =
|
|
styles[ol.geom.GeometryType.POLYGON];
|
|
|
|
styles[ol.geom.GeometryType.LINE_STRING] = [
|
|
new ol.style.Style({
|
|
stroke: new ol.style.Stroke({
|
|
color: white,
|
|
width: width + 2
|
|
})
|
|
}),
|
|
new ol.style.Style({
|
|
stroke: new ol.style.Stroke({
|
|
color: blue,
|
|
width: width
|
|
})
|
|
})
|
|
];
|
|
styles[ol.geom.GeometryType.MULTI_LINE_STRING] =
|
|
styles[ol.geom.GeometryType.LINE_STRING];
|
|
|
|
styles[ol.geom.GeometryType.POINT] = [
|
|
new ol.style.Style({
|
|
image: new ol.style.Circle({
|
|
radius: width * 2,
|
|
fill: new ol.style.Fill({
|
|
color: blue
|
|
}),
|
|
stroke: new ol.style.Stroke({
|
|
color: white,
|
|
width: width / 2
|
|
})
|
|
}),
|
|
zIndex: Infinity
|
|
})
|
|
];
|
|
styles[ol.geom.GeometryType.MULTI_POINT] =
|
|
styles[ol.geom.GeometryType.POINT];
|
|
|
|
styles[ol.geom.GeometryType.GEOMETRY_COLLECTION] =
|
|
styles[ol.geom.GeometryType.POLYGON].concat(
|
|
styles[ol.geom.GeometryType.POINT]
|
|
);
|
|
|
|
return styles;
|
|
};
|