Итак, я работаю в песочнице, чтобы имитировать среду приложения, в котором я хочу реализовать это перетаскивание. Извините за многословность, но я действительно хочу убедиться, что правильно объясню проблему, поскольку я видели несколько более старых сообщений по этой проблеме, на которые либо не было ответа, либо был дан неправильный вопрос.
КРАТКАЯ ВЕРСИЯ
- cdk dnd не будет автоматически прокручиваться
- сделал свой автопрокрутку
- cdk dnd не выпадает после прокрутки
Хитрость в том, что, похоже, функция автоматической прокрутки cdk Drag and Drop работает только из коробки в отношении либо всего размера окна, либо, если это div с фиксированной высотой с overflow-y: scroll (это то, что я пытаюсь to do), то это должно быть на уровне cdkDropList. К сожалению, из-за компонентной архитектуры моего приложения в настоящее время это НЕ вариант.
Я написал свою собственную функцию автопрокрутки, которая прокручивает div в зависимости от положения мыши на экране во время перетаскивания элемента, у меня это работает, но большая проблема заключается в том, что как только div начинает прокрутку вы теряете возможность оставить элемент в списке.
Вот HTML-код моего родительского компонента (div с фиксированной высотой и положением переполнения)
<div #ScrollDiv style="height: 200px; width: 200px; overflow-y: scroll; padding: 5px;">
<app-child (itemSelected)="itemSelection($event)"></app-child>
</div>
Вот шаблон дочернего компонента с директивами cdk
<div cdkDropList style="border: 2px solid purple;" (cdkDropListDropped)="drop($event)">
<div cdkDrag [cdkDragData]="draggers" *ngFor="let item of draggers; let i = index"
style="height: 30px; border: 2px solid blue; margin: 5px"
(mousedown)="grabDrag()">
{{item}}</div>
</div>
На этом этапе я могу перетащить в свое окно, но автопрокрутка не работает, поэтому я добавил автопрокрутку в файл Type Script родительского компонента, изменив положение прокрутки на (mousemove). Для позиций для начала прокрутки вверх / вниз значения жестко запрограммированы на странице, с которой я работаю.
import { Component, OnInit, ElementRef, ViewChild, AfterViewInit, ChangeDetectionStrategy } from '@angular/core';
import { Subscription, fromEvent } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
title = 'drag-sizing';
itemSelected = false;
isScrolling = false;
smoothScroll;
scrollSpeed = 2;
@ViewChild('ScrollDiv', {static: true}) public myScrollContainer: ElementRef;
ngAfterViewInit() {
fromEvent(this.myScrollContainer.nativeElement, 'mousemove').subscribe((event: MouseEvent) => {
if (this.itemSelected) {
if (event.clientY < 150) {
this.isScrolling = true;
if (!this.smoothScroll) {
this.smoothScroll = setInterval(() => {
this.scrollUp();
}, 10);
}
} else if (event.clientY > 300) {
this.isScrolling = true;
if (!this.smoothScroll) {
this.smoothScroll = setInterval(() => {
this.scrollDown();
}, 10);
}
} else {
clearInterval(this.smoothScroll);
this.smoothScroll = undefined;
this.isScrolling = false;
}
} else {
clearInterval(this.smoothScroll);
this.smoothScroll = undefined;
this.isScrolling = false;
}
});
}
scrollInner() {
this.myScrollContainer.nativeElement.scrollTop += 2;
}
itemSelection(event) {
this.itemSelected = event;
if (!this.itemSelected) {
clearInterval(this.smoothScroll);
this.smoothScroll = undefined;
}
}
scrollUp() {
if (this.isScrolling === true) {
this.myScrollContainer.nativeElement.scrollTop -= this.scrollSpeed;
}
}
scrollDown() {
if (this.isScrolling === true) {
this.myScrollContainer.nativeElement.scrollTop += this.scrollSpeed;
}
}
}
и дочерний компонент TypeScript, который излучает, что элемент перетаскивается и имеет функцию перетаскивания
import { Component, OnInit, Input, ElementRef, ViewChild, AfterViewInit, Output, EventEmitter } from '@angular/core';
import { Subscription, fromEvent, BehaviorSubject, Subject } from 'rxjs';
import { CdkDragDrop, transferArrayItem, moveItemInArray } from '@angular/cdk/drag-drop';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.css']
})
export class ChildComponent implements AfterViewInit {
@Output() itemSelected = new EventEmitter<boolean>();
itemIsSelected = false;
draggers = ['item 0', 'item 1', 'item 2'...]
ngAfterViewInit(): void {
fromEvent(document, 'mouseup').subscribe(() => {
this.itemIsSelected = false;
this.itemSelected.emit(this.itemIsSelected);
});
}
grabDrag() {
this.itemIsSelected = true;
this.itemSelected.emit(this.itemIsSelected);
}
drop(event: CdkDragDrop<any>) {
console.log(event);
moveItemInArray(this.draggers, event.previousIndex, event.currentIndex);
}
}
(могут быть некоторые вещи, которые я не использую, оставшиеся после неудачных попыток)
В любом случае: я знаю, что это было долго, но основное поведение, которое я пытаюсь преодолеть / выяснить, это Когда я перетаскиваю элемент и прокручиваю от небольшого фрагмента массива в его исходном порту просмотра, перетаскивание cdk больше не позволяет мне бросать элемент в эту позицию массива ... элемент все еще кажется ПЕРЕТАСКИВАЮЩИМ, но это наводит меня на мысль, что он больше не распознает ЗОНУ ВЫПАДЕНИЯ.