React + Threejs + Swiper パノラマ効果を実現するための完全なコード

React + Threejs + Swiper パノラマ効果を実現するための完全なコード

パノラマビュー効果を見てみましょう: 住所を表示
スクリーンショット:

パノラマ

体験してみると、周囲の環境がぐるりと回転し、地球が丸いように感じませんか? 😁
それは正しい!正解おめでとうございます!地球は丸い! 👀

パノラマ効果の実現

上記のヒントから、threejs に少し詳しい友人は、このパノラマ効果が実際には球体を使用して実現されていることを推測したかもしれません。そして、球体内側の表面にテクスチャ マップを貼り付けただけです (ホイールを外側に転がすと、この球体を見ることができます。ガラス玉のように見え、非常に美しいです。イースター エッグもあります 😁 (まあ、口に出すとイースター エッグではありませんが)):

ここに画像の説明を挿入

最初、視点は球体の中心にあり、視点の動きは threejs が提供するOrbitControlsツールによって制御されます。

この球体を作成するコードは次のようになります。

const ジオメトリ = new THREE.SphereBufferGeometry(500, 32, 32);
geometry.scale(-1, 1, 1); // テクスチャを反転する const material = new THREE.MeshBasicMaterial({
    map: new THREE.TextureLoader().load(imglist[0].default) // 画像のURLまたはパス、あるいはデータURIを渡します。
});
const mesh = new THREE.Mesh(geometry, material);
シーンを追加します(メッシュ);

const controls = new OrbitControls(カメラ、renderer.domElement);
コントロールのパンを有効にする = false;
コントロールの最大距離 = 1000;

Data URIが何なのか分からない場合は、MDNのドキュメントを参照してください。

カルーセル

カルーセルは、非常に便利な swiper ライブラリを使用して実装されています。詳細については、ドキュメントを参照してください。
カルーセルをスライドすると、 onSliderChangeイベントがトリガーされます。このイベントは、現在のswiperパラメータとして渡します。現在アクティブになっている要素から画像を取得し、球体のテクスチャ マップを置き換えることができます。

onSliderChange = curSwiper => {
    const メッシュ = this.mesh;
    const テクスチャ = imglist[curSwiper.activeIndex].default;
    mesh.material.map = new THREE.TextureLoader().load(texture);
};

以下は私のスワイパー設定です。SwiperSlider はスライド可能なカルーセル カード、EffectCoverflow はスライド時にトリガーされる効果、スワイパーは Fade、Coverflow、Flip、Cube の 4 つのオプション効果を提供します。 imglist画像のグループであり、 imglist[i].default属性には画像の base64 エンコードが格納されます。

'swiper/react' から { Swiper、SwiperSlide } をインポートします。
'swiper' から SwiperCore をインポートします。{EffectCoverflow}
'swiper/swiper.min.css' をインポートします。
'swiper/components/effect-coverflow/effect-coverflow.min.css' をインポートします。

SwiperCore.use([EffectCoverflow]);

//....
<スワイパー
    className='パノラマ画像'
    spaceBetween={50} // 間隔 slidesPerView={3} // スライドショーでプレビューできる画像の数 onSlideChange={this.onSliderChange} // スライド時にトリガーされるコールバック onSwiper={(swiper) => console.log(swiper)} // 初期ロード時にトリガーされるコールバック direction='vertical' // スライドショーの方向、デフォルトでは水平
    effect={'coverflow'} // スライド効果 grabCursor={true} // マウスをカルーセル上に置いたときにドラッグを表示するかどうか centeredSlides={true} // 現在アクティブな画像を中央に配置するかどうか coverflowEffect={{ // カバーフロー効果のパラメータ設定。自分で調整できます "rotate": 50,
        「ストレッチ」: 0,
        「深さ」: 100,
        「修飾子」: 1,
        "スライドシャドウ": true
    }}
    {
        imglist.map((img, idx) => {
            <SwiperSlide key={idx}> を返します
                <img src={img.default} className='パノラマ画像'></img>
            </スワイパースライド>
        })
    }
</スワイパー>

パノラマ効果の実装については以上です。もちろん、ご質問があれば、メッセージを残したり、私のコード(下記に掲載)を参照したりできます。threejsとreactをある程度理解していれば、このような効果を実現することは難しくないと思いますし、コードの量も非常に少ないです〜

完全なコード

React をインポートします。{ コンポーネント } から 'react' をインポートします。

'@theme/Layout' からレイアウトをインポートします。
'@docusaurus/Head' から Head をインポートします。

* を 'three' から THREE としてインポートします。
'three/examples/jsm/controls/OrbitControls' から {OrbitControls } をインポートします。
'アンダースコア' から _ として * をインポートします。
'antd' から { message } をインポートします。

'swiper/react' から { Swiper、SwiperSlide } をインポートします。
'swiper' から SwiperCore をインポートします。{EffectCoverflow}
'swiper/swiper.min.css' をインポートします。
'swiper/components/effect-coverflow/effect-coverflow.min.css' をインポートします。

'./index.css' をインポートします。
'./imgs.json' から imgs をインポートします。

SwiperCore.use([EffectCoverflow]);

const imglist = imgs.map(img => {
    戻り値は require('../../../static/img/panoramic/' + img.name); です。
});

エクスポートデフォルトクラスPanormaticはComponentを拡張します{
    コンストラクタ() {
        素晴らしい();
        this.renderer = null;
        this.camera = null;
        this.scene = null;
        this.container = null;
        this.controls = null;
        this.showMessage = true; // イースターエッグプロンプト}

    コンポーネントマウント() {
        const コンテナ = document.getElementById('パノラマキャンバスコンテナ');
        const キャンバス = document.getElementById('パノラマキャンバス');
        const レンダラー = new THREE.WebGLRenderer({ canvas, antialias: true });

        renderer.setClearColor(0xffffff); // b2e0df 緑豆ペースト colorrenderer.setPixelRatio( window.devicePixelRatio );
        定数height = container.clientHeight;
        定数幅 = コンテナ.clientWidth;
        レンダラーのサイズを設定します(幅、高さ)。
        
        const カメラ = new THREE.PerspectiveCamera(60, 幅 / 高さ, 1, 30000);
        カメラの位置を0, 0, 1に設定します。
        カメラの中心を新しいTHREE.Vector3(0, 0, 0);

        const scene = new THREE.Scene();

        const ジオメトリ = new THREE.SphereBufferGeometry(500, 32, 32);
        geometry.scale(-1, 1, 1); // テクスチャを反転する const material = new THREE.MeshBasicMaterial({
            マップ: 新しい THREE.TextureLoader().load(imglist[0].default)
        });
        const mesh = new THREE.Mesh(geometry, material);
        シーンを追加します(メッシュ);

        const controls = new OrbitControls(カメラ、renderer.domElement);
        // controls.enableZoom = false;
        コントロールのパンを有効にする = false;
        コントロールの最大距離 = 1000;

        this.renderer = レンダラー;
        this.camera = カメラ;
        this.scene = シーン;
        this.container = コンテナ;
        this.controls = コントロール;
        this.mesh = メッシュ;

        // プロンプトボックスのグローバル構成を設定します message.config({
            上: 100,
            期間: 3.5,
            最大数: 1,
        });

        this.onControlsChange = _.throttle(this.onChange, 100);
        controls.addEventListener('change', this.onControlsChange);
        ウィンドウにイベント リスナーを追加します ('サイズ変更'、this.onWindowResize);
        このレンダリングループ();
    }

    コンポーネントのマウントを解除します(){
        const メッシュ = this.mesh;
        メッシュマテリアルを破棄します。
        メッシュのジオメトリを破棄します。
        this.scene.remove(メッシュ);
        ウィンドウのサイズ変更イベントを削除します。
        this.controls.removeEventListener('change', this.onControlsChange);
        メッセージ.destroy();
    }

    onChange = (e) => {
        カメラを定数に設定する。
        カメラの位置からカメラの中心までの距離が700以上の場合
            if (this.showMessage) {
                message.success('🎊パノラマ効果の小さな秘密を発見できておめでとうございます〜🎉');
                this.showMessage = false;
            }
        } それ以外 {
            this.showMessage = true;
        }
    }

    onSliderChange = (curSwiper) => {
        const メッシュ = this.mesh;
        const テクスチャ = imglist[curSwiper.activeIndex].default;
        mesh.material.map = new THREE.TextureLoader().load(texture);
    };

    ウィンドウのサイズ変更 = () => {
        カメラを定数に設定する。
        const レンダラー = this.renderer;
        定数の幅 = this.container.clientWidth;
        高さ = this.container.clientHeight;
        
        カメラのアスペクト = 幅 / 高さ;
        カメラの投影マトリックスを更新します。
        
        レンダラーのサイズを設定します(幅、高さ)。
    };

    レンダリングループ = () => {
        this.renderer.render(this.scene、this.camera);
        アニメーションフレームをリクエストします(this.renderLoop);
    };

    与える() {
        戻る (
            <レイアウト>
                <ヘッド>
                    <title>パノラマ | Yle</title>
                </ヘッド>
                <div id='パノラマコンテナ'>
                    <スワイパー
                        className='パノラマ画像'
                        間隔={50}
                        スライド数/ビュー={3}
                        onSlideChange={this.onSliderChange}
                        onSwiper={(スワイパー) => console.log(スワイパー)}
                        方向='垂直'
                        効果={'カバーフロー'}
                        グラブカーソル={true}
                        centeredSlides={true}
                        カバーフロー効果={{
                            「回転」: 50,
                            「ストレッチ」: 0,
                            「深さ」: 100,
                            「修飾子」: 1,
                            "スライドシャドウ": true
                        }}
                    >
                        {
                            imglist.map((img, idx) => {
                                <SwiperSlide key={idx}> を返します
                                    <img src={img.default} className='パノラマ画像'></img>
                                </スワイパースライド>
                            })
                        }
                    </スワイパー>
                    <div id='パノラマキャンバスコンテナ'>
                        <canvas id='パノラマキャンバス'></canvas>
                    </div>
                </div>
                
                
            </レイアウト>
        );
    }
}

パノラマ効果を実現するためのReact + Threejs + Swiperの完全なコードに関するこの記事はこれで終わりです。より関連性の高いReactパノラマコンテンツについては、123WORDPRESS.COMの以前の記事を検索するか、次の関連記事を引き続き参照してください。今後も123WORDPRESS.COMを応援していただければ幸いです。

以下もご興味があるかもしれません:
  • three.js を使用して Vue でパノラマを実現する完全な例
  • Three.js をベースに 360 度パノラマ画像を実現
  • Three.jsプラグインをベースに360度パノラマを作成する
  • THREE.JS 入門チュートリアル (6) パノラマを作成する手順
  • JSはパノラマ画像効果の360度回転を実現

<<:  VMware 仮想マシン ブリッジ モードでインターネットにアクセスできない問題を解決する方法

>>:  Navicat を使用してリモート Linux MySQL データベースに接続するときに発生する 10061 不明エラーの詳細な説明

推薦する

MySQL カーソルの概念と使用法の詳細な説明

この記事では、例を使用して MySQL カーソルの概念と使用方法を説明します。ご参考までに、詳細は以...

HTML テーブルタグチュートリアル (13): 内部境界スタイル属性ルール

RULES を使用すると、テーブルの内部境界のスタイルを制御できます。基本的な構文<TABLE...

docker を使用して Spring Boot をデプロイし、Skywalking に接続する方法

目次1. 概要1. スカイウォーキング入門2. スカイウォーキング建築3. スカイウォーキングはどの...

Vueコンポーネント間の通信の非常に詳細な要約

目次序文1. Props、$emit一方向データフロー2. $親、$子3. $attrs、$list...

MySQLテーブルの自動インクリメント列の初期値をリセットする方法

MySQLテーブルの自動インクリメント列の初期値をリセットする方法1. 問題の説明MySQL データ...

Docker ベースの Redis マスタースレーブ クラスタの実装

目次1. Redisイメージを取得する2. 6つのRedisコンテナを作成する3. Redisコンテ...

MySQLとOracleの違いのまとめ(機能性能の比較、選択、使用時のSQLなど)

1. 同時実行性同時実行性は OLTP データベースの最も重要な機能ですが、同時実行性にはリソース...

Ubuntu 16.04 に nvidia ドライバー + CUDA + cuDNN をインストールする詳細なチュートリアル

準備1. GPUがCUDAをサポートしているかどうかを確認するlspci | grep -i nvi...

便利で使いやすいウェブアプリケーションを設計するための 10 のヒント

より使いやすい Web アプリケーションを設計するための 10 のヒントをご紹介します。ヒント1: ...

JSは賞金の重さに基づいて当選確率を計算します

目次1. シナリオ例1.1. 抽選の賞品名を設定する1.2. 各賞の重みを設定する1.3. ラッキー...

JSはオンラインでのアナウンスのスクロール効果を実現します

この記事では、オンラインアナウンスのスクロール効果を実現するためのJSの具体的なコードを参考までに共...

MySQL ストレージ エンジン MyISAM と InnoDB の違いの概要

1. MySQLのデフォルトストレージエンジンの変更MySQL 5.1 より前のバージョンでは、デフ...

大規模なデータテーブルのコピー効率を向上させるMySQLソリューション

序文この記事では主に、MySQL で大規模なデータ テーブルのコピーの効率を向上させることに関する関...

JavaScript を使用してテーブル情報を追加および削除する

JavaScript 入門JavaScript は軽量なインタープリタ型の Web 開発言語です。言...

MySQL 5.7 スレーブノードからマルチスレッド マスター スレーブ レプリケーションを構成する方法の詳細な説明

序文MySQL は MySQL 5.6 からマルチスレッド レプリケーションをサポートしていますが、...