【问题标题】:Angular Animation - find the currently animating elements matched by :leaveAngular Animation - 查找当前与 :leave 匹配的动画元素
【发布时间】:2021-12-30 17:42:31
【问题描述】:

我正在使用BrowserAnimationsModule,并使用路由器设置了一些动画,以便当前组件滑出,而新/下一个组件在用户导航时滑入。这很好用。

但是,我现在想在每个动画的开始 + 结束时执行一些操作。我正在使用AnimationEventcallback 采取行动,但我需要具体了解哪些动画组件(或只是 dom 元素)当前正在进入或离开 dom,也就是哪些与 query(':enter') 或 @987654329 匹配@,这样我就可以定位运行:leave 动画的特定组件。我的动画看起来像:

export function fadeIn() {
    return [
        query(':enter, :leave', style({ position: 'fixed', width: '100%' }), { optional: true }),
        query(':enter', style({ opacity: '0' }), { optional: true }),
        query(':leave', style({ opacity: '0' }), { optional: true }),
        group([
            query(':enter', group([
                animate('11000ms ease', style({opacity: '1'})),
                animateChild()
            ]), opt)
        ])
    ];
}

我知道 angular 在动画运行时设置类ng-animating,如下所示: ...但这还不足以区分 :leave:enter

*如果你想知道我想要做什么 - 我想在 :leave 组件/元素上设置 pointer-events: none,以防止用户在此动画期间单击 dom 元素,因为在开始时动画,:leave 组件上的角度调用 onDestroy(),这有点破坏它们,因此在动画运行的这段时间跨度内单击它们的 dom 元素可能会导致错误。我不希望在每个组件的 onDestroy() 方法中填充代码以将它们标识为 ':leave' 组件,如果有一种不那么乏味的方法的话。

我正在使用 Angular 7,但对可能需要升级的解决方案持开放态度。

edit - 添加说明: 我已经在使用上面提到的 AnimationEvent 回调,但我不知道如何判断哪些组件或 dom 元素正在进入或离开。总是有 2 个组件同时动画,一个进入,一个离开。看看我发布的 img,其中 dom 中有 <app-splash><app-account-recovery>,它们都是 class=router-outlet-wrapper 的子代(router-outlet-wrapper 是 animEvent.element 在进入和离开事件回调中始终指向的内容) .

我的代码非常接近于这个 ng 示例:

https://github.com/matsko/ng4-animations-preview/blob/master/src/app/app.component.html https://github.com/matsko/ng4-animations-preview/blob/master/src/app/app.component.ts

请注意,每个组件 ts 文件中没有动画代码 - 全部在 AppComponent 中完成,因此所有组件都作为 <router-outlet> 的同级放置,AnimationEvent.triggerName 始终 = routerAnimations

我确实注意到 :leave 元素似乎总是在 <router-outlet> 之后的第二个兄弟元素 - 在我的 img 中,这意味着 <app-account-recovery> 正在离开,但依赖这样一个未指定的细节感觉很糟糕。

一个可接受的答案必须能够明确告诉我当前哪个元素正在运行 :leave 动画。

【问题讨论】:

  • 我检查了当被破坏的组件动画时没有事件监听器,例如。而且我想所有角度监听器都会发生同样的情况——只要你不添加香草 js 监听器,你应该没问题——不是吗?
  • 你能提供一个stackblitz吗?
  • 也许您可以在导航时将html指针事件设置为无?
  • @PetrAveryanov 这就是问题所在 - ng 在 :leave 开始之前删除了它的事件监听器。在我的例子中,我有一个表单元素,它通常有提交事件监听器,阻止它提交到 action 属性。但是,这些事件处理程序已经消失,因此如果您在此期间单击,表单会提交并造成很多混乱。我想其他此类错误存在于应用程序的其他地方,因此我想尝试完全阻止用户交互:离开元素。
  • @PetrAveryanov 在动画期间禁用所有指针事件可能是一个可以接受的中间立场,尽管我更喜欢让 :enter 元素尽可能交互,否则快速点击用户会在点击“do”时感到困惑有时什么都没有”。

标签: angular animation


【解决方案1】:

您可以使用AnimationEvent 来实现。

@Component({
  host: {
    '[@myAnimationTrigger]': 'someExpression',
    '(@myAnimationTrigger.start)': 'captureStartEvent($event)',
    '(@myAnimationTrigger.done)': 'captureDoneEvent($event)',
  },
  animations: [
    trigger("myAnimationTrigger", [
       // ...
    ])
  ]
})
class MyComponent {
  someExpression: any = false;
  captureStartEvent(event: AnimationEvent) {
    // the toState, fromState and totalTime data is accessible from the event variable
  }

  captureDoneEvent(event: AnimationEvent) {
    // the toState, fromState and totalTime data is accessible from the event variable
  }
}

模型如下:

interface AnimationEvent {
  fromState: string
  toState: string
  totalTime: number
  phaseName: string
  element: any
  triggerName: string
  disabled: boolean
}

您可以通过这些属性确定您是否在:leave

【讨论】:

  • 我已经尝试过了,但是event.element 总是指向我的class=router-outlet-wrapper 元素。请查看我更新的帖子 - 我编辑了 edit 下面的部分
  • @goat 我想现在你可以让它变得非常简单。获取所有子元素。如果有 3 个,那么你需要第 2 个和第 3 个
  • @Sergey 但我怎么知道这两个中的哪一个要离开?就像我在帖子中所说的那样,指望订单是未指定的行为并且可能不可靠。
  • 在其 toState @Sergey 上过滤数组
  • 我有一种感觉,新的路线总是最后一条
【解决方案2】:

如果您只想在为:leave 制作动画期间将pointer-events 设置为none,请尝试在query 本身内设置它:

query(':leave', style({ opacity: '0', 'pointer-events': 'none' }), { optional: true }),

【讨论】:

  • 我在问这个问题之前试过了,除非我犯了错误,否则它不起作用。我确实添加了其他样式,例如 bg 颜色,所以我认为我做得对,甚至尝试了 pointerEventspointer-events
  • @goat 你试过keyframes吗?我认为可能是最后分配了指针事件。相反,如果您使用偏移量为 0 的关键帧,它应该会有所帮助,因为它将成为初始点而不是最后一个点
猜你喜欢
  • 2010-09-24
  • 2015-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-23
  • 1970-01-01
相关资源
最近更新 更多