Event Thresholds & Constraints
In complex map applications, you often need to limit which features a user can interact with or define specific conditions under which an interaction (like dragging or clicking) should trigger. AurOpenlayers provides a declarative way to handle these constraints within the interactions block of a FeatureDescriptor.
Restricting Interaction Targets
By default, enabling an interaction like translate (dragging) makes every feature in that layer interactive. To restrict this to specific features—for example, only the feature currently being "edited" in a side panel—use the pickTarget filter.
Step 1: Define the Selection Logic
The pickTarget function receives a list of candidates (the features and models found under the cursor). You return the specific candidate that should be "picked."
// Example: Only allow dragging the point currently selected for editing
translate: {
cursor: 'grab',
pickTarget: ({ candidates }) =>
candidates.find(c => c.model.id === this.editingPointId),
// Optional: Visual state applied while dragging
state: 'DRAG',
}
If pickTarget returns undefined or null, the interaction will not start, effectively ignoring the user's attempt to drag other features.
Implementing Interaction States
Providing visual feedback during an interaction is crucial for UX. You can define a state string (like 'DRAG' or 'SELECTED') in the interaction config, and then define how the feature should look in that state within the style configuration.
Step 2: Configure the Visual Feedback
- Define the state in the interaction.
- Define the style patch in the
statesobject of your feature style.
feature: {
style: {
base: (model) => ({ color: '#1d4ed8', radius: 7 }),
states: {
// This style is applied only when the interaction is active
DRAG: () => ({
color: '#dc2626', // Change color to red while dragging
radius: 10, // Make it larger
}),
},
render: (opts) => new Style({ /* ... OpenLayers style ... */ })
},
interactions: {
translate: {
state: 'DRAG' // Links to the style state above
}
}
}
Lifecycle Hooks and Threshold Logic
Interactions provide onStart and onEnd hooks. These allow you to execute business logic, such as triggering Angular change detection or updating a "loading" or "dragging" status in your UI.
Step 3: Syncing Map Events with UI State
Since map interactions often happen outside of Angular's NgZone, you should wrap UI updates in zone.run() to ensure the view updates immediately.
translate: {
onStart: () => {
this.zone.run(() => {
this.isDragging = true;
});
return true; // Return true to allow the interaction to proceed
},
onEnd: () => {
this.zone.run(() => {
this.isDragging = false;
});
return true;
}
}
Advanced: Handling Thresholds
If you need to implement a "movement threshold" (e.g., the user must move the mouse at least 5 pixels before the model starts updating), you can handle this logic inside the applyGeometryToModel function or by tracking movement in onStart.
However, the framework handles the heavy lifting of hit-testing. By setting propagation: 'stop', you can ensure that once a threshold is met on one layer, the event doesn't bleed through to features on layers underneath.
Summary of Interaction Constraints
| Property | Purpose |
| :--- | :--- |
| enabled | A boolean or function to globally toggle the interaction. |
| pickTarget | A filter function to choose which specific feature is interactive. |
| cursor | The CSS cursor to show when hovering over a valid target. |
| state | The internal state ID to apply to the feature (triggers style changes). |
| propagation | Set to 'stop' to prevent the interaction from triggering on lower layers. |