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?

【JavaScript】画像ファイルで3Dの360°スクロールを実現する

Posted at

背景

以下の参考サイト
https://themecut.jp/24/final/
このサイトの中の、ウィッグ作品をマウスの横スクロールでぐるりと360°回転して確認できる動きがあったので、どうにかできないかなあと思いつつ、ちょっとやってみました。

※画像は、そのまま参考サイトのものを使用させて頂きました。

実際のコード

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>360° 回転ビューア</title>
    <style>
        #viewer {
            width: 500px;
            height: 500px;
            background: url('3d.jpg') no-repeat;
            background-size: 100% auto;
            cursor: grab;
            border: 2px solid #ccc;
            margin: 20px;
        }
        
        .info {
            margin: 20px;
        }
    </style>
</head>

<body>
    <!-- マネキンを表示するエリア -->
    <div id="viewer"></div>
    
    <div class="info">
        <p>現在のフレーム: <span id="frameNumber">0</span> / 46</p>
        <p>マウスホイールまたは横ドラッグで回転</p>
    </div>

    <script>
        const viewer = document.getElementById("viewer");
        const frameNumberDisplay = document.getElementById("frameNumber");

        const frameCount = 46;   // フレーム数(画像内のコマ数)
        let currentFrame = 0;    // 現在表示中のフレーム番号
        let isDragging = false;  // マウスドラッグ中かどうかの判定
        let startX = 0;          // ドラッグ開始時のX座標

        // フレームを更新する関数
        function updateFrame(frame) {
            const frameHeight = viewer.clientHeight; // ビューアの高さ(画像の高さ)を取得
            
            // 無限回転を可能にする正規化
            // フレーム番号を0からframeCount-1の範囲に正規化
            const normalizedFrame = ((frame % frameCount) + frameCount) % frameCount;
            console.log(`Normalized Frame: ${normalizedFrame}`);
            
            // 背景位置を更新(縦方向にずらして別のフレームを表示)
            viewer.style.backgroundPosition = `0px -${normalizedFrame * frameHeight}px`

            // 現在のフレーム番号を表示
            frameNumberDisplay.textContent = normalizedFrame;
        }

        // マウスドラッグで回転(横ドラッグ対応)
        // ドラッグ開始
        viewer.addEventListener("mousedown", (e) => {
            isDragging = true;  // ドラッグ開始フラグ
            startX = e.clientX; // 開始位置のX座標を記録
            viewer.style.cursor = "grabbing"; // カーソルを「つかんでいる」形に
        });
        // ドラッグ中
        document.addEventListener("mousemove", (e) => {
            if (isDragging) {
                const deltaX = e.clientX - startX; // 移動距離を計算
                const sensitivity = 2; // 感度調整
                
                if (Math.abs(deltaX) > sensitivity) {
                    const direction = deltaX > 0 ? 1 : -1; // 右ドラッグで進む、左ドラッグで戻る
                    currentFrame += direction;
                    updateFrame(currentFrame);
                    startX = e.clientX; // 開始位置を更新
                }
            }
        });

        // ドラッグ終了
        document.addEventListener("mouseup", () => {
            isDragging = false; // ドラッグ終了
            viewer.style.cursor = "grab"; // カーソルを元に戻す
        });

        // 初期表示
        updateFrame(0);
    </script>
</body>

</html>

苦労点

360°以上回転させると、表示されなくなって真っ白になる現象が起こってたのですが、AIのclaudeを利用し、以下の理論でなんとか切り抜けました。

無限ループ正規化の仕組み

frameが47になったら → 0に戻る
frameが-1になったら → 45に戻る
結果:0〜45の範囲で無限ループ

通常の範囲内(最大値の46フレーム内)
frame = 10の場合
((10 % 46) + 46) % 46
= (10 + 46) % 46
= 56 % 46
= 10

frame = 45の場合
((45 % 46) + 46) % 46
= (45 + 46) % 46
= 91 % 46
= 45

範囲(最大値の46フレーム)を超えた場合
frame = 46の場合(1周目)
((46 % 46) + 46) % 46
= (0 + 46) % 46
= 46 % 46
= 0  ← 0に戻る!

frame = 47の場合
((47 % 46) + 46) % 46
= (1 + 46) % 46
= 47 % 46
= 1

frame = 92の場合(2周目)
((92 % 46) + 46) % 46
= (0 + 46) % 46
= 46 % 46
= 0  ← また0に戻る!


負の数(逆回転)
frame = -1の場合
((-1 % 46) + 46) % 46
= (-1 + 46) % 46
= 45 % 46
= 45  ← 45に戻る!

frame = -2の場合
((-2 % 46) + 46) % 46
= (-2 + 46) % 46
= 44 % 46
= 44

frame = -47の場合
((-47 % 46) + 46) % 46
= (-1 + 46) % 46
= 45 % 46
= 45

メモ程度ですので、さらに追記等すると思います!

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?