Do not hit-detect the same feature multiple times
In other words forEachFeatureAtPixel should not call the user-provided callback more than once for a given feature.
This commit is contained in:
@@ -121,6 +121,8 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel =
|
|||||||
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();
|
||||||
|
/** @type {Object.<string, boolean>} */
|
||||||
|
var features = {};
|
||||||
return this.replayGroup_.forEachGeometryAtPixel(extent, resolution,
|
return this.replayGroup_.forEachGeometryAtPixel(extent, resolution,
|
||||||
rotation, coordinate, frameState.skippedFeatureUids,
|
rotation, coordinate, frameState.skippedFeatureUids,
|
||||||
/**
|
/**
|
||||||
@@ -131,7 +133,11 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtPixel =
|
|||||||
function(geometry, data) {
|
function(geometry, data) {
|
||||||
var feature = /** @type {ol.Feature} */ (data);
|
var feature = /** @type {ol.Feature} */ (data);
|
||||||
goog.asserts.assert(goog.isDef(feature));
|
goog.asserts.assert(goog.isDef(feature));
|
||||||
return callback.call(thisArg, feature, layer);
|
var key = goog.getUid(feature).toString();
|
||||||
|
if (!(key in features)) {
|
||||||
|
features[key] = true;
|
||||||
|
return callback.call(thisArg, feature, layer);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -148,6 +148,8 @@ ol.source.ImageVector.prototype.forEachFeatureAtPixel = function(
|
|||||||
if (goog.isNull(this.replayGroup_)) {
|
if (goog.isNull(this.replayGroup_)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
} else {
|
} else {
|
||||||
|
/** @type {Object.<string, boolean>} */
|
||||||
|
var features = {};
|
||||||
return this.replayGroup_.forEachGeometryAtPixel(
|
return this.replayGroup_.forEachGeometryAtPixel(
|
||||||
extent, resolution, 0, coordinate, skippedFeatureUids,
|
extent, resolution, 0, coordinate, skippedFeatureUids,
|
||||||
/**
|
/**
|
||||||
@@ -157,7 +159,12 @@ ol.source.ImageVector.prototype.forEachFeatureAtPixel = function(
|
|||||||
*/
|
*/
|
||||||
function(geometry, data) {
|
function(geometry, data) {
|
||||||
var feature = /** @type {ol.Feature} */ (data);
|
var feature = /** @type {ol.Feature} */ (data);
|
||||||
return callback(feature);
|
goog.asserts.assert(goog.isDef(feature));
|
||||||
|
var key = goog.getUid(feature).toString();
|
||||||
|
if (!(key in features)) {
|
||||||
|
features[key] = true;
|
||||||
|
return callback(feature);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -58,6 +58,44 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#forEachFeatureAtPixel', function() {
|
||||||
|
var renderer;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
var map = new ol.Map({});
|
||||||
|
var layer = new ol.layer.Vector({
|
||||||
|
source: new ol.source.Vector()
|
||||||
|
});
|
||||||
|
renderer = new ol.renderer.canvas.VectorLayer(
|
||||||
|
map.getRenderer(), layer);
|
||||||
|
var replayGroup = {};
|
||||||
|
renderer.replayGroup_ = replayGroup;
|
||||||
|
replayGroup.forEachGeometryAtPixel = function(extent, resolution,
|
||||||
|
rotation, coordinate, skippedFeaturesUids, callback) {
|
||||||
|
var geometry = new ol.geom.Point([0, 0]);
|
||||||
|
var feature = new ol.Feature();
|
||||||
|
callback(geometry, feature);
|
||||||
|
callback(geometry, feature);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls callback once per feature', function() {
|
||||||
|
var spy = sinon.spy();
|
||||||
|
var coordinate = [0, 0];
|
||||||
|
var frameState = {
|
||||||
|
extent: [1, 1, 10, 10],
|
||||||
|
skippedFeatureUids: {},
|
||||||
|
viewState: {
|
||||||
|
resolution: 1,
|
||||||
|
rotation: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
renderer.forEachFeatureAtPixel(
|
||||||
|
coordinate, frameState, spy, undefined);
|
||||||
|
expect(spy.callCount).to.be(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user