[從 0 開始的 Angular 生活]No.55 如何調整 Bootstrap4 的 NavBar 使其增強使用者體驗

前言

這篇主要記錄自己在寫玩具 (side project) 時遇到的小問題,也是蠻常見的需求。

我習慣開發時使用 Bootstrap4 ,而在 Bootstrap4 中有提供 NavBar 的元件供開發者快速套版,亦有相關的 ClassName 可供使用,那麼該如何進一步的提升使用者體驗呢 (UX)?

本文環境

  • Angular CLI: 8.3.20
  • Angular: 8.2.14
  • Bootstrap: 4.3.1

實作

常常看到某些網站的 NavBar 在使用者往下捲動 ScrollBar 時, NavBar 會往上隱藏;反之,當往上捲動時則顯示。

那麼該如何調整 Angular & Bootstrap 來達成我們的需求呢?

Bootstrap

需要進行 HTML & CSS 的調整,程式碼如:

navbar.component.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<header class="sticky-top" [ngClass]="{'hidden': isNavBarHidden}">
<nav class="navbar navbar-expand-md navbar-dark bg-main">
<a routerLink="/dashboard" class="navbar-brand">
<i class="fas fa-home fa-fw mr-1"></i>
<h1 class="h5 mb-0 d-inline-block">ipsum dolor.</h1>
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a routerLink="products" class="nav-link" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: false }">
<i class="fas fa-list fa-fw mr-1"></i>產品列表
</a>
</li>
<li class="nav-item">
<a routerLink="orders" class="nav-link" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: false }">
<i class="fas fa-list fa-fw mr-1"></i>訂單列表
</a>
</li>
</ul>
<a href="#" class="nav-link logout" id="logout">
<i class="fas fa-sign-out-alt fa-fw mr-1"></i>登出
</a>
</div>
</nav>
</header>

navbar.component.scss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
.navbar-toggler {
transition: all .3s;
&:focus{
outline: 0px;
}
&:hover{
border: 1px solid rgba(255,255,255,0.5);
}
}

.logout {
color: rgba(255,255,255,.5);
padding-left: 0;
padding-right: 0;
&:hover{
color: rgba(255,255,255,.75);
}
}

.sticky-top {
transition: transform .3s;
&.hidden {
transform: translateY(-100%);
}
}

透過調整 .sticky-top 並且當 ClassName 內同時具有 sticky-tophidden 時透過 transform 隱藏 NavBar 。

Angular

接著需要針對 scroll 進行監聽

navbar.component.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import { Component, OnInit, OnDestroy } from '@angular/core';

@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit, OnDestroy {
constructor() { }

private last_known_scroll_position = 0;
private ticking = false;
private _isNavBarHidden = false;
private scrollBarListener: () => void;

ngOnInit() {
this.addScrollBarListener();
}

ngOnDestroy(): void {
this.removeScrollBarListener();
}

private removeScrollBarListener(): void {
window.removeEventListener('scroll', this.scrollBarListener);
}

private getWindowScrollY(): void {
if (!this.ticking) {
window.requestAnimationFrame(() => this.navBarDisplay());
}
this.ticking = true;
}

private navBarDisplay(): void {
if (this.last_known_scroll_position < window.scrollY) {
this._isNavBarHidden = true;
}
if (this.last_known_scroll_position >= window.scrollY) {
this._isNavBarHidden = false;
}
this.ticking = false;
this.last_known_scroll_position = window.scrollY;
}

public get isNavBarHidden(): boolean {
return this._isNavBarHidden;
}

}

說明:

  • 監聽 scroll 滾動事件
  • ngOnDestroy 時將監聽卸掉
  • 由於 scroll 滾動事件觸發的非常頻繁,需要加上額外的措施
  • 關於 requestAnimationFrame 的補充
  • 使用一個屬性來記錄最後 scrollY 的位置,如 last_known_scroll_position
    • 這樣才有辦法比較當前的 window.scrollYlast_known_scroll_position 是往上捲還是往下捲
    • 先比較,最後才更新 last_known_scroll_position 的值
  • 根據捲動的方向給予對應的 ClassName

成果展示

結論

因為還沒這個玩具還沒完成,暫時還不想公開,所以就不附上完整的 code 了。

不過這個範例還蠻簡單的,我想應該貼上片段就足夠了 (?)

這樣就達成強化 NavBar UX 的目的了:

  • 往下捲可能代表使用者想看畫面的內容,所以隱藏 NavBar
  • 往上捲可能代表使用者在找 NavBar ,所以顯示

如果不想只單純的使用 sticky-top 不妨嘗試這樣的方式,讓網站更加活潑哦~

0%