今天,我們將進一步增強【Day - 22】的文法檢查功能。當檢測到文法錯誤時,3D動畫機器人頭上將出現一個帶有驚歎號的按鈕作為提示。使用者若想進一步瞭解詳情,只需點擊此按鈕,就能看到文法錯誤的完整解析。為了達到這個效果,今天我們將會使用Sheet Modal來實現。那麼開始實作吧!
首先建立一個GrammerMistake元件。在grammermistake.component.ts
中,注入Status Service並訂閱【Day - 22】已準備好的grammerStatus$
。當文法有誤被偵測到時,就可以利用這個訂閱來控制GrammerMistake元件的顯示狀態:
constructor(private statusService: StatusService) { }
get grammerStatus$(): Observable<GrammerDataModel> {
return this.statusService.grammerStatus$;
}
在grammermistake.component.html
中,直接訂閱grammerStatus$
:
<div class=" flex flex-row justify-center items-center w-16 h-16">
<div *ngIf="(grammerStatus$ | async)?.hasGrammerMistake">
<div
class="ball-animation border-2 border-white-300 bg-amber-400 z-10 rounded-full p-1 w-full h-full flex justify-center items-center">
<ion-icon class="text-white text-4xl" name="bulb-outline"></ion-icon>
</div>
</div>
</div>
其中ball-animation類別提供了一個彈跳效果的CSS動畫:
.ball-animation {
animation: bounce 2s infinite;
}
@keyframes bounce {
0%,
20%,
50%,
80%,
100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
為了提升使用者體驗,我在ngIf
中應用了Angular Animation,讓元件以淡入淡出的方式呈現,避免突然的顯示或消失:
@Component({
selector: 'app-grammermistake',
standalone: true,
imports: [
CommonModule,
IonicModule
],
templateUrl: './grammermistake.component.html',
styleUrls: ['./grammermistake.component.scss'],
animations: [
trigger('fadeInOut', [
state('void', style({ opacity: 0 })),
transition('void <=> *', animate(400)),
]),
]
})
<div class=" flex flex-row justify-center items-center w-16 h-16">
<div *ngIf="(grammerStatus$ | async)?.hasGrammerMistake" [@fadeInOut]>
<div
class="ball-animation border-2 border-white-300 bg-amber-400 z-10 rounded-full p-1 w-full h-full flex justify-center items-center">
<ion-icon class="text-white text-4xl" name="bulb-outline"></ion-icon>
</div>
</div>
</div>
當需要在Angular中使用動畫,要確保在main.ts
檔案中,使用importProvidersFrom(BrowserAnimationsModule)
或Angular 14.1開始可以使用的provideAnimations()
:
bootstrapApplication(AppComponent, {
providers: [
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
importProvidersFrom(IonicModule.forRoot({})),
provideRouter(routes),
//importProvidersFrom(HttpClientModule),
//Since Angular 15
provideHttpClient(),
// importProvidersFrom(BrowserAnimationsModule),
//Since Angular 14.1
provideAnimations(),
],
});
最終,在Home主頁加入了這個元件,文法錯誤的提示按鈕就順利建立完畢:
<div class="w-full h-full bg-white">
<div class="flex flex-col w-full h-full">
<div class="flex-none flex justify-center items-center pt-20">
<!-- 文法提示 -->
<app-grammermistake></app-grammermistake>
</div>
<div class="relative flex flex-col w-full h-full">
<!-- 3D機器人動畫 -->
<app-robot3d class="flex-grow flex-shrink w-full pb-20"></app-robot3d>
</div>
<div class="flex-none flex flex-row justify-between items-center pb-10 relative">
<div class="flex-grow">
<!-- 重播按鈕 -->
<app-replayaudio></app-replayaudio>
</div>
<div class="flex-grow">
<!-- 錄音按鈕 -->
<app-voicerecording (getRecordingBase64Text)="OnGetRecordingBase64Text($event)"></app-voicerecording>
</div>
<div class="flex-grow">
<div class="w-14"></div>
</div>
</div>
</div>
</div>
Modal是一個會出現在APP內容頂部的對話框元件,使用者必須先關閉它才能繼續其他交互操作。Modal適用於多種場景,包括「展示消息」、「蒐集使用者輸入」或「提供額外的資訊」等。另外,Sheet Modal是Ionic 6所推出的全新模式,它在移動端應用程式中叫「Bottom Sheet」。這種設計在「Instagram」、「Youtube」、「Google Map」等知名APP中都可以看到其應用。
在GrammerMistake元件的grammermistake.component.html
中,我加入了IonModal
元件。要啟用Sheet Modal,必須設定initialBreakpoint
和breakpoints
兩個屬性,缺一不可:
<ion-modal #modal [initialBreakpoint]="0.6" [breakpoints]="[0, 0.6, 1]">
<ng-template>
<ion-header>
<ion-toolbar>
<ion-title>AI文法解析</ion-title>
<ion-buttons slot="end">
<ion-button (click)="modal.dismiss()">
<ion-icon slot="icon-only" name="close-outline"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<div class="flex flex-col p-4">
<div class="mb-2"><span class="bg-rose-400 text-white font-bold rounded-2xl px-2 py-1">錯誤句型:</span></div>
<div class="mb-6 underline pl-2 text-gray-600">{{ (grammerStatus$ | async)?.mistakeSentence }}</div>
<div class="mb-2"><span class="bg-lime-500 text-white font-bold rounded-2xl px-2 py-1">錯誤解析:</span></div>
<div class="pl-2 align-baseline">
<p class="text-gray-800"></p>
</div>
</div>
</ion-content>
</ng-template>
</ion-modal>
另外,Sheet Modal也有以下常見事件:
當點擊提示按鈕時,利用範本參考變數直接調用modal.present()
方法以開啟Sheet Modal:
<div class=" flex flex-row justify-center items-center w-16 h-16">
<div *ngIf="(grammerStatus$ | async)?.hasGrammerMistake" (click)="modal.present()" [@fadeInOut]>
<div
class="ball-animation border-2 border-white-300 bg-amber-400 z-10 rounded-full p-1 w-full h-full flex justify-center items-center">
<ion-icon class="text-white text-4xl" name="bulb-outline"></ion-icon>
</div>
</div>
</div>
Bottom Sheet的設計在許多知名的應用中都能見到,其實用性和直觀性讓使用者體驗更加順暢。Ionic所提供的Modal元件,不僅能讓我們快速的建置和實現Bottom Sheet功能,還具有其他多樣化的設定。例如,Modal可以設定不同的動畫效果、大小和位置,且可完全自訂其內容和樣式,讓開發者能夠根據特定的需求和場景進行更靈活的設計和實作。
Github專案程式碼:Ionic結合ChatGPT - Day23