diff --git a/src/ol/render/canvas/replaygroup.js b/src/ol/render/canvas/replaygroup.js index f37e7a3851..cfdcb7cba2 100644 --- a/src/ol/render/canvas/replaygroup.js +++ b/src/ol/render/canvas/replaygroup.js @@ -321,18 +321,21 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function( }); } + var replayType; + /** * @param {ol.Feature|ol.render.Feature} feature Feature. * @return {?} Callback result. */ - function hitDetectionCallback(feature) { + function featureCallback(feature) { var imageData = context.getImageData(0, 0, contextSize, contextSize).data; for (var i = 0; i < contextSize; i++) { for (var j = 0; j < contextSize; j++) { if (mask[i][j]) { if (imageData[(j * contextSize + i) * 4 + 3] > 0) { var result; - if (!declutteredFeatures || declutteredFeatures.indexOf(feature) !== -1) { + if (!(declutteredFeatures && (replayType == ReplayType.IMAGE || replayType == ReplayType.TEXT)) || + declutteredFeatures.indexOf(feature) !== -1) { result = callback(feature); } if (result) { @@ -347,8 +350,37 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function( } } - return this.replayHitDetection_(context, transform, rotation, - skippedFeaturesHash, hitDetectionCallback, hitExtent, declutterReplays); + /** @type {Array.} */ + var zs = Object.keys(this.replaysByZIndex_).map(Number); + zs.sort(numberSafeCompareFunction); + + var i, j, replays, replay, result; + for (i = zs.length - 1; i >= 0; --i) { + var zIndexKey = zs[i].toString(); + replays = this.replaysByZIndex_[zIndexKey]; + for (j = _ol_render_replay_.ORDER.length - 1; j >= 0; --j) { + replayType = _ol_render_replay_.ORDER[j]; + replay = replays[replayType]; + if (replay !== undefined) { + if (declutterReplays && + (replayType == ReplayType.IMAGE || replayType == ReplayType.TEXT)) { + var declutter = declutterReplays[zIndexKey]; + if (!declutter) { + declutterReplays[zIndexKey] = [replay, transform.slice(0)]; + } else { + declutter.push(replay, transform.slice(0)); + } + } else { + result = replay.replayHitDetection(context, transform, rotation, + skippedFeaturesHash, featureCallback, hitExtent); + if (result) { + return result; + } + } + } + } + } + return undefined; }; @@ -457,59 +489,6 @@ ol.render.canvas.ReplayGroup.prototype.replay = function(context, }; -/** - * @private - * @param {CanvasRenderingContext2D} context Context. - * @param {ol.Transform} transform Transform. - * @param {number} viewRotation View rotation. - * @param {Object.} skippedFeaturesHash Ids of features - * to skip. - * @param {function((ol.Feature|ol.render.Feature)): T} featureCallback - * Feature callback. - * @param {ol.Extent=} opt_hitExtent Only check features that intersect this - * extent. - * @param {Object.=} opt_declutterReplays Declutter - * replays. - * @return {T|undefined} Callback result. - * @template T - */ -ol.render.canvas.ReplayGroup.prototype.replayHitDetection_ = function( - context, transform, viewRotation, skippedFeaturesHash, - featureCallback, opt_hitExtent, opt_declutterReplays) { - /** @type {Array.} */ - var zs = Object.keys(this.replaysByZIndex_).map(Number); - zs.sort(ol.array.numberSafeCompareFunction); - - var i, j, replays, replay, result; - for (i = zs.length - 1; i >= 0; --i) { - var zIndexKey = zs[i].toString(); - replays = this.replaysByZIndex_[zIndexKey]; - for (j = ol.render.replay.ORDER.length - 1; j >= 0; --j) { - var replayType = ol.render.replay.ORDER[j]; - replay = replays[replayType]; - if (replay !== undefined) { - if (opt_declutterReplays && - (replayType == ol.render.ReplayType.IMAGE || replayType == ol.render.ReplayType.TEXT)) { - var declutter = opt_declutterReplays[zIndexKey]; - if (!declutter) { - opt_declutterReplays[zIndexKey] = [replay, transform.slice(0)]; - } else { - declutter.push(replay, transform.slice(0)); - } - } else { - result = replay.replayHitDetection(context, transform, viewRotation, - skippedFeaturesHash, featureCallback, opt_hitExtent); - if (result) { - return result; - } - } - } - } - } - return undefined; -}; - - /** * @const * @private diff --git a/test/spec/ol/map.test.js b/test/spec/ol/map.test.js index b4c1d1f7ea..99d6e425b3 100644 --- a/test/spec/ol/map.test.js +++ b/test/spec/ol/map.test.js @@ -5,7 +5,7 @@ goog.require('ol.Map'); goog.require('ol.MapEvent'); goog.require('ol.Overlay'); goog.require('ol.View'); -goog.require('ol.geom.Point'); +goog.require('ol.geom.LineString'); goog.require('ol.has'); goog.require('ol.interaction'); goog.require('ol.interaction.DoubleClickZoom'); @@ -197,14 +197,14 @@ describe('ol.Map', function() { document.body.appendChild(target); map = new ol.Map({ target: target, - layers: [new ol.layer.Vector({ - source: new ol.source.Vector({ - features: [new ol.Feature(new ol.geom.Point([0, 0]))] + layers: [new ol.layer.Vector_({ + source: new ol.source.Vector_({ + features: [new ol.Feature(new ol.geom.LineString([[-50, 0], [50, 0]]))] }) })], view: new ol.View({ center: [0, 0], - zoom: 2 + zoom: 17 }) }); map.renderSync(); @@ -224,6 +224,20 @@ describe('ol.Map', function() { expect(features[0]).to.be.an(ol.Feature); }); + it('returns an array of found features with declutter: true', function() { + var layer = map.getLayers().item(0); + map.removeLayer(layer); + var otherLayer = new _ol_layer_Vector_({ + declutter: true, + source: layer.getSource() + }); + map.addLayer(otherLayer); + map.renderSync(); + var features = map.getFeaturesAtPixel([50, 50]); + expect(features).to.be.an(Array); + expect(features[0]).to.be.an(_ol_Feature_); + }); + it('respects options', function() { var otherLayer = new ol.layer.Vector({ source: new ol.source.Vector