Fork me on GitHub

如何实现一个可以传入自定义动画的angular组件

学习 angular 过程中想开发一个允许传入自定义动画的 Popup 组件,本以为是个简单的事情,没想到中间断断续续耗费了我一周时间。

  • 允许设置弹出位置,暂时只需要考虑
  • 组件默认有自己动画,根据位置不同,默认动画也不同,比如位置为 ,那么动画就是从上方滑入,为 ,那么动画就是从中间淡入。用户可以传入一个自定义动画配置以替换默认动画效果。
  • 支持动画结束后发射事件,比如我想依靠这个 Popup 组件实现一个动态 Toast 组件(通过 componentFactory),Toast 组件在一定时间后自动销毁,那么就需要 Popup 组件支持在动画结束后发送一个事件,然后 Toast Service 监听它,而后调用 destroy,实现一个动态组件的方法可以看这里

根据以上需求,结果我翻遍 Google,看别人 ui 库源码都不能满足我要求,因为他们组件动画都是写死的,要么是通过 @Component 的元数据 animations 配置,要么是类名 + css 实现,根本没法让外部通过属性传入。
但功夫不负有心人,终于我在 StackOverflow 翻到一个答案,那就是使用 AnimationBuilder,简而言之就是它允许你手动为元素构建一个动画,官方 demo 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// import the service from BrowserAnimationsModule
import { AnimationBuilder } from '@angular/animations'
// require the service as a dependency
class MyCmp {
constructor(private _builder: AnimationBuilder) {}

makeAnimation(element: any) {
// first define a reusable animation
const myAnimation = this._builder.build([
style({ width: 0 }),
animate(1000, style({ width: '100px' })),
])

// use the returned factory object to create a player
const player = myAnimation.create(element)

player.play()
}
}

🎉 最终效果

https://stackblitz.com/edit/ngx-popup-demo

最终封装后的组件已发布到 npm,有需要的可以看看,没准开发时可以帮你节省不少时间呢。

结束语

作为前端真的很有必要封装一个 Popup 组件,Vue 也好,React 也好,Angular 也好。很多常见弹层效果都可以依赖它进行二次封装,Toast 组件可以用它,Modal 组件可以用它,Notify 组件可以用它,Drawer 组件可以用它,各种底部弹出的 Picker 组件也可以用它,性价比实在是太高了。。🐮🍺