Get rid of ol.FeatureOverlay

This also introduces a wrapX option to the Draw, Modify and Select
interaction.
This commit is contained in:
Andreas Hocevar
2015-06-09 13:25:51 +02:00
parent 54da473991
commit 53d5d8c1d9
28 changed files with 177 additions and 676 deletions

View File

@@ -1,5 +1,39 @@
## Upgrade notes ## Upgrade notes
### v3.7.0
#### Removal of `ol.FeatureOverlay`
Instead of an `ol.FeatureOverlay`, we now use an `ol.layer.Vector` with an
`ol.source.Vector`. If you previously had:
```js
var featureOverlay = new ol.FeatureOverlay({
map: map,
style: overlayStyle
});
featureOverlay.addFeature(feature);
featureOverlay.removeFeature(feature);
var collection = featureOverlay.getFeatures();
```
you will have to change this to:
```js
var collection = new ol.Collection();
var featureOverlay = new ol.layer.Vector({
map: map,
style: overlayStyle,
source: new ol.source.Vector({
features: collection,
useSpatialIndex: false // optional, might improve performance
});
});
featureOverlay.getSource().addFeature(feature);
featureOverlay.getSource().removeFeature(feature);
```
With the removal of `ol.FeatureOverlay`, `zIndex` symbolizer properties of overlays are no longer stacked per map, but per layer/overlay. If you previously had multiple feature overlays where you controlled the rendering order of features by using `zIndex` symbolizer properties, you can now achieve the same rendering order only if all overlay features are on the same layer.
Note that `ol.FeatureOverlay#getFeatures()` returned an `{ol.Collection.<ol.Feature>}`, whereas `ol.source.Vector#getFeatures()` returns an `{Array.<ol.Feature>}`.
### v3.6.0 ### v3.6.0
#### `ol.interaction.Draw` changes #### `ol.interaction.Draw` changes

View File

@@ -1,11 +1,13 @@
goog.require('ol.FeatureOverlay'); goog.require('ol.Collection');
goog.require('ol.Map'); goog.require('ol.Map');
goog.require('ol.View'); goog.require('ol.View');
goog.require('ol.events.condition'); goog.require('ol.events.condition');
goog.require('ol.interaction.Draw'); goog.require('ol.interaction.Draw');
goog.require('ol.interaction.Modify'); goog.require('ol.interaction.Modify');
goog.require('ol.layer.Tile'); goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.source.MapQuest'); goog.require('ol.source.MapQuest');
goog.require('ol.source.Vector');
goog.require('ol.style.Circle'); goog.require('ol.style.Circle');
goog.require('ol.style.Fill'); goog.require('ol.style.Fill');
goog.require('ol.style.Stroke'); goog.require('ol.style.Stroke');
@@ -24,11 +26,9 @@ var map = new ol.Map({
}) })
}); });
// The features are not added to a regular vector layer/source, var features = new ol.Collection();
// but to a feature overlay which holds a collection of features. var featureOverlay = new ol.layer.Vector({
// This collection is passed to the modify and also the draw source: new ol.source.Vector({features: features}),
// interaction, so that both can add or modify features.
var featureOverlay = new ol.FeatureOverlay({
style: new ol.style.Style({ style: new ol.style.Style({
fill: new ol.style.Fill({ fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0.2)' color: 'rgba(255, 255, 255, 0.2)'
@@ -48,7 +48,7 @@ var featureOverlay = new ol.FeatureOverlay({
featureOverlay.setMap(map); featureOverlay.setMap(map);
var modify = new ol.interaction.Modify({ var modify = new ol.interaction.Modify({
features: featureOverlay.getFeatures(), features: features,
// the SHIFT key must be pressed to delete vertices, so // the SHIFT key must be pressed to delete vertices, so
// that new vertices can be drawn at the same position // that new vertices can be drawn at the same position
// of existing vertices // of existing vertices
@@ -62,7 +62,7 @@ map.addInteraction(modify);
var draw; // global so we can remove it later var draw; // global so we can remove it later
function addInteraction() { function addInteraction() {
draw = new ol.interaction.Draw({ draw = new ol.interaction.Draw({
features: featureOverlay.getFeatures(), features: features,
type: /** @type {ol.geom.GeometryType} */ (typeSelect.value) type: /** @type {ol.geom.GeometryType} */ (typeSelect.value)
}); });
map.addInteraction(draw); map.addInteraction(draw);

View File

@@ -1,12 +1,13 @@
goog.require('ol.Feature'); goog.require('ol.Feature');
goog.require('ol.FeatureOverlay');
goog.require('ol.Geolocation'); goog.require('ol.Geolocation');
goog.require('ol.Map'); goog.require('ol.Map');
goog.require('ol.View'); goog.require('ol.View');
goog.require('ol.control'); goog.require('ol.control');
goog.require('ol.geom.Point'); goog.require('ol.geom.Point');
goog.require('ol.layer.Tile'); goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.source.OSM'); goog.require('ol.source.OSM');
goog.require('ol.source.Vector');
goog.require('ol.style.Circle'); goog.require('ol.style.Circle');
goog.require('ol.style.Fill'); goog.require('ol.style.Fill');
goog.require('ol.style.Stroke'); goog.require('ol.style.Stroke');
@@ -85,7 +86,9 @@ geolocation.on('change:position', function() {
new ol.geom.Point(coordinates) : null); new ol.geom.Point(coordinates) : null);
}); });
var featuresOverlay = new ol.FeatureOverlay({ var featuresOverlay = new ol.layer.Vector({
map: map, map: map,
features: [accuracyFeature, positionFeature] source: new ol.source.Vector({
features: [accuracyFeature, positionFeature]
})
}); });

View File

@@ -1,5 +1,4 @@
goog.require('ol.Feature'); goog.require('ol.Feature');
goog.require('ol.FeatureOverlay');
goog.require('ol.Map'); goog.require('ol.Map');
goog.require('ol.View'); goog.require('ol.View');
goog.require('ol.geom.Point'); goog.require('ol.geom.Point');
@@ -102,12 +101,14 @@ for (i = 0; i < featureCount; i += 30) {
overlayFeatures.push(clone); overlayFeatures.push(clone);
} }
var featureOverlay = new ol.FeatureOverlay({ var featureOverlay = new ol.layer.Vector({
map: map, map: map,
source: new ol.source.Vector({
features: overlayFeatures
}),
style: new ol.style.Style({ style: new ol.style.Style({
image: icons[iconCount - 1] image: icons[iconCount - 1]
}), })
features: overlayFeatures
}); });
map.on('click', function(evt) { map.on('click', function(evt) {

View File

@@ -1,6 +1,5 @@
goog.require('ol.Attribution'); goog.require('ol.Attribution');
goog.require('ol.Feature'); goog.require('ol.Feature');
goog.require('ol.FeatureOverlay');
goog.require('ol.Map'); goog.require('ol.Map');
goog.require('ol.View'); goog.require('ol.View');
goog.require('ol.control'); goog.require('ol.control');
@@ -180,7 +179,8 @@ map.on('postcompose', function(evt) {
} }
}); });
var featureOverlay = new ol.FeatureOverlay({ var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector(),
map: map, map: map,
style: new ol.style.Style({ style: new ol.style.Style({
image: new ol.style.Circle({ image: new ol.style.Circle({
@@ -203,7 +203,7 @@ document.getElementById('time').addEventListener('input', function() {
if (highlight === undefined) { if (highlight === undefined) {
highlight = new ol.Feature(new ol.geom.Point(coordinate)); highlight = new ol.Feature(new ol.geom.Point(coordinate));
feature.set('highlight', highlight); feature.set('highlight', highlight);
featureOverlay.addFeature(highlight); featureOverlay.getSource().addFeature(highlight);
} else { } else {
highlight.getGeometry().setCoordinates(coordinate); highlight.getGeometry().setCoordinates(coordinate);
} }

View File

@@ -1,9 +1,9 @@
goog.require('ol.FeatureOverlay');
goog.require('ol.Map'); goog.require('ol.Map');
goog.require('ol.View'); goog.require('ol.View');
goog.require('ol.format.GeoJSON'); goog.require('ol.format.GeoJSON');
goog.require('ol.layer.Image'); goog.require('ol.layer.Image');
goog.require('ol.layer.Tile'); goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.source.ImageVector'); goog.require('ol.source.ImageVector');
goog.require('ol.source.MapQuest'); goog.require('ol.source.MapQuest');
goog.require('ol.source.Vector'); goog.require('ol.source.Vector');
@@ -42,7 +42,8 @@ var map = new ol.Map({
}) })
}); });
var featureOverlay = new ol.FeatureOverlay({ var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector(),
map: map, map: map,
style: new ol.style.Style({ style: new ol.style.Style({
stroke: new ol.style.Stroke({ stroke: new ol.style.Stroke({
@@ -71,10 +72,10 @@ var displayFeatureInfo = function(pixel) {
if (feature !== highlight) { if (feature !== highlight) {
if (highlight) { if (highlight) {
featureOverlay.removeFeature(highlight); featureOverlay.getSource().removeFeature(highlight);
} }
if (feature) { if (feature) {
featureOverlay.addFeature(feature); featureOverlay.getSource().addFeature(feature);
} }
highlight = feature; highlight = feature;
} }

View File

@@ -24,7 +24,9 @@ var vector = new ol.layer.Vector({
}) })
}); });
var select = new ol.interaction.Select(); var select = new ol.interaction.Select({
wrapX: false
});
var modify = new ol.interaction.Modify({ var modify = new ol.interaction.Modify({
features: select.getFeatures() features: select.getFeatures()

View File

@@ -1,4 +1,3 @@
goog.require('ol.FeatureOverlay');
goog.require('ol.Map'); goog.require('ol.Map');
goog.require('ol.View'); goog.require('ol.View');
goog.require('ol.format.GeoJSON'); goog.require('ol.format.GeoJSON');
@@ -60,7 +59,8 @@ var map = new ol.Map({
var highlightStyleCache = {}; var highlightStyleCache = {};
var featureOverlay = new ol.FeatureOverlay({ var featureOverlay = new ol.layer.Vector({
source: new ol.source.Vector(),
map: map, map: map,
style: function(feature, resolution) { style: function(feature, resolution) {
var text = resolution < 5000 ? feature.get('name') : ''; var text = resolution < 5000 ? feature.get('name') : '';
@@ -106,10 +106,10 @@ var displayFeatureInfo = function(pixel) {
if (feature !== highlight) { if (feature !== highlight) {
if (highlight) { if (highlight) {
featureOverlay.removeFeature(highlight); featureOverlay.getSource().removeFeature(highlight);
} }
if (feature) { if (feature) {
featureOverlay.addFeature(feature); featureOverlay.getSource().addFeature(feature);
} }
highlight = feature; highlight = feature;
} }

View File

@@ -2366,7 +2366,8 @@ olx.interaction.DragZoomOptions.prototype.style;
* geometryFunction: (ol.interaction.DrawGeometryFunctionType|undefined), * geometryFunction: (ol.interaction.DrawGeometryFunctionType|undefined),
* geometryName: (string|undefined), * geometryName: (string|undefined),
* condition: (ol.events.ConditionType|undefined), * condition: (ol.events.ConditionType|undefined),
* freehandCondition: (ol.events.ConditionType|undefined)}} * freehandCondition: (ol.events.ConditionType|undefined),
* wrapX: (boolean|undefined)}}
* @api * @api
*/ */
olx.interaction.DrawOptions; olx.interaction.DrawOptions;
@@ -2470,6 +2471,14 @@ olx.interaction.DrawOptions.prototype.condition;
olx.interaction.DrawOptions.prototype.freehandCondition; olx.interaction.DrawOptions.prototype.freehandCondition;
/**
* Wrap the world horizontally on the sketch overlay. Default is `false`.
* @type {boolean|undefined}
* @api
*/
olx.interaction.DrawOptions.prototype.wrapX;
/** /**
* @typedef {{condition: (ol.events.ConditionType|undefined), * @typedef {{condition: (ol.events.ConditionType|undefined),
* duration: (number|undefined), * duration: (number|undefined),
@@ -2545,7 +2554,8 @@ olx.interaction.KeyboardZoomOptions.prototype.delta;
* @typedef {{deleteCondition: (ol.events.ConditionType|undefined), * @typedef {{deleteCondition: (ol.events.ConditionType|undefined),
* pixelTolerance: (number|undefined), * pixelTolerance: (number|undefined),
* style: (ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction|undefined), * style: (ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction|undefined),
* features: ol.Collection.<ol.Feature>}} * features: ol.Collection.<ol.Feature>,
* wrapX: (boolean|undefined)}}
* @api * @api
*/ */
olx.interaction.ModifyOptions; olx.interaction.ModifyOptions;
@@ -2587,6 +2597,14 @@ olx.interaction.ModifyOptions.prototype.style;
olx.interaction.ModifyOptions.prototype.features; olx.interaction.ModifyOptions.prototype.features;
/**
* Wrap the world horizontally on the sketch overlay. Default is `false`.
* @type {boolean|undefined}
* @api
*/
olx.interaction.ModifyOptions.prototype.wrapX;
/** /**
* @typedef {{duration: (number|undefined)}} * @typedef {{duration: (number|undefined)}}
* @api * @api
@@ -2708,7 +2726,8 @@ olx.interaction.PointerOptions.prototype.handleUpEvent;
* removeCondition: (ol.events.ConditionType|undefined), * removeCondition: (ol.events.ConditionType|undefined),
* toggleCondition: (ol.events.ConditionType|undefined), * toggleCondition: (ol.events.ConditionType|undefined),
* multi: (boolean|undefined), * multi: (boolean|undefined),
* filter: (ol.interaction.SelectFilterFunction|undefined)}} * filter: (ol.interaction.SelectFilterFunction|undefined),
* wrapX: (boolean|undefined)}}
* @api * @api
*/ */
olx.interaction.SelectOptions; olx.interaction.SelectOptions;
@@ -2803,6 +2822,14 @@ olx.interaction.SelectOptions.prototype.multi;
olx.interaction.SelectOptions.prototype.filter; olx.interaction.SelectOptions.prototype.filter;
/**
* Wrap the world horizontally on the selection overlay. Default is `true`.
* @type {boolean|undefined}
* @api
*/
olx.interaction.SelectOptions.prototype.wrapX;
/** /**
* Options for snap * Options for snap
* @typedef {{ * @typedef {{

View File

@@ -1,326 +0,0 @@
goog.provide('ol.FeatureOverlay');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.object');
goog.require('ol.Collection');
goog.require('ol.CollectionEventType');
goog.require('ol.Feature');
goog.require('ol.render.EventType');
goog.require('ol.renderer.vector');
goog.require('ol.style.Style');
/**
* @classdesc
* A mechanism for changing the style of a small number of features on a
* temporary basis, for example highlighting. This is necessary with the Canvas
* renderer, where, unlike in SVG, features cannot be individually referenced.
* See examples/vector-layers for an example: create a FeatureOverlay with a
* different style, copy the feature(s) you want rendered in this different
* style into it, and then remove them again when you're finished.
*
* @constructor
* @param {olx.FeatureOverlayOptions=} opt_options Options.
* @api
*/
ol.FeatureOverlay = function(opt_options) {
var options = goog.isDef(opt_options) ? opt_options : {};
/**
* @private
* @type {ol.Collection.<ol.Feature>}
*/
this.features_ = null;
/**
* @private
* @type {Array.<goog.events.Key>}
*/
this.featuresListenerKeys_ = null;
/**
* @private
* @type {Object.<string, goog.events.Key>}
*/
this.featureChangeListenerKeys_ = null;
/**
* @private
* @type {ol.Map}
*/
this.map_ = null;
/**
* @private
* @type {goog.events.Key}
*/
this.postComposeListenerKey_ = null;
/**
* @private
* @type {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction}
*/
this.style_ = null;
/**
* @private
* @type {ol.style.StyleFunction|undefined}
*/
this.styleFunction_ = undefined;
this.setStyle(goog.isDef(options.style) ?
options.style : ol.style.defaultStyleFunction);
if (goog.isDef(options.features)) {
if (goog.isArray(options.features)) {
this.setFeatures(new ol.Collection(options.features.slice()));
} else {
goog.asserts.assertInstanceof(options.features, ol.Collection,
'options.features should be an ol.Collection');
this.setFeatures(options.features);
}
} else {
this.setFeatures(new ol.Collection());
}
if (goog.isDef(options.map)) {
this.setMap(options.map);
}
};
/**
* Add a feature to the overlay.
* @param {ol.Feature} feature Feature.
* @api
*/
ol.FeatureOverlay.prototype.addFeature = function(feature) {
this.features_.push(feature);
};
/**
* Get the features on the overlay.
* @return {ol.Collection.<ol.Feature>} Features collection.
* @api
*/
ol.FeatureOverlay.prototype.getFeatures = function() {
return this.features_;
};
/**
* Get the map associated with the overlay.
* @return {?ol.Map} The map with which this feature overlay is associated.
* @api
*/
ol.FeatureOverlay.prototype.getMap = function() {
return this.map_;
};
/**
* @private
*/
ol.FeatureOverlay.prototype.handleFeatureChange_ = function() {
this.render_();
};
/**
* @private
* @param {ol.CollectionEvent} collectionEvent Collection event.
*/
ol.FeatureOverlay.prototype.handleFeaturesAdd_ = function(collectionEvent) {
goog.asserts.assert(!goog.isNull(this.featureChangeListenerKeys_),
'this.featureChangeListenerKeys_ should not be null');
var feature = /** @type {ol.Feature} */ (collectionEvent.element);
this.featureChangeListenerKeys_[goog.getUid(feature).toString()] =
goog.events.listen(feature, goog.events.EventType.CHANGE,
this.handleFeatureChange_, false, this);
this.render_();
};
/**
* @private
* @param {ol.CollectionEvent} collectionEvent Collection event.
*/
ol.FeatureOverlay.prototype.handleFeaturesRemove_ = function(collectionEvent) {
goog.asserts.assert(!goog.isNull(this.featureChangeListenerKeys_),
'this.featureChangeListenerKeys_ should not be null');
var feature = /** @type {ol.Feature} */ (collectionEvent.element);
var key = goog.getUid(feature).toString();
goog.events.unlistenByKey(this.featureChangeListenerKeys_[key]);
delete this.featureChangeListenerKeys_[key];
this.render_();
};
/**
* Handle changes in image style state.
* @param {goog.events.Event} event Image style change event.
* @private
*/
ol.FeatureOverlay.prototype.handleImageChange_ = function(event) {
this.render_();
};
/**
* @param {ol.render.Event} event Event.
* @private
*/
ol.FeatureOverlay.prototype.handleMapPostCompose_ = function(event) {
if (goog.isNull(this.features_)) {
return;
}
var styleFunction = this.styleFunction_;
if (!goog.isDef(styleFunction)) {
styleFunction = ol.style.defaultStyleFunction;
}
var replayGroup = /** @type {ol.render.IReplayGroup} */
(event.replayGroup);
goog.asserts.assert(goog.isDef(replayGroup),
'replayGroup should be defined');
var frameState = event.frameState;
var pixelRatio = frameState.pixelRatio;
var resolution = frameState.viewState.resolution;
var squaredTolerance = ol.renderer.vector.getSquaredTolerance(resolution,
pixelRatio);
var i, ii, styles, featureStyleFunction;
this.features_.forEach(function(feature) {
featureStyleFunction = feature.getStyleFunction();
styles = goog.isDef(featureStyleFunction) ?
featureStyleFunction.call(feature, resolution) :
styleFunction(feature, resolution);
if (!goog.isDefAndNotNull(styles)) {
return;
}
ii = styles.length;
for (i = 0; i < ii; ++i) {
ol.renderer.vector.renderFeature(replayGroup, feature, styles[i],
squaredTolerance, this.handleImageChange_, this);
}
}, this);
};
/**
* Remove a feature from the overlay.
* @param {ol.Feature} feature The feature to be removed.
* @api
*/
ol.FeatureOverlay.prototype.removeFeature = function(feature) {
this.features_.remove(feature);
};
/**
* @private
*/
ol.FeatureOverlay.prototype.render_ = function() {
if (!goog.isNull(this.map_)) {
this.map_.render();
}
};
/**
* Set the features for the overlay.
* @param {ol.Collection.<ol.Feature>} features Features collection.
* @api
*/
ol.FeatureOverlay.prototype.setFeatures = function(features) {
if (!goog.isNull(this.featuresListenerKeys_)) {
goog.array.forEach(this.featuresListenerKeys_, goog.events.unlistenByKey);
this.featuresListenerKeys_ = null;
}
if (!goog.isNull(this.featureChangeListenerKeys_)) {
goog.array.forEach(
goog.object.getValues(this.featureChangeListenerKeys_),
goog.events.unlistenByKey);
this.featureChangeListenerKeys_ = null;
}
this.features_ = features;
if (!goog.isNull(features)) {
this.featuresListenerKeys_ = [
goog.events.listen(features, ol.CollectionEventType.ADD,
this.handleFeaturesAdd_, false, this),
goog.events.listen(features, ol.CollectionEventType.REMOVE,
this.handleFeaturesRemove_, false, this)
];
this.featureChangeListenerKeys_ = {};
features.forEach(function(feature) {
this.featureChangeListenerKeys_[goog.getUid(feature).toString()] =
goog.events.listen(feature, goog.events.EventType.CHANGE,
this.handleFeatureChange_, false, this);
}, this);
}
this.render_();
};
/**
* Set the map for the overlay.
* @param {ol.Map} map Map.
* @api
*/
ol.FeatureOverlay.prototype.setMap = function(map) {
if (!goog.isNull(this.postComposeListenerKey_)) {
goog.events.unlistenByKey(this.postComposeListenerKey_);
this.postComposeListenerKey_ = null;
}
this.render_();
this.map_ = map;
if (!goog.isNull(map)) {
this.postComposeListenerKey_ = goog.events.listen(
map, ol.render.EventType.POSTCOMPOSE, this.handleMapPostCompose_, false,
this);
map.render();
}
};
/**
* 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.
* @param {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction} style
* Overlay style.
* @api
*/
ol.FeatureOverlay.prototype.setStyle = function(style) {
this.style_ = style;
this.styleFunction_ = ol.style.createStyleFunction(style);
this.render_();
};
/**
* Get the style for features. This returns whatever was passed to the `style`
* option at construction or to the `setStyle` method.
* @return {ol.style.Style|Array.<ol.style.Style>|ol.style.StyleFunction}
* Overlay style.
* @api
*/
ol.FeatureOverlay.prototype.getStyle = function() {
return this.style_;
};
/**
* Get the style function.
* @return {ol.style.StyleFunction|undefined} Style function.
* @api
*/
ol.FeatureOverlay.prototype.getStyleFunction = function() {
return this.styleFunction_;
};

View File

@@ -10,7 +10,6 @@ goog.require('goog.events.Event');
goog.require('ol.Collection'); goog.require('ol.Collection');
goog.require('ol.Coordinate'); goog.require('ol.Coordinate');
goog.require('ol.Feature'); goog.require('ol.Feature');
goog.require('ol.FeatureOverlay');
goog.require('ol.MapBrowserEvent'); goog.require('ol.MapBrowserEvent');
goog.require('ol.MapBrowserEvent.EventType'); goog.require('ol.MapBrowserEvent.EventType');
goog.require('ol.Object'); goog.require('ol.Object');
@@ -27,6 +26,7 @@ goog.require('ol.geom.Polygon');
goog.require('ol.geom.SimpleGeometry'); goog.require('ol.geom.SimpleGeometry');
goog.require('ol.interaction.InteractionProperty'); goog.require('ol.interaction.InteractionProperty');
goog.require('ol.interaction.Pointer'); goog.require('ol.interaction.Pointer');
goog.require('ol.layer.Vector');
goog.require('ol.source.Vector'); goog.require('ol.source.Vector');
goog.require('ol.style.Style'); goog.require('ol.style.Style');
@@ -269,10 +269,14 @@ ol.interaction.Draw = function(options) {
/** /**
* Draw overlay where our sketch features are drawn. * Draw overlay where our sketch features are drawn.
* @type {ol.FeatureOverlay} * @type {ol.layer.Vector}
* @private * @private
*/ */
this.overlay_ = new ol.FeatureOverlay({ this.overlay_ = new ol.layer.Vector({
source: new ol.source.Vector({
useSpatialIndex: false,
wrapX: goog.isDef(options.wrapX) ? options.wrapX : false
}),
style: goog.isDef(options.style) ? style: goog.isDef(options.style) ?
options.style : ol.interaction.Draw.getDefaultStyleFunction() options.style : ol.interaction.Draw.getDefaultStyleFunction()
}); });
@@ -674,7 +678,7 @@ ol.interaction.Draw.prototype.abortDrawing_ = function() {
this.sketchFeature_ = null; this.sketchFeature_ = null;
this.sketchPoint_ = null; this.sketchPoint_ = null;
this.sketchLine_ = null; this.sketchLine_ = null;
this.overlay_.getFeatures().clear(); this.overlay_.getSource().clear();
} }
return sketchFeature; return sketchFeature;
}; };
@@ -701,7 +705,9 @@ ol.interaction.Draw.prototype.updateSketchFeatures_ = function() {
if (!goog.isNull(this.sketchPoint_)) { if (!goog.isNull(this.sketchPoint_)) {
sketchFeatures.push(this.sketchPoint_); sketchFeatures.push(this.sketchPoint_);
} }
this.overlay_.setFeatures(new ol.Collection(sketchFeatures)); var overlaySource = this.overlay_.getSource();
overlaySource.clear();
overlaySource.addFeatures(sketchFeatures);
}; };

View File

@@ -7,7 +7,6 @@ goog.require('goog.functions');
goog.require('ol.Collection'); goog.require('ol.Collection');
goog.require('ol.CollectionEventType'); goog.require('ol.CollectionEventType');
goog.require('ol.Feature'); goog.require('ol.Feature');
goog.require('ol.FeatureOverlay');
goog.require('ol.MapBrowserEvent.EventType'); goog.require('ol.MapBrowserEvent.EventType');
goog.require('ol.ViewHint'); goog.require('ol.ViewHint');
goog.require('ol.coordinate'); goog.require('ol.coordinate');
@@ -21,6 +20,8 @@ goog.require('ol.geom.MultiPolygon');
goog.require('ol.geom.Point'); goog.require('ol.geom.Point');
goog.require('ol.geom.Polygon'); goog.require('ol.geom.Polygon');
goog.require('ol.interaction.Pointer'); goog.require('ol.interaction.Pointer');
goog.require('ol.layer.Vector');
goog.require('ol.source.Vector');
goog.require('ol.structs.RBush'); goog.require('ol.structs.RBush');
goog.require('ol.style.Style'); goog.require('ol.style.Style');
@@ -112,10 +113,14 @@ ol.interaction.Modify = function(options) {
/** /**
* Draw overlay where are sketch features are drawn. * Draw overlay where are sketch features are drawn.
* @type {ol.FeatureOverlay} * @type {ol.layer.Vector}
* @private * @private
*/ */
this.overlay_ = new ol.FeatureOverlay({ this.overlay_ = new ol.layer.Vector({
source: new ol.source.Vector({
useSpatialIndex: false,
wrapX: goog.isDef(options.wrapX) ? options.wrapX : false
}),
style: goog.isDef(options.style) ? options.style : style: goog.isDef(options.style) ? options.style :
ol.interaction.Modify.getDefaultStyleFunction() ol.interaction.Modify.getDefaultStyleFunction()
}); });
@@ -208,7 +213,7 @@ ol.interaction.Modify.prototype.handleFeatureRemove_ = function(evt) {
// There remains only vertexFeature… // There remains only vertexFeature…
if (!goog.isNull(this.vertexFeature_) && if (!goog.isNull(this.vertexFeature_) &&
this.features_.getLength() === 0) { this.features_.getLength() === 0) {
this.overlay_.removeFeature(this.vertexFeature_); this.overlay_.getSource().removeFeature(this.vertexFeature_);
this.vertexFeature_ = null; this.vertexFeature_ = null;
} }
}; };
@@ -383,7 +388,7 @@ ol.interaction.Modify.prototype.createOrUpdateVertexFeature_ =
if (goog.isNull(vertexFeature)) { if (goog.isNull(vertexFeature)) {
vertexFeature = new ol.Feature(new ol.geom.Point(coordinates)); vertexFeature = new ol.Feature(new ol.geom.Point(coordinates));
this.vertexFeature_ = vertexFeature; this.vertexFeature_ = vertexFeature;
this.overlay_.addFeature(vertexFeature); this.overlay_.getSource().addFeature(vertexFeature);
} else { } else {
var geometry = /** @type {ol.geom.Point} */ (vertexFeature.getGeometry()); var geometry = /** @type {ol.geom.Point} */ (vertexFeature.getGeometry());
geometry.setCoordinates(coordinates); geometry.setCoordinates(coordinates);
@@ -630,7 +635,7 @@ ol.interaction.Modify.prototype.handlePointerAtPixel_ = function(pixel, map) {
} }
} }
if (!goog.isNull(this.vertexFeature_)) { if (!goog.isNull(this.vertexFeature_)) {
this.overlay_.removeFeature(this.vertexFeature_); this.overlay_.getSource().removeFeature(this.vertexFeature_);
this.vertexFeature_ = null; this.vertexFeature_ = null;
} }
}; };
@@ -800,7 +805,7 @@ ol.interaction.Modify.prototype.removeVertex_ = function() {
newSegmentData); newSegmentData);
this.updateSegmentIndices_(geometry, index, segmentData.depth, -1); this.updateSegmentIndices_(geometry, index, segmentData.depth, -1);
this.overlay_.removeFeature(this.vertexFeature_); this.overlay_.getSource().removeFeature(this.vertexFeature_);
this.vertexFeature_ = null; this.vertexFeature_ = null;
} }
} }

View File

@@ -8,10 +8,11 @@ goog.require('goog.events.Event');
goog.require('goog.functions'); goog.require('goog.functions');
goog.require('ol.CollectionEventType'); goog.require('ol.CollectionEventType');
goog.require('ol.Feature'); goog.require('ol.Feature');
goog.require('ol.FeatureOverlay');
goog.require('ol.events.condition'); goog.require('ol.events.condition');
goog.require('ol.geom.GeometryType'); goog.require('ol.geom.GeometryType');
goog.require('ol.interaction.Interaction'); goog.require('ol.interaction.Interaction');
goog.require('ol.layer.Vector');
goog.require('ol.source.Vector');
goog.require('ol.style.Style'); goog.require('ol.style.Style');
@@ -73,7 +74,7 @@ goog.inherits(ol.SelectEvent, goog.events.Event);
/** /**
* @classdesc * @classdesc
* Handles selection of vector data. A {@link ol.FeatureOverlay} is maintained * Handles selection of vector data. An {@link ol.source.Vector} is maintained
* internally to store the selected feature(s). Which features are selected is * internally to store the selected feature(s). Which features are selected is
* determined by the `condition` option, and optionally the `toggle` or * determined by the `condition` option, and optionally the `toggle` or
* `add`/`remove` options. * `add`/`remove` options.
@@ -160,14 +161,18 @@ ol.interaction.Select = function(opt_options) {
/** /**
* @private * @private
* @type {ol.FeatureOverlay} * @type {ol.layer.Vector}
*/ */
this.featureOverlay_ = new ol.FeatureOverlay({ this.featureOverlay_ = new ol.layer.Vector({
source: new ol.source.Vector({
useSpatialIndex: false,
wrapX: options.wrapX
}),
style: goog.isDef(options.style) ? options.style : style: goog.isDef(options.style) ? options.style :
ol.interaction.Select.getDefaultStyleFunction() ol.interaction.Select.getDefaultStyleFunction()
}); });
var features = this.featureOverlay_.getFeatures(); var features = this.featureOverlay_.getSource().getFeaturesCollection();
goog.events.listen(features, ol.CollectionEventType.ADD, goog.events.listen(features, ol.CollectionEventType.ADD,
this.addFeature_, false, this); this.addFeature_, false, this);
goog.events.listen(features, ol.CollectionEventType.REMOVE, goog.events.listen(features, ol.CollectionEventType.REMOVE,
@@ -183,7 +188,7 @@ goog.inherits(ol.interaction.Select, ol.interaction.Interaction);
* @api stable * @api stable
*/ */
ol.interaction.Select.prototype.getFeatures = function() { ol.interaction.Select.prototype.getFeatures = function() {
return this.featureOverlay_.getFeatures(); return this.featureOverlay_.getSource().getFeaturesCollection();
}; };
@@ -204,7 +209,7 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
var toggle = this.toggleCondition_(mapBrowserEvent); var toggle = this.toggleCondition_(mapBrowserEvent);
var set = !add && !remove && !toggle; var set = !add && !remove && !toggle;
var map = mapBrowserEvent.map; var map = mapBrowserEvent.map;
var features = this.featureOverlay_.getFeatures(); var features = this.featureOverlay_.getSource().getFeaturesCollection();
var /** @type {Array.<ol.Feature>} */ deselected = []; var /** @type {Array.<ol.Feature>} */ deselected = [];
var /** @type {Array.<ol.Feature>} */ selected = []; var /** @type {Array.<ol.Feature>} */ selected = [];
var change = false; var change = false;
@@ -280,7 +285,8 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
*/ */
ol.interaction.Select.prototype.setMap = function(map) { ol.interaction.Select.prototype.setMap = function(map) {
var currentMap = this.getMap(); var currentMap = this.getMap();
var selectedFeatures = this.featureOverlay_.getFeatures(); var selectedFeatures =
this.featureOverlay_.getSource().getFeaturesCollection();
if (!goog.isNull(currentMap)) { if (!goog.isNull(currentMap)) {
selectedFeatures.forEach(currentMap.unskipFeature, currentMap); selectedFeatures.forEach(currentMap.unskipFeature, currentMap);
} }

View File

@@ -577,10 +577,8 @@ ol.Map.prototype.disposeInternal = function() {
* @param {function(this: S, ol.Feature, ol.layer.Layer): T} callback Feature * @param {function(this: S, ol.Feature, ol.layer.Layer): T} callback Feature
* callback. The callback will be called with two arguments. The first * callback. The callback will be called with two arguments. The first
* argument is one {@link ol.Feature feature} at the pixel, the second is * argument is one {@link ol.Feature feature} at the pixel, the second is
* the {@link ol.layer.Layer layer} of the feature. If the detected feature * the {@link ol.layer.Layer layer} of the feature. To stop detection,
* is not on a layer, but on a {@link ol.FeatureOverlay}, then the second * callback functions can return a truthy value.
* argument to this function will be `null`. To stop detection, callback
* functions can return a truthy value.
* @param {S=} opt_this Value to use as `this` when executing `callback`. * @param {S=} opt_this Value to use as `this` when executing `callback`.
* @param {(function(this: U, ol.layer.Layer): boolean)=} opt_layerFilter Layer * @param {(function(this: U, ol.layer.Layer): boolean)=} opt_layerFilter Layer
* filter function. The filter function will receive one argument, the * filter function. The filter function will receive one argument, the
@@ -618,10 +616,8 @@ ol.Map.prototype.forEachFeatureAtPixel =
* @param {ol.Pixel} pixel Pixel. * @param {ol.Pixel} pixel Pixel.
* @param {function(this: S, ol.layer.Layer): T} callback Layer * @param {function(this: S, ol.layer.Layer): T} callback Layer
* callback. Will receive one argument, the {@link ol.layer.Layer layer} * callback. Will receive one argument, the {@link ol.layer.Layer layer}
* that contains the color pixel. If the detected color value is not from a * that contains the color pixel. To stop detection, callback functions can
* layer, but from a {@link ol.FeatureOverlay}, then the argument to this * return a truthy value.
* function will be `null`. To stop detection, callback functions can return
* a truthy value.
* @param {S=} opt_this Value to use as `this` when executing `callback`. * @param {S=} opt_this Value to use as `this` when executing `callback`.
* @param {(function(this: U, ol.layer.Layer): boolean)=} opt_layerFilter Layer * @param {(function(this: U, ol.layer.Layer): boolean)=} opt_layerFilter Layer
* filter function. The filter function will receive one argument, the * filter function. The filter function will receive one argument, the

View File

@@ -471,8 +471,8 @@ ol.render.canvas.Immediate.prototype.drawCircleGeometry =
* Render a feature into the canvas. In order to respect the zIndex of the * Render a feature into the canvas. In order to respect the zIndex of the
* style this method draws asynchronously and thus *after* calls to * style this method draws asynchronously and thus *after* calls to
* drawXxxxGeometry have been finished, effectively drawing the feature * drawXxxxGeometry have been finished, effectively drawing the feature
* *on top* of everything else. You probably should be using * *on top* of everything else. You probably should be using an
* {@link ol.FeatureOverlay} instead of calling this method directly. * {@link ol.layer.Vector} instead of calling this method directly.
* *
* @param {ol.Feature} feature Feature. * @param {ol.Feature} feature Feature.
* @param {ol.style.Style} style Style. * @param {ol.style.Style} style Style.

View File

@@ -35,14 +35,13 @@ ol.render.EventType = {
* @param {ol.render.EventType} type Type. * @param {ol.render.EventType} type Type.
* @param {Object=} opt_target Target. * @param {Object=} opt_target Target.
* @param {ol.render.VectorContext=} opt_vectorContext Vector context. * @param {ol.render.VectorContext=} opt_vectorContext Vector context.
* @param {ol.render.IReplayGroup=} opt_replayGroup Replay group.
* @param {olx.FrameState=} opt_frameState Frame state. * @param {olx.FrameState=} opt_frameState Frame state.
* @param {?CanvasRenderingContext2D=} opt_context Context. * @param {?CanvasRenderingContext2D=} opt_context Context.
* @param {?ol.webgl.Context=} opt_glContext WebGL Context. * @param {?ol.webgl.Context=} opt_glContext WebGL Context.
*/ */
ol.render.Event = function( ol.render.Event = function(
type, opt_target, opt_vectorContext, opt_replayGroup, opt_frameState, type, opt_target, opt_vectorContext, opt_frameState, opt_context,
opt_context, opt_glContext) { opt_glContext) {
goog.base(this, type, opt_target); goog.base(this, type, opt_target);
@@ -53,11 +52,6 @@ ol.render.Event = function(
*/ */
this.vectorContext = opt_vectorContext; this.vectorContext = opt_vectorContext;
/**
* @type {ol.render.IReplayGroup|undefined}
*/
this.replayGroup = opt_replayGroup;
/** /**
* @type {olx.FrameState|undefined} * @type {olx.FrameState|undefined}
* @api * @api

View File

@@ -131,8 +131,8 @@ ol.renderer.canvas.Layer.prototype.dispatchComposeEvent_ =
var render = new ol.render.canvas.Immediate( var render = new ol.render.canvas.Immediate(
context, frameState.pixelRatio, frameState.extent, transform, context, frameState.pixelRatio, frameState.extent, transform,
frameState.viewState.rotation); frameState.viewState.rotation);
var composeEvent = new ol.render.Event(type, layer, render, null, var composeEvent = new ol.render.Event(type, layer, render, frameState,
frameState, context, null); context, null);
layer.dispatchEvent(composeEvent); layer.dispatchEvent(composeEvent);
render.flush(); render.flush();
} }

View File

@@ -10,7 +10,6 @@ goog.require('ol');
goog.require('ol.RendererType'); goog.require('ol.RendererType');
goog.require('ol.css'); goog.require('ol.css');
goog.require('ol.dom'); goog.require('ol.dom');
goog.require('ol.extent');
goog.require('ol.layer.Image'); goog.require('ol.layer.Image');
goog.require('ol.layer.Layer'); goog.require('ol.layer.Layer');
goog.require('ol.layer.Tile'); goog.require('ol.layer.Tile');
@@ -18,13 +17,11 @@ goog.require('ol.layer.Vector');
goog.require('ol.render.Event'); goog.require('ol.render.Event');
goog.require('ol.render.EventType'); goog.require('ol.render.EventType');
goog.require('ol.render.canvas.Immediate'); goog.require('ol.render.canvas.Immediate');
goog.require('ol.render.canvas.ReplayGroup');
goog.require('ol.renderer.Map'); goog.require('ol.renderer.Map');
goog.require('ol.renderer.canvas.ImageLayer'); goog.require('ol.renderer.canvas.ImageLayer');
goog.require('ol.renderer.canvas.Layer'); goog.require('ol.renderer.canvas.Layer');
goog.require('ol.renderer.canvas.TileLayer'); goog.require('ol.renderer.canvas.TileLayer');
goog.require('ol.renderer.canvas.VectorLayer'); goog.require('ol.renderer.canvas.VectorLayer');
goog.require('ol.renderer.vector');
goog.require('ol.source.State'); goog.require('ol.source.State');
goog.require('ol.vec.Mat4'); goog.require('ol.vec.Mat4');
@@ -103,55 +100,27 @@ ol.renderer.canvas.Map.prototype.dispatchComposeEvent_ =
var extent = frameState.extent; var extent = frameState.extent;
var pixelRatio = frameState.pixelRatio; var pixelRatio = frameState.pixelRatio;
var viewState = frameState.viewState; var viewState = frameState.viewState;
var projection = viewState.projection;
var resolution = viewState.resolution;
var rotation = viewState.rotation; var rotation = viewState.rotation;
var offsetX = 0; var transform = this.getTransform(frameState);
if (projection.canWrapX()) {
var projectionExtent = projection.getExtent();
var worldWidth = ol.extent.getWidth(projectionExtent);
var x = frameState.focus[0];
if (x < projectionExtent[0] || x > projectionExtent[2]) {
var worldsAway = Math.ceil((projectionExtent[0] - x) / worldWidth);
offsetX = worldWidth * worldsAway;
extent = [
extent[0] + offsetX, extent[1],
extent[2] + offsetX, extent[3]
];
}
}
var transform = this.getTransform(frameState, offsetX);
var tolerance = ol.renderer.vector.getTolerance(resolution, pixelRatio);
var replayGroup = new ol.render.canvas.ReplayGroup(
tolerance, extent, resolution);
var vectorContext = new ol.render.canvas.Immediate(context, pixelRatio, var vectorContext = new ol.render.canvas.Immediate(context, pixelRatio,
extent, transform, rotation); extent, transform, rotation);
var composeEvent = new ol.render.Event(type, map, vectorContext, var composeEvent = new ol.render.Event(type, map, vectorContext,
replayGroup, frameState, context, null); frameState, context, null);
map.dispatchEvent(composeEvent); map.dispatchEvent(composeEvent);
replayGroup.finish();
if (!replayGroup.isEmpty()) {
replayGroup.replay(context, pixelRatio, transform, rotation, {});
}
vectorContext.flush(); vectorContext.flush();
this.replayGroup = replayGroup;
} }
}; };
/** /**
* @param {olx.FrameState} frameState Frame state. * @param {olx.FrameState} frameState Frame state.
* @param {number} offsetX Offset on the x-axis in view coordinates.
* @protected * @protected
* @return {!goog.vec.Mat4.Number} Transform. * @return {!goog.vec.Mat4.Number} Transform.
*/ */
ol.renderer.canvas.Map.prototype.getTransform = function(frameState, offsetX) { ol.renderer.canvas.Map.prototype.getTransform = function(frameState) {
var pixelRatio = frameState.pixelRatio; var pixelRatio = frameState.pixelRatio;
var viewState = frameState.viewState; var viewState = frameState.viewState;
var resolution = viewState.resolution; var resolution = viewState.resolution;
@@ -159,8 +128,7 @@ ol.renderer.canvas.Map.prototype.getTransform = function(frameState, offsetX) {
this.canvas_.width / 2, this.canvas_.height / 2, this.canvas_.width / 2, this.canvas_.height / 2,
pixelRatio / resolution, -pixelRatio / resolution, pixelRatio / resolution, -pixelRatio / resolution,
-viewState.rotation, -viewState.rotation,
-viewState.center[0] - offsetX, -viewState.center[0], -viewState.center[1]);
-viewState.center[1]);
}; };

View File

@@ -77,7 +77,6 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
function(frameState, layerState, context) { function(frameState, layerState, context) {
var extent = frameState.extent; var extent = frameState.extent;
var focus = frameState.focus;
var pixelRatio = frameState.pixelRatio; var pixelRatio = frameState.pixelRatio;
var skippedFeatureUids = layerState.unmanaged ? var skippedFeatureUids = layerState.unmanaged ?
{} : frameState.skippedFeatureUids; {} : frameState.skippedFeatureUids;
@@ -109,20 +108,11 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
// see http://jsperf.com/context-save-restore-versus-variable // see http://jsperf.com/context-save-restore-versus-variable
var alpha = replayContext.globalAlpha; var alpha = replayContext.globalAlpha;
replayContext.globalAlpha = layerState.opacity; replayContext.globalAlpha = layerState.opacity;
var noSkip = {};
var focusX = focus[0];
replayGroup.replay(replayContext, pixelRatio, transform, rotation,
skippedFeatureUids);
if (vectorSource.getWrapX() && projection.canWrapX() && if (vectorSource.getWrapX() && projection.canWrapX() &&
!ol.extent.containsExtent(projectionExtent, extent)) { !ol.extent.containsExtent(projectionExtent, extent)) {
var projLeft = projectionExtent[0];
var projRight = projectionExtent[2];
// A feature from skippedFeatureUids will only be skipped in the world
// that has the frameState's focus, because this is where a feature
// overlay for highlighting or selection would render the skipped
// feature.
replayGroup.replay(replayContext, pixelRatio, transform, rotation,
projLeft <= focusX && focusX <= projRight ?
skippedFeatureUids : noSkip);
var startX = extent[0]; var startX = extent[0];
var worldWidth = ol.extent.getWidth(projectionExtent); var worldWidth = ol.extent.getWidth(projectionExtent);
var world = 0; var world = 0;
@@ -132,8 +122,7 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
offsetX = worldWidth * world; offsetX = worldWidth * world;
transform = this.getTransform(frameState, offsetX); transform = this.getTransform(frameState, offsetX);
replayGroup.replay(replayContext, pixelRatio, transform, rotation, replayGroup.replay(replayContext, pixelRatio, transform, rotation,
projLeft + offsetX <= focusX && focusX <= projRight + offsetX ? skippedFeatureUids);
skippedFeatureUids : noSkip);
startX += worldWidth; startX += worldWidth;
} }
world = 0; world = 0;
@@ -143,13 +132,9 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame =
offsetX = worldWidth * world; offsetX = worldWidth * world;
transform = this.getTransform(frameState, offsetX); transform = this.getTransform(frameState, offsetX);
replayGroup.replay(replayContext, pixelRatio, transform, rotation, replayGroup.replay(replayContext, pixelRatio, transform, rotation,
projLeft + offsetX <= focusX && focusX <= projRight + offsetX ? skippedFeatureUids);
skippedFeatureUids : noSkip);
startX -= worldWidth; startX -= worldWidth;
} }
} else {
replayGroup.replay(
replayContext, pixelRatio, transform, rotation, skippedFeatureUids);
} }
if (replayContext != context) { if (replayContext != context) {

View File

@@ -20,13 +20,11 @@ goog.require('ol.layer.Vector');
goog.require('ol.render.Event'); goog.require('ol.render.Event');
goog.require('ol.render.EventType'); goog.require('ol.render.EventType');
goog.require('ol.render.canvas.Immediate'); goog.require('ol.render.canvas.Immediate');
goog.require('ol.render.canvas.ReplayGroup');
goog.require('ol.renderer.Map'); goog.require('ol.renderer.Map');
goog.require('ol.renderer.dom.ImageLayer'); goog.require('ol.renderer.dom.ImageLayer');
goog.require('ol.renderer.dom.Layer'); goog.require('ol.renderer.dom.Layer');
goog.require('ol.renderer.dom.TileLayer'); goog.require('ol.renderer.dom.TileLayer');
goog.require('ol.renderer.dom.VectorLayer'); goog.require('ol.renderer.dom.VectorLayer');
goog.require('ol.renderer.vector');
goog.require('ol.source.State'); goog.require('ol.source.State');
goog.require('ol.vec.Mat4'); goog.require('ol.vec.Mat4');
@@ -139,7 +137,6 @@ ol.renderer.dom.Map.prototype.dispatchComposeEvent_ =
var extent = frameState.extent; var extent = frameState.extent;
var pixelRatio = frameState.pixelRatio; var pixelRatio = frameState.pixelRatio;
var viewState = frameState.viewState; var viewState = frameState.viewState;
var resolution = viewState.resolution;
var rotation = viewState.rotation; var rotation = viewState.rotation;
var context = this.context_; var context = this.context_;
var canvas = context.canvas; var canvas = context.canvas;
@@ -153,18 +150,10 @@ ol.renderer.dom.Map.prototype.dispatchComposeEvent_ =
-viewState.center[0], -viewState.center[1]); -viewState.center[0], -viewState.center[1]);
var vectorContext = new ol.render.canvas.Immediate(context, pixelRatio, var vectorContext = new ol.render.canvas.Immediate(context, pixelRatio,
extent, this.transform_, rotation); extent, this.transform_, rotation);
var replayGroup = new ol.render.canvas.ReplayGroup(
ol.renderer.vector.getTolerance(resolution, pixelRatio), extent,
resolution);
var composeEvent = new ol.render.Event(type, map, vectorContext, var composeEvent = new ol.render.Event(type, map, vectorContext,
replayGroup, frameState, context, null); frameState, context, null);
map.dispatchEvent(composeEvent); map.dispatchEvent(composeEvent);
replayGroup.finish();
if (!replayGroup.isEmpty()) {
replayGroup.replay(context, pixelRatio, this.transform_, rotation, {});
}
vectorContext.flush(); vectorContext.flush();
this.replayGroup = replayGroup;
} }
}; };

View File

@@ -165,8 +165,8 @@ ol.renderer.dom.VectorLayer.prototype.dispatchEvent_ =
var render = new ol.render.canvas.Immediate( var render = new ol.render.canvas.Immediate(
context, frameState.pixelRatio, frameState.extent, transform, context, frameState.pixelRatio, frameState.extent, transform,
frameState.viewState.rotation); frameState.viewState.rotation);
var event = new ol.render.Event(type, layer, render, null, var event = new ol.render.Event(type, layer, render, frameState,
frameState, context, null); context, null);
layer.dispatchEvent(event); layer.dispatchEvent(event);
render.flush(); render.flush();
} }

View File

@@ -48,12 +48,6 @@ ol.renderer.Map = function(container, map) {
*/ */
this.map_ = map; this.map_ = map;
/**
* @protected
* @type {ol.render.IReplayGroup}
*/
this.replayGroup = null;
/** /**
* @private * @private
* @type {Object.<string, ol.renderer.Layer>} * @type {Object.<string, ol.renderer.Layer>}
@@ -137,7 +131,6 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate =
var result; var result;
var viewState = frameState.viewState; var viewState = frameState.viewState;
var viewResolution = viewState.resolution; var viewResolution = viewState.resolution;
var viewRotation = viewState.rotation;
/** @type {Object.<string, boolean>} */ /** @type {Object.<string, boolean>} */
var features = {}; var features = {};
@@ -168,13 +161,6 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate =
} }
} }
if (!goog.isNull(this.replayGroup)) {
result = this.replayGroup.forEachFeatureAtCoordinate(translatedCoordinate,
viewResolution, viewRotation, {}, forEachFeatureAtCoordinate);
if (result) {
return result;
}
}
var layerStates = frameState.layerStatesArray; var layerStates = frameState.layerStatesArray;
var numLayers = layerStates.length; var numLayers = layerStates.length;
var i; var i;
@@ -216,20 +202,7 @@ ol.renderer.Map.prototype.forEachLayerAtPixel =
var result; var result;
var viewState = frameState.viewState; var viewState = frameState.viewState;
var viewResolution = viewState.resolution; var viewResolution = viewState.resolution;
var viewRotation = viewState.rotation;
if (!goog.isNull(this.replayGroup)) {
var coordinate = this.getMap().getCoordinateFromPixel(pixel);
var hasFeature = this.replayGroup.forEachFeatureAtCoordinate(coordinate,
viewResolution, viewRotation, {}, goog.functions.TRUE);
if (hasFeature) {
result = callback.call(thisArg, null);
if (result) {
return result;
}
}
}
var layerStates = frameState.layerStatesArray; var layerStates = frameState.layerStatesArray;
var numLayers = layerStates.length; var numLayers = layerStates.length;
var i; var i;

View File

@@ -247,7 +247,7 @@ ol.renderer.webgl.Layer.prototype.dispatchComposeEvent_ =
var render = new ol.render.webgl.Immediate( var render = new ol.render.webgl.Immediate(
context, center, resolution, rotation, size, extent, pixelRatio); context, center, resolution, rotation, size, extent, pixelRatio);
var composeEvent = new ol.render.Event( var composeEvent = new ol.render.Event(
type, layer, render, null, frameState, null, context); type, layer, render, frameState, null, context);
layer.dispatchEvent(composeEvent); layer.dispatchEvent(composeEvent);
} }
}; };

View File

@@ -24,9 +24,7 @@ goog.require('ol.layer.Vector');
goog.require('ol.render.Event'); goog.require('ol.render.Event');
goog.require('ol.render.EventType'); goog.require('ol.render.EventType');
goog.require('ol.render.webgl.Immediate'); goog.require('ol.render.webgl.Immediate');
goog.require('ol.render.webgl.ReplayGroup');
goog.require('ol.renderer.Map'); goog.require('ol.renderer.Map');
goog.require('ol.renderer.vector');
goog.require('ol.renderer.webgl.ImageLayer'); goog.require('ol.renderer.webgl.ImageLayer');
goog.require('ol.renderer.webgl.Layer'); goog.require('ol.renderer.webgl.Layer');
goog.require('ol.renderer.webgl.TileLayer'); goog.require('ol.renderer.webgl.TileLayer');
@@ -287,27 +285,14 @@ ol.renderer.webgl.Map.prototype.dispatchComposeEvent_ =
var resolution = viewState.resolution; var resolution = viewState.resolution;
var center = viewState.center; var center = viewState.center;
var rotation = viewState.rotation; var rotation = viewState.rotation;
var tolerance = ol.renderer.vector.getTolerance(resolution, pixelRatio);
var vectorContext = new ol.render.webgl.Immediate(context, var vectorContext = new ol.render.webgl.Immediate(context,
center, resolution, rotation, size, extent, pixelRatio); center, resolution, rotation, size, extent, pixelRatio);
var replayGroup = new ol.render.webgl.ReplayGroup(tolerance, extent);
var composeEvent = new ol.render.Event(type, map, vectorContext, var composeEvent = new ol.render.Event(type, map, vectorContext,
replayGroup, frameState, null, context); frameState, null, context);
map.dispatchEvent(composeEvent); map.dispatchEvent(composeEvent);
replayGroup.finish(context);
if (!replayGroup.isEmpty()) {
// use default color values
var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_;
replayGroup.replay(context, center, resolution, rotation, size,
pixelRatio, d.opacity, d.brightness, d.contrast,
d.hue, d.saturation, {});
}
replayGroup.getDeleteResourcesFunction(context)();
vectorContext.flush(); vectorContext.flush();
this.replayGroup = replayGroup;
} }
}; };
@@ -561,37 +546,8 @@ ol.renderer.webgl.Map.prototype.forEachFeatureAtCoordinate =
return false; return false;
} }
var context = this.getContext();
var viewState = frameState.viewState; var viewState = frameState.viewState;
// do the hit-detection for the overlays first
if (!goog.isNull(this.replayGroup)) {
/** @type {Object.<string, boolean>} */
var features = {};
// use default color values
var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_;
result = this.replayGroup.forEachFeatureAtCoordinate(coordinate,
context, viewState.center, viewState.resolution, viewState.rotation,
frameState.size, frameState.pixelRatio,
d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {},
/**
* @param {ol.Feature} feature Feature.
* @return {?} Callback result.
*/
function(feature) {
goog.asserts.assert(goog.isDef(feature), 'received a feature');
var key = goog.getUid(feature).toString();
if (!(key in features)) {
features[key] = true;
return callback.call(thisArg, feature, null);
}
});
if (result) {
return result;
}
}
var layerStates = frameState.layerStatesArray; var layerStates = frameState.layerStatesArray;
var numLayers = layerStates.length; var numLayers = layerStates.length;
var i; var i;
@@ -623,22 +579,8 @@ ol.renderer.webgl.Map.prototype.hasFeatureAtCoordinate =
return false; return false;
} }
var context = this.getContext();
var viewState = frameState.viewState; var viewState = frameState.viewState;
// do the hit-detection for the overlays first
if (!goog.isNull(this.replayGroup)) {
// use default color values
var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_;
hasFeature = this.replayGroup.hasFeatureAtCoordinate(coordinate,
context, viewState.center, viewState.resolution, viewState.rotation,
frameState.size, frameState.pixelRatio,
d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {});
if (hasFeature) {
return true;
}
}
var layerStates = frameState.layerStatesArray; var layerStates = frameState.layerStatesArray;
var numLayers = layerStates.length; var numLayers = layerStates.length;
var i; var i;
@@ -669,27 +611,9 @@ ol.renderer.webgl.Map.prototype.forEachLayerAtPixel =
return false; return false;
} }
var context = this.getContext();
var viewState = frameState.viewState; var viewState = frameState.viewState;
var result; var result;
// do the hit-detection for the overlays first
if (!goog.isNull(this.replayGroup)) {
// use default color values
var d = ol.renderer.webgl.Map.DEFAULT_COLOR_VALUES_;
var coordinate = this.getMap().getCoordinateFromPixel(pixel);
var hasFeature = this.replayGroup.hasFeatureAtCoordinate(coordinate,
context, viewState.center, viewState.resolution, viewState.rotation,
frameState.size, frameState.pixelRatio,
d.opacity, d.brightness, d.contrast, d.hue, d.saturation, {});
if (hasFeature) {
result = callback.call(thisArg, null);
if (result) {
return result;
}
}
}
var layerStates = frameState.layerStatesArray; var layerStates = frameState.layerStatesArray;
var numLayers = layerStates.length; var numLayers = layerStates.length;
var i; var i;

View File

@@ -1,42 +0,0 @@
goog.provide('ol.test.FeatureOverlay');
describe('ol.FeatureOverlay', function() {
describe('constructor', function() {
it('creates an new feature overlay', function() {
var featureOverlay = new ol.FeatureOverlay();
expect(featureOverlay).to.be.a(ol.FeatureOverlay);
});
it('takes features', function() {
var featureOverlay = new ol.FeatureOverlay({
features: [new ol.Feature(new ol.geom.Point([0, 0]))]
});
expect(featureOverlay.getFeatures().getLength()).to.be(1);
});
it('takes a style', function() {
var style = [new ol.style.Style()];
var featureOverlay = new ol.FeatureOverlay({
style: [new ol.style.Style()]
});
expect(featureOverlay.getStyle()).to.eql(style);
expect(featureOverlay.getStyleFunction()()).to.eql(style);
});
it('takes a map', function() {
var map = new ol.Map({});
var featureOverlay = new ol.FeatureOverlay({
map: map
});
expect(featureOverlay.getMap()).to.eql(map);
});
});
});
goog.require('ol.Feature');
goog.require('ol.FeatureOverlay');
goog.require('ol.Map');
goog.require('ol.geom.Point');
goog.require('ol.style.Style');

View File

@@ -619,17 +619,19 @@ describe('ol.interaction.Draw', function() {
describe('#setActive(false)', function() { describe('#setActive(false)', function() {
it('unsets the map from the feature overlay', function() { it('unsets the map from the feature overlay', function() {
var spy = sinon.spy(interaction.overlay_, 'setMap');
interaction.setActive(false); interaction.setActive(false);
expect(interaction.overlay_.map_).to.be(null); expect(spy.getCall(0).args[0]).to.be(null);
}); });
it('aborts the drawing', function() { it('aborts the drawing', function() {
interaction.setActive(false); interaction.setActive(false);
expect(interaction.sketchFeature_).to.be(null); expect(interaction.sketchFeature_).to.be(null);
}); });
it('fires change:active', function() { it('fires change:active', function() {
var spy = sinon.spy(interaction.overlay_, 'setMap');
var listenerSpy = sinon.spy(function() { var listenerSpy = sinon.spy(function() {
// test that the interaction's change:active listener is called first // test that the interaction's change:active listener is called first
expect(interaction.overlay_.map_).to.be(null); expect(spy.getCall(0).args[0]).to.be(null);
}); });
interaction.on('change:active', listenerSpy); interaction.on('change:active', listenerSpy);
interaction.setActive(false); interaction.setActive(false);
@@ -642,13 +644,15 @@ describe('ol.interaction.Draw', function() {
interaction.setActive(false); interaction.setActive(false);
}); });
it('sets the map into the feature overlay', function() { it('sets the map into the feature overlay', function() {
var spy = sinon.spy(interaction.overlay_, 'setMap');
interaction.setActive(true); interaction.setActive(true);
expect(interaction.overlay_.map_).to.be(map); expect(spy.getCall(0).args[0]).to.be(map);
}); });
it('fires change:active', function() { it('fires change:active', function() {
var spy = sinon.spy(interaction.overlay_, 'setMap');
var listenerSpy = sinon.spy(function() { var listenerSpy = sinon.spy(function() {
// test that the interaction's change:active listener is called first // test that the interaction's change:active listener is called first
expect(interaction.overlay_.map_).not.to.be(null); expect(spy.getCall(0).args[0]).to.be(map);
}); });
interaction.on('change:active', listenerSpy); interaction.on('change:active', listenerSpy);
interaction.setActive(true); interaction.setActive(true);
@@ -682,8 +686,9 @@ describe('ol.interaction.Draw', function() {
}); });
describe('#setMap(null) when interaction is active', function() { describe('#setMap(null) when interaction is active', function() {
it('unsets the map from the feature overlay', function() { it('unsets the map from the feature overlay', function() {
var spy = sinon.spy(interaction.overlay_, 'setMap');
interaction.setMap(null); interaction.setMap(null);
expect(interaction.overlay_.map_).to.be(null); expect(spy.getCall(0).args[0]).to.be(null);
}); });
it('aborts the drawing', function() { it('aborts the drawing', function() {
interaction.setMap(null); interaction.setMap(null);
@@ -695,15 +700,17 @@ describe('ol.interaction.Draw', function() {
describe('#setMap(map)', function() { describe('#setMap(map)', function() {
describe('#setMap(map) when interaction is active', function() { describe('#setMap(map) when interaction is active', function() {
it('sets the map into the feature overlay', function() { it('sets the map into the feature overlay', function() {
var spy = sinon.spy(interaction.overlay_, 'setMap');
interaction.setMap(map); interaction.setMap(map);
expect(interaction.overlay_.map_).to.be(map); expect(spy.getCall(0).args[0]).to.be(map);
}); });
}); });
describe('#setMap(map) when interaction is not active', function() { describe('#setMap(map) when interaction is not active', function() {
it('does not set the map into the feature overlay', function() { it('does not set the map into the feature overlay', function() {
interaction.setActive(false); interaction.setActive(false);
var spy = sinon.spy(interaction.overlay_, 'setMap');
interaction.setMap(map); interaction.setMap(map);
expect(interaction.overlay_.map_).to.be(null); expect(spy.getCall(0).args[0]).to.be(null);
}); });
}); });

View File

@@ -219,15 +219,8 @@ describe('ol.interaction.Select', function() {
beforeEach(function() { beforeEach(function() {
interaction.setActive(false); interaction.setActive(false);
}); });
it('sets the map into the feature overlay', function() {
interaction.setActive(true);
expect(interaction.featureOverlay_.map_).to.be(map);
});
it('fires change:active', function() { it('fires change:active', function() {
var listenerSpy = sinon.spy(function() { var listenerSpy = sinon.spy();
// test that the interaction's change:active listener is called first
expect(interaction.featureOverlay_.map_).not.to.be(null);
});
interaction.on('change:active', listenerSpy); interaction.on('change:active', listenerSpy);
interaction.setActive(true); interaction.setActive(true);
expect(listenerSpy.callCount).to.be(1); expect(listenerSpy.callCount).to.be(1);
@@ -253,8 +246,9 @@ describe('ol.interaction.Select', function() {
}); });
describe('#setMap(null) when interaction is active', function() { describe('#setMap(null) when interaction is active', function() {
it('unsets the map from the feature overlay', function() { it('unsets the map from the feature overlay', function() {
var spy = sinon.spy(interaction.featureOverlay_, 'setMap');
interaction.setMap(null); interaction.setMap(null);
expect(interaction.featureOverlay_.map_).to.be(null); expect(spy.getCall(0).args[0]).to.be(null);
}); });
}); });
}); });
@@ -262,8 +256,9 @@ describe('ol.interaction.Select', function() {
describe('#setMap(map)', function() { describe('#setMap(map)', function() {
describe('#setMap(map) when interaction is active', function() { describe('#setMap(map) when interaction is active', function() {
it('sets the map into the feature overlay', function() { it('sets the map into the feature overlay', function() {
var spy = sinon.spy(interaction.featureOverlay_, 'setMap');
interaction.setMap(map); interaction.setMap(map);
expect(interaction.featureOverlay_.map_).to.be(map); expect(spy.getCall(0).args[0]).to.be(map);
}); });
}); });
}); });

View File

@@ -31,52 +31,6 @@ describe('ol.renderer.canvas.Map', function() {
renderer.layerRenderers_[goog.getUid(layer)] = layerRenderer; renderer.layerRenderers_[goog.getUid(layer)] = layerRenderer;
}); });
it('uses correct extent and offset on wrapped worlds', function() {
var spy = sinon.spy(renderer, 'getTransform');
var proj = new ol.proj.Projection({
code: 'foo',
extent: [-180, -90, 180, 90],
global: true
});
var frameState = {
coordinateToPixelMatrix: map.coordinateToPixelMatrix_,
pixelToCoordinateMatrix: map.pixelToCoordinateMatrix_,
pixelRatio: 1,
size: [100, 100],
skippedFeatureUids: {},
extent: proj.getExtent(),
viewState: {
center: [0, 0],
projection: proj,
resolution: 1,
rotation: 0
},
layerStates: {},
layerStatesArray: [{
layer: layer,
sourceState: 'ready',
visible: true,
minResolution: 1,
maxResolution: 2
}],
postRenderFunctions: []
};
frameState.focus = [0, 0];
// focus is on real world
renderer.renderFrame(frameState);
expect(spy.getCall(0).args[1]).to.be(0);
expect(renderer.replayGroup.maxExtent_).to.eql([-180, -90, 180, 90]);
frameState.focus = [-200, 0];
// focus is one world left of the real world
renderer.renderFrame(frameState);
expect(spy.getCall(1).args[1]).to.be(360);
expect(renderer.replayGroup.maxExtent_).to.eql([180, -90, 540, 90]);
frameState.focus = [200, 0];
// focus is one world right of the real world
renderer.renderFrame(frameState);
expect(spy.getCall(2).args[1]).to.be(-360);
expect(renderer.replayGroup.maxExtent_).to.eql([-540, -90, -180, 90]);
});
}); });
}); });
@@ -84,7 +38,6 @@ describe('ol.renderer.canvas.Map', function() {
goog.require('ol.layer.Vector'); goog.require('ol.layer.Vector');
goog.require('ol.Map'); goog.require('ol.Map');
goog.require('ol.proj.Projection');
goog.require('ol.renderer.canvas.Layer'); goog.require('ol.renderer.canvas.Layer');
goog.require('ol.renderer.canvas.Map'); goog.require('ol.renderer.canvas.Map');
goog.require('ol.source.Vector'); goog.require('ol.source.Vector');