Skip to content

写真が画面の端から端へ流れる無限ループするアニメーション 4種

[!NOTE] TweenMax が非推奨になったためGSAP3に置き換えて加筆・修正しました。

一列に並んだ要素が右から左あるいは上から下など、画面の端から端へ流れるように動く無限ループアニメーションを4パターン作成します。画像は途切れることなく無限にループします。記事内のコード、デモサイトはいずれも右から左へ動くように作成しています。

※ 記事内のコードはベンダープレフィックスを省略しています。

実現したいこと

CSS animationで作る無限ループアニメーション

動かしたい要素(画像群)を一列に並べた横長(あるいは縦長)の1枚の画像を作成します。用意した画像をhtmlで2回続けて読み込み、それらをひとつの div で囲みます。

<div class="loop_wrap"><img src="img.jpg" /><img src="img.jpg" /></div>

ウィンドウ幅いっぱいに画像を表示させたいので、全体を囲う divwidth: 100vw;overflow: hidden; を指定します。画像を横並びにしたいので display: flex; も指定します。高さは任意の高さを設定してください。

.loop_wrap {
  display: flex;
  width: 100vw;
  height: 300px;
  overflow: hidden;
}

.loop_wrap img {
  width: auto;
  height: 100%;
}

画面の端から端へと流れる動きは transform プロパティの translateX でX軸方向の移動距離を変えることで横にスライドして流れるような動きを実現します。開始と終了地点の異なるアニメーションを2つ用意します。

@keyframes loop {
  0% {
    transform: translateX(100%);
  }
  to {
    transform: translateX(-100%);
  }
}

@keyframes loop2 {
  0% {
    transform: translateX(0);
  }
  to {
    transform: translateX(-200%);
  }
}

作成したアニメーションを動かしたい要素に指定します。作成した2種類のアニメーションをhtmlで2回読み込んだ画像それぞれに設定します。このとき animation-duration を同じ数値にして片方の画像にdurationの半分の時間の animation-delay を設定します。無限にループさせたいので animation プロパティに infiniteを指定します。 animation-timing-function は一定に変化する linear を指定します。

.loop_wrap img:first-child {
  animation: loop 50s -25s linear infinite;
}

.loop_wrap img:last-child {
  animation: loop2 50s linear infinite;
}

画像を2回読み込む理由

スタート地点の異なるアニメーションを2つ用意し、片方の画像にdelayを設定しましたが、2つの画像の動きを分けて図解してみます。画像1(緑)はX軸方向100%から-100%へ移動し100%に戻り再び-100%へ移動するという動きを繰り返し、画像2(黄)はX軸方向を0から-200%へ移動し、0に戻り再び-200%へ移動するという動きを繰り返します。これにより画像が途切れることなく横に流れているように見せています。

※ ウィンドウサイズを変更した際に画像がウィンドウ幅より小さくなると、ループの繰り返しのなかで余白が生じるため、ウィンドウ幅いっぱいに表示する可変レイアウトの場合は対処が必要です。

デモ

CSSアニメーションで作る無限ループアニメーション

CSS animationで作る無限ループアニメーション(複数要素)

ギャラリーのように画像やリンク要素などひとつひとつが独立した要素を並べてループさせることも可能です。ここではリンク要素にもなっている画像+テキストの集まりをループさせてみます。

ループさせたい要素群を2グループに分けます。以下では同じものを2回読み込んでいますが、要素のグループが2つあれば中身は同じでなくても構いません。要素のグループをひとつの div で囲みます。

<div class="loop_wrap">
  <ul>
    <li>
      <a href="#"><img src="img_01.jpg" alt="" />CAR</a>
    </li>
    <li>
      <a href="#"><img src="img_02.jpg" alt="" />CITY</a>
    </li>
    <li>
      <a href="#"><img src="img_03.jpg" alt="" />TAXI</a>
    </li>
    <li>
      <a href="#"><img src="img_04.jpg" alt="" />NEON</a>
    </li>
  </ul>
  <ul>
    <li>
      <a href="#"><img src="img_01.jpg" alt="" />CAR</a>
    </li>
    <li>
      <a href="#"><img src="img_02.jpg" alt="" />CITY</a>
    </li>
    <li>
      <a href="#"><img src="img_03.jpg" alt="" />TAXI</a>
    </li>
    <li>
      <a href="#"><img src="img_04.jpg" alt="" />NEON</a>
    </li>
  </ul>
</div>

CSSのアニメーションは最初の例と同じです。img タグの部分を ul に変えてください。 ul 内の横並びなどのスタイルの設定の詳細は省きます。適宜調整してください。

リンク要素を並べてループさせる場合、このままでは流しそうめんのようになってしまうので、クリックしやすいようにマウスをのせたときにアニメーションが一時停止するようにします。

animation-play-state プロパティを使用します。一時停止の paused を指定するのですが、全体を囲う divhover 時のプロパティに指定します。グループを囲う ul に指定しまうと、マウスが乗っていないもう片方のグループは一時停止せず動き続けてしまうためです。

.loop_wrap:hover ul {
  animation-play-state: paused;
}

デモ

CSSアニメーションで作る無限ループアニメーション(複数要素)

CSS animationで作る無限ループアニメーション(テキスト要素)

テキストのみでもアニメーションさせることは可能です。ループさせたいテキストをdiv要素の中にいくつか記述します。

<div class="loop_wrap">
  <div>How to make a loop animation.</div>
  <div>How to make a loop animation.</div>
  <div>How to make a loop animation.</div>
  <div>How to make a loop animation.</div>
  <div>How to make a loop animation.</div>
</div>

テキストを囲うdvd要素に flex: 0 0 auto と 改行を防ぐ white-space: nowrap; を設定します。
テキストサイズやテキスト間の余白は適宜調整してください。

.loop_wrap div {
  flex: 0 0 auto;
  white-space: nowrap;
}

アニメーションは画像の場合と同じです。2つの異なる動きが交互に適用されるように :nth-child(odd) と :nth-child(even) を使用します。

.loop_wrap div:nth-child(odd) {
  animation: loop 50s -25s linear infinite;
}

.loop_wrap div:nth-child(even) {
  animation: loop2 50s linear infinite;
}

デモ

CSSアニメーションで作る無限ループアニメーション(テキスト要素)

GSAPで作る無限ループアニメーション(旧TweenMax)

JavaScriptのアニメーションライブラリ「GSAP」を利用してループを作成します。

ループさせたい画像を横に並べた1枚の画像を用意して、htmlで読み込みます。

<div id="loop" class="loop_wrap">
  <img src="img.jpg" alt="" />
</div>

後ほどJavaScriptで画像を複製して、横幅を設定するので、CSSは以下のようにします。

.loop_wrap {
  display: -webkit-flex;
  display: flex;
  height: auto;
  overflow: hidden;
}

.loop_wrap > * {
  height: auto;
}

アニメーションの設定は、GSAPのTimelineを使用して、オプションでrepeat: -1(繰り返し=無制限)を設定します。横に流れるアニメーション部分は、TweenMaxでX軸の移動を設定します。

Timelineのオプションのtl.pause()を使用すると、CSSと同様にマウスをのせた場合/はずれた場合でアニメーションの一時停止/再開を設定することもできます。

$(function () {
  const loop = document.getElementById("loop_js");

  // タイムラインを作成
  const loopAnim = gsap.timeline({
    repeat: -1, //繰り返し無制限
  });

  // div内の画像をloopItemとして定義
  let loopItem = (window.innerWidth, loop.children[0]);

  // 画像と画像を囲むdivに横幅を設定
  loopItem.style.width = `${window.innerWidth}px`;
  loop.style.width = `${window.innerWidth * 3}px`;

  // 複製した画像をdiv内に挿入
  loop.appendChild(loopItem.cloneNode(true));
  loop.appendChild(loopItem.cloneNode(true));

  // アニメーションの設定
  loopAnim
    .to(loop, { duration: 100, ease: "power0.easeNone", xPercent: -66.6666 })
    .to(loop, { duration: 0, ease: "power0.easeNone", x: 0 });
});

デモ

GSAPで作る無限ループアニメーション(旧TweenMax)