Improves drag-and-drop scroll compensation.
Enhances drag-and-drop functionality by accurately compensating for scroll during drag operations. This ensures the dragged element remains correctly positioned relative to the mouse, even when the user scrolls the content during the drag. It achieves this by: - Tracking whether scrolling has occurred during a drag operation. - Factoring scroll delta into target position calculation. - Updating targetY/currentY instead of directly manipulating the clone's style.
This commit is contained in:
parent
dbbd19de13
commit
9a7a90c124
1 changed files with 41 additions and 21 deletions
|
|
@ -47,6 +47,7 @@ export class DragDropManager {
|
||||||
private initialScrollTop = 0;
|
private initialScrollTop = 0;
|
||||||
private initialCloneTop = 0;
|
private initialCloneTop = 0;
|
||||||
private isScrollCompensating = false; // Track if scroll compensation is active
|
private isScrollCompensating = false; // Track if scroll compensation is active
|
||||||
|
private hasScrolledDuringDrag = false; // Track if we have scrolled during this drag operation
|
||||||
private scrollListener: ((e: Event) => void) | null = null;
|
private scrollListener: ((e: Event) => void) | null = null;
|
||||||
|
|
||||||
// Smooth drag animation
|
// Smooth drag animation
|
||||||
|
|
@ -127,6 +128,7 @@ export class DragDropManager {
|
||||||
// Listen to edge-scroll events to control scroll compensation
|
// Listen to edge-scroll events to control scroll compensation
|
||||||
this.eventBus.on('edgescroll:started', () => {
|
this.eventBus.on('edgescroll:started', () => {
|
||||||
this.isScrollCompensating = true;
|
this.isScrollCompensating = true;
|
||||||
|
this.hasScrolledDuringDrag = true;
|
||||||
console.log('🎬 DragDropManager: Edge-scroll started - disabling continueDrag()');
|
console.log('🎬 DragDropManager: Edge-scroll started - disabling continueDrag()');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -194,21 +196,20 @@ export class DragDropManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.buttons === 1) {
|
if (event.buttons === 1) {
|
||||||
const currentPosition: MousePosition = { x: event.clientX, y: event.clientY };
|
// Always update mouse position from event
|
||||||
this.currentMousePosition = currentPosition; // Track current mouse position
|
this.currentMousePosition = { x: event.clientX, y: event.clientY };
|
||||||
|
|
||||||
// Try to initialize drag if not started
|
// Try to initialize drag if not started
|
||||||
if (!this.isDragStarted && this.originalElement) {
|
if (!this.isDragStarted && this.originalElement) {
|
||||||
if (!this.initializeDrag(currentPosition)) {
|
if (!this.initializeDrag(this.currentMousePosition)) {
|
||||||
return; // Not enough movement yet
|
return; // Not enough movement yet
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue drag if started //TODO: This has to be fixed... it fires way too many events, we can do better
|
// Continue drag if started
|
||||||
if (this.isDragStarted && this.originalElement && this.draggedClone) {
|
if (this.isDragStarted && this.originalElement && this.draggedClone) {
|
||||||
//console.log("Continue drag if started", this.draggedClone);
|
this.continueDrag(this.currentMousePosition);
|
||||||
this.continueDrag(currentPosition);
|
this.detectColumnChange(this.currentMousePosition);
|
||||||
this.detectColumnChange(currentPosition);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -265,7 +266,14 @@ export class DragDropManager {
|
||||||
if (column) {
|
if (column) {
|
||||||
// Calculate raw Y position relative to column (accounting for mouse offset)
|
// Calculate raw Y position relative to column (accounting for mouse offset)
|
||||||
const columnRect = column.boundingClientRect;
|
const columnRect = column.boundingClientRect;
|
||||||
const eventTopY = currentPosition.y - columnRect.top - this.mouseOffset.y;
|
let eventTopY = currentPosition.y - columnRect.top - this.mouseOffset.y;
|
||||||
|
|
||||||
|
// Kompenser for scroll bevægelse hvis vi har scrollet
|
||||||
|
if (this.scrollableContent && this.initialScrollTop > 0) {
|
||||||
|
const totalScrollDelta = this.scrollableContent.scrollTop - this.initialScrollTop;
|
||||||
|
eventTopY += totalScrollDelta;
|
||||||
|
}
|
||||||
|
|
||||||
this.targetY = Math.max(0, eventTopY);
|
this.targetY = Math.max(0, eventTopY);
|
||||||
this.targetColumn = column;
|
this.targetColumn = column;
|
||||||
|
|
||||||
|
|
@ -453,38 +461,47 @@ export class DragDropManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle scroll during drag - compensate clone position
|
* Handle scroll during drag - compensate clone position via targetY/currentY
|
||||||
*/
|
*/
|
||||||
private handleScroll(): void {
|
private handleScroll(): void {
|
||||||
if (!this.isDragStarted || !this.draggedClone || !this.scrollableContent || !this.isScrollCompensating) return;
|
if (!this.isDragStarted || !this.draggedClone || !this.scrollableContent || !this.isScrollCompensating) return;
|
||||||
|
|
||||||
// First time scrolling - save initial positions NOW!
|
// First time scrolling - save initial positions NOW!
|
||||||
|
if(this.initialScrollTop == 0) {
|
||||||
if(this.initialScrollTop == 0)
|
|
||||||
this.initialScrollTop = this.scrollableContent.scrollTop;
|
this.initialScrollTop = this.scrollableContent.scrollTop;
|
||||||
if(this.initialCloneTop == 0)
|
}
|
||||||
|
if(this.initialCloneTop == 0) {
|
||||||
this.initialCloneTop = parseFloat(this.draggedClone.style.top || '0');
|
this.initialCloneTop = parseFloat(this.draggedClone.style.top || '0');
|
||||||
|
|
||||||
|
|
||||||
console.log('💾 DragDropManager: Scroll compensation started', {
|
console.log('💾 DragDropManager: Scroll compensation started', {
|
||||||
initialScrollTop: this.initialScrollTop,
|
initialScrollTop: this.initialScrollTop,
|
||||||
initialCloneTop: this.initialCloneTop
|
initialCloneTop: this.initialCloneTop
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const currentScrollTop = this.scrollableContent.scrollTop;
|
const currentScrollTop = this.scrollableContent.scrollTop;
|
||||||
const totalScrollDelta = currentScrollTop - this.initialScrollTop;
|
const totalScrollDelta = currentScrollTop - this.initialScrollTop;
|
||||||
|
|
||||||
// Beregn ny position baseret på initial position + total scroll delta
|
// Beregn ny position baseret på initial position + total scroll delta
|
||||||
const newTop = this.initialCloneTop + totalScrollDelta;
|
const newTop = this.initialCloneTop + totalScrollDelta;
|
||||||
this.draggedClone.style.top = `${newTop}px`;
|
|
||||||
|
// Opdater targetY og currentY i stedet for direkte clone opdatering
|
||||||
|
this.targetY = newTop;
|
||||||
|
this.currentY = newTop;
|
||||||
|
|
||||||
|
// Kald animateDrag() hvis ikke allerede kører
|
||||||
|
if (this.dragAnimationId === null) {
|
||||||
|
this.animateDrag();
|
||||||
|
}
|
||||||
|
|
||||||
console.log('📜 DragDropManager: Scroll compensation', {
|
console.log('📜 DragDropManager: Scroll compensation', {
|
||||||
initialScrollTop: this.initialScrollTop,
|
initialScrollTop: this.initialScrollTop,
|
||||||
currentScrollTop,
|
currentScrollTop,
|
||||||
totalScrollDelta,
|
totalScrollDelta,
|
||||||
initialCloneTop: this.initialCloneTop,
|
initialCloneTop: this.initialCloneTop,
|
||||||
newTop
|
newTop,
|
||||||
|
targetY: this.targetY,
|
||||||
|
currentY: this.currentY
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -507,6 +524,9 @@ export class DragDropManager {
|
||||||
this.draggedClone = null;
|
this.draggedClone = null;
|
||||||
this.currentColumn = null;
|
this.currentColumn = null;
|
||||||
this.isDragStarted = false;
|
this.isDragStarted = false;
|
||||||
|
this.hasScrolledDuringDrag = false;
|
||||||
|
this.initialScrollTop = 0;
|
||||||
|
this.initialCloneTop = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue