JavaScript

一文字ずつのテキストアニメーションを途中にタグがあってもJavaScriptとCSSで実装

最終更新日:

長いタイトルですみません。
しかしながらもう一度(※)、さらに補足も加えて言うと、

「凝ったテキストアニメーションのために1文字ずつspanで囲むことを、途中にHTMLのタグがあってもJavaScriptで実装する方法(jQueryなし)」

をご紹介します。

例えば全てのh2要素に同じテキストアニメーションをつけるといったことをしたくなると思うのですが、見出し要素は、

<h2>BringFlower<br><span class="sub">ブリングフラワー</span><h2>

のように、br要素(タグ)やspan要素(タグ)をつけることがあると思います。その場合でも動く、というのが一つのポイントです。

※ちなみに私はSEO対策でタイトルたまに変えるので、画像のタイトル表記とここでの表記が異なっている可能性はありますがご承知おきください。

実現できるアニメーション例

これからご紹介するJavaScriptの実装を行うことで実現できるアニメーション例をまずひとつお示しします。

BringFlower
ウェブで広げる、繋がる。

※2回目以降再生する場合はリセットボタンを押してから再生ボタンを押してください。

アニメーション例の解説

  • 1文字ずつspan要素で囲って、animation-delayプロパティで1文字目より2文字目が0.1秒遅いアニメーション、2文字目はそれよりさらに0.1秒遅いアニメーションが動く、というように、1文字ごとに0.1秒ずつ遅くアニメーションが動くようにしてあります。
  • :nth-child(even)nth-child(odd)を使って、奇数番目の文字と偶数番目の文字で、初期位置とアニメーションの動く方向を変えています。

つまりアニメーション自体は、HTMLとCSSだけで実現しています。
なので1箇所だけなら最初からHTMLとCSSをそのように書けばよいですが、多くの個所、例えば全ての見出し要素に同じこういったアニメーションをつけるとなると、現実的ではありません。

JavaScriptでの実装

特定の要素(この例ではtextAnimaとクラス名が付けられた要素)の中に入っている文字を1文字ずつspan要素で囲い、かつstyle属性でanimation-delayプロパティもつけるというのが次のJavaScriptです。

ここでポイントが、特定の要素の中に<br><span>などのタグが入っていても動作させているということです。それがなくて、かつjQueryでよければ、紹介されているサイトはあります。

また、1文字ごとに異なるスタイルを当てやすいように、char c-01, char c-02というようにクラス名も個別につけています。

  1. function spanWrap() {
  2. const targets = document.querySelectorAll('.textAnima')
  3. targets.forEach( function (target) {
  4. let nodes = [...target.childNodes];
  5. let textBox = '';
  6. nodes.forEach( function (node) {
  7. if (node.nodeType == 3) { //テキストの場合
  8. let text = node.textContent.replace(/\r?\n/g, ''); //テキストから改行コード削除
  9. text.split('').forEach(function (t, i) {
  10. if (t !== " ") {
  11. if (i < 10) {
  12. textBox += '<span class="char c-0' + (i + 1) + '" ' + 'style="animation-delay:.' + i + 's;">' + t + '</span>';
  13. } else {
  14. let n = i / 10;
  15. textBox += '<span class="char c-0' + (i + 1) + '" ' + 'style="animation-delay:' + n + 's;">' + t + '</span>';
  16. }
  17. } else {
  18. textBox += t;
  19. }
  20. });
  21. } else if (node.contains(node) == true) { // テキストではなく、子ノード(=span要素)を持つ
  22. // そのまま連結
  23. textBox = textBox + node.outerHTML;
  24. } else { // テキストではなく、br要素などspan要素以外の要素を持つ
  25. // そのまま連結 ※br要素などをspan要素とは別に処理する場合はここに書く
  26. textBox = textBox + node.outerHTML;
  27. }
  28. })
  29. target.innerHTML = textBox
  30. })
  31. }
  32. spanWrap();

デモその2

こちらも再生ボタンを押してみてください。最初のデモのCSSアニメーションに対して、opacity: 0からopacity: 1への変化を加えたのと、回転を加えただけです。

こうやって色々遊べると思うので、この記事をきっかけに面白いアニメーション作れた方は問い合わせフォームからそのソースコードを連絡ください。

BringFlower
ウェブで広げる、繋がる。

※2回目以降再生する場合はリセットボタンを押してから再生ボタンを押してください。

まとめ

1文字ずつ動かすテキストアニメーションの作り方、いかがでしたでしょうか?