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

如何在Angular CDK中实现拖拽图片的克隆、自动排列与重对齐?

问题描述

我正在开发Angular拖拽功能,需要实现以下需求:

  • 拖拽图片时生成克隆副本
  • 将图片放入指定容器后固定在该容器内
  • 若放入错误容器,图片需返回原位置
  • 支持同一容器放置多张图片,且自动依次排列
  • 移除中间图片后,剩余图片自动重新对齐

请问如何通过Angular CDK实现这些功能?

现有代码

HTML

<div class="drop-container">
  <div cdkDropList
       #doneList="cdkDropList"
       [cdkDropListData]="done"
       class="drop-list rec"
       (cdkDropListDropped)="drop($event)">
    <div class="example-box" *ngFor="let item of done" cdkDrag><img [src]="item" /></div>
  </div>
</div>

<div class="drag-container"> 
  <div cdkDropList
       [cdkDropListData]="todo"
       [cdkDropListConnectedTo]="[doneList]"
       [cdkDropListSortingDisabled]="true"
       class="drag-list"
       (cdkDropListEntered)="entered($event)"
       (cdkDropListExited)="exited($event)"
       [ngClass]="{'drag-stop': count === 1}">
    <ng-container *ngFor="let item of todo">
      <img [src]="item" cdkDrag [cdkDragData]="item" />
      <div class="example-box" >
        <img [src]="item" *ngIf="transferringItem === item"/>
      </div>
    </ng-container>
  </div>
</div>

TypeScript

import { Component } from "@angular/core";
import { CdkDragDrop, copyArrayItem, CdkDragExit, CdkDragEnter } from "@angular/cdk/drag-drop";

@Component({
  selector: 'app-halsband',
  templateUrl: './halsband.component.html',
  styleUrl: './halsband.component.css'
})
export class HalsbandComponent {
  todo:string[] = ['assets/Images/images/Tiobas_b3.png'];
  done: string[] = [''];
  transferringItem: string = '';
  count: number = 0;

  drop(event: CdkDragDrop<string[]>) {
    this.count++;
    if (event.previousContainer.id !== event.container.id) {
      copyArrayItem(
        event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );
    }
    this.transferringItem = '';
  }

  entered(e: CdkDragEnter<any>) {
    this.transferringItem = '';
  }

  exited(e: CdkDragExit<any>) {
    console.log(e.item.data);
    this.transferringItem = e.item.data;
  }
}

CSS

.drop-container {
  display: flex;
  justify-content: center;
  width: 100%; 
}

.drop-list {
  border: solid 1px #ccc; 
  background: white;
  border-radius: 4px;
  overflow: hidden;
  display: flex;
  width: 15vw;
  height: 15vw;
}

.drag-container {
  display: flex;
  justify-content: center;
  width: 100%;
  margin-top:2vw;
}

.example-box {
  padding: 20px 10px;
  border-bottom: solid 1px #ccc;
  color: rgba(0, 0, 0, 0.87);
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
  cursor: move;
  background: white;
  font-size: 14px;
}

.cdk-drag-preview {
  box-sizing: border-box;
  border-radius: 4px;
  box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
}

.rec .cdk-drag-placeholder {
  opacity: 0;
}

.cdk-drag-animating {
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

.example-box:last-child {
  border: none;
}

.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder) {
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

.drag-stop {
  opacity: 0.3;
  pointer-events: none;
}
解决方案与代码修改

以下是针对需求的具体实现调整:

1. 拖拽生成克隆副本

给拖拽图片添加[cdkDragCopy]="true"属性,Angular CDK会自动创建拖拽副本,原元素保留在初始容器。

2. 指定容器判断与返回原位置

给目标容器添加id="target-container",在drop事件中仅允许拖入该容器,其他容器不执行复制操作,CDK会自动将拖拽元素返回原位置。

3. 多张图片自动排列

修改目标容器的CSS,开启flex-wrap: wrap并设置间距,实现图片自动换行排列。

4. 移除图片后自动对齐

添加删除按钮,通过splice删除数组元素,*ngFor会自动重新渲染列表,剩余图片自动对齐。

修改后的完整代码

HTML

<div class="drop-container">
  <div cdkDropList
       #doneList="cdkDropList"
       id="target-container"
       [cdkDropListData]="done"
       class="drop-list rec"
       (cdkDropListDropped)="drop($event)">
    <div class="example-box" *ngFor="let item of done; let i = index" cdkDrag>
      <img [src]="item" />
      <button (click)="removeItem(i)">删除</button>
    </div>
  </div>
</div>

<div class="drag-container"> 
  <div cdkDropList
       [cdkDropListData]="todo"
       [cdkDropListConnectedTo]="[doneList]"
       [cdkDropListSortingDisabled]="true"
       class="drag-list">
    <img [src]="item" *ngFor="let item of todo" cdkDrag [cdkDragData]="item" [cdkDragCopy]="true" />
  </div>
</div>

TypeScript

import { Component } from "@angular/core";
import { CdkDragDrop, copyArrayItem } from "@angular/cdk/drag-drop";

@Component({
  selector: 'app-halsband',
  templateUrl: './halsband.component.html',
  styleUrl: './halsband.component.css'
})
export class HalsbandComponent {
  todo:string[] = ['assets/Images/images/Tiobas_b3.png'];
  done: string[] = []; // 移除默认空字符串占位

  drop(event: CdkDragDrop<string[]>) {
    // 仅允许拖入指定目标容器
    if (event.container.id === 'target-container') {
      copyArrayItem(
        event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex
      );
    }
  }

  removeItem(index: number) {
    this.done.splice(index, 1);
  }
}

CSS

.drop-container {
  display: flex;
  justify-content: center;
  width: 100%; 
}

.drop-list {
  border: solid 1px #ccc; 
  background: white;
  border-radius: 4px;
  overflow: auto;
  display: flex;
  flex-wrap: wrap; /* 开启自动换行 */
  gap: 10px; /* 图片间距 */
  padding: 10px;
  width: 40vw;
  min-height: 15vw;
}

.drag-container {
  display: flex;
  justify-content: center;
  width: 100%;
  margin-top:2vw;
}

.example-box {
  padding: 5px;
  border: solid 1px #ccc;
  border-radius: 4px;
  display: flex;
  flex-direction: column;
  align-items: center;
  box-sizing: border-box;
  cursor: move;
  background: white;
}

.example-box img {
  width: 80px;
  height: 80px;
  object-fit: cover;
}

.cdk-drag-preview {
  box-sizing: border-box;
  border-radius: 4px;
  box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), 0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
}

.rec .cdk-drag-placeholder {
  opacity: 0;
}

.cdk-drag-animating {
  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 19:39:53