-
Notifications
You must be signed in to change notification settings - Fork 7
Description
The onDragUpdate callback in onDrag method provides diffX/diffY values that represent the incremental difference between the previous and current mouse position, not the absolute difference from the drag start position.
This is unexpected behavior and makes it difficult to implement common drag patterns where you need to know the total displacement from the starting point.
Current Behavior
onDragUpdate?: (
diff: {
prevCoords: [number, number];
currentCoords: [number, number];
diffX: number; // difference between prevCoords and currentCoords
diffY: number; // resets each frame
},
event: MouseEvent
) => void;The diffX/diffY values are calculated as:
const diffX = (startDragCoords[0] - currentCoords[0]) | 0;
const diffY = (startDragCoords[1] - currentCoords[1]) | 0;
// ...
startDragCoords = currentCoords; // resets after each updateThis means:
diffX/diffYrepresent only the movement since the last frame- Cumulative tracking requires manual accumulation in user code
- Integer truncation (
| 0) combined with per-frame reset causes precision loss
`
Expected Behavior
Provide absolute diff from drag start, or add additional fields for both use cases:
onDragUpdate?: (
diff: {
startCoords: [number, number]; // initial position when drag started
prevCoords: [number, number]; // position on previous frame
currentCoords: [number, number]; // current position
// Absolute diff from start (most common use case)
diffX: number; // currentCoords.x - startCoords.x
diffY: number; // currentCoords.y - startCoords.y
// Incremental diff from previous frame (for specific use cases)
deltaDiffX: number; // currentCoords.x - prevCoords.x
deltaDiffY: number; // currentCoords.y - prevCoords.y
},
event: MouseEvent
) => void;Use Case Example
When implementing a draggable component, the typical pattern is:
// What users expect to write:
onDragUpdate: (diff) => {
element.x = initialX + diff.diffX; // absolute position from start
element.y = initialY + diff.diffY;
}
// What users currently have to write:
let accumulatedX = 0;
let accumulatedY = 0;
onDragUpdate: (diff) => {
accumulatedX += diff.diffX; // manual accumulation
accumulatedY += diff.diffY;
element.x = initialX + accumulatedX;
element.y = initialY + accumulatedY;
}Suggested Solution
Option 1: Change diffX/diffY to absolute values (breaking change):
// Keep startDragCoords constant, don't reset after each update
const diffX = startDragCoords[0] - currentCoords[0];
const diffY = startDragCoords[1] - currentCoords[1];
// Remove: startDragCoords = currentCoords;Option 2: Add new fields while keeping backward compatibility:
diff: {
prevCoords: [number, number];
currentCoords: [number, number];
startCoords: [number, number]; // NEW: initial drag position
diffX: number; // keep current behavior for backward compatibility
diffY: number;
totalDiffX: number; // NEW: absolute diff from start
totalDiffY: number; // NEW: absolute diff from start
}Additionally needs to remove integer truncation and document the incremental behavior:
const diffX = startDragCoords[0] - currentCoords[0]; // no truncation
const diffY = startDragCoords[1] - currentCoords[1];Additional Context
- The current incremental approach with
| 0truncation causes visible drag lag, especially with slow mouse movements - Most drag implementations expect absolute diff from start position
- The
prevCoordsfield suggests incremental tracking is intentional, but having both options would improve DX