diff --git a/src/ol/render/canvas/ReplayGroup.js b/src/ol/render/canvas/ReplayGroup.js index 300cf05248..3ae68cca7e 100644 --- a/src/ol/render/canvas/ReplayGroup.js +++ b/src/ol/render/canvas/ReplayGroup.js @@ -322,18 +322,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) { @@ -348,8 +351,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; }; @@ -458,59 +490,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(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 == ReplayType.IMAGE || replayType == 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 9a0fa6b161..b0b3ea566f 100644 --- a/test/spec/ol/map.test.js +++ b/test/spec/ol/map.test.js @@ -3,7 +3,7 @@ import Map from '../../../src/ol/Map.js'; import MapEvent from '../../../src/ol/MapEvent.js'; import Overlay from '../../../src/ol/Overlay.js'; import _ol_View_ from '../../../src/ol/View.js'; -import Point from '../../../src/ol/geom/Point.js'; +import LineString from '../../../src/ol/geom/LineString.js'; import _ol_has_ from '../../../src/ol/has.js'; import {defaults as defaultInteractions} from '../../../src/ol/interaction.js'; import DoubleClickZoom from '../../../src/ol/interaction/DoubleClickZoom.js'; @@ -197,12 +197,12 @@ describe('ol.Map', function() { target: target, layers: [new _ol_layer_Vector_({ source: new _ol_source_Vector_({ - features: [new _ol_Feature_(new Point([0, 0]))] + features: [new _ol_Feature_(new LineString([[-50, 0], [50, 0]]))] }) })], view: new _ol_View_({ center: [0, 0], - zoom: 2 + zoom: 17 }) }); map.renderSync(); @@ -222,6 +222,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_