mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(drag-drop): allow for dragging sequence to be delayed (#14732)
Adds the `cdkDragStartDelay` input that allows for the dragging sequence to be delayed by X amount of milliseconds. Fixes #13908.
This commit is contained in:
committed by
Jeremy Elbourn
parent
5d3f5157ca
commit
bcf278179b
@@ -703,6 +703,36 @@ describe('CdkDrag', () => {
|
||||
}).toThrowError(/^cdkDrag must be attached to an element node/);
|
||||
}));
|
||||
|
||||
it('should allow for the dragging sequence to be delayed', fakeAsync(() => {
|
||||
// We can't use Jasmine's `clock` because Zone.js interferes with it.
|
||||
spyOn(Date, 'now').and.callFake(() => currentTime);
|
||||
let currentTime = 0;
|
||||
|
||||
const fixture = createComponent(StandaloneDraggable);
|
||||
fixture.componentInstance.dragStartDelay = 1000;
|
||||
fixture.detectChanges();
|
||||
const dragElement = fixture.componentInstance.dragElement.nativeElement;
|
||||
|
||||
expect(dragElement.style.transform).toBeFalsy('Expected element not to be moved by default.');
|
||||
|
||||
startDraggingViaMouse(fixture, dragElement);
|
||||
currentTime += 750;
|
||||
dispatchMouseEvent(document, 'mousemove', 50, 100);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(dragElement.style.transform)
|
||||
.toBeFalsy('Expected element not to be moved if the drag timeout has not passed.');
|
||||
|
||||
// The first `mousemove` here starts the sequence and the second one moves the element.
|
||||
currentTime += 500;
|
||||
dispatchMouseEvent(document, 'mousemove', 50, 100);
|
||||
dispatchMouseEvent(document, 'mousemove', 50, 100);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(dragElement.style.transform).toBe('translate3d(50px, 100px, 0px)',
|
||||
'Expected element to be dragged after all the time has passed.');
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('draggable with a handle', () => {
|
||||
@@ -2832,6 +2862,7 @@ describe('CdkDrag', () => {
|
||||
<div
|
||||
cdkDrag
|
||||
[cdkDragBoundary]="boundarySelector"
|
||||
[cdkDragStartDelay]="dragStartDelay"
|
||||
(cdkDragStarted)="startedSpy($event)"
|
||||
(cdkDragReleased)="releasedSpy($event)"
|
||||
(cdkDragEnded)="endedSpy($event)"
|
||||
@@ -2847,6 +2878,7 @@ class StandaloneDraggable {
|
||||
endedSpy = jasmine.createSpy('ended spy');
|
||||
releasedSpy = jasmine.createSpy('released spy');
|
||||
boundarySelector: string;
|
||||
dragStartDelay: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -110,6 +110,12 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
|
||||
*/
|
||||
@Input('cdkDragBoundary') boundaryElementSelector: string;
|
||||
|
||||
/**
|
||||
* Amount of milliseconds to wait after the user has put their
|
||||
* pointer down before starting to drag the element.
|
||||
*/
|
||||
@Input('cdkDragStartDelay') dragStartDelay: number = 0;
|
||||
|
||||
/** Whether starting to drag this element is disabled. */
|
||||
@Input('cdkDragDisabled')
|
||||
get disabled(): boolean {
|
||||
@@ -303,6 +309,7 @@ export class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDestroy {
|
||||
|
||||
ref.disabled = this.disabled;
|
||||
ref.lockAxis = this.lockAxis;
|
||||
ref.dragStartDelay = this.dragStartDelay;
|
||||
ref
|
||||
.withBoundaryElement(this._getBoundaryElement())
|
||||
.withPlaceholderTemplate(placeholder)
|
||||
|
||||
@@ -167,6 +167,9 @@ export class DragRef<T = any> {
|
||||
*/
|
||||
private _lastTouchEventTime: number;
|
||||
|
||||
/** Time at which the last dragging sequence was started. */
|
||||
private _dragStartTime: number;
|
||||
|
||||
/** Cached reference to the boundary element. */
|
||||
private _boundaryElement: HTMLElement | null = null;
|
||||
|
||||
@@ -200,6 +203,12 @@ export class DragRef<T = any> {
|
||||
/** Axis along which dragging is locked. */
|
||||
lockAxis: 'x' | 'y';
|
||||
|
||||
/**
|
||||
* Amount of milliseconds to wait after the user has put their
|
||||
* pointer down before starting to drag the element.
|
||||
*/
|
||||
dragStartDelay: number = 0;
|
||||
|
||||
/** Whether starting to drag this element is disabled. */
|
||||
get disabled(): boolean {
|
||||
return this._disabled || !!(this._dropContainer && this._dropContainer.disabled);
|
||||
@@ -474,12 +483,13 @@ export class DragRef<T = any> {
|
||||
const pointerPosition = this._getPointerPositionOnPage(event);
|
||||
const distanceX = Math.abs(pointerPosition.x - this._pickupPositionOnPage.x);
|
||||
const distanceY = Math.abs(pointerPosition.y - this._pickupPositionOnPage.y);
|
||||
const isOverThreshold = distanceX + distanceY >= this._config.dragStartThreshold;
|
||||
|
||||
// Only start dragging after the user has moved more than the minimum distance in either
|
||||
// direction. Note that this is preferrable over doing something like `skip(minimumDistance)`
|
||||
// in the `pointerMove` subscription, because we're not guaranteed to have one move event
|
||||
// per pixel of movement (e.g. if the user moves their pointer quickly).
|
||||
if (distanceX + distanceY >= this._config.dragStartThreshold) {
|
||||
if (isOverThreshold && (Date.now() >= this._dragStartTime + (this.dragStartDelay || 0))) {
|
||||
this._hasStartedDragging = true;
|
||||
this._ngZone.run(() => this._startDragSequence(event));
|
||||
}
|
||||
@@ -675,6 +685,7 @@ export class DragRef<T = any> {
|
||||
const pointerPosition = this._pickupPositionOnPage = this._getPointerPositionOnPage(event);
|
||||
this._pointerDirectionDelta = {x: 0, y: 0};
|
||||
this._pointerPositionAtLastDirectionChange = {x: pointerPosition.x, y: pointerPosition.y};
|
||||
this._dragStartTime = Date.now();
|
||||
this._dragDropRegistry.startDragging(this, event);
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -14,6 +14,7 @@ export declare class CdkDrag<T = any> implements AfterViewInit, OnChanges, OnDes
|
||||
boundaryElementSelector: string;
|
||||
data: T;
|
||||
disabled: boolean;
|
||||
dragStartDelay: number;
|
||||
dropContainer: CdkDropList;
|
||||
dropped: EventEmitter<CdkDragDrop<any>>;
|
||||
element: ElementRef<HTMLElement>;
|
||||
@@ -204,6 +205,7 @@ export declare class DragRef<T = any> {
|
||||
beforeStarted: Subject<void>;
|
||||
data: T;
|
||||
disabled: boolean;
|
||||
dragStartDelay: number;
|
||||
dropped: Subject<{
|
||||
previousIndex: number;
|
||||
currentIndex: number;
|
||||
|
||||
Reference in New Issue
Block a user