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?

【Next.js】 レンダリング時にアニメーションがリセットされるものとされないものがある

Last updated at Posted at 2025-01-26

はじめに

Next.jsでサイト制作中に、ページが再レンダリングするとき、アニメーションがリセットされるものとされないものの2種類あることに気づきました。本記事では、以下について詳しく解説します。

  • CSS アニメーションがリセットされない理由
  • JavaScript アニメーションがリセットされる理由
  • 解決策としてのアニメーションのコンポーネント化

最後に簡単なコード例を通して、実際の実装方法をお伝えします。

アニメーションがリセットされるものとされないものの違い

1. CSS アニメーションはリセットされない

CSS のアニメーションは、ブラウザのレンダリングエンジンで再生されています。そのため、React や Next.js のコンポーネントの再レンダリングやページ遷移の影響を受けません。

2. JavaScript アニメーションはリセットされる

JavaScript アニメーションは、レンダリングの影響を直接受けます。レンダリング時に状態がリセットされ、アニメーションが最初からやり直しになることがあります。

再レンダリングで React が古い DOM 要素を削除し、新しい要素を作成した場合、古い要素に紐づいていたJSアニメーションの状態はすべて失われます。

またReact の useEffect や useState は、コンポーネントが再レンダリングされると再実行されるため、JSアニメーションの進行状況がリセットされます。

例:

import { useState, useEffect } from "react";
import JSAnimatedBox from "./JSAnimatedBox";
import CSSAnimatedBox from "./CSSAnimatedBox";

const Page = () => {
  const [scrollPosition, setScrollPosition] = useState(0);

  useEffect(() => {
    const handleScroll = () => {
      setScrollPosition(window.scrollY); // スクロール位置を状態で管理
    };

    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, []);

  return (
    <div>
      <h1>スクロールアニメーション</h1>
      <p>現在のスクロール位置: {scrollPosition}</p>
      {/* CSS アニメーション部分 */}
      <CSSAnimatedBox />
      {/* JavaScript アニメーション部分 */}
      <JSAnimatedBox />
    </div>
  );
};

export default ScrollAnimation;

この場合、コンポーネントが再レンダリングされるとCSSAnimatedBoxコンポーネントは最後までアニメーションが実行され、JSAnimatedBoxのアニメーションは初期化されます。


解決策: アニメーション部分のコンポーネント化

JavaScript アニメーションがリセットされるのを防ぐために、ページ全体がレンダリングされてる要因のコードをコンポーネント化して影響範囲をコンポーネント内に留めておく必要があります

修正版: コンポーネント化されたアニメーション

import ScrollWatcher from "./ScrollWatcher";
import JSAnimatedBox from "./JSAnimatedBox";
import CSSAnimatedBox from "./CSSAnimatedBox";

const ScrollAnimation = () => {
  return (
    <div>
      <h1>スクロールアニメーション</h1>
      {/* スクロール監視部分 */}
      <ScrollWatcher />
      {/* CSS アニメーション部分 */}
      <CSSAnimatedBox />
      {/* JavaScript アニメーション部分 */}
      <JSAnimatedBox />
    </div>
  );
};

export default ScrollAnimation;

結論

  • CSS アニメーションはブラウザのレンダリングエンジンが制御しているため、リセットされることはありません。
  • JavaScript アニメーションはレンダリングに依存するため、再レンダリング時にリセットされます。
  • レンダリング影響範囲内にjsアニメーション置かないように適宜コンポーネント化する
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?