JavaScript12(サイト作成(4))

1:ヘッダーやサイドバーを作成しベースを完成させる

モバイルメニューのところで作成したstyle.scssを流用する

_mobile-menu.scssにリネームしてmodulesに貼り付けする

style.scssで読み込むのも忘れずに

_mobile-menu.scssに以下の記述を追加

$cMenuClose: Black;
$cMenuOpen: Black;

.mobile-menu {
  position: fixed;
  right: 0;
// 上から60px
  top: 60px;
  width: 300px;

  & .logo {
    padding: 0 40px;
    font-size: 38px;
}
// BEM(Block Element Modifier)
  &__btn {
    background-color: unset;
    border: none;
    outline: none !important;
    cursor: pointer;
 
    & > span {
      background-color: $cMenuClose;
      width: 35px;
      height: 2px;
      display: block;
      margin-bottom: 9px;
      transition: transform 0.7s;
 
    &:last-child {
      margin-bottom: 0;
  }
 }
}
// 黒い膜をつける
    &__cover {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.3);
      opacity: 0;
      visibility: hidden; 
      transition: opacity 1s;
      cursor: pointer;
      z-index: 200;
 }
  &__main {
    padding: 0;
// 3Dアニメーションをしたいとき親の要素につける
    perspective: 2000px;
    transform-style: preserve-3d;
}
  &__item {
// ・をけす
    list-style: none;
    display: block;
    transform: translate3d(0, 0, -1000px);
    padding: 0 40px;
    transition: transform 0.3s, opacity 0.2s;
    opacity: 0;
}
  &__link {
// 左右いっぱいに広がるようにする
    display: block;
    margin-top: 30px;
    color: $cBlack;
// 下線を削除
   text-decoration: none !important;
  }
}

.menu-open {
// クリックしたときに左下にずれるアニメーションの設定
  & #container {
    transform: translate(-300px, 60px);
    box-shadow: 0 8px 40px -10px rgba(0, 0, 0, 0.8);
}
 // クリックされたときの記述を書く
  & .mobile-menu {
  &__cover {
    opacity: 1;
    visibility: visible;
}
  &__item {
    transform: none;
    opacity: 1;
// 要素を少しずつ遅延して表示
@for $i from 1 through 5 {
&:nth-child(#{$i}) {
transition-delay: $i * 0.07s;
  }
 }
}
  &__btn {
    & > span {
      background-color: $cMenuOpen;
 
  &:nth-child(1) {
    transition-delay: 70ms;
    transform: translateY(11px) rotate(135deg);
}
  &:nth-child(2) {
    transition-delay: 0s;
    transform: translateX(-18px) scaleX(0);
}
  &:nth-child(3) {
    transition-delay: 140ms;
    transform: translateY(-11px) rotate(-135deg);
    }
   }
  }
 }
}

ここでスマホ画面のアニメーションやスタイルの設定をしている

index.htmlに以下の記述を追加(<body>から)してヘッダーとサイドバー追加

<body>
  <div id="global-container">
   <div id="container">
    <div class="mobile-menu__cover"></div>
<!-- スクロール監視のためのタグ-->
     <div class="nav-trigger"></div>
<!-- ここからヘッダー-->
<header class="header">
  <div class="header__inner">
   <div class="logo item">
    <img src="images/logo.svg" alt="" class="logo__img" />
     <span class="logo__Flower">Flower</span>
     <span class="logo__Garden"> Garden
 </div>
<nav class="header__nav">
 <ul class="header__ul">
  <li class="header__li item"><a href="#">Service</a></li>
  <li class="header__li item"><a href="#">Company</a></li>
  <li class="header__li item">
    <a class="btn filled" href="#">Contact</a>
  </li>
 </ul>
</nav>
<!-- ハンバーガーメニュー-->
  <button class="mobile-menu__btn">
   <span></span>
   <span></span>
   <span></span>
  </button>
 </div>
</header>
<!-- ヘッダー終わり-->
 <div id="content">
<!-- ヒーロスライダーここから-->
  <div class="hero">
   <div class="swiper-container">
    <div class="swiper-wrapper">
<!-- スライドの部分 -->
 <div class="swiper-slide">
   <!-- 画像の真ん中の文字 -->
    <div class="hero__title">Magnificence</div>
     <image src="images/Dahlia.jpg" alt=""></image>
 </div>
   <div class="swiper-slide">
    <div class="hero__title">Solidarity</div>
     <image src="images/Gaillardia.jpg" alt=""></image>
 </div>
 <div class="swiper-slide">
  <div class="hero__title">Gentility</div>
    <image src="images/Geranium.jpg" alt=""></image>
  </div>
 </div>
   <div class="hero__footer">
 <!-- ↓矢印の部分 -->
    <img class="hero__downarrow" src="images/arrow.svg" />
     <span class="hero__scrolltext">scroll</span>
  </div>
 </div>
</div>
 <div id="main-content">
<!-- サイドバーの左部分-->
  <aside class="side left">
    <div class="side__inner">
     <a class="twitter icon tween-animate-title" href="#">Twitter</a>
     <a class="fb icon tween-animate-title" href="#">Facebook</a>
 </div>
</aside>
<main>
<!--Worldの始まり -->
 <section class="world">
   <div class="world__inner">
    <div class="world__img cover-slide">
     <img class="img-zoom" src="images/Rose-banquet3.jpg" alt=""/>
 </div>
 <div class="world__texts appear left">
  <div class="world__texts-inner">
<!--横線の設定 -->
   <div class="world__title main-title item">
    <span class="purple">Flower </span>
     <span>of the World</span>
</div>
<div class="world__sub sub-title item">世界のお花をあなたに</div>
 <div class="world__description item">
  <p>世界150ヶ国の花を<br />あなたにお届けします。</p>
  <p>あなたの望む花がきっと見つかります。</p>
   </div>
    <div class="world__btn item">
     <button class="btn filled">もっと詳しく</button>
    </div>
   </div>
  </div>
 </div>
</section>
<!--world終り -->
<!--flowersここから -->
<section class="flowers">
 <div>
 <h2 class="main-title tween-animate-title">Pick up</h2>
  <p class="sub-title tween-animate-title">日本のお花ピックアップ特集</p>
 </div>
 <div class="flowers__inner">
  <div class="flowers__item">
   <div class="cover-slide hover-darken">
    <div class="bg-img-zoom img-bg50" style="background-image: url(images/Alstroemeria.jpg)">
  </div>
  </div>
   <p class="flowers__title">旬の花</p>
   <p class="sub-title tween-animate-title">4月の旬の花はアルストロメリア</p>
  </div>
 <div class="flowers__item">
 <div class="cover-slide hover-darken">
  <div class="bg-img-zoom img-bg50" style="background-image: url(images/Birthday2.jpg)">
  </div>
   </div>
    <p class="flowers__title">誕生日プレゼント特集</p>
    <p class="sub-title tween-animate-title">大切なあの人に贈るプレゼント</p>
   </div>
    <div class="flowers__item">
     <div class="cover-slide hover-darken">
   <div class="bg-img-zoom img-bg50" style="background-image: url(images/Rose-banquet.jpg)">
   </div>
  </div>
   <p class="flowers__title">バラ特集</p>
   <p class="sub-title tween-animate-title">華やかな花といえばバラ</p>
  </div>
   <div class="flowers__item">
    <div class="cover-slide hover-darken">
    <div class="bg-img-zoom img-bg50" style="background-image: url(images/peach.jpg)">
   </div>
  </div>
   <p class="flowers__title">春の花特集</p>
   <p class="sub-title tween-animate-title">春の花をピックアップ</p>
  </div>
   <button class="btn slide-bg">さらに詳しく</button>
  </section>
<!--ここからpopular -->
 <section class="popular">
  <div class="popular__header">
   <h2 class="main-title tween-animate-title">Popular Place</h2>
   <p class="sub-title tween-animate-title">人気の花畑観光地のツアー</p>
  </div>
<!-- グレーの背景の部分 -->
  <div class="popular__inner appear up">
  <div class="popular__container">
  <div class="popular__item item">
   <div class="popular__img">
    <img src="images/Georgia.jpg" alt="" />
   </div>
  <div class="popular__title">Georgia</div>
  </div>
<div class="popular__item item">
  <div class="popular__img">
   <img src="images/Montreal.jpg" alt="" />
  </div>
   <div class="popular__title">Montreal</div>
   </div>
  <div class="popular__item item">
  <div class="popular__img">
   <img src="images/Flowers3.jpg" alt="" />
  </div>
   <div class="popular__title">北海道</div>
   </div>
  <div class="popular__item item">
   <div class="popular__img">
    <img src="images/Shibazakura.jpg" alt="" />
   </div>
   <div class="popular__title">千葉</div>
   </div>
  <div class="popular__btn appear up">
   <button class="btn cover-3d item">
    <span>一覧から探す</span>
   </button>
    </div>
   </div>
  </div>
 </section>
<!--popularここまで -->
//サイドバー右の設定
 <aside class="side right">
   <div class="side__inner">
    <span class="tween-animate-title">©Ota</span>
   </div>
  </aside>
 </div>
</div>
//フッターの設定
<footer class="footer appear up">
 <div class="logo item">
  <img src="images/logo.svg" alt="" class="logo__img" />
   <span class="logo__Flower">Flower </span>
   <span class="logo__Garden"> Garden</span>
 </div>
 <nav class="footer__nav">
   <ul class="footer__ul">
    <li class="footer__li item"><a href="#">Service</a></li>
    <li class="footer__li item"><a href="#">Contact</a></li>
    <li class="footer__li item"><a href="#">Company</a></li>
    <li class="footer__li item"><a href="#">Sitemap</a></li>
   </ul>
    <div class="footer__copyright item">© Ota
   </div>
  </nav>
 </footer>
</div>
<!--モバイルメニューの設定-->
<nav class="mobile-menu">
  <div class="logo">
    <img src="images/logo.svg" alt="" class="logo__img" />
   <span class="logo__Flower ">Flower </span>
   <span class="logo__Garden">Garden</span>
  </div>
   <ul class="mobile-menu__main">
    <li class="mobile-menu__item">
     <a class="mobile-menu__link" href="#">
      <span class="main-title">Our Service</span>
      <span class="sub-title">サービスについて</span>
     </a>
    </li>
    <li class="mobile-menu__item">
     <a class="mobile-menu__link" href="#">
      <span class="main-title">About Us</span>
      <span class="sub-title">私たちについて</span>
     </a>
    </li>
    <li class="mobile-menu__item">
     <a class="mobile-menu__link" href="#">
      <span class="main-title">Contact Us</span>
      <span class="sub-title">コンタクト方法</span>
     </a>
    </li>
   </ul>
  </nav>
 </div>
</div>
  <script src="scripts/vendors/swiper.min.js"></script>
  <script src="scripts/vendors/TweenMax.min.js"></script>
  <script src="scripts/vendors/scroll-polyfill.js"></script>
  <script src="scripts/libs/scroll.js"></script>
  <script src="scripts/libs/text-animation.js"></script>
  <script src="scripts/libs/hero-slider.js"></script>
  <script src="scripts/libs/mobile-menu.js"></script>
  <script src="scripts/main.js"></script>
</body>
</html>

コメントでどこが何を担当しているか確認するとよい

_base.scssに以下の記述を追加

ヘッダーの部分

.header {
// 画面の上部に固定
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: $navHeight;
// 背景色を透明に
  background-color: transparent;
  display: flex;
  align-items: center;
// ヘッダーを最前面にくるようにする
  z-index: 100;

  &.triggered {
    background-color: rgba(255, 255, 255, 0.9);
    box-shadow: 10px 0 25px -10px rgba(0, 0, 0, 0.5);
}
// スマホ画面ではヘッダー表示しない
  &__nav {
    display: none;
}

  &__ul {
    display: flex;
// 上下中央揃えにする
    align-items: center;
    padding: 0;
    margin: 0;
    list-style: none;
}

  &__li {
    margin-left: 20px;

  & > a {
    color: $cBlack;
    text-decoration: none !important;
// すべて大文字にする
    text-transform: uppercase;
 }
}

  & .logo {
    font-size: 38px;
    justify-content: center;
}

  &__inner {
    display: flex;
    justify-content: space-between;
    align-items: center;
// navとコンテンツのラインを同じにする
    @extend .content-width;
 }
}

main.jsを以下の記述にする(完成版)

document.addEventListener('DOMContentLoaded', function () {
  // mainにMainを格納して呼び出す
  const main = new Main();
});
// 新しくメインクラスを作りそのなかにプライベートメソッドを格納
class Main {
  constructor() {
// headerやsideのDOMをクエリーセレクターで取得
  this.header = document.querySelector('.header');
  this.sides = document.querySelectorAll('.side');
// 配列にScrollObserverのインスタンスを格納する。変数_observersを初期化
  this._observers = [];
// _scrollInitを呼ぶ
  this._init();
}
// インスタンス化されたオブジェクトが配列に格納される(セッターメソッド)
  set observers(val) {
    this._observers.push(val);
}
// ゲッターメソッド(値を取得する方のメソッド)
  get observers() {
    return this._observers;
}

_init() {
  new MobileMenu();
  this.hero = new HeroSlider('.swiper-container');
  Pace.on('done', this._paceDone.bind(this));
}
// ロードが完了した段階でアニメーションするようにする
_paceDone() {
  this._scrollInit();
}

_inviewAnimation(el, inview) {
// もし画面内に入ってきたらinviewを付加
  if(inview) {
    el.classList.add('inview');
// 画面外になったらinviewを削除
  }else {
    el.classList.remove('inview');
 }
}
_navAnimation(el, inview) {
// 画面の中に入ったらtriggeredを削除
  if(inview) {
    this.header.classList.remove('triggered');
// 画面の外に出たらtriggeredを付与
  } else {
    this.header.classList.add('triggered');
 }
}

_sideAnimation(el, inview) {
  if(inview) {
    this.sides.forEach(side => side.classList.add('inview'));
  } else {
    this.sides.forEach(side => side.classList.remove('inview'));
 }
}
_textAnimation(el, inview) {
  if(inview) {
// tweenを使うときは書き換える(Tweenを追加)
    const ta = new TweenTextAnimation(el);
    ta.animate();
 }
}
_toggleSlideAnimation(el, inview) {
// 画面の中に入ったらヒーロースライダーを開始
  if(inview) {
    this.hero.start();
// 画面の外に出たらヒーロースライダーを止めてパフォーマンスを下げないようにする
  } else {
    this.hero.stop();
}
}
_destroyObservers() {
  this.observers.forEach(ob => {
  ob.destroy();
});
}
// デストロイメソッドの追加
destroy() {
  this._destroyObservers();
}

_scrollInit() {
// セッターメソッドを呼んでいて右辺の値が(val)に格納される
// this._navAnimation.bind(this)でないとエラー(プライベートメソッド内でthisを使っているため)
// スクロール監視が何度でも発動するように{once: false}する
this.observers = new ScrollObserver('.nav-trigger', this._navAnimation.bind(this), {once: false});
// カバースライドに対してのインスタンス化
this.observers = new ScrollObserver('.cover-slide', this._inviewAnimation);
// this._navAnimation.bind(this)でないとエラー(プライベートメソッド内でthisを使っているため)
this.observers = new ScrollObserver('.appear', this._inviewAnimation, {rootMargin: "-100px 0px"});
this.observers = new ScrollObserver('.tween-animate-title', this._textAnimation, {rootMargin: "-200px 0px"});
// スワイパーコンテナーを監視する
this.observers = new ScrollObserver('.swiper-container', this._toggleSlideAnimation.bind(this), {once: false});
// rootMarginで発火するタイミングを制御 
this.observers = new ScrollObserver('#main-content', this._sideAnimation.bind(this), {once: false, rootMargin: "-300px 0px"});
}
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です