Hit-detect skipped features, but not on unmanaged layer

This commit is contained in:
Andreas Hocevar
2016-02-17 00:42:44 +01:00
parent c836f97ec3
commit 9f0fefd42d
9 changed files with 40 additions and 47 deletions

View File

@@ -177,7 +177,7 @@ ol.interaction.Select = function(opt_options) {
*/ */
layerFilter = function(layer) { layerFilter = function(layer) {
goog.asserts.assertFunction(options.layers); goog.asserts.assertFunction(options.layers);
return layer === featureOverlay || options.layers(layer); return options.layers(layer);
}; };
} else { } else {
var layers = options.layers; var layers = options.layers;
@@ -186,7 +186,7 @@ ol.interaction.Select = function(opt_options) {
* @return {boolean} Include. * @return {boolean} Include.
*/ */
layerFilter = function(layer) { layerFilter = function(layer) {
return layer === featureOverlay || ol.array.includes(layers, layer); return ol.array.includes(layers, layer);
}; };
} }
} else { } else {
@@ -322,18 +322,13 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
* @param {ol.layer.Layer} layer Layer. * @param {ol.layer.Layer} layer Layer.
*/ */
function(feature, layer) { function(feature, layer) {
goog.asserts.assertInstanceof(feature, ol.Feature); if (this.filter_(feature, layer)) {
if (layer !== null) { if ((add || toggle) &&
if (add || toggle) { !ol.array.includes(features.getArray(), feature)) {
if (this.filter_(feature, layer) && selected.push(feature);
!ol.array.includes(features.getArray(), feature) && this.addFeatureLayerAssociation_(feature, layer);
!ol.array.includes(selected, feature)) { } else if ((remove || toggle) &&
selected.push(feature); ol.array.includes(features.getArray(), feature)) {
this.addFeatureLayerAssociation_(feature, layer);
}
}
} else if (this.featureOverlay_.getSource().hasFeature(feature)) {
if (remove || toggle) {
deselected.push(feature); deselected.push(feature);
this.removeFeatureLayerAssociation_(feature); this.removeFeatureLayerAssociation_(feature);
} }

View File

@@ -604,9 +604,8 @@ ol.Map.prototype.disposeInternal = function() {
* called with two arguments. The first argument is one * called with two arguments. The first argument is one
* {@link ol.Feature feature} or * {@link ol.Feature feature} or
* {@link ol.render.Feature render feature} at the pixel, the second is * {@link ol.render.Feature render feature} at the pixel, the second is
* the {@link ol.layer.Layer layer} of the feature and will be null for * the {@link ol.layer.Layer layer} of the feature. To stop detection,
* unmanaged layers. To stop detection, callback functions can return a * callback functions can return a truthy value.
* 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

@@ -158,11 +158,10 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate = function(c
var resolution = frameState.viewState.resolution; var resolution = frameState.viewState.resolution;
var rotation = frameState.viewState.rotation; var rotation = frameState.viewState.rotation;
var layer = this.getLayer(); var layer = this.getLayer();
var layerState = frameState.layerStates[goog.getUid(layer)];
/** @type {Object.<string, boolean>} */ /** @type {Object.<string, boolean>} */
var features = {}; var features = {};
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution, return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution,
rotation, layerState.managed ? frameState.skippedFeatureUids : {}, rotation, {},
/** /**
* @param {ol.Feature|ol.render.Feature} feature Feature. * @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {?} Callback result. * @return {?} Callback result.

View File

@@ -309,7 +309,6 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
var resolution = frameState.viewState.resolution; var resolution = frameState.viewState.resolution;
var rotation = frameState.viewState.rotation; var rotation = frameState.viewState.rotation;
var layer = this.getLayer(); var layer = this.getLayer();
var layerState = frameState.layerStates[goog.getUid(layer)];
/** @type {Object.<string, boolean>} */ /** @type {Object.<string, boolean>} */
var features = {}; var features = {};
@@ -343,8 +342,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
} }
replayGroup = tile.getReplayState().replayGroup; replayGroup = tile.getReplayState().replayGroup;
found = found || replayGroup.forEachFeatureAtCoordinate( found = found || replayGroup.forEachFeatureAtCoordinate(
tileSpaceCoordinate, resolution, rotation, tileSpaceCoordinate, resolution, rotation, {},
layerState.managed ? frameState.skippedFeatureUids : {},
/** /**
* @param {ol.Feature|ol.render.Feature} feature Feature. * @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {?} Callback result. * @return {?} Callback result.

View File

@@ -179,11 +179,10 @@ ol.renderer.dom.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coor
var resolution = frameState.viewState.resolution; var resolution = frameState.viewState.resolution;
var rotation = frameState.viewState.rotation; var rotation = frameState.viewState.rotation;
var layer = this.getLayer(); var layer = this.getLayer();
var layerState = frameState.layerStates[goog.getUid(layer)];
/** @type {Object.<string, boolean>} */ /** @type {Object.<string, boolean>} */
var features = {}; var features = {};
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution, return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution,
rotation, layerState.managed ? frameState.skippedFeatureUids : {}, rotation, {},
/** /**
* @param {ol.Feature|ol.render.Feature} feature Feature. * @param {ol.Feature|ol.render.Feature} feature Feature.
* @return {?} Callback result. * @return {?} Callback result.

View File

@@ -131,19 +131,17 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, fram
var viewState = frameState.viewState; var viewState = frameState.viewState;
var viewResolution = viewState.resolution; var viewResolution = viewState.resolution;
/** @type {Object.<string, boolean>} */
var features = {};
/** /**
* @param {ol.Feature|ol.render.Feature} feature Feature. * @param {ol.Feature|ol.render.Feature} feature Feature.
* @param {ol.layer.Layer} layer Layer.
* @return {?} Callback result. * @return {?} Callback result.
*/ */
function forEachFeatureAtCoordinate(feature) { function forEachFeatureAtCoordinate(feature, layer) {
goog.asserts.assert(feature !== undefined, 'received a feature'); goog.asserts.assert(feature !== undefined, 'received a feature');
var key = goog.getUid(feature).toString(); var key = goog.getUid(feature).toString();
if (!(key in features)) { if (!(key in frameState.skippedFeatureUids &&
features[key] = true; !frameState.layerStates[goog.getUid(layer)].managed)) {
return callback.call(thisArg, feature, null); return callback.call(thisArg, feature, layer);
} }
} }
@@ -172,9 +170,7 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, fram
if (layer.getSource()) { if (layer.getSource()) {
result = layerRenderer.forEachFeatureAtCoordinate( result = layerRenderer.forEachFeatureAtCoordinate(
layer.getSource().getWrapX() ? translatedCoordinate : coordinate, layer.getSource().getWrapX() ? translatedCoordinate : coordinate,
frameState, frameState, forEachFeatureAtCoordinate, thisArg);
layerState.managed ? callback : forEachFeatureAtCoordinate,
thisArg);
} }
if (result) { if (result) {
return result; return result;

View File

@@ -115,7 +115,7 @@ ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate = function(co
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, return this.replayGroup_.forEachFeatureAtCoordinate(coordinate,
context, viewState.center, viewState.resolution, viewState.rotation, context, viewState.center, viewState.resolution, viewState.rotation,
frameState.size, frameState.pixelRatio, layerState.opacity, frameState.size, frameState.pixelRatio, layerState.opacity,
layerState.managed ? frameState.skippedFeatureUids : {}, {},
/** /**
* @param {ol.Feature} feature Feature. * @param {ol.Feature} feature Feature.
* @return {?} Callback result. * @return {?} Callback result.

View File

@@ -738,16 +738,6 @@ ol.source.Vector.prototype.handleFeatureChange_ = function(event) {
}; };
/**
* @param {ol.Feature} feature Feature.
* @return {boolean} Feature is in source.
*/
ol.source.Vector.prototype.hasFeature = function(feature) {
var id = feature.getId();
return id ? id in this.idIndex_ : goog.getUid(feature) in this.undefIdIndex_;
};
/** /**
* @return {boolean} Is empty. * @return {boolean} Is empty.
*/ */

View File

@@ -55,13 +55,30 @@ describe('ol.renderer.canvas.Map', function() {
expect(cb.firstCall.args[1]).to.be(layer); expect(cb.firstCall.args[1]).to.be(layer);
}); });
it('calls callback with null for unmanaged layers', function() { it('calls callback for unmanaged layers', function() {
layer.setMap(map); layer.setMap(map);
map.renderSync(); map.renderSync();
var cb = sinon.spy(); var cb = sinon.spy();
map.forEachFeatureAtPixel(map.getPixelFromCoordinate([0, 0]), cb); map.forEachFeatureAtPixel(map.getPixelFromCoordinate([0, 0]), cb);
expect(cb).to.be.called(); expect(cb).to.be.called();
expect(cb.firstCall.args[1]).to.be(null); expect(cb.firstCall.args[1]).to.be(layer);
});
it('calls callback with main layer when skipped feature on unmanaged layer', function() {
var feature = layer.getSource().getFeatures()[0];
var managedLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [feature]
})
});
map.addLayer(managedLayer);
map.skipFeature(feature);
layer.setMap(map);
map.renderSync();
var cb = sinon.spy();
map.forEachFeatureAtPixel(map.getPixelFromCoordinate([0, 0]), cb);
expect(cb.callCount).to.be(1);
expect(cb.firstCall.args[1]).to.be(managedLayer);
}); });
it('filters managed layers', function() { it('filters managed layers', function() {