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 不明エラーの詳細な説明

推薦する

Alibaba Cloud ECS centos6.8 に MySql5.7 をインストールして設定するチュートリアル

Alibaba Cloud yum コマンドでのデフォルトの MySQL バージョンは 5.17**...

Dockerfile を使用して Docker でイメージを構築する方法

イメージを構築するこれまで、テストやデモンストレーションにさまざまなイメージを使用しました。多くの場...

単一の MySQL テーブルで数千万のデータを処理するアイデアを共有する

目次プロジェクトの背景改善案データ特性を観察するマルチプロセスアイデアの要約データ処理スキルプロジェ...

JavaScriptはフォームデータの非同期取得を実装します

この記事では、フォームデータの非同期取得を実現するためのJavaScriptの具体的なコードを例とし...

JavaScriptのモジュール性を理解する方法

目次1. ブラウザのサポート2.エクスポートモジュールのエクスポート3. モジュールをインポートする...

JavaScriptはランダムコードの生成と検証を実現する

JavaScriptでのランダムコードの生成と検証は参考までに。具体的な内容は以下のとおりです。イベ...

CSS3で実装された3Dトンネル効果

達成された効果実装コードhtml <div class="scene"&g...

Linux 負荷分散 LVS の詳細な理解

目次1. LVS 負荷分散2. 負荷分散LVSの基本紹介3. LVSアーキテクチャ3.1 ロードバラ...

Web デザインにおける Less と More について語る (写真)

Less is More は多くのデザイナーのキャッチフレーズです。これは建築界の巨匠ルートヴィヒ...

Vueはツリー構造の追加、削除、変更、チェックのサンプルコードを実装します

実は多くの会社がユーザー権限ツリーに似た機能を持っています。最近、追加、削除、修正のツリー構造を書き...

elementui の el-popover スタイルの変更が有効にならない問題の解決策

element-uiを使用する場合、el-popoverというよく使われるコンポーネントがありますが...

JavaScript の BigIn 関数の共通プロパティをまとめます

目次1. 概要2. 属性1. 数学演算子2. 比較演算子3. ブール演算結論1. 概要BigInt ...

Linux システムで crontab を使用して MySQL データベースを定期的にバックアップする方法

システムの crontab を使用して定期的にバックアップ ファイルを実行し、バックアップ結果を日付...

Dockerを使用してLaravelおよびVueプロジェクトの開発環境を構築する詳細な説明

この記事では、Docker で構築された Laravel および Vue プロジェクトの開発環境を紹...

MySQLデータベース移行におけるデータ文字化けの問題を解決する

リーダーの指示のもと、Java プロジェクトを引き継ぎ、リファクタリングを行う必要がありました。同時...