0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rails + Turbo + Stimulusでローディングアニメーションを実装する方法(dot bounce版)

Posted at

ローディングアニメーションを実装する🌀

Rails + Turbo + Stimulus 環境で
ページ遷移やフォーム送信時に自動表示されるローディングを実装します。

この手順通りに進めれば、他プロジェクトでもそのまま再現可能です。

0. ローディングの仕組みを理解する

ローディングは次の 2つの要素 で構成されます。

役割 内容
(1) DOM(application.html.erb) ローディング画面の見た目(overlay)
(2) Stimulus Controller Turbo のイベントを監視して表示 / 非表示を制御

DOM を置くだけでは動きません。
Turbo のイベントを Stimulus が捕まえることで自動表示されます。

1. レイアウトにローディング用 DOM を置く

対象ファイル:

app/views/layouts/application.html.erb

</body> の直前に追加します。

<!-- ローディングオーバーレイ -->
<div
  data-controller="loading"
  data-loading-target="overlay"
  class="fixed inset-0 z-[9999] flex flex-col items-center justify-center
         bg-white/70 backdrop-blur-sm hidden">

  <!-- ドット3つのアニメーション -->
  <div class="flex space-x-2 mb-3">
    <div class="w-3 h-3 bg-orange-500 rounded-full animate-bounce"></div>
    <div class="w-3 h-3 bg-orange-400 rounded-full animate-bounce [animation-delay:0.15s]"></div>
    <div class="w-3 h-3 bg-orange-300 rounded-full animate-bounce [animation-delay:0.3s]"></div>
  </div>

  <p class="text-sm text-gray-700 font-medium">
    読み込み中です
  </p>
</div>

ポイント

  • hidden で初期状態は非表示
  • data-controller="loading" で Stimulus と紐付け
  • animation-delay をずらして自然な跳ね感を演出

2. Stimulus コントローラで表示 / 非表示を制御する

対象ファイル:

app/javascript/controllers/loading_controller.js

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["overlay"]

  connect() {
    this.show = this.show.bind(this)
    this.hide = this.hide.bind(this)

    this.delayTimer = null
    this.DELAY = 600 // おすすめ:500〜700ms(チラつき防止)

    // Turbo イベントを監視
    document.addEventListener("turbo:before-visit", this.show)
    document.addEventListener("turbo:submit-start", this.show)
    document.addEventListener("turbo:load", this.hide)
    document.addEventListener("turbo:submit-end", this.hide)
  }

  disconnect() {
    document.removeEventListener("turbo:before-visit", this.show)
    document.removeEventListener("turbo:submit-start", this.show)
    document.removeEventListener("turbo:load", this.hide)
    document.removeEventListener("turbo:submit-end", this.hide)
  }

  show() {
    if (!this.hasOverlayTarget) return

    // 既存タイマーがあればクリア(イベント多重発火対策)
    if (this.delayTimer) {
      clearTimeout(this.delayTimer)
    }

    // 一定時間後に表示
    this.delayTimer = setTimeout(() => {
      this.overlayTarget.classList.remove("hidden")
    }, this.DELAY)
  }

  hide() {
    if (!this.hasOverlayTarget) return

    // 表示前ならキャンセル
    if (this.delayTimer) {
      clearTimeout(this.delayTimer)
      this.delayTimer = null
    }

    this.overlayTarget.classList.add("hidden")
  }
}

なぜ遅延を入れるのか?

  • ページ遷移が高速な場合 → ローディングが一瞬だけ表示されてチラつく

  • 500〜700ms 遅らせる → 「待つときだけ出る」自然な UX になる

3. Turbo が発火するイベント一覧

Stimulus でキャッチしているイベントは以下の 4 つです。

イベント名 発火タイミング ローディング挙動
turbo:before-visit 別ページへ遷移する直前 show
turbo:submit-start フォーム送信開始 show
turbo:load 画面描画完了(初回含む) hide
turbo:submit-end フォーム送信完了 hide

※ turbo:load は 初回ロード時にも必ず発火 するため、
「保険的に hide する用途」として使うのが定番です。

4. Stimulus の読み込み設定

Rails(stimulus-rails)標準構成では、

*_controller.js を配置
controllers/index.js で登録

という形で読み込まれます。

// app/javascript/controllers/index.js

import { application } from "./application"

import LoadingController from "./loading_controller"
application.register("loading", LoadingController)

5. 実装チェックリスト

次の 5 点が揃っていればローディングは動きます。

✔ application.html.erb に overlay がある

✔ data-controller="loading" が付いている

✔ loading_controller.js が正しい場所にある

✔ Stimulus が読み込まれている

✔ Turbo が有効(リンク・フォームが Turbo)

6. よくあるエラーと対処法

症状 原因 対処
ローディングが出ない Controller が読み込まれていない index.js を確認
ずっと表示される hide が発火していない turbo:load を確認
一瞬しか表示されない 遷移が高速すぎる 遅延時間を増やす
モーダル内だけ使いたい layout に置いている 専用 layout に移動

7. 応用できるように理解しておくポイント

オーバーレイはレイアウトに置く
→ 全ページ共通なら application.html.erb

Turbo イベントが制御の起点
→ Stimulus は「いつ表示するか」を決める役割

Tailwind だけで表現可能
→ bounce / pulse / spin などに簡単に変更できる

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?