JavaScript6(画面のスクロールを検知して発火)

5.5から続く

1:画面のスクロールを検知してテキストアニメーションをする

mixinはいつもどおりなので省略

HTMLの記述

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css"
integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp"
crossorigin="anonymous"/>
<link href="https://fonts.googleapis.com/css2?family=Teko:wght@500&display=swap"
rel="stylesheet"/>
<link rel="stylesheet" href="style.css" />
  <title>Document</title>
</head>
<body>
  <section>
    <div class="animate-title">Start Animation</div>
  </section>
  <section>
    <div class="animate-title">Use what you have.</div>
  </section>
  <section>
    <div class="animate-title">Do what you can.</div>
  </section>
<!-- main.jsよりも先に読み込ませる -->
  <script src="text-animation.js"></script>
  <script src="main.js"></script>
</body>
</html>

SCSSの記述

@import "mixin";
html {
  font-family: "Teko", sans-serif;
}
body {
  margin: 0;
}
section {
  position: relative;
  height: 100vh;
  background-color: teal;

  &:nth-child(2) {
    background-color: mediumvioletred;
}
  &:nth-child(3) {
    background-color: orange;
 }
}
.animate-title,
.tween-animate-title {
  position: absolute;
// 文字が画面中央に来るようにする
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: white;
  opacity: 0;
  font-size: 2em;

  &.inview {
    opacity: 1;
  & .char {
    display: inline-block;
 }
}
  & .char {
    opacity: 0;
 }
}

.animate-title.inview .char {
@include animation(
$name: kf-animate-chars,
$duration: 0.5s,
$timing-function: cubic-bezier(0.39, 1.57, 0.58, 1),
$fill-mode: both
);

@for $i from 1 through 30 {
  &:nth-child(#{$i}) {
    animation-delay: $i * 0.04s;
  }
 }
}

@keyframes kf-animate-chars {
0% {
  opacity: 0;
  transform: translateY(-50%);
}

100% {
  opacity: 1;
  transform: translateY(0);
 }
}

main.jsの記述

document.addEventListener('DOMContentLoaded', function () {
// .animate-titleの要素を取得(複数取得したいのでAll)
  const els = document.querySelectorAll('.animate-title');
  const cb = function (entries, observer) {
  entries.forEach(entry => {
  if (entry.isIntersecting) {
// entry.targetにしないとエラー
  const ta = new TextAnimation(entry.target);
  ta.animate();
//一度アニメーションが実行されたら監視をやめる
  observer.unobserve(entry.target);
  } else { 
  }
 });
};
// よく使うオプション
  const options = {
// 交差対象の親要素
  root: null,
//左右で設定すると交差しない場合があるので注意!
  rootMargin: "0px",
//設定すると判定が厳しくなる(上端や下端が交差するまで判定しない)
  threshold: 0
};
// コールバック関数を用いて初期化
  const io = new IntersectionObserver(cb, options);
  console.log(io);
// 要素が複数あるためループで回して監視
  els.forEach(el => io.observe(el));
  console.log(els);
});

text-animation.jsの記述

//まず初めに<span class>文字</span>としたい、空白も表現したい
class TextAnimation {
  constructor(el) {
    this.DOM = {};
// elがDOMのときthis.Dom.elに格納、falseのときdocument.querySelector(el);でDOMを取得する
    this.DOM.el = el instanceof HTMLElement ? el : document.querySelector(el);
    console.log(this.DOM.el)
// 上の3項演算子の元の記法
// if(el instanceof HTMLElement) {
// this.DOM.el = el;
// } else {
// this.DOM.el = document.querySelector(el);
// }
    this.chars = this.DOM.el.innerHTML.trim().split("");
    console.log(this.chars)
    this.DOM.el.innerHTML = this._splitText();
    console.log(this.DOM.el.innerHTML)
}
  _splitText() {
     return this.chars.reduce((acc, curr) => {
       curr = curr.replace(/\s+/, ' ');
       return `${acc}<span class="char">${curr}</span>`;
 }, "");
}
  animate() {
    this.DOM.el.classList.toggle('inview');
 }
}
// 継承するには(再利用するには?)
class TweenTextAnimation extends TextAnimation {
  constructor(el) {
    super(el);
    this.DOM.chars = this.DOM.el.querySelectorAll('.char');
}
// 記載を書き換えたい(オーバーライド)場合
  animate() {
// inviewをつける
  this.DOM.el.classList.add('inview');
// TweenMaxの書き方(toメソッド)対象となるDOMアニメーションの間隔
  this.DOM.chars.forEach((c, i) => {
// オプションeaseファンクション,delayの間隔,オプション
    TweenMax.to(c, .6, {
    ease: Back.easeOut,
    delay: i * .05,
// アニメーションの始まる状態
    startAt: { y: '-50%', opacity: 0},
// 終了時の状態
    y: '0%',
    opacity: 1
  });
 });
}
}
  1. console.log(io);の中身でIntersectionObserverが呼ばれている。
  2. console.log(els);の中身でDOM要素animate-titleがループ処理されたので3つ全て格納されている
  3. console.log(this.DOM.el)の中身で、3項演算子でelがDOMのときにはthis.Dom.elに格納してそうでないときは、querySelector(el);でDOMを取得して格納している。
  4. console.log(this.chars)の中身で配列の中に加工前のものが入っている。
  5. console.log(this.DOM.el.innerHTML)の中身で加工したあとの文字列が出力されている。
  6. 以下2番めのアニメーションで、3の部分の処理が行われている。
  7. 1番目と同じなので略

6.1に続きます

コメントを残す

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