From 61245fb83abc2589985efb6f5ffb72c824a526ed Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Mon, 1 Jan 2018 18:04:00 +0100 Subject: [PATCH] Merge pull request #7668 from ahocevar/hit-detect-text-background Hit detect text background --- src/ol/render/canvas/polygonreplay.js | 2 +- src/ol/render/canvas/replay.js | 43 +++++++++++++++++++-------- src/ol/render/canvas/textreplay.js | 4 ++- test/rendering/ol/style/text.test.js | 3 ++ 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/ol/render/canvas/polygonreplay.js b/src/ol/render/canvas/polygonreplay.js index 8589850203..ccf5891d37 100644 --- a/src/ol/render/canvas/polygonreplay.js +++ b/src/ol/render/canvas/polygonreplay.js @@ -215,7 +215,7 @@ ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyles_ = function(geometr var state = this.state; var fillStyle = state.fillStyle; if (fillStyle !== undefined) { - this.updateFillStyle(state, this.applyFill, geometry); + this.updateFillStyle(state, this.createFill, geometry); } if (state.strokeStyle !== undefined) { this.updateStrokeStyle(state, this.applyStroke); diff --git a/src/ol/render/canvas/replay.js b/src/ol/render/canvas/replay.js index a017ddad79..5221872dca 100644 --- a/src/ol/render/canvas/replay.js +++ b/src/ol/render/canvas/replay.js @@ -270,7 +270,16 @@ ol.render.canvas.Replay.prototype.replayImage_ = function(context, x, y, image, ol.extent.createOrUpdate(boxX, boxY, boxX + boxW, boxY + boxH, box); } var canvas = context.canvas; - var intersects = box[0] <= canvas.width && box[2] >= 0 && box[1] <= canvas.height && box[3] >= 0; + var strokePadding = strokeInstruction ? (strokeInstruction[2] * scale / 2) : 0; + var intersects = + box[0] - strokePadding <= canvas.width && box[2] + strokePadding >= 0 && + box[1] - strokePadding <= canvas.height && box[3] + strokePadding >= 0; + + if (snapToPixel) { + x = Math.round(x); + y = Math.round(y); + } + if (declutterGroup) { if (!intersects && declutterGroup[4] == 1) { return; @@ -956,15 +965,16 @@ ol.render.canvas.Replay.prototype.setFillStrokeStyle = function(fillStyle, strok /** * @param {ol.CanvasFillStrokeState} state State. * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry. + * @return {Array.<*>} Fill instruction. */ -ol.render.canvas.Replay.prototype.applyFill = function(state, geometry) { +ol.render.canvas.Replay.prototype.createFill = function(state, geometry) { var fillStyle = state.fillStyle; var fillInstruction = [ol.render.canvas.Instruction.SET_FILL_STYLE, fillStyle]; if (typeof fillStyle !== 'string') { var fillExtent = geometry.getExtent(); fillInstruction.push([fillExtent[0], fillExtent[3]]); } - this.instructions.push(fillInstruction); + return fillInstruction; }; @@ -972,25 +982,34 @@ ol.render.canvas.Replay.prototype.applyFill = function(state, geometry) { * @param {ol.CanvasFillStrokeState} state State. */ ol.render.canvas.Replay.prototype.applyStroke = function(state) { - this.instructions.push([ - ol.render.canvas.Instruction.SET_STROKE_STYLE, - state.strokeStyle, state.lineWidth * this.pixelRatio, state.lineCap, - state.lineJoin, state.miterLimit, - this.applyPixelRatio(state.lineDash), state.lineDashOffset * this.pixelRatio - ]); + this.instructions.push(this.createStroke(state)); }; /** * @param {ol.CanvasFillStrokeState} state State. - * @param {function(this:ol.render.canvas.Replay, ol.CanvasFillStrokeState, (ol.geom.Geometry|ol.render.Feature))} applyFill Apply fill. + * @return {Array.<*>} Stroke instruction. + */ +ol.render.canvas.Replay.prototype.createStroke = function(state) { + return [ + _ol_render_canvas_Instruction_.SET_STROKE_STYLE, + state.strokeStyle, state.lineWidth * this.pixelRatio, state.lineCap, + state.lineJoin, state.miterLimit, + this.applyPixelRatio(state.lineDash), state.lineDashOffset * this.pixelRatio + ]; +}; + + +/** + * @param {ol.CanvasFillStrokeState} state State. + * @param {function(this:ol.render.canvas.Replay, ol.CanvasFillStrokeState, (ol.geom.Geometry|ol.render.Feature)):Array.<*>} createFill Create fill. * @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry. */ -ol.render.canvas.Replay.prototype.updateFillStyle = function(state, applyFill, geometry) { +_ol_render_canvas_Replay_.prototype.updateFillStyle = function(state, createFill, geometry) { var fillStyle = state.fillStyle; if (typeof fillStyle !== 'string' || state.currentFillStyle != fillStyle) { if (fillStyle !== undefined) { - applyFill.call(this, state, geometry); + this.instructions.push(createFill.call(this, state, geometry)); } state.currentFillStyle = fillStyle; } diff --git a/src/ol/render/canvas/textreplay.js b/src/ol/render/canvas/textreplay.js index 48f09bcbe1..b934fc5e5b 100644 --- a/src/ol/render/canvas/textreplay.js +++ b/src/ol/render/canvas/textreplay.js @@ -263,8 +263,10 @@ ol.render.canvas.TextReplay.prototype.drawText = function(geometry, feature) { this.beginGeometry(geometry, feature); if (textState.backgroundFill || textState.backgroundStroke) { this.setFillStrokeStyle(textState.backgroundFill, textState.backgroundStroke); - this.updateFillStyle(this.state, this.applyFill, geometry); + this.updateFillStyle(this.state, this.createFill, geometry); + this.hitDetectionInstructions.push(this.createFill(this.state, geometry)); this.updateStrokeStyle(this.state, this.applyStroke); + this.hitDetectionInstructions.push(this.createStroke(this.state)); } this.drawTextImage_(label, begin, end); this.endGeometry(geometry, feature); diff --git a/test/rendering/ol/style/text.test.js b/test/rendering/ol/style/text.test.js index 6c267e4834..9fef701313 100644 --- a/test/rendering/ol/style/text.test.js +++ b/test/rendering/ol/style/text.test.js @@ -352,6 +352,9 @@ describe('ol.rendering.style.Text', function() { })); features[2].getStyle().getText().setPadding([5, 10, 15, 0]); map.getView().fit(vectorSource.getExtent()); + map.once('postrender', function() { + expect(map.getFeaturesAtPixel([178, 120])).to.have.length(1); + }); expectResemble(map, 'rendering/ol/style/expected/text-background.png', IMAGE_TOLERANCE, done); });