JavaScript

リペリングエフェクトの仕組み 基本・応用実装例

Webデザインの世界では、ユーザーの操作に応じて動的に変化するエフェクトが重要視されています。その中でも、「リペリングエフェクト」は、マウスカーソルやタッチ操作に対して要素が反発するように動くインタラクティブな演出として注目されています。

このエフェクトを適用することで、ユーザー体験(UX)が向上し、視覚的な魅力が増すだけでなく、Webサイトの印象を強く残すことができます。

本記事では、リペリングエフェクトの基本から応用実装までを詳しく解説し、実際のコード例を交えて、誰でも簡単に実装できるようにご紹介します。

1. リペリングエフェクトとは何か?

リペリングエフェクトの定義

リペリングエフェクトとは、マウスカーソルやタッチ操作を感知し、特定の要素が「反発する」ように動くエフェクトです。磁石の同極が反発するような動きに似ており、ユーザーが操作するとインタラクティブに反応するため、動的な表現が可能になります。

ユーザー体験への影響

リペリングエフェクトを適用することで、以下のようなメリットが得られます。

メリット 説明
視覚的な魅力 直感的なインタラクションが可能
ユーザーの滞在時間向上 エフェクトが興味を引き、離脱を防ぐ
ブランディング効果 独自の動きを作ることで印象に残る

一方で、過度な使用はユーザーのストレスを生む可能性もあるため、適度に取り入れることが重要です。

 

2. 基本実装例

ここでは、JavaScriptとCSSを使ったシンプルなリペリングエフェクトの実装例を紹介します。

基本コード(HTML + CSS + JavaScript)

以下のコードでは、カーソルが近づくと円形の要素が反発する簡単なリペリングエフェクトを実装しています。

See the Pen
Repelling effect 01
by Rin (@rinblog0408)
on CodePen.

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>リペリングエフェクト</title>
    <style>
        body { margin: 0; overflow: hidden; background-color: #222; }
        .circle {
            position: absolute;
            width: 50px;
            height: 50px;
            background-color: #f39c12;
            border-radius: 50%;
            transition: transform 0.2s ease-out;
        }
    </style>
</head>
<body>
    <div class="circle" id="circle"></div>
    <script>
        const circle = document.getElementById("circle");
        document.addEventListener("mousemove", (e) => {
            const dx = e.clientX - circle.offsetLeft - 25;
            const dy = e.clientY - circle.offsetTop - 25;
            const distance = Math.sqrt(dx * dx + dy * dy);

            if (distance < 100) {
                const angle = Math.atan2(dy, dx);
                const repelX = Math.cos(angle) * 100;
                const repelY = Math.sin(angle) * 100;
                circle.style.transform = `translate(${repelX}px, ${repelY}px)`;
            } else {
                circle.style.transform = "translate(0, 0)";
            }
        });
    </script>
</body>
</html>

 

解説

  • mousemove イベントを使用してカーソルの位置を取得。
  • カーソルと円の距離を計算し、近づくと反発するように座標を調整。
  • transform を使いスムーズな動きを実現。

この基本実装をベースに、さらに高度なエフェクトを追加できます。

 

3. 応用実装例①:要素ごとの反発強度を変える

See the Pen
Repelling effect 02
by Rin (@rinblog0408)
on CodePen.

特徴

この応用例では、各円がそれぞれ異なる反発強度を持つことで、カーソルが近づいた際に異なる挙動を示します。

  • 小さな円は大きく反発しやすい。
  • 大きな円はあまり動かない(重いイメージ)。
  • カーソルの近さによって異なる反発力を適用。

実装コード(HTML + CSS + JavaScript)

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>リペリングエフェクト(異なる反発強度)</title>
    <style>
        body { margin: 0; overflow: hidden; background-color: #222; }
        .container { position: relative; width: 100vw; height: 100vh; }
        .circle {
            position: absolute;
            border-radius: 50%;
            transition: transform 0.2s ease-out;
        }
        .circle.small { width: 40px; height: 40px; background-color: #e74c3c; } /* 小さい円(反発強) */
        .circle.medium { width: 70px; height: 70px; background-color: #3498db; } /* 中サイズ */
        .circle.large { width: 100px; height: 100px; background-color: #2ecc71; } /* 大きい円(反発弱) */
    </style>
</head>
<body>
    <div class="container">
        <div class="circle small" data-intensity="150" style="top: 30%; left: 20%;"></div>
        <div class="circle medium" data-intensity="100" style="top: 50%; left: 50%;"></div>
        <div class="circle large" data-intensity="50" style="top: 70%; left: 80%;"></div>
    </div>

    <script>
        const circles = document.querySelectorAll(".circle");

        document.addEventListener("mousemove", (e) => {
            circles.forEach(circle => {
                const rect = circle.getBoundingClientRect();
                const dx = e.clientX - (rect.left + rect.width / 2);
                const dy = e.clientY - (rect.top + rect.height / 2);
                const distance = Math.sqrt(dx * dx + dy * dy);
                const intensity = parseFloat(circle.dataset.intensity);

                if (distance < intensity) {
                    const angle = Math.atan2(dy, dx);
                    const repelX = Math.cos(angle) * (intensity - distance);
                    const repelY = Math.sin(angle) * (intensity - distance);
                    circle.style.transform = `translate(${repelX}px, ${repelY}px)`;
                } else {
                    circle.style.transform = "translate(0, 0)";
                }
            });
        });
    </script>
</body>
</html>

 

ポイント

  • .small クラスの円(赤色)は 強く反発 する(data-intensity="150")。
  • .medium クラスの円(青色)は 中程度の反発data-intensity="100")。
  • .large クラスの円(緑色)は あまり動かないdata-intensity="50")。
  • data-intensity を使い、それぞれ異なる反発力を持つ。

カーソルを動かすと、円ごとに異なる反発の動きがはっきりわかるようになります。

 

4. 応用実装例②:グラフィックと連携したリペリングエフェクト

See the Pen
Repelling effect 03
by Rin (@rinblog0408)
on CodePen.

特徴

この例では、Three.js を使用して パーティクル(粒子) をカーソルの動きに応じて反発させる実装を行います。

実装コード(HTML + Three.js)

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>リペリングエフェクト(Three.js)</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <style>
        body { margin: 0; overflow: hidden; background-color: black; }
    </style>
</head>
<body>
    <script>
        let scene, camera, renderer, particles, mouseX = 0, mouseY = 0;

        function init() {
            scene = new THREE.Scene();
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
            camera.position.z = 500;

            renderer = new THREE.WebGLRenderer();
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);

            let geometry = new THREE.BufferGeometry();
            let vertices = [];

            for (let i = 0; i < 500; i++) {
                let x = Math.random() * 800 - 400;
                let y = Math.random() * 800 - 400;
                let z = Math.random() * 800 - 400;
                vertices.push(x, y, z);
            }

            geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));

            let material = new THREE.PointsMaterial({ color: 0xffffff, size: 5 });
            particles = new THREE.Points(geometry, material);
            scene.add(particles);

            document.addEventListener("mousemove", onMouseMove);
            animate();
        }

        function onMouseMove(event) {
            mouseX = (event.clientX / window.innerWidth) * 2 - 1;
            mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
        }

        function animate() {
            requestAnimationFrame(animate);

            particles.rotation.x += mouseY * 0.02;
            particles.rotation.y += mouseX * 0.02;

            renderer.render(scene, camera);
        }

        window.addEventListener("resize", () => {
            renderer.setSize(window.innerWidth, window.innerHeight);
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
        });

        init();
    </script>
</body>
</html>

 

ポイント

  • Three.js を使用し、3D空間内で 点(パーティクル) を配置。
  • mousemove イベントで マウスの動きに応じて回転 する仕組み。
  • GPUを活用し、軽量でスムーズな動き を実現。

このエフェクトを応用することで、Webサイトの背景やローディング画面などに活用できます。

 

5. まとめ

  • リペリングエフェクトは、ユーザーの操作に応じた動的な演出が可能。
  • 基本的な実装はJavaScriptとCSSで簡単に実現できる。
  • 応用として、要素ごとに異なる反発強度を設定したり、3Dグラフィックと組み合わせることで、より高度な表現が可能。
ABOUT ME
りん
このブログでは、Web開発やプログラミングに関する情報を中心に、私が日々感じたことや学んだことをシェアしています。技術と生活の両方を楽しめるブログを目指して、日常で触れた出来事や本、ゲームの話題も取り入れています。気軽に覗いて、少しでも役立つ情報や楽しいひとときを見つけてもらえたら嬉しいです。