Academia 4

アジェンダ

  • スクロールでいろいろやってみたい!
  • スクロールしたら文字がふわっと現れる
  • 読み込みしたら文字が1文字ずつ連続で現れる

スクロールしたら文字がふわっと現れる

準備

  • 前回使用したHTML素材を使用(URLよりDL可能)
  • imagesフォルダの中身を、バラバラのサイズの画像に差し替える(以前までは正方形にトリミングした画像を使っていたが、今回からはトリミングしていない画像を使う。)
  • headタグのapp.jsの上に下記コードを追加
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.min.js"></script>

スクロールしたら何かをする、というのはどうやるか

addEventListenerを使う Eventとは、例えばスクロールやクリックなど、ブラウザ上で発生するなんらかの「動き」のことを指す。 addEventListenerとは、その名の通り「何らかの動き(event)」がないかどうか「待っている(listen)」という状態。具体的にはこのように書く。

window.addEventListener("scroll", function () {
  console.log("スクロールしている");
});
target.addEventListener("event_name", function);

という構文。 すなわち、イベントが発生したときに〇〇する!というもの。 要素を検証より、consoleを立ち上げてチェックしてみよう。

f:id:dorak:20200508134114p:plain

スクロールのたびに「スクロールしている」というワードが表示されているはず。

console.log();とは

consoleになにかを表示するための命令。 consoleはシステムに直接命令を下したりエラーの確認をする場所。ここにエラーなどが表示される。

function?

functionとは、「関数」のこと。難しく考えがちだが、直訳すると「機能、作用、働き」。例えば文字の色を変えるなど、なんらかの機能を書いておくことができる。 書き方は次の通り。

function (引数) {はたらきの内容}

//具体例
function () {
  document.getElementById('target').classList.add('functionTest');
  console.log('クラスを変えたよ');
}

// ↑targetというidを持つHTMLに対して、functionTestというクラスを追加する関数

ふわっと出す、を考える

「Works」が視界に入ってきたらふわっと出したい アニメーションはJavascriptだけで完結するものではない。CSSと組み合わせて行う。 結論的には以下の手順。 1. ふわっと出したいものをCSSで透明にしておく。加えて、下から上にテキストが出てくるように、position: relativeとbottomプロパティを使って下に置いておく 2. 上記を打ち消すCSSクラスを用意しておく。つまり、透明状態を解除、位置をもとに戻す、というイメージ 3. 特定の箇所にスクロールしたら2のクラスがつくように

対象となるHTLMは<h2 class="headline"><span>Works</span></h2>

  1. 透明かつ下に隠しておくコード 透明にするのはopacity、位置を移動させるにはposition: relative;bottomプロパティ、そしてボックスモデルからはみ出た要素を隠すのがoverflow:hidden;。なので下記のようなHTMLとcss
<h2 id="section-title" class="headline">
  <span id="section-title-text">Works</span>
</h2>
.headline {
  font-size: 40px;
  margin: 24px 0;
  padding-left: 24px;
  overflow: hidden;
}

.headline span {
  opacity: 0;
  bottom: -100px;
  transition: all ease-in-out 0.5s;
  position: relative;
}
  1. 打ち消しクラスの用意
span.popup {
  bottom: 0;
  opacity: 1;
}
  1. 打ち消しクラスを、特定の位置まで来たときに付与するjs
window.addEventListener("scroll", function () {
  const target = document.getElementById("section-title");
  const stPosition = target.getBoundingClientRect().bottom - window.innerHeight;
  console.log(stPosition);
  if (stPosition < 0) {
    document.getElementById("section-title-text").classList.add("popup");
  }
});

特定の位置、をどうやって判定するか?

今回は、「Works」が視界に入ってきたらふわっと出したい。 「視界」とは?ブラウザが表示できている領域、すなわちビューポートと言い換える

やり方は以下 1. ターゲット要素の相対的な座標を取得する 2. 1から現在の画面の高さを引く(ビューポートの高さ)ことで、視界に入ったときに〇〇する、を実現する 3. クラスを追加するコードを書く

  1. ターゲット要素の相対的な座標を取得する target.getBoundingClientRect().bottomで、ビューポートの左上からターゲットのボックスモデルの下部までの距離を取得できる。 スクロールのたびに上記の値を取得するようにすれば、いずれはゼロになるはず。ゼロになったときに〇〇する、といったコードを書くことを目的とする

f:id:dorak:20200508145804p:plain (引用:https://qiita.com/makoto1219/items/9d5b71a792025703cdea)

  1. 1から現在の画面の高さを引く(ビューポートの高さ)ことで、視界に入ったときに〇〇する、を実現する 1で取得した距離は、あくまでビューポートの左上から計算する、となっている。ということは、値がゼロになるのはあくまで視界に入ってきたときではなく視界から出ていくときとなる。どうすればいいか?

  2. ビューポートの高さを足してあげる。そうすることで、視界に入ってきたときにちょうど1の値が0になる

  3. クラスを追加するコードを書く

読み込みしたら文字が1文字ずつ現れる

ここまでやった知識で実現可能。 要素一つずつに対して、透明度とpositionを設定していくやり方。

  1. TweenMaxを読み込む
  2. 1文字ずつ扱えるように、1文字単位でHTMLタグを分割する
  3. コードを書く

今日使うライブラリ「TweenMax」

Javascriptを用いたアニメーションと言えば「TweenMax - Products - GreenSock」。

TweenMaxの「Tween」とは、「Between(〜と〜の間、という意味の英単語)」からきていることが示すように、ある地点からある地点への変化をJavascriptで指定できる機能を持ったライブラリ。

AfterEffectsやPremiere, Flashでアニメーションを作ったことがある人なら、だいたい考え方は一緒なのでとっつきやすい。

1はいいとして2から 2. 1文字ずつ扱えるように、1文字単位でHTMLタグを分割する

<div class="cover">
  <div id="main-title" class="clearfix">
    <p class="showText">P</p>
    <p class="showText">O</p>
    <p class="showText">R</p>
    <p class="showText">T</p>
    <p class="showText">F</p>
    <p class="showText">O</p>
    <p class="showText">L</p>
    <p class="showText">I</p>
    <p class="showText">O</p>
  </div>
</div>
  1. コードを書く 注意!アニメーション系のコードはHTMLが読み込まれる前に実行されるとエラーになる。なので、下記の書き方を徹底する。
$(document).ready(function() {
  //ここにコードを入れる
});

$(document).readyは、HTMLが読み込まれたあとに、という意味。

$(document).ready(function () {
  gsap.from(".showText", 2, {
    duration: 1,
    opacity: 0,
    yPercent: 100,
    stagger: 0.5,
  });
});