基于拖放容器的不同cdk-drag-preview动画

Different cdk-drag-preview animation based on drop container

我试图在释放拖动的组件时根据放置容器获得不同的动画。 基本上,我有两个 cdkDropList。一个是卡片列表(多个可拖动元素),另一个是只有一个元素的卡片查看器,大小是原来的两倍。用户可以将卡片从列表中拖到查看器中,以获得更好的视图。

当用户拖放卡片时,有两种情况:

您可以使用以下 css 设置卡片滑动到其目标位置的动画:

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

到目前为止,还不错。 但是,我现在必须添加条件 css 规则,如果放置容器是查看器,则添加 "transform: scale(2);"。

这就是我卡住的地方!

我试图避免直接 DOM 访问,遵循 angular 指南,所以我想在卡片动画时添加 class 到卡片。但是 CDK 似乎没有办法获得 preview/animating 组件的引用!

我已经成功获取了目标大小和拖拽组件,在我的组件ts中有如下代码:

  onDragEnter(event: CdkDragEnter) {
    if (_.contains(event.container.element.nativeElement.classList,"large")){
      this.targetSize= "large";
    } else {
      this.targetSize= "medium";
    }
  }      
  onDragRelease(event: CdkDragRelease) {
    this.renderer.addClass(event.source.element.nativeElement, this.targetSize);
  }

但是,此引用是拖动对象的引用,而不是预览对象!当在动画上放置一个很长的计时器以允许我检查它时,我可以看到以下 DOM 个元素:

    <div _ngcontent-auk-c7="" cdkdrag="" class="cdk-drag large" 
ng-reflect-data="[object Object]" style="display: none;">...</div>

    <div _ngcontent-auk-c7="" cdkdrag="" class="cdk-drag cdk-drag-preview cdk-drag-animating" 
ng-reflect-data="[object Object]" style="touch-action: none; -webkit-user-drag: none; -webkit-tap-highlight-color: transparent; user-select: none; width: 135px; height: 175px; transform: translate3d(415px, 84px, 0px); pointer-events: none; margin: 0px; position: fixed; top: 0px; left: 0px; z-index: 1000;" dir="ltr"><!----><div _ngcontent-auk-c7="" class="card-holder medium"><app-card-base _ngcontent-auk-c7="" _nghost-auk-c8="" ng-reflect-card="[object Object]" ng-reflect-size="medium"><div _ngcontent-auk-c8="" class="card-container medium flip-front" ng-reflect-klass="card-container" ng-reflect-ng-class="medium,flip-front">...</div>

如您所见,我们有两个元素,一个具有正确的 class "large",但在 "display:none" 上,第二个具有 classes "cdk-drag-preview cdk-drag-animating",但不是新的 class "large".

因此,由于我无法向第二个元素添加 class,因此我无法使其有条件地更改其动画... 一个奇怪的副作用是新的 class "large" 被添加到卡中,并且将来从这张卡中 cdk-drag-preview 将有 "large" class!然而,这并不好,因为它似乎表明我应该在 拖动开始之前 class ,当我不知道用户是否真的将它拖动到查看器时下拉列表..

长话短说:

  • 我需要根据目标 dropList 动态添加 class 到 cdk-drag-preview。
  • cdk-drag-preview 似乎无法在任何 cdk-drag 事件中被引用
  • 因此我无法将我的 class 添加到其中并在拖动开始后更改最终动画。

好吧,这不是我想要的,但它确实有效..

在 cdkDragReleased 事件中,我通过 "document.querySelector"...

获得了 cdkDragPreview 元素的引用

我不认为它遵循 Angular 的指导方针,但至少我让它起作用了,现在我的卡片动画根据目标 DropList 正确缩放..

  onDragRelease(event: CdkDragRelease) {
    const preview = new ElementRef<HTMLElement>(document.querySelector(".cdk-drag.cdk-drag-preview"));
    this.renderer.addClass(preview.nativeElement, this.targetSize);
  }

HTML

(cdkDropListEntered)="cdkDropListEntered($event)"
(cdkDropListExited)="cdkDropListExited($event)"

TypeScript

  cdkDropListEntered(event: CdkDragEnter<string[]>) {
    const preview = new ElementRef<HTMLElement>(document.querySelector('.cdk-drag.cdk-drag-preview'));
    this.renderer.addClass(preview.nativeElement, 'class-name');
  }

  cdkDropListExited(event: CdkDragExit<string[]>) {
    const preview = new ElementRef<HTMLElement>(document.querySelector('.cdk-drag.cdk-drag-preview'));
    this.renderer.removeClass(preview.nativeElement, 'class-name');
  }