codeazuki
@codeazuki

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

クリックで画像が出現する処理をどう書けばよいですか?

 クリックで画像がランダムに出現する処理はどのように書けばよいですか?
https://suisei-inc.com/
 上記サイトのように、イラストがカーソルを遅れて追いかけながら、かつ画面をクリックするごとに、そこからランダムに画像が出現する、そして、5枚ほど登場した時点で、自然にフェードアウトする繰り返し処理を書きたいです。

1

2Answer

※この記事は機械翻訳により日本語に翻訳されています。

どのプログラミング言語を使用するか指定されていなかったので、JSとHTMLをベースにした例をここに示します。この種の質問に対しては、ChatGPTや他の有名な大規模言語モデル(LLM)が簡単にコードを提供できることに注意してください。これは私がo1-previewモデルから得た例です。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>カーソル追従イラストとランダム画像</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            position: relative;
            height: 100vh;
            background-color: #f0f0f0;
        }
        .illustration {
            position: absolute;
            pointer-events: none;
            will-change: transform;
        }
        .random-image {
            position: absolute;
            transition: opacity 0.5s linear;
            opacity: 1;
        }
    </style>
</head>
<body>
    <script>
        // カーソルの位置を保持する変数
        var mouseX = window.innerWidth / 2;
        var mouseY = window.innerHeight / 2;
        var illustrationX = mouseX;
        var illustrationY = mouseY;

        // 画像を管理する配列
        var imagesArray = [];

        // クリック回数をカウントする変数
        var clickCounter = 0;
        var maxClicks = 6; // 6回目のクリック後に画像がフェードアウト

        // ランダム画像のURL配列
        var randomImages = [
            'https://via.placeholder.com/100x100/ff0000/ffffff?text=1',
            'https://via.placeholder.com/100x100/00ff00/ffffff?text=2',
            'https://via.placeholder.com/100x100/0000ff/ffffff?text=3',
            'https://via.placeholder.com/100x100/ffff00/ffffff?text=4',
            'https://via.placeholder.com/100x100/00ffff/ffffff?text=5'
        ];

        // イラスト要素を作成
        var illustration = document.createElement('img');
        illustration.src = 'https://via.placeholder.com/50x50/000000/ffffff?text=Cursor';
        illustration.classList.add('illustration');
        document.body.appendChild(illustration);

        // イラスト画像の読み込み後
        illustration.onload = function () {
            illustrationX = mouseX;
            illustrationY = mouseY;
            updateIllustration(); // アニメーションを開始
        };

        // マウス位置の更新
        document.addEventListener('mousemove', onMouseMove);

        function onMouseMove(event) {
            mouseX = event.clientX;
            mouseY = event.clientY;
        }

        // 遅延付きでイラストの位置を更新
        function updateIllustration() {
            var dx = mouseX - illustrationX;
            var dy = mouseY - illustrationY;
            var delayFactor = 0.1; // 遅延の調整

            illustrationX += dx * delayFactor;
            illustrationY += dy * delayFactor;

            illustration.style.transform = 'translate(' + (illustrationX - illustration.width / 2) + 'px, ' + (illustrationY - illustration.height / 2) + 'px)';

            requestAnimationFrame(updateIllustration);
        }

        // クリック時にランダム画像を生成
        document.addEventListener('click', onClick);

        function onClick(event) {
            clickCounter++; // クリックカウンターを増加

            var randomImage = document.createElement('img');
            var randomIndex = Math.floor(Math.random() * randomImages.length);
            randomImage.src = randomImages[randomIndex];
            randomImage.classList.add('random-image');
            randomImage.style.opacity = 1;
            document.body.appendChild(randomImage);

            // 画像の読み込み後に位置を設定
            randomImage.onload = function () {
                randomImage.style.left = (mouseX - randomImage.width / 2) + 'px';
                randomImage.style.top = (mouseY - randomImage.height / 2) + 'px';
            };

            // 画像を配列に追加
            imagesArray.push(randomImage);

            // 6回目のクリック後に全ての画像をフェードアウト
            if (clickCounter === maxClicks) {
                imagesArray.forEach(function(image) {
                    image.style.opacity = 0;
                    // フェードアウト後にDOMから削除
                    image.addEventListener('transitionend', function () {
                        if (image.parentNode) {
                            image.parentNode.removeChild(image);
                        }
                    });
                });
                // 配列をクリア
                imagesArray = [];
                // クリックカウンターをリセット
                clickCounter = 0;
            }
        }
    </script>
</body>
</html>

コードの説明

カーソル追従イラスト

  • マウスの位置を追跡し、遅延を持たせてイラストが追従するようにしています。
  • updateIllustration 関数でイラストの位置を更新しています。

ランダム画像の生成

  • クリックごとに onClick 関数が呼ばれ、ランダムな画像を生成します。
  • 画像はクリックした位置(カーソル位置)に配置されます。

画像のフェードアウトとサイクルのリセット

  • クリックカウンターを導入し、6回目のクリックで全ての画像がフェードアウトします。
  • フェードアウト後、画像はDOMから削除され、クリックカウンターがリセットされます。
  • 次のクリックから新たなサイクルが始まります。

注意事項

カスタマイズ

  • randomImages 配列や illustration.src を変更して、お好みの画像に差し替えることができます。
  • maxClicks の値を変更することで、フェードアウトが起こるクリック回数を調整できます。

スタイルの調整

  • CSS内の transition プロパティを変更して、フェードアウトの速度を調整できます。
0Like

面白いWebデザインですね!!
既に回答をされている方がいらっしゃいますが...
稚拙ながら回答させていただきます。
下記などで試してみてはいかがでしょうか?

実装すること

①マウスストーカー
②Heroエリアがクリックされると画像が表示される
※参考サイトの挙動を見る感じ上記の実装で対応きるかなと思います

ざっくりした処理の内容

①マウスストーカー
・マウスの位置座標の取得→マウスストーカーを追従させる
・マウスストーカーの制御→Heroエリアでのみ表示

②Heroエリアがクリックされると画像が表示される
・重複なくランダムに数を抽出
・抽出したランダムな数に基づいて画像を表示
・任意のクリック回数で表示した画像をリセットする

画像のフェードインやフェードアウトはCSSアニメーションで実現しています。

HTML

    <header id="header"></header>
    <main>
      <div class="mouseStoker"></div>
      <section id="hero"></section>
      <section id="paragraph"></section>
    </main>

CSS

     body {
        margin: 0;
        padding: 0;
      }

      #header {
        width: 100vw;
        height: 70px;
        background-color: black;
        position: fixed;
        z-index: 10;
      }
      #hero {
        width: 100vw;
        height: 100vh;
        background-color: white;
        padding-top: 70px;
        position: relative;
        /*↓Hero要素から画像がはみ出ないようにする*/
        overflow: hidden; 
      }

      #paragraph {
        width: 100vw;
        height: 100vh;
        background-color: gray;
      }

      /* マウスストーカー */
      .mouseStoker{
        width: 40px;
        height: 40px;
        position: fixed;
        display: none;
        border-radius: 50%;
        background-color: red;
        top: 0;
        left: 0;
        z-index: 5;
      }

      .active {
        display: block;
      }

      /* クリックイベントで表示する画像 */
      .image {
        width: 300px;
        height: auto;
        position: absolute;
        animation: fadein 1s forwards;
      }

      @keyframes fadein{
        0%{
          opacity: 0;
        }
        100%{
          opacity: 1;
        }
      }

      .hidden{
        animation: fadeout 1s forwards;
      }

      @keyframes fadeout{
        0%{
          opacity: 1;
        }
        100%{
          opacity: 0;
        }
      }

JS

const hero = document.getElementById("hero");
const mouseStoker = document.querySelector(".mouseStoker");
//マウスの位置座標
let mouseX = 0;
let mouseY = 0;
//画像のパス(ファイル名を格納)
const paths = ["img1.jpg", "img2.jpg", "img3.jpg"];
//重複せずにランダムな値を取り出すための配列
let selectNumbers = [];

/*==========
マウスストーカー
==========*/
//マウスの位置座標の取得とマウスストカーの移動
document.addEventListener('mousemove', (e) => {
  mouseX = e.clientX;
  mouseY = e.clientY;
  updateMouseStoker(mouseX, mouseY);
});

function updateMouseStoker(x, y) {
  mouseStoker.style.transform = `translate(${x}px, ${y}px)`;
}
//マウスストーカーの制御
hero.addEventListener('mouseover', () => handlerMouseStoker(true));
hero.addEventListener('mouseout', () => handlerMouseStoker(false));
function handlerMouseStoker(isActive) {
  mouseStoker.classList.toggle('active', isActive);
}

/*==========
Heroエリアをクリックして画像の表示
==========*/
hero.addEventListener("click", () => {
  //ランダムに画像の表示
  if (selectNumbers.length < paths.length) {
    const num = getRandomNumber(selectNumbers, paths);
    const newImage = createImage(num);
    newImage.onload = () => positionImage(newImage);
    hero.appendChild(newImage);
  } else {
    //任意の回数以上クリックされたら表示した画像をすべて削除
    //今回は表示用に用意した画像の枚数(paths)を任意の回数設定
    resetImages();
  }
});


//重複なくランダムに数を抽出する関数
function getRandomNumber(selectNumbers, array) {
    let num;
    let isVaild = false;
    while (!isVaild) {
        num = Math.floor(Math.random() * paths.length);
        if (!selectNumbers.includes(num)) {
            isVaild = true
        }
    }
    selectNumbers.push(num);
    return num;
}

//抽出したランダムな数に応じて画像要素を生成する関数
const createImage = (num) => {
  const newImage = document.createElement("img");
  newImage.setAttribute("src", `./assets/image/${paths[num]}`);
  newImage.setAttribute("class", "image");
  return newImage;
};


//表示する画像の位置を中心に合わせる関数
function positionImage(newImage) {
  const [centerX, centerY] = getCenterImage(newImage);
  newImage.style.left = `${mouseX - centerX}px`;
  newImage.style.top = `${mouseY - centerY}px`;
}

//表示する画像の中心を取得
const getCenterImage = (newImage) => {
  const rect = newImage.getBoundingClientRect();
  const centerX =rect.width / 2;
  const centerY = rect.height / 2
  return [centerX, centerY];
};

//画像を削除する関数
function resetImages() {
  selectNumbers = [];
  const images = document.querySelectorAll(".image");
  images.forEach((e) => {
    e.classList.add('hidden');
    e.addEventListener('animationend', () => e.remove());
  });
}


0Like

Your answer might help someone💌