質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

1回答

1234閲覧

Angularでページごとに色が変わるヘッダーを作りたい

sunny_day

総合スコア1

Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2020/08/20 00:45

前提・実現したいこと

AngularでWEBサイトを製作しており、スクロールすると色が変わるヘッダーメニューを作りました。
ページトップでは透明で、スクロールするとfixedクラスが付与されて黒になるというものです。
しかし、トップ(home)ページ以外のページ(今回のcontactページ)ではスクロール関係無しに常に黒いヘッダーにしたいです。

イメージ説明

発生している問題

「ページ遷移後、URLがcontactであれば、not-homeクラスを付けて背景色を黒にする」というイメージで書きました。
確かにこれで遷移直後はnot-homeクラスが付いているのですが、スクロールするとnot-homeが消えてしまい、onWindowScrollの処理が優先されます。
そのため、ページトップまでスクロールするとfixedクラスも消え、透明なヘッダーになります。

トップページでは背景が動画のため、下へスクロールするまでは背景透明の白文字ヘッダーで良いのですが、トップ以外のページでは背景が白なので、ヘッダーが黒でないと文字が見辛く、その問題を解決したいです。

該当のソースコード

html

1 <!-- header.component.html --> 2<nav class="float-menu {{navbarStyle}}"> 3 <div class="head-wrap"> 4 <div class="pc-menu"> 5 <div class="ui secondary menu"> 6 <a class="item" href="#"> 7 <span class="color:white;">Logo</span> 8 </a> 9 <div class="right menu"> 10 <!-- #aboutはhomeページのアンカーリンク --> 11 <a href="#about">はじめに</a> 12 <a routerLink="/contact">お問合せ</a> 13 </div> 14 </div> 15 </div> 16 </div> 17</nav>

css

1// header.component.css 2.float-menu { 3 position: fixed; 4 top: 0; 5 width: 100%; 6 margin: 0 auto; 7 z-index: 10; 8 transition: all 0.5s ease; 9} 10 11.float-menu.fixed { 12 background: rgba(0,0,0,.6); 13} 14 15.float-menu.not-home { 16 background: rgba(0,0,0,.6); 17}

ts

1// header.component.ts 2import { Component, OnInit, HostListener } from '@angular/core'; 3import { Router, NavigationEnd, Event as NavigationEvent } from '@angular/router'; 4import { Constant } from '../constant'; 5 6@Component({ 7 selector: 'app-header', 8 templateUrl: './header.component.html', 9 styleUrls: ['./header.component.css'] 10}) 11export class HeaderComponent implements OnInit { 12 public navbarStyle = 'hidden'; 13 14 constructor( 15 private router: Router 16 ) { } 17 18 ngOnInit() { 19 this.router.events.forEach((event: NavigationEvent) => { 20 // ページ遷移後の処理 21 if (event instanceof NavigationEnd) { 22 if (event.urlAfterRedirects.indexOf(Constant.rpContact) >= 0) { 23 this.navbarStyle = 'not-home'; 24 } 25 } 26 }); 27 } 28 29 @HostListener('window:scroll', []) 30 onWindowScroll() { 31 if (window.pageYOffset > 20) { 32 this.navbarStyle = 'fixed'; 33 } else { 34 this.navbarStyle = ''; 35 } 36 } 37}

ts

1// constant.ts 2export class Constant { 3 //ルーティングパス 4 static readonly rpHome = ''; 5 static readonly rpContact = 'contact'; 6}

ts

1// app-routing.module.ts 2import { RouterModule, Routes } from '@angular/router'; 3import { NgModule } from '@angular/core'; 4import { HomeComponent } from './home/home.component'; 5import { ContactComponent } from './contact/contact.component'; 6 7const routes: Routes = [ 8 { path: '', component: HomeComponent }, 9 { path: 'contact', component: ContactComponent } 10]; 11@NgModule({ 12 imports: [ 13 RouterModule.forRoot(routes, { 14 scrollPositionRestoration: 'enabled', 15 anchorScrolling: 'enabled', 16 scrollOffset: [0, 0] 17 }) 18 ], 19 exports: [RouterModule], 20 providers: [] 21}) 22export class AppRoutingModule {}

開発環境

Angular CLI: 10.0.6 Node: 12.18.3 OS: darwin x64 Angular: 10.0.10 ... animations, common, compiler, compiler-cli, core, forms ... language-service, platform-browser, platform-browser-dynamic ... router Ivy Workspace: Yes Package Version ----------------------------------------------------------- @angular-devkit/architect 0.1000.6 @angular-devkit/build-angular 0.1000.6 @angular-devkit/build-optimizer 0.1000.6 @angular-devkit/build-webpack 0.1000.6 @angular-devkit/core 10.0.6 @angular-devkit/schematics 10.0.6 @angular/cdk 10.1.3 @angular/cli 10.0.6 @angular/material 10.1.3 @ngtools/webpack 10.0.6 @schematics/angular 10.0.6 @schematics/update 0.1000.6 rxjs 6.6.2 typescript 3.9.7 webpack 4.43.0

見様見真似で書いたコードで分かりづらく申し訳ありません。
また、初めて質問するので至らない点も多々あるかと思います。
どなたかAngularやTypeScriptの書き方に詳しい方、お知恵をお貸し下さい。
よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

onWindowScrollの処理が優先されます。

優先というか、
ngOnInitの処理は遷移後最初しか行われません。
対して、@HostListener('window:scroll', [])の処理は、
スクロールの度に処理が実行されるので、そちらの処理が有効になるのは当然の話です。

コメントを受けまして、考え方と、例示をします。
homeかどうかを、クラスプロパティとして、保持し、それをもって、
スクロール20px以内時のクラス名を動的に変更とすればいいかと。
下記構文でいかがでしょうか。

typescript

1// 上部構文は省略 2 3export class HeaderComponent implements OnInit { 4 public navbarStyle = 'hidden'; 5 // ホームかどうかをbooleanで保持するためのプロパティ 6 private homeFlg = true; 7 8 constructor( 9 private router: Router 10 ) { } 11 12 ngOnInit() { 13 this.router.events.forEach((event: NavigationEvent) => { 14 // ページ遷移後の処理 15 if (event instanceof NavigationEnd) { 16 if (event.urlAfterRedirects.includes(Constant.rpContact)) { 17 this.navbarStyle = 'not-home'; 18 this.homeFlg = false; 19 } else { 20 this.homeFlg = true; 21 } 22 } 23 }); 24 } 25 26 @HostListener('window:scroll', []) 27 onWindowScroll() { 28 if (window.pageYOffset > 20) { 29 this.navbarStyle = 'fixed'; 30 } else { 31 this.navbarStyle = this.homeFlg ? '' : 'not-home'; 32 } 33 } 34}

つまりは、homeかどうかを保持しておき、その真偽によって、当てるクラス文字列を変える、という感じです。
あとは、もし条件を増やしたいとなれば、
ngOnInitメソッド中にて、switch構文によって、条件を入れ替えたり、すればいいかと。

---- 以下元構文回答 ----

onWindowScrollの処理中の、
this.navbarStyle = '';
this.navbarStyle = 'not-home';にすればいいのではないでしょうか?

投稿2020/08/20 00:58

編集2020/08/20 01:56
miyabi_takatsuk

総合スコア9528

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sunny_day

2020/08/20 01:33

こんなに早く回答して頂きありがとうございます! まだまだ理解が乏しいので、大変ためになります。 onWindowScrollの処理では、スクロールが20未満の時に「this.navbarStyle = '';」とすることでクラスを付けず、透明なヘッダーにしています。 その為、そこにnot-homeを入れると全ページで反映されるので『ページごとに色を変える』という目的から離れてしまいます。 言い方を変えると、URLがhomeページで、スクロール位置が20未満の時だけヘッダーを透明に出来れば良いのですが、難しいですかね…。
miyabi_takatsuk

2020/08/20 01:44

あ、なるほどですね。 つまり、本質問のコンポーネントは、全ページで読み込んでいるコンポーネント、ということですね? 回答修正してみます。
sunny_day

2020/08/20 01:49

はい、そうです。 ヘッダーコンポーネントは全ページ共通で読み込んでいます。 お手数おかけします。ありがとうございます!
miyabi_takatsuk

2020/08/20 01:58

回答追記しました。 もし、条件など食い違うのならば、 考え方のみ参考にし、自身で条件などを組み直してください。 また、文字列の存在有無の確認は、 includesの方がより簡単に確認できます。 (JS上での割と新しめのメソッドですが、TypeScriptでもあります)
sunny_day

2020/08/20 02:34

丁寧な回答ありがとうございます。 ご提示頂いた考え方で条件を変えるのもうまくいきました。 3日間悩んでいたので、ここまで詳しく教えて頂けて大変感謝しております!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問