今回はテキストを無限ループさせる方法を記述していきます。
画像の無限ループはよくありますが、テキストの無限ループも稀にあったりするので覚えてもらえたら嬉しいです。
デモページからコピペで使用できるのでぜひ使用していただけたらと思います!
■使用したスキル
・HTML(Living Standard)
・CSS3
・javaScript(ES2023), jQuery, slick, swiper
■目次
気になるところをクリックしてください!
■実装方法
ここでは方法を3つ紹介します。
■その他
- ・デモ
- ・動画比較
- ・メリット・デメリット
- ・まとめ
■CSSのanimationプロパティを用いた方法
animationプロパティとは、要素に対してアニメーションを付与するものであり、アニメーションはキーフレーム(@keyframes)で定めたスタイルに従って動きます。
実際のデモと一緒に説明していきます。
クリックしてサンプルコードを見る
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<ul class="slider loop"> <li>テキスト1</li> <li>テキスト2</li> <li>テキストテキスト3</li> <li>テキストテキスト4</li> <li>テキストテキストテキスト5</li> <li>テキストテキストテキスト6</li> </ul> <div class="slider-wrap"> <ul class="slider loop"> <li>テキスト1</li> <li>テキスト2</li> <li>テキストテキスト3</li> <li>テキストテキスト4</li> <li>テキストテキストテキスト5</li> <li>テキストテキストテキスト6</li> ...上記と同じ要素を秒数の長さによって数セット追加(↓) <li>テキスト1</li> <li>テキスト2</li> <li>テキストテキスト3</li> <li>テキストテキスト4</li> <li>テキストテキストテキスト5</li> <li>テキストテキストテキスト6</li> </ul> </div> <style type="text/css"> @keyframes loop { from { transform: translateX(0); } to { transform: translateX(-100%); // 左向きの場合はtranslateX(100%)に } } .loop { display: flex; justify-content: center; align-items: center; animation: loop-left 秒数 infinite linear 遅延秒数 both; } .slider li { display: inline-block; word-break: keep-all; } .slider-wrap { width: 100vw; overflow: hidden; // 画面外に溢れた分を見切れるように } </style> |
■何をしているのか
まず全体を覆うslider-wrapを用意します。こちらにCSSプロパティwidth: 100vwとoverflow: hiddenをセットで使うことで画面外を見切れさせ、ウィンドウを横にスクロールできてしまう問題を防ぎます。
次に、.loop(ループさせたい要素を内包した親要素)に対してdisplay: flexとanimationを付与します。display: flexは要素を横や縦に並び替えるといったもので標準値は横並びになります。これによってテキスト群を横並びにします。
animationによって横にスライドする動きを作るのですがslickやswiperのような子要素一つ一つをスライドさせるといった概念ではないため、1つのスライドに対して何秒といった動きはつけられません。そのため親要素 / アニメーション秒数(ここでは親要素の右端が左端の開始地点までスライドするまでの時間※見切れている要素も含む)がおおよその秒数になります。注意点としてあくまでアニメーションは親要素が動いているだけなので子要素数(スライドの数)が空の状態でも秒数の限り動き続けます。これによってアニメーション秒数が子要素数(スライドの数)より多い場合は空の要素が見えてしまうため、そうならないよう同じ要素を追加する必要があります。アニメーション秒数が短すぎてもスライドの速度が速すぎてしまうためアニメーション秒数を維持しつ子要素数(スライド数)を確保しましょう。
ポイントとしてはanimationの最後にbothがとても重要になります。これはanimation-fill-modeプロパティでありアニメーション前後の動きを指定しています。ここでbothとは「開始時に終了時の状態を維持、終了時に開始時の状態に戻る」効果があります。つまり上記のように要素が続け様表示され続ける状態だと状態を維持しつつ、次の動きも用意するというbothの特性が必要になります。
animation:
https://developer.mozilla.org/ja/docs/Web/CSS/animation
他の実装方法はこちら
■jQueryを使用した「slick」プラグインを用いた方法
「slick」はjQueryライブラリを使用したスライダー作成用のプラグインです。
様々なoption(拡張機能)がある中で、テキストを無限ループさせる方法を記述します。
クリックしてサンプルコードを見る
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<div class="slider-wrap"> <ul class="slider" id="js-slick-slider"> <li>テキスト1</li> <li>テキスト2</li> <li>テキストテキスト3</li> <li>テキストテキスト4</li> <li>テキストテキストテキスト5</li> <li>テキストテキストテキスト6</li> </ul> </div> <script type="text/javascript"> const setSlickElementsWidth = () => { const elements = document.querySelectorAll('#js-slick-slider li'); for(let i = 0; i < elements.length; i++) { const width = elements[i].offsetWidth; elements[i].style.width = `${width}px`; } } const setTextSpeed = (length) => { return length * 500; } const slickFunction = () => { $("#js-slick-slider").slick({ infinite: true, autoplay: true, autoplaySpeed: 0, speed: setTextSpeed(要素の文字数), cssEase: "linear", swipe: false, arrows: false, pauseOnFocus: false, pauseOnHover: false, variableWidth: true, }) .on("afterChange", function(event, slick, currentSlide, nextSlide) { switch (currentSlide){ case 何番目の要素: $(this).slick("slickSetOption", "speed", setTextSpeed(要素の文字数)); // 初期設定以外の文字数の要素 default: $(this).slick("slickSetOption", "speed", setTextSpeed(要素の文字数)); // 初期設定と同じ break; } }); } window.addEventListener('DOMContentLoaded', () => { setSlickElementsWidth(); slickFunction(); }); </script> |
■何をしているのか
まずjQueryライブラリ, slickプラグインを読み込みます。以下はCDN(外部読み込み)の場合です。
1 2 3 4 5 6 7 |
// jQuery <script src="https://cdn.jsdelivr.net/npm/jquery@3.1.1/dist/jquery.min.js"></script> // slick <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick-theme.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.css"> <script src="https://cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.js"></script> |
次に#js-slick-slider(ループさせたい要素を内包した親要素)に対して関数(slickFunction)を定義します。
optionとして必要になるのが以下になります。
1 2 3 4 5 6 7 |
・infinite:無限ループさせる(true) ・autoplay:自動再生(true) ・autoplaySpeed:自動再生間のインターバル秒数(0) ・speed:スライド秒数(数値(ミリ秒)で記入、ここでは文字数において時間を返すsetTextSpeedという関数を別途設けています。※固定値でも可) ・cssEase:スライドの動き方(一定の動きにしたいのでlinear) ・swipe, arrows, pauseOnFocus, pauseOnHover:ユーザーアクションに関するもの(ユーザーアクションを起こす時にラグが発生するので基本false) ・variableWidth:スライド幅の自動計算を行うか(スライド毎に横幅異なるためfalse) |
また、上記で設定したspeedに対して、要素毎にスライド秒数を揃えるために.on(“afterChange”)というイベント関数を使用します。
初期設定したspeedというのは「要素幅 / speed」となるため要素幅が可変の場合だと要素毎にスライド秒数が異なります。
そのため、初期で見越していた要素幅が変わる場合上記のイベント関数を使用して例外処置を取ります。
※僕の場合は要素幅を文字数として見ているため文字数 x 秒数の関数(setTextSpeed)を別途用意しています。
実際に作成すると以下のようになります。
また、任意ですがsetSlickElementsWidthという関数により子要素(スライド)毎に横幅を指定しています。これを指定することで微妙なラグを防ぐことができます。
slick:
https://kenwheeler.github.io/slick/
他の実装方法はこちら
■「swiper」プラグインを用いた方法
「swiper」はslick同様にスライダー作成用のプラグインです。こちらはjQueryライブラリが必要がありません。
同様にテキストを無限ループさせる方法を記述します。
クリックしてサンプルコードを見る
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
<div class="slider-wrap"> <ul class="slider swiper" id="js-swiper-slider"> <div class="swiper-wrapper"> <div class="swiper-slide">テキスト1</div> <div class="swiper-slide">テキスト2</div> <div class="swiper-slide">テキストテキスト3</div> <div class="swiper-slide">テキストテキスト4</div> <div class="swiper-slide">テキストテキストテキスト5</div> <div class="swiper-slide">テキストテキストテキスト6</div> </div> </ul> </div> <style type="text/css"> .swiper-slide { width: auto; } .swiper-wrapper { transition: all .3s ease; -webkit-transition-timing-function: linear!important; -o-transition-timing-function: linear!important; transition-timing-function: linear!important; } </style> <script type="text/javascript"> const setSwiperElementsWidth = () => { const elements = document.querySelectorAll('#js-swiper-slider .swiper-slide'); for(let i = 0; i < elements.length; i++) { const width = elements[i].offsetWidth; elements[i].style.width = `${width}px`; } } const setTextSpeed = (length) => { return length * 500; } const swiperFunction = () => { const swiper = new Swiper("#js-swiper-slider", { autoplay: { delay: 0, reverseDirection: false, pauseOnMouseEnter: false, disableOnInteraction: false, }, loop: true, slidesPerView: 'auto', speed: setTextSpeed(要素の文字数), allowTouchMove: false, }) .on('slideChange', function (swiper) { switch (swiper.realIndex){ case 何番目の要素: swiper.params.speed = setTextSpeed(要素の文字数); // 初期設定以外の文字数の要素 default: swiper.params.speed = setTextSpeed(要素の文字数); // 初期設定と同じ break; } }); } window.addEventListener('DOMContentLoaded', () => { setSwiperElementsWidth(); swiperFunction(); }); </script> |
■何をしているのか
まずswiperプラグインを読み込みます。以下はCDN(外部読み込み)の場合です。
1 2 |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.css"> <script src="https://cdn.jsdelivr.net/npm/swiper@8/swiper-bundle.min.js"></script> |
次に#js-swiper-slider(ループさせたい要素を内包した親要素)に対して関数(swiperFunction)を定義します。
optionとして必要になるのが以下になります。
1 2 3 4 5 6 7 8 |
・autoplay:自動再生(true) └ delay:自動再生間のインターバル秒数(0) └ reverseDirection(左スライド:false, 右スライド:true) └ pauseOnMouseEnter, disableOnInteraction:ユーザーアクションに関するもの(ユーザーアクションを起こす時にラグが発生するので基本false) ・loop:無限ループ(true) ・slidesPerView:左右のスライドをはみ出してみせるか(必要なし:'auto') ・speed:スライド秒数(数値(ミリ秒)で記入、ここでは文字数において時間を返すsetTextSpeedという関数を別途設けています。※固定値でも可) ・allowTouchMove:ユーザーアクションに関するもの(ユーザーアクションを起こす時にラグが発生するので基本false) |
その他、スライドの動きなどはoption(拡張機能)ではなく、cssによって決められているためtransition-timing-function: linear;を設定する必要があります。
また、上記で設定したspeedに対して、要素毎にスライド秒数を揃えるために.on(“slideChange”)というイベント関数を使用します。
初期設定したspeedというのは「要素幅 / speed」となるため要素幅が可変の場合だと要素毎にスライド秒数が異なります。
そのため、初期で見越していた要素幅が変わる場合上記のイベント関数を使用して例外処置を取ります。
※僕の場合は要素幅を文字数として見ているため文字数 x 秒数の関数(setTextSpeed)を別途用意しています。
実際に作成すると以下のようになります。
また、任意ですがsetSwiperElementsWidthという関数により子要素(スライド)毎に横幅を指定しています。これを指定することで微妙なラグを防ぐことができます。
swiper:
https://swiperjs.com/
他の実装方法はこちら
■デモ(animation, slick, swiper)
See the Pen
Text Loop (Animation & Swiper & Slick) by kozawa (@sige0821)
on CodePen.
■動画比較
上からanimation, slick, swiperの順です。
■メリット・デメリット
■animation
メリット
・動きが限りなく一定
・javaScriptを記述する必要がない。
デメリット
・アニメーション秒数によって、同じ子要素(スライド)を追加する必要がある。
・1スライド秒数何秒という定義が難しい。
■slick
メリット
・スライドを自動生成・削除してくれるので同じ子要素(スライド)を追加する必要がない。
・1スライド毎に秒数指定ができる。
・option(拡張機能)が豊富なので、スライダーをやりたい場合はまずこれを重宝する。
デメリット
・javaScriptの記述が必要。
・jQueryライブラリが必要。
・若干動きの遅延があり、スライドによって速度が変わることがある。
■swiper
メリット
・jQueryライブラリが必要ない。
・スライドを自動生成・削除してくれるので同じ子要素(スライド)を追加する必要がない。
・1スライド毎に秒数指定ができる。
デメリット
・javaScriptの記述が必要。
・若干動きの遅延があり、スライドによって速度が変わることがある(slickより目立つ)。
・若干動きがカクっとなる時がある。
■まとめ
どの方法にもメリット・デメリットは存在しますが個人的には直感的にできるslickがおすすめです!
animationのように空の状態が見えてしまうリスクがないからです。
一方でアニメーションのガクつきが気になる方、javaScriptが面倒だという方はanimationをお勧めします!
最後まで読んでいただきありがとうございました!
それではまたお会いしましょう。
コーダーからWebデザイナーからフロントエンドエンジニアへ。クライアントページ作成や開発周りなど広くやらせてもらってます。作るのが好き!