どうも、くまだ です。
JavaScriptとSassをつかって、文字分割のアニメーションについて書いていきます。勉強したやつのアウトプットなので、オリジナルで考えたわけではありません。
今回使用する主なメソッドは、以下のメソッド。
- split()
- reduce()
スクロールしたらテキストが横に流れるアニメーションはこちら。
文字分割のアニメーション htmlとSass
まずは完成版から。
これを作っていきます。最初に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">
    <title>Document</title>
    <link rel="stylesheet" href="css/style.css">
    <link href="https://fonts.googleapis.com/css2?family=Teko:wght@500&display=swap" rel="stylesheet">
</head>
<body>
    <div class="container">
        <div class="animation">
            アニメーション しますー。
        </div>
    </div>
    <script src="main.js"></script>
</body>
</html>次にSassのコードを書きます。
.container {
  position: relative;
  height: 100vh;
}
.animation {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  opacity: 0;
  font-size: 24px;
  font-weight: bold;
  &.in {
    opacity: 1;
    
    .cat {
      display: inline-block;
      animation: cat_in 3s ease;
      animation-delay: 0;
      @for $i from 1 through 13 {
        &:nth-child(#{$i}) {
          animation-delay: $i * .06s;
        }
      }
    }
  }
}
@keyframes cat_in {
  0% {
    transform: translateY(-50%) rotate(-180deg);
    opacity: 0;
  }
  100% {
    transform: translate(0) rotate(360deg);
    opacity: 1;
  }
}.in クラスはJavaScriptでクラスを付与させます。@keyframes cat_in でアニメーションの設定をしておきます。cat クラスは、JavaScriptでhtmlの文字を分割した文字一つ一つにあてるためのクラスです。
JavaScriptによって文章が1文字ずつに分割され、1文字ずつに.catクラスを付与。そしてcat_inアニメーションが入ります。
.catクラスが付与され、分割された文字はそれぞれ、@for文の記述のanimation-delayで0.06sずつ遅らせてアニメーションを動かします。
JavaScriptでも似たようなfor文(ループ処理)がありますが、それといっしょです。
@forの構文は以下のような記述です。
@for $変数名 from 開始値 through 終了値 {
// ここにスタイルをあてる処理を書く
}
もしくは、
@for $変数名 from 開始値 to 終了値 {
// ここにスタイルをあてる処理を書く
}throughとto の違いは、
- throughは、その数値を含める
- to はその数値を含まない
以下は、参考記事です。
文字分割のアニメーション JavaScript
次にJavaScriptの記述を書いていきます。(\マークは、バックスラッシュに変換してください)
'use strict';
document.addEventListener('DOMContentLoaded',()=>{
  const elm = document.querySelector('.animation');
  elm.classList.add('in');
  const cut = elm.innerHTML.trim().split("");
  elm.innerHTML = cut.reduce((i, j) => {
    j = j.replace(/\s+/, ' ');//replace:置換
    return `${i}<span class="cat">${j}</span>`;
  }, "");
});addEventListener メソッドは、イベントリスナー(イベントに合わせて実行させる関数)を登録するためのメソッドです。
DOMContentLoadedイベントは、HTMLの初期文章の読込が完全に読み込まれたタイミングで発生します。(スタイルシート、画像などの読込の完了は待たない)
document.querySelector で.animationを取得し、変数 elmに格納。
格納したelmに、classList.add でin クラスを付与。
classList は、特定のクラス名を追加・削除・参照することができるプロパティです。
使い方としては、上記のように classList.add(クラス名)みたいな感じでつかいます。classList関係で使えるものだと以下のようなものがあります。
- add・・・クラス追加
- remove・・・クラス削除
- contains・・・クラスがあるか確認
- toggle・・・クラスがあれば削除、なければ追加
変数elmを、innerHTMLで操作します。
innerHTMLは、HTML要素の中身を変更することができるプロパティです。trim()で空白を取り除き、splitメソッドで文字列を分割しています。
splitメソッドは、例えば以下みたいな感じで使うことができます。
const Arry = 'yamada taro';
const ret = Arry.split("");
console.log(ret);これをコンソール画面で見ると、

と、こんな感じで分割されます。
なので、elmをinnerHTMLによる操作によって、trim()によって空白を取り除き、splitで一文字ずつ分割してそれをcutに格納します。
そして次はreduceメソッドの部分ですが、以下のような構文で書きます。
reduce((累積値, 要素)={
});
例えば、reduce関数をつかって足し算をすると、
const num = [2,3,6,7,100];
const total = num.reduce((i,j)=>{
  return i + j;
});
console.log(total); // 118このように、複数個の配列やオブジェクトをひとつにまとめる関数です。
例えば、上記のアニメーションを一文字ずつ分割してそれぞれspanタグで括りたいとします。すると下記のような感じで書きます。
const NewArry = mojiArry.reduce((x, y)=> {
  return `${x}<span>${y}</span>`;
});
console.log(NewArry);これを検証ツールで確認すると、

分割された文字列にspanタグが挿入されています。
reduceメソッドの動きとしては、
〇1回目のループ:
初期値がx(xの中身はyamada taroの y )。
yにspanタグがつく(yの中身はyamada taro の a )。
〇2回目のループ:
xにはy<span>a</span>(1回目のループの結果)。
yにはspanタグがつく( yの中身はyamada taro の m )
〇3回目のループ:
xにはy<span>a</span><span>d</span>(2回目のループの結果)。
yにはspanタグがつく( yの中身はyamada taro の a )
以下、繰り返し。
そして、よく見ると最初の「y」がspanタグで括られていません。これを解決するためには、
const NewArry = mojiArry.reduce((x, y)=> {
  return `${x}<span>${y}</span>`;
}, '');
console.log(NewArry);前と変わったのは、}); を、 }, ”);に変更しただけです。

}, ”); の”には初期値を設定します。初期値に空文字を設定すると、上記のような処理になります。reduceメソッドの動きとしては、
〇1回目のループ:
初期値がx(xの中身は、初期値の空白” )。
yにspanタグがつく(yの中身はyamada taro の y )。
〇2回目のループ:
xには、空白<span>y</span>(1回目のループの結果)。
yにはspanタグがつく( yの中身はyamada taro の a )
〇3回目のループ:
xには、空白<span>y</span><span>a</span>(2回目のループの結果)。
yにはspanタグがつく( yの中身はyamada taro の m )
以下、繰り返し。
という感じになります。この要領で、<span class=”cat”></span>を挿入していきます。
elm.innerHTML = cut.reduce((i, j) => {
    j = j.replace(/\s+/, ' ');//replace:置換
    return `${i}<span class="cat">${j}</span>`;
  }, ""); //初期値は空
});
replaceに関しては、以下参考記事です。
というわけで、以下の処理を行うと、文字分割アニメーションをつくることができます。
ここまで読んでくださりありがとうございました。




