diff --git a/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.directive.ts b/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.directive.ts index 293019c5c84..0c54471268b 100644 --- a/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.directive.ts +++ b/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.directive.ts @@ -282,7 +282,7 @@ export class IgxDragDirective implements AfterContentInit, OnDestroy { public ghostHost; /** - * An @Input property that specifies the offset of the ghost created relative to the mouse in pixels. + * An @Input property that specifies the offset of the dragged element relative to the mouse in pixels. * By default it's taking the relative position to the mouse when the drag started and keeps it the same. * ```html *
@@ -294,15 +294,15 @@ export class IgxDragDirective implements AfterContentInit, OnDestroy { */ @Input() public set ghostOffsetX(value) { - this._ghostOffsetX = parseInt(value, 10); + this._offsetX = parseInt(value, 10); } public get ghostOffsetX() { - return this._ghostOffsetX; + return this._offsetX !== undefined ? this._offsetX : this._defaultOffsetX; } /** - * An @Input property that specifies the offset of the ghost created relative to the mouse in pixels. + * An @Input property that specifies the offset of the dragged element relative to the mouse in pixels. * By default it's taking the relative position to the mouse when the drag started and keeps it the same. * ```html *
@@ -314,11 +314,11 @@ export class IgxDragDirective implements AfterContentInit, OnDestroy { */ @Input() public set ghostOffsetY(value) { - this._ghostOffsetY = parseInt(value, 10); + this._offsetY = parseInt(value, 10); } public get ghostOffsetY() { - return this._ghostOffsetY; + return this._offsetY !== undefined ? this._offsetY : this._defaultOffsetY ; } /** @@ -613,8 +613,6 @@ export class IgxDragDirective implements AfterContentInit, OnDestroy { protected _baseMarginTop = 0; protected _baseOriginX; protected _baseOriginY; - protected _baseLeft; - protected _baseTop; protected _startX = 0; protected _startY = 0; protected _lastX = 0; @@ -622,8 +620,10 @@ export class IgxDragDirective implements AfterContentInit, OnDestroy { protected _dragStarted = false; /** Drag ghost related properties */ - protected _ghostOffsetX; - protected _ghostOffsetY; + protected _defaultOffsetX; + protected _defaultOffsetY; + protected _offsetX; + protected _offsetY; protected _ghostStartX; protected _ghostStartY; protected _ghostHostX = 0; @@ -887,22 +887,10 @@ export class IgxDragDirective implements AfterContentInit, OnDestroy { this._startY = event.touches[0].pageY; } - let offsetX; - if (this.ghostOffsetX !== undefined) { - offsetX = this.ghostOffsetX; - } else { - offsetX = this.baseLeft + this.getWindowScrollLeft() - this._startX; - } - - let offsetY; - if (this.ghostOffsetY !== undefined) { - offsetY = this.ghostOffsetY; - } else { - offsetY = this.baseTop + this.getWindowScrollTop() - this._startY; - } - - this._ghostStartX = this._startX + offsetX; - this._ghostStartY = this._startY + offsetY; + this._defaultOffsetX = this.baseLeft + this.getWindowScrollLeft() - this._startX; + this._defaultOffsetY = this.baseTop + this.getWindowScrollTop() - this._startY; + this._ghostStartX = this._startX + this.ghostOffsetX; + this._ghostStartY = this._startY + this.ghostOffsetY; this._lastX = this._startX; this._lastY = this._startY; } @@ -950,7 +938,15 @@ export class IgxDragDirective implements AfterContentInit, OnDestroy { this._dragStarted = true; if (this.ghost) { // We moved enough so ghostElement can be rendered and actual dragging to start. + // When creating it will take into account any offset set by the user by default. this.createGhost(pageX, pageY); + } else if (this._offsetX !== undefined || this._offsetY !== undefined) { + // There is no need for ghost, but we will need to position initially the base element to reflect any offset. + const transformX = (this._offsetX !== undefined ? this._offsetX - this._defaultOffsetX : 0) + + this.getTransformX(this.element.nativeElement); + const transformY = (this._offsetY !== undefined ? this._offsetY - this._defaultOffsetY : 0) + + this.getTransformY(this.element.nativeElement); + this.setTransformXY(transformX, transformY); } } else { return; @@ -1393,10 +1389,6 @@ export class IgxDragDirective implements AfterContentInit, OnDestroy { /** Method setting transformation to the base draggable element. */ protected setTransformXY(x: number, y: number) { - const curX = this.getTransformX(this.element.nativeElement); - const curY = this.getTransformY(this.element.nativeElement); - this._baseLeft += x - curX; - this._baseTop += y - curY; this.element.nativeElement.style.transform = 'translate3d(' + x + 'px, ' + y + 'px, 0px)'; } diff --git a/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.spec.ts b/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.spec.ts index 66dca1d9108..eb04051764f 100644 --- a/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.spec.ts +++ b/projects/igniteui-angular/src/lib/directives/drag-drop/drag-drop.spec.ts @@ -547,6 +547,43 @@ describe('General igxDrag/igxDrop', () => { expect(firstDrag.dragStart.emit).toHaveBeenCalled(); })); + it('should position the base element relative to the mouse using offsetX and offsetY correctly.', (async() => { + const firstDrag = fix.componentInstance.dragElems.first; + const firstElement = firstDrag.element.nativeElement; + const startingX = (dragDirsRects[0].left + dragDirsRects[0].right) / 2; + const startingY = (dragDirsRects[0].top + dragDirsRects[0].bottom) / 2; + firstDrag.ghost = false; + firstDrag.ghostOffsetX = 0; + firstDrag.ghostOffsetY = 0; + firstDrag.ghostTemplate = fix.componentInstance.ghostTemplate; + + // Step 1. + UIInteractions.simulatePointerEvent('pointerdown', firstElement, startingX, startingY); + fix.detectChanges(); + await wait(); + + // Step 2. + UIInteractions.simulatePointerEvent('pointermove', firstElement, startingX + 10, startingY + 10); + fix.detectChanges(); + await wait(100); + + // Step 3. + UIInteractions.simulatePointerEvent('pointermove', firstElement, startingX + 20, startingY + 20); + fix.detectChanges(); + await wait(100); + + // We compare the base position and the new position + how much the mouse has moved. + // + 10 margin to the final ghost position + expect(firstElement.getBoundingClientRect().left).toEqual(startingX + 20); + expect(firstElement.getBoundingClientRect().top).toEqual(startingY + 20); + expect(firstElement.innerText).toEqual('Drag 1'); + + // Step 4. + UIInteractions.simulatePointerEvent('pointerup', firstElement, startingX + 20, startingY + 20); + fix.detectChanges(); + await wait(); + })); + it('should correctly set location using setLocation() method when ghost is disabled', (async() => { const firstDrag = fix.componentInstance.dragElems.first; const firstElement = firstDrag.element.nativeElement;