Files
openlayers/lib/OpenLayers/Layer/Vector.js
crschmidt 3948913bfc Merge all changes from the naturaldocs sandbox. This brings all the work that
has been done in the NaturalDocs branch back to trunk. Thanks to everyone who
helped out in making this happen. (I could list people, but the list would
be long, and I'm already mentally on vacation.)


git-svn-id: http://svn.openlayers.org/trunk/openlayers@3545 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
2007-06-29 15:59:20 +00:00

440 lines
13 KiB
JavaScript

/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
* See http://svn.openlayers.org/trunk/openlayers/repository-license.txt
* for the full text of the license. */
/**
* @requires OpenLayers/Layer.js
* @requires OpenLayers/Renderer.js
* @requires OpenLayers/Feature/Vector.js
*
* Class: OpenLayers.Layer.Vector
* Instances of OpenLayers.Layer.Vector are used to render vector data from
* a variety of sources. Create a new image layer with the
* <OpenLayers.Layer.Vector> constructor.
*
* Inherits from:
* - <OpenLayers.Layer>
*/
OpenLayers.Layer.Vector = OpenLayers.Class.create();
OpenLayers.Layer.Vector.prototype =
OpenLayers.Class.inherit(OpenLayers.Layer, {
/**
* APIProperty: isBaseLayer
* {Boolean} The layer is a base layer. Default is true. Set this property
* in the layer options
*/
isBaseLayer: false,
/**
* APIProperty: isFixed
* {Boolean} Whether the layer remains in one place while dragging the
* map.
*/
isFixed: false,
/**
* APIProperty: isVector
* {Boolean} Whether the layer is a vector layer.
*/
isVector: true,
/**
* APIProperty: features
* Array({<OpenLayers.Feature.Vector>})
*/
features: null,
/**
* Property: selectedFeatures
* Array({<OpenLayers.Feature.Vector>})
*/
selectedFeatures: null,
/**
* APIProperty: reportError
* {Boolean} report error message via alert() when loading of renderers
* fails.
*/
reportError: true,
/**
* APIProperty: style
* {Object} Default style for the layer
*/
style: null,
/**
* Property: renderers
* Array({String}) List of supported Renderer classes. Add to this list to
* add support for additional renderers. This list is ordered:
* the first renderer which returns true for the 'supported()'
* method will be used, if not defined in the 'renderer' option.
*/
renderers: ['SVG', 'VML'],
/**
* Property: renderer
* {<OpenLayers.Renderer>}
*/
renderer: null,
/**
* APIProperty: geometryType
* {String} geometryType allows you to limit the types of geometries this
* layer supports. This should be set to something like
* "OpenLayers.Geometry.Point" to limit types.
*/
geometryType: null,
/**
* Property: drawn
* {Boolean} Whether the Vector Layer features have been drawn yet.
*/
drawn: false,
/**
* Constructor: OpenLayers.Layer.Vector
* Create a new vector layer
*
* Parameters:
* name - {String} A name for the layer
* options - {Object} options Object with non-default properties to set on
* the layer.
*
* Return:
* {<OpenLayers.Layer.Vector>} A new vector layer
*/
initialize: function(name, options) {
var defaultStyle = OpenLayers.Feature.Vector.style['default'];
this.style = OpenLayers.Util.extend({}, defaultStyle);
OpenLayers.Layer.prototype.initialize.apply(this, arguments);
// allow user-set renderer, otherwise assign one
if (!this.renderer || !this.renderer.supported()) {
this.assignRenderer();
}
// if no valid renderer found, display error
if (!this.renderer || !this.renderer.supported()) {
this.renderer = null;
this.displayError();
}
this.features = new Array();
this.selectedFeatures = new Array();
},
/**
* APIMethod: destroy
* Destroy this layer
*/
destroy: function() {
OpenLayers.Layer.prototype.destroy.apply(this, arguments);
this.destroyFeatures();
this.features = null;
this.selectedFeatures = null;
if (this.renderer) {
this.renderer.destroy();
}
this.renderer = null;
this.geometryType = null;
this.drawn = null;
},
/**
* Method: assignRenderer
* Iterates through the available renderer implementations and selects
* and assigns the first one whose "supported()" function returns true.
*/
assignRenderer: function() {
for (var i = 0; i < this.renderers.length; i++) {
var rendererClass = OpenLayers.Renderer[this.renderers[i]];
if (rendererClass && rendererClass.prototype.supported()) {
this.renderer = new rendererClass(this.div);
break;
}
}
},
/**
* Method: displayError
* Let the user know their browser isn't supported.
*/
displayError: function() {
if (this.reportError) {
var message = "Your browser does not support vector rendering. " +
"Currently supported renderers are:\n";
message += this.renderers.join("\n");
alert(message);
}
},
/**
* Method: setMap
* The layer has been added to the map.
*
* If there is no renderer set, the layer can't be used. Remove it.
* Otherwise, give the renderer a reference to the map and set its size.
*
* Parameters:
* map - {<OpenLayers.Map>}
*/
setMap: function(map) {
OpenLayers.Layer.prototype.setMap.apply(this, arguments);
if (!this.renderer) {
this.map.removeLayer(this);
} else {
this.renderer.map = this.map;
this.renderer.setSize(this.map.getSize());
}
},
/**
* Method: onMapResize
* Notify the renderer of the change in size.
*
*/
onMapResize: function() {
OpenLayers.Layer.prototype.onMapResize.apply(this, arguments);
this.renderer.setSize(this.map.getSize());
},
/**
* Method: moveTo
* Reset the vector layer's div so that it once again is lined up with
* the map. Notify the renderer of the change of extent, and in the
* case of a change of zoom level (resolution), have the
* renderer redraw features.
*
* If the layer has not yet been drawn, cycle through the layer's
* features and draw each one.
*
* Parameters:
* bounds - {<OpenLayers.Bounds>}
* zoomChanged - {Boolean}
* dragging - {Boolean}
*/
moveTo: function(bounds, zoomChanged, dragging) {
OpenLayers.Layer.prototype.moveTo.apply(this, arguments);
if (!dragging) {
this.div.style.left = - parseInt(this.map.layerContainerDiv.style.left) + "px";
this.div.style.top = - parseInt(this.map.layerContainerDiv.style.top) + "px";
var extent = this.map.getExtent();
this.renderer.setExtent(extent);
}
if (!this.drawn || zoomChanged) {
this.drawn = true;
for(var i = 0; i < this.features.length; i++) {
var feature = this.features[i];
this.drawFeature(feature);
}
}
},
/**
* APIMethod: addFeatures
* Add Features to the layer.
*
* Parameters:
* features - {Array(<OpenLayers.Feature.Vector>)}
*/
addFeatures: function(features) {
if (!(features instanceof Array)) {
features = [features];
}
for (var i = 0; i < features.length; i++) {
var feature = features[i];
if (this.geometryType &&
!(feature.geometry instanceof this.geometryType)) {
var throwStr = "addFeatures : component should be an " +
this.geometryType.prototype.CLASS_NAME;
throw throwStr;
}
this.features.push(feature);
//give feature reference to its layer
feature.layer = this;
if (!feature.style) {
feature.style = OpenLayers.Util.extend({}, this.style);
}
this.preFeatureInsert(feature);
if (this.drawn) {
this.drawFeature(feature);
}
this.onFeatureInsert(feature);
}
},
/**
* APIMethod: removeFeatures
*
* Parameters:
* features - {Array(<OpenLayers.Feature.Vector>)}
*/
removeFeatures: function(features) {
if (!(features instanceof Array)) {
features = [features];
}
for (var i = features.length - 1; i >= 0; i--) {
var feature = features[i];
this.features = OpenLayers.Util.removeItem(this.features, feature);
if (feature.geometry) {
this.renderer.eraseGeometry(feature.geometry);
}
//in the case that this feature is one of the selected features,
// remove it from that array as well.
if (OpenLayers.Util.indexOf(this.selectedFeatures, feature) != -1){
OpenLayers.Util.removeItem(this.selectedFeatures, feature);
}
}
},
/**
* APIMethod: destroyFeatures
* Destroy all features on the layer and empty the selected features array.
*/
destroyFeatures: function () {
this.selectedFeatures = new Array();
for (var i = this.features.length - 1; i >= 0; i--) {
this.features[i].destroy();
}
},
/**
* Method: drawFeature
* Draw (or redraw) a feature on the layer. If the optional style argument
* is included, this style will be used. If no style is included, the
* feature's style will be used. If the feature doesn't have a style,
* the layer's style will be used.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
* style - {Object}
*/
drawFeature: function(feature, style) {
if(style == null) {
if(feature.style) {
style = feature.style;
} else {
style = this.style;
}
}
this.renderer.drawFeature(feature, style);
},
/**
* Method: eraseFeatures
* Erase features from the layer.
*
* Parameters:
* features - {Array(OpenLayers.Feature.Vector)}
*/
eraseFeatures: function(features) {
this.renderer.eraseFeatures(features);
},
/**
* Method: getFeatureFromEvent
* Given an event, return a feature if the event occurred over one.
* Otherwise, return null.
*
* Parameters:
* evt - {Event}
*
* Returns:
* {<OpenLayers.Feature.Vector>} A feature if one was under the event.
*/
getFeatureFromEvent: function(evt) {
var featureId = this.renderer.getFeatureIdFromEvent(evt);
return this.getFeatureById(featureId);
},
/**
* APIMethod: getFeatureById
* Given a feature id, return the feature if it exists in the features array
*
* Parameters:
* featureId - {String}
*
* Returns:
* {<OpenLayers.Feature.Vector>} A feature corresponding to the given
* featureId
*/
getFeatureById: function(featureId) {
//TBD - would it be more efficient to use a hash for this.features?
var feature = null;
for(var i=0; i<this.features.length; ++i) {
if(this.features[i].id == featureId) {
feature = this.features[i];
break;
}
}
return feature;
},
/**
* Unselect the selected features
* i.e. clears the featureSelection array
* change the style back
clearSelection: function() {
var vectorLayer = this.map.vectorLayer;
for (var i = 0; i < this.map.featureSelection.length; i++) {
var featureSelection = this.map.featureSelection[i];
vectorLayer.drawFeature(featureSelection, vectorLayer.style);
}
this.map.featureSelection = [];
},
*/
/**
* APIMethod: onFeatureInsert
* method called after a feature is inserted.
* Does nothing by default. Override this if you
* need to do something on feature updates.
*
* Paarameters:
* feature - {<OpenLayers.Feature.Vector>}
*/
onFeatureInsert: function(feature) {
},
/**
* APIMethod: preFeatureInsert
* method called before a feature is inserted.
* Does nothing by default. Override this if you
* need to do something when features are first added to the
* layer, but before they are drawn, such as adjust the style.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
*/
preFeatureInsert: function(feature) {
},
/**
* Constant: CLASS_NAME
* {String} 'OpenLayers.Layer.Vector'
*/
CLASS_NAME: "OpenLayers.Layer.Vector"
});