我正在进行一个项目,在这个项目中,我需要实现某种类型的拖放区域,您可以从列表中拖动元素,然后将它们放到可以自由拖动的区域中。我还想为区域使用cdkDropList,因为它提供了连接列表的所有工具。我使用这个例子作为实现的参考,但我无法使它正常工作。
当我在区域中放置一个项目时,它不会掉到光标所在的位置,它只会转到我的区域的左上角,就像在列表中一样。
当我在区域中拖动一个项目时,它会正确地拖到我想要它被丢弃的地方,或者在下降点附近被拖放,或者回到左上角。
这里是我的cdkDrag元素,它不同于上面链接的示例,因为我绝对需要它在它自己的组件中(我希望在将来对它应用一些逻辑),但它本质上是相同的概念( cdkDropList div中的cdkDrag div)。我设法使用输出将所有需要的事件路由到父元素(区域)。
<div class="element-box"
cdkDrag
cdkDragBoundary={{boundary_name}}
(cdkDragDropped)="dragDroppedEventToParent($event)"
(cdkDragStarted)="dragStartedEventToParent($event)"
(cdkDragMoved)="dragMovedEventToParent($event)">
{{object_name}}
<div *cdkDragPlaceholder class="field-placeholder"></div>
</div>下面是,用于拖动元素的逻辑:
export class ElementBoxComponent implements OnInit {
@Input () object_name: string;
@Input () boundary_name: string;
@Input () itemSelf: any;
@Output () dragMovedEvent = new EventEmitter<CdkDragMove>();
@Output () dragStartedEvent = new EventEmitter<CdkDragStart>();
@Output () dragDroppedEvent = new EventEmitter<any>();
constructor() {}
ngOnInit(): void {
}
dragMovedEventToParent(event: CdkDragMove) {
this.dragMovedEvent.emit(event);
}
dragStartedEventToParent(event: CdkDragStart){
this.dragStartedEvent.emit(event);
}
dragDroppedEventToParent(event: CdkDragEnd){
this.dragDroppedEvent.emit({event, "self": this.itemSelf});
}
}下面是我的拖放区域元素,其中我呈现了拖放元素(您可以看到我将输出路由到区域逻辑中的方法):
<div class="drop-container"
#cdkBoard
cdkDropList
[id]="'cdkBoard'"
[cdkDropListData]="itemsInBoard"
[cdkDropListConnectedTo]="connectedTo"
cdkDropListSortingDisabled="true"
(cdkDropListDropped)="itemDropped($event)">
<app-element-box *ngFor="let item of itemsInBoard; let i=index"
object_name="{{item.name}}"
boundary_name=".drop-container"
itemSelf="{{item}}"
style="position:absolute; z-index:i"
[style.top]="item.top"
[style.left]="item.left"
(dragMovedEvent)="elementIsMoving($event)"
(dragStartedEvent)="startedDragging($event)"
(dragDroppedEvent)="stoppedDragging($event)"></app-element-box>
<svg-container class="bin-container" containerId="bin-image-container" *ngIf="_binVisible" height=40>
<svg-image class="bin-icon" [imageUrl]="BIN_ICON_URL" height=40 width=40></svg-image>
</svg-container>
</div>下面是我的拖放区的TS文件中的相关方法:
itemDropped(event: CdkDragDrop<any[]>) {
if (event.previousContainer === event.container) {
moveItemInArray(this.itemsInBoard, event.previousIndex, event.currentIndex);
} else {
copyArrayItem(
event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex
)
}
}
changePosition(event: CdkDragDrop<any>, field) {
const rectZone = this.dropZone.nativeElement.getBoundingClientRect();
const rectElement = event.item.element.nativeElement.getBoundingClientRect();
const top = rectElement.top + event.distance.y - rectZone.top;
const left = rectElement.left + event.distance.x - rectZone.left;
const out = (top < 0) || (left < 0) || (top > (rectZone.height - rectElement.height)) || (left > (rectZone.width - rectElement.width));
if (!out) {
event.item.element.nativeElement.style.top = top + 'px';
event.item.element.nativeElement.style.left = left + 'px';
} else {
this.itemsInBoard = this.itemsInBoard.filter((x) => x != event.item);
}
}同样,惟一的区别是,我的元素被封装在它们自己的组件中,并且我访问组件的顶部和左边样式元素的方式是不同的(示例中的代码没有工作)。我知道问题在于计算顶部变量和左变量的方法,但我已经坚持了一个星期了,似乎找不到它的问题所在。
这是一个短演示视频,如果您想更好地可视化我正在谈论的东西。
有人知道这是怎么回事吗?我愿意听取任何建议,谢谢:)
发布于 2021-11-13 10:51:19
没有乱七八糟的闪电战很难知道出了什么问题
在这一堆闪电战中,我做了两个ckd列表
一个cdkDropList (todoList)是典型的“列表”,另一个是dropZone (doneList)。我的元素在路上
{label:string,x:number,y:number,'z-index':number}cdkDrag中的dropZone阻碍了
<div cdkDrag class="item-box"
[style.top.px]="item.y"
[style.left.px]="item.x"
[style.z-index]="item['z-index']"
>我选择todoList连接到dropZone,但是dropZone没有连接到任何东西。当我移动dropZone的元素时,如果它移开了这个元素,只需添加到列表中
我们需要把doneList作为ElementRef
@ViewChild('doneList',{read:ElementRef,static:true}) dropZone:ElementRef;以及相关函数
drop(event: CdkDragDrop<any[]>) {
if (event.previousContainer === event.container) {
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
} else {
transferArrayItem(
event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex,
);
event.item.data.y=(this._pointerPosition.y-this.dropZone.nativeElement.getBoundingClientRect().top)
event.item.data.x=(this._pointerPosition.x-this.dropZone.nativeElement.getBoundingClientRect().left)
this.changeZIndex(event.item.data)
}
this.posInside={source:null,x:0,y:0}
}
moved(event: CdkDragMove) {
this._pointerPosition=event.pointerPosition;
}
changeZIndex(item:any)
{
this.done.forEach(x=>x['z-index']=(x==item?1:0))
}
changePosition(event:CdkDragDrop<any>,field)
{
const rectZone=this.dropZone.nativeElement.getBoundingClientRect()
const rectElement=event.item.element.nativeElement.getBoundingClientRect()
let y=+field.y+event.distance.y
let x=+field.x+event.distance.x
const out=y<0 || x<0 || (y>(rectZone.height-rectElement.height)) || (x>(rectZone.width-rectElement.width))
if (!out)
{
field.y=y
field.x=x
}
else{
this.todo.push(field)
this.done=this.done.filter(x=>x!=field)
}
}喜欢.html
<div class="wrapper">
<div
cdkDropList
#todoList="cdkDropList"
[cdkDropListData]="todo"
[cdkDropListConnectedTo]="[doneList]"
class="example-list"
(cdkDropListDropped)="drop($event)"
>
<div
class="example-box"
*ngFor="let item of todo"
cdkDrag
[cdkDragData]="item"
(cdkDragMoved)="moved($event)"
>
{{ item.label }}
<div *cdkDragPlaceholder class="field-placeholder"></div>
</div>
</div>
<div
cdkDropList
#doneList="cdkDropList"
[cdkDropListData]="done"
class="drag-zone"
cdkDropListSortingDisabled="true"
(cdkDropListDropped)="drop($event)"
>
<ng-container *ngFor="let item of done">
<div
cdkDrag
class="item-box"
[style.top.px]="item.y"
[style.left.px]="item.x"
[style.z-index]="item['z-index']"
(cdkDragStarted)="changeZIndex(item)"
(cdkDragDropped)="changePosition($event, item)"
>
{{ item.label }}
<div *cdkDragPlaceholder class="field-placeholder"></div>
</div>
</ng-container>
</div>
</div>https://stackoverflow.com/questions/69932412
复制相似问题