diff --git a/src/cdk/drag-drop/drag.spec.ts b/src/cdk/drag-drop/drag.spec.ts index a37613983cb..6aeb5e05117 100644 --- a/src/cdk/drag-drop/drag.spec.ts +++ b/src/cdk/drag-drop/drag.spec.ts @@ -504,6 +504,7 @@ describe('CdkDrag', () => { expect(dragElement.style.touchAction) .not.toEqual('none', 'should not disable touchAction on when there is a drag handle'); }); + it('should be able to reset a freely-dragged item to its initial position', fakeAsync(() => { const fixture = createComponent(StandaloneDraggable); fixture.detectChanges(); @@ -556,7 +557,17 @@ describe('CdkDrag', () => { expect(fixture.componentInstance.endedSpy).toHaveBeenCalledTimes(1); })); - }); + it('should round the transform value', fakeAsync(() => { + const fixture = createComponent(StandaloneDraggable); + fixture.detectChanges(); + const dragElement = fixture.componentInstance.dragElement.nativeElement; + + expect(dragElement.style.transform).toBeFalsy(); + dragElementViaMouse(fixture, dragElement, 13.37, 37); + expect(dragElement.style.transform).toBe('translate3d(13px, 37px, 0px)'); + })); + + }); describe('draggable with a handle', () => { it('should not be able to drag the entire element if it has a handle', fakeAsync(() => { diff --git a/src/cdk/drag-drop/drag.ts b/src/cdk/drag-drop/drag.ts index c852a91a397..0a553e18fb5 100644 --- a/src/cdk/drag-drop/drag.ts +++ b/src/cdk/drag-drop/drag.ts @@ -866,7 +866,9 @@ interface Point { * @param y Desired position of the element along the Y axis. */ function getTransform(x: number, y: number): string { - return `translate3d(${x}px, ${y}px, 0)`; + // Round the transforms since some browsers will + // blur the elements, for sub-pixel transforms. + return `translate3d(${Math.round(x)}px, ${Math.round(y)}px, 0)`; } /** Creates a deep clone of an element. */ diff --git a/src/cdk/drag-drop/drop-list.ts b/src/cdk/drag-drop/drop-list.ts index 00ab3c667af..bd2e4be865b 100644 --- a/src/cdk/drag-drop/drop-list.ts +++ b/src/cdk/drag-drop/drop-list.ts @@ -362,10 +362,12 @@ export class CdkDropList implements OnInit, OnDestroy { // Note that we shouldn't use `getBoundingClientRect` here to update the cache, because the // elements may be mid-animation which will give us a wrong result. if (isHorizontal) { - elementToOffset.style.transform = `translate3d(${sibling.offset}px, 0, 0)`; + // Round the transforms since some browsers will + // blur the elements, for sub-pixel transforms. + elementToOffset.style.transform = `translate3d(${Math.round(sibling.offset)}px, 0, 0)`; this._adjustClientRect(sibling.clientRect, 0, offset); } else { - elementToOffset.style.transform = `translate3d(0, ${sibling.offset}px, 0)`; + elementToOffset.style.transform = `translate3d(0, ${Math.round(sibling.offset)}px, 0)`; this._adjustClientRect(sibling.clientRect, offset, 0); } });