在Angular中为Tailwind中的汉堡包菜单制作动画



我在Angular应用程序中使用Tailwind UI,可以使用以下命令打开/关闭汉堡包菜单

<header>
<div class="-mr-2 -my-2 md:hidden">
<button type="button" (click)="toggleMobileMenu()"
class="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"
aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<div class="absolute z-30 top-0 inset-x-0 p-2 transition transform origin-top-right md:hidden" *ngIf="mobileMenuOpen">
<div class="rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 bg-white divide-y-2 divide-gray-50">
<div class="flex items-center justify-between">
<button (click)="toggleMobileMenu()" type="button"
class="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"
aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="py-6 px-5">
<div class="grid gap-4">
<a routerLink="/" class="text-base font-medium text-gray-900 hover:text-gray-700">
Home
</a>
</div>
</div>
</div>
</div>
</header>

toggleMobileMenu() {
this.mobileMenuOpen = !this.mobileMenuOpen;
}

这是一个非常简单的例子。

如何使其动画化?

说明如下:

Mobile menu, show/hide based on mobile menu state.
Entering: "duration-200 ease-out"
From: "opacity-0 scale-95"
To: "opacity-100 scale-100"
Leaving: "duration-100 ease-in"
From: "opacity-100 scale-100"
To: "opacity-0 scale-95"

我不知道怎么把它转换成角度动画

我将遵循以下方法:

  1. 确保导入BrowserAnimationsModule
@NgModule({
imports: [ BrowserModule, BrowserAnimationsModule, ... ],
...
})
  1. @Component装饰器下创建animations数组如下
@Component({
,,,,
animations: [
trigger("openClose", [
// ...
state(
"open",
style({
opacity: 1,
transform: "scale(1, 1)"
})
),
state(
"closed",
style({
opacity: 0,
transform: "scale(0.95, 0.95)"
})
),
transition("open => closed", [animate("100ms ease-in")]),
transition("closed => open", [animate("200ms ease-out")])
])
]
})

在我们下面包含的动画数组中

  • trigger("openClose", [ ...]),它定义了触发器的名称。这将在HTML模板中用于绑定到dom元素

  • 使用state('stateName'定义2个状态在我们上面的例子中,状态名称是openclosed

  • 在state下,我们使用style({ ... })

    定义样式
  • 我们最终使用transition(...)定义过渡。这将定义时间和动画风格

更多关于动画的介绍

  1. 为状态定义getter
get openCloseTrigger() {
return this.mobileMenuOpen ? "open" : "closed";
}
  1. 在HTML中绑定getter的状态
<div [@openClose]="openCloseTrigger" ...> 
<!-- Other stuff here -->
</div>

一切都应该准备好了,你的菜单应该像你想要的那样动画

看到这个演示在stackblitz

关闭浏览器导航我们可以利用NavigationEnd事件来实现这个功能。当用户在一个特定的页面上时,他们不会离开这个页面,因此没有NavigationEnd。菜单将保持打开,但当他们导航到另一个页面时,NavigationEnd事件将被调用,菜单将关闭

这是方法

constructor(private router: Router) {}
navigationEnd$ = this.router.events.pipe(
filter(event => event instanceof NavigationEnd),
tap(() => (this.mobileMenuOpen = false))
);
ngOnInit() {
this.navigationEnd$.subscribe();
}

查看这个功能在stackblitz

这是一种只使用顺风类制作动画的方法。这是一个stackblitz演示

下面是一个简短的解释。

最初对于移动菜单div,我们设置了顺风类,使div处于隐藏状态。为了达到这个目的,我们使用了。

scale-95,opacity-0,我们还使用pointer-events-none来避免隐藏状态下的交互。

,当菜单处于活动状态时,我们添加以下类:

scale-100,opacity-100,pointer-events-auto.

和动画这些属性,我们使用transition类的divduration-200类的过渡时间。

<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">
<header>
<div class="-mr-2 -my-2 md:hidden">
<button type="button" (click)="toggleMobileMenu()"
class="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"
aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<!-- here we have added transition transform scale-95 opacity-0 duration-200 pointer-events-none -->
<div class="absolute z-30 top-0 inset-x-0 p-2 transition transform scale-95 opacity-0 duration-200 pointer-events-none md:hidden"
[ngClass]="{'scale-100 pointer-events-auto opacity-100': mobileMenuOpen}">
<!-- then toggle classes scale-100 opacity-100 and pointer-events-auto -->
<div class="rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 bg-white divide-y-2 divide-gray-50">
<div class="flex items-center justify-between">
<button (click)="toggleMobileMenu()" type="button"
class="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"
aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="py-6 px-5">
<div class="grid gap-4">
<a routerLink="/" (click)="toggleMobileMenu()" class="text-base font-medium text-gray-900 hover:text-gray-700">
Home
</a>
</div>
</div>
</div>
</div>
</header> 

所以,只要使用正确的顺风类,你就可以达到动画效果。

这个帖子真的帮我指明了正确的方向。使用Angular 14 &以下是我最终成功的方法。

我需要呈现一个通知来显示来自http请求的响应。我已经创建了一个我订阅的NotificationService,它处理show (emit)。我发现这个线程(s)是超级有帮助的完成。

// app.component.ts
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [],
animations: [
trigger('renderNotification', [
transition(':enter', [
style({
transform: 'translateY(0.5rem)',
opacity: 0,
}),
animate(
'150ms 0ms ease-out',
style({
transform: 'translateY(0)',
opacity: 1,
})
),
]),
transition(':leave', [
style({
transform: 'translateY(0)',
opacity: 1,
}),
animate(
'100ms 0ms ease-in',
style({
transform: 'translateX(0.5rem)',
opacity: 0,
})
),
]),
]),
],
})
export class AppComponent implements OnInit {
showNotification: boolean = false;
...
}
<!-- app.component.html -->
<div class="flex h-full">
<div
aria-live="assertive"
class="pointer-events-none fixed inset-0 z-50 flex items-end px-4 py-6 sm:items-start sm:p-6"
>
<div class="flex w-full flex-col items-center space-y-4 sm:items-end">
<app-notifications
class=""
[@renderNotification]="notification.show"
*ngIf="showNotification"
[type]="notification.type"
[title]="notification.title"
[body]="notification.body"
(closeNotificationEvent)="closeNotification()"
></app-notifications>
</div>
</div>
...
<div class="flex min-w-0 flex-1 flex-col overflow-hidden">
<router-outlet></router-outlet>
</div>
</div>

希望这对其他人有帮助!

最新更新