LoginSignup
12
5

More than 5 years have passed since last update.

Angularで下にスクロールすると消えて、上にスクロールすると現れるヘッダー

Posted at

FacebookのSPアプリとかのあれをAngularで実現します。
jQuery、Angular1.x系ではHeadroom.jsというライブラリで実現できるらしのですが、
残念ながらAngular2/4系には対応していなかったので、別の方法で実装することにしました。

実現したいのはこの動き↓
Headroom.js Demo

参考

jQueryで実装している方がいたので、これを参考にしました。大変参考になりました。
http://weboook.blog22.fc2.com/blog-entry-412.html

Windowイベントを取得するために HostListener を使いました。
http://blog.yuhiisk.com/archive/2016/05/12/angular2-window-event.html

DOMアクセスには DOCUMENT を使いました。
https://angular.io/api/platform-browser/DOCUMENT

やったこと

まずは、ベースとなるAngularプロジェクトを作成します。
今回はangular-cliでベースのプロジェクトを作成しました。

ng new angular-hide-header-sample

ベースにしたプロジェクト

src
├── src/app
│   ├── src/app/app.component.css
│   ├── src/app/app.component.html
│   ├── src/app/app.component.spec.ts
│   ├── src/app/app.component.ts
│   └── src/app/app.module.ts
├── src/assets
├── src/environments
│   ├── src/environments/environment.prod.ts
│   └── src/environments/environment.ts
├── src/favicon.ico
├── src/index.html
├── src/main.ts
├── src/polyfills.ts
├── src/styles.css
├── src/test.ts
├── src/tsconfig.app.json
├── src/tsconfig.spec.json
└── src/typings.d.ts

ヘッダーコンポーネント作成

angular-cliで作成したプロジェクトにヘッダーコンポーネントを追加します。

ng g component header
header.component.html
<nav class="header">
  <!-- 実際にはここにmenuを実装 -->
  <p>header</p>
</nav>
header.component.css
.header {
  position: fixed;
  z-index: 99;
  top: 0;
  left: 0;
  width: 100%;
  height: 60px;
  background: rgba(0,0,0,.5);
  transition: .5s;
}

ヘッダーコンポーネントをapp.componentに追加

angular-cliで作成した際に作成されるtopページにそのまま追記しました。

app.component.html
<app-header></app-header>
<!--The content below is only a placeholder and can be replaced.-->
<!-- ...略 -->

この時点で、npm startを実行しブラウザからlocalhost:4200を確認すると、次のように表示されているはずです。 この時点では、hederは最上部に固定されたままですが、このあと更に修正していきます。

スクリーンショット 2017-08-18 22.34.02.png

ヘッダーコンポーネントを修正

実際に表示を切り替えるロジックを実装していきます。

ヘッダーの位置を動的に変更するために、[style.top.px]でコンポーネントからcssの値を設定できるようにします。

header.component.html
<nav class="header" [style.top.px]="headerPos">
  <p>header</p>
  <!-- 実際にはここにmenuを実装 -->
</nav>

Inject HostListener DOCUMENTをそれぞれインポート
クラスのメンバー変数のうち、ofsetにはヘッダーの高さを指定します。

header.component.ts
import { Component, OnInit, Inject, HostListener } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
  private ofset: number = 60;
  private startPos: number = 0;
  private headerPos: number = 0;


  constructor(@Inject(DOCUMENT) private document: Document) { }
  ngOnInit() {
  }

  @HostListener('window:scroll', ['$event'])
  onScroll(event) {
    let currentPos = this.document.body.scrollTop;
    if(currentPos > this.startPos) {
      if(this.document.body.scrollTop >= this.ofset) {
        this.headerPos = -this.ofset;
      }
    } else {
      this.headerPos = 0;
    }
    this.startPos = currentPos;
  }

}

完成

次のような感じで、それっぽく動きます。

8月-18-2017 23-05-42.gif

サンプル

今回作成した、サンプルプロジェクトはGitHubに置きました。

12
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
5