From 49c6ab716ce0c38f8ef959a5346c562c86bc60a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sun, 7 Feb 2021 01:46:26 +0100 Subject: [PATCH] Fix VectorLayer hitdetect inaccuracy Due to rounding the hitdetection may have been off by one pixel. At map edge the pixel coordinate may exceed the map's dimensions if an decimal pixel ratio is used, this is fixed by clamping to the canvas dimensions. --- src/ol/render/canvas/hitdetect.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ol/render/canvas/hitdetect.js b/src/ol/render/canvas/hitdetect.js index 69014b87b9..a95b77d653 100644 --- a/src/ol/render/canvas/hitdetect.js +++ b/src/ol/render/canvas/hitdetect.js @@ -6,6 +6,7 @@ import CanvasImmediateRenderer from './Immediate.js'; import GeometryType from '../../geom/GeometryType.js'; import IconAnchorUnits from '../../style/IconAnchorUnits.js'; import {Icon} from '../../style.js'; +import {clamp} from '../../math.js'; import {createCanvasContext2D} from '../../dom.js'; import {intersects} from '../../extent.js'; import {numberSafeCompareFunction} from '../../array.js'; @@ -162,8 +163,13 @@ export function createHitDetectionImageData( export function hitDetect(pixel, features, imageData) { const resultFeatures = []; if (imageData) { + // The pixel coordinate is clamped down to the hit-detect canvas' size to account + // for browsers returning coordinates slightly larger than the actual canvas size + // due to a non-integer pixel ratio. const index = - (Math.round(pixel[0] / 2) + Math.round(pixel[1] / 2) * imageData.width) * + (clamp(Math.floor(Math.round(pixel[0]) / 2), 0, imageData.width - 1) + + clamp(Math.floor(Math.round(pixel[1]) / 2), 0, imageData.height - 1) * + imageData.width) * 4; const r = imageData.data[index]; const g = imageData.data[index + 1];