Order callback calls by distance to click position

All callback calls for hits with a tolerance > 0 are queued and
called ordered by distance after all hits are detected.
This commit is contained in:
Maximilian Krög
2020-11-29 02:32:04 +01:00
parent 4546eff66e
commit 23dc768c2e
10 changed files with 239 additions and 119 deletions
+10 -11
View File
@@ -55,7 +55,7 @@ import {transform2D} from '../../geom/flat/transform.js';
/**
* @template T
* @typedef {function(import("../../Feature.js").FeatureLike, import("../../geom/SimpleGeometry.js").default): T=} FeatureCallback
* @typedef {function(import("../../Feature.js").FeatureLike, import("../../geom/SimpleGeometry.js").default): T} FeatureCallback
*/
/**
@@ -602,9 +602,9 @@ class Executor {
* @param {import("../../transform.js").Transform} transform Transform.
* @param {Array<*>} instructions Instructions array.
* @param {boolean} snapToPixel Snap point symbols and text to integer pixels.
* @param {FeatureCallback<T>|undefined} featureCallback Feature callback.
* @param {import("../../extent.js").Extent=} opt_hitExtent Only check features that intersect this
* extent.
* @param {FeatureCallback<T>=} opt_featureCallback Feature callback.
* @param {import("../../extent.js").Extent=} opt_hitExtent Only check
* features that intersect this extent.
* @param {import("rbush").default=} opt_declutterTree Declutter tree.
* @return {T|undefined} Callback result.
* @template T
@@ -615,7 +615,7 @@ class Executor {
transform,
instructions,
snapToPixel,
featureCallback,
opt_featureCallback,
opt_hitExtent,
opt_declutterTree
) {
@@ -1052,9 +1052,9 @@ class Executor {
++i;
break;
case CanvasInstruction.END_GEOMETRY:
if (featureCallback !== undefined) {
if (opt_featureCallback !== undefined) {
feature = /** @type {import("../../Feature.js").FeatureLike} */ (instruction[1]);
const result = featureCallback(feature, currentGeometry);
const result = opt_featureCallback(feature, currentGeometry);
if (result) {
return result;
}
@@ -1174,10 +1174,9 @@ class Executor {
* @param {CanvasRenderingContext2D} context Context.
* @param {import("../../transform.js").Transform} transform Transform.
* @param {number} viewRotation View rotation.
* @param {FeatureCallback<T>} opt_featureCallback
* Feature callback.
* @param {import("../../extent.js").Extent=} opt_hitExtent Only check features that intersect this
* extent.
* @param {FeatureCallback<T>=} opt_featureCallback Feature callback.
* @param {import("../../extent.js").Extent=} opt_hitExtent Only check
* features that intersect this extent.
* @return {T|undefined} Callback result.
* @template T
*/
+9 -5
View File
@@ -161,7 +161,7 @@ class ExecutorGroup {
* @param {number} resolution Resolution.
* @param {number} rotation Rotation.
* @param {number} hitTolerance Hit tolerance in pixels.
* @param {import("./Executor.js").FeatureCallback<T>} callback Feature callback.
* @param {function(import("../../Feature.js").FeatureLike, import("../../geom/SimpleGeometry.js").default, number): T} callback Feature callback.
* @param {Array<import("../../Feature.js").FeatureLike>} declutteredFeatures Decluttered features.
* @return {T|undefined} Callback result.
* @template T
@@ -187,7 +187,8 @@ class ExecutorGroup {
-coordinate[1]
);
if (!this.hitDetectionContext_) {
const newContext = !this.hitDetectionContext_;
if (newContext) {
this.hitDetectionContext_ = createCanvasContext2D(
contextSize,
contextSize
@@ -201,7 +202,7 @@ class ExecutorGroup {
) {
context.canvas.width = contextSize;
context.canvas.height = contextSize;
} else {
} else if (!newContext) {
context.clearRect(0, 0, contextSize, contextSize);
}
@@ -226,7 +227,7 @@ class ExecutorGroup {
/**
* @param {import("../../Feature.js").FeatureLike} feature Feature.
* @param {import("../../geom/SimpleGeometry.js").default} geometry Geometry.
* @return {?} Callback result.
* @return {T|undefined} Callback result.
*/
function featureCallback(feature, geometry) {
const imageData = context.getImageData(0, 0, contextSize, contextSize)
@@ -239,7 +240,10 @@ class ExecutorGroup {
builderType !== BuilderType.TEXT) ||
declutteredFeatures.indexOf(feature) !== -1
) {
const result = callback(feature, geometry);
const idx = (indexes[i] - 3) / 4;
const x = hitTolerance - (idx % contextSize);
const y = hitTolerance - ((idx / contextSize) | 0);
const result = callback(feature, geometry, x * x + y * y);
if (result) {
return result;
}