You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Angular Material cdkDropList元素拖拽远离后脱离原容器

实现方案

该效果可以实现,无需依赖cdkDropList的多列表关联逻辑,核心是通过拖拽事件判断位置阈值,结合CDK原生自由拖拽能力完成:

核心实现步骤

1. 绑定拖拽事件判断脱离阈值

在cdkDragReleased或cdkDropListDropped事件中,获取拖拽结束时的指针坐标,和原拖放列表的边界对比,超过自定义阈值则触发脱离逻辑,示例代码如下:

import { CdkDragRelease, CdkDrag } from '@angular/cdk/drag-drop';

// 原列表数据源
items = ['元素1', '元素2', '元素3', '元素4'];
// 自由放置元素数据源
freeItems = [];
// 自定义脱离阈值:距离原列表边界50px即判定为脱离
private readonly THRESHOLD = 50;

@ViewChild('originDropList') originDropList: ElementRef;

onDragReleased(event: CdkDragRelease) {
  const listRect = this.originDropList.nativeElement.getBoundingClientRect();
  const dragPosition = event.source.getFreeDragPosition();

  // 判断是否超出脱离阈值范围
  const isOutOfList = 
    dragPosition.x < listRect.left - this.THRESHOLD ||
    dragPosition.x > listRect.right + this.THRESHOLD ||
    dragPosition.y < listRect.top - this.THRESHOLD ||
    dragPosition.y > listRect.bottom + this.THRESHOLD;

  if (isOutOfList) {
    // 从原列表移除对应元素
    const dragItem = event.source.data;
    const itemIndex = this.items.findIndex(i => i === dragItem);
    if (itemIndex > -1) {
      this.items.splice(itemIndex, 1);
    }
    // 加入自由放置元素列表,记录当前位置
    this.freeItems.push({
      content: dragItem,
      x: dragPosition.x,
      y: dragPosition.y
    });
  }
}

2. 模板层分别渲染原列表和自由放置元素

单独渲染已经脱离原列表的元素,直接添加cdkDrag属性无需包裹在cdkDropList内,默认就支持松开后停在当前位置不会回弹:

<!-- 原拖放列表 -->
<div 
  cdkDropList 
  #originDropList="cdkDropList" 
  [cdkDropListData]="items"
  (cdkDragReleased)="onDragReleased($event)"
>
  <div cdkDrag *ngFor="let item of items" [cdkDragData]="item">
    {{ item }}
  </div>
</div>

<!-- 自由放置区域 -->
<div class="free-drag-area">
  <div
    cdkDrag
    *ngFor="let freeItem of freeItems"
    [style.left.px]="freeItem.x"
    [style.top.px]="freeItem.y"
    style="position: absolute;"
  >
    {{ freeItem.content }}
  </div>
</div>

优化选项

  • 若无需保留原列表的排序能力,可以直接给元素添加[cdkDragReturnToOrigin]="false"属性,拖拽到任意位置松开都不会回弹到原列表,再配合事件逻辑处理原列表元素移除即可。
  • 自由放置的元素可以按需添加边界限制,比如通过cdkDragBoundary属性限定只能在指定区域内拖拽。

内容的提问来源于stack exchange,提问作者ebarooni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 00:27:03