初めまして!新卒1年目エンジニアのよこちです。

新卒研修にて自己紹介サイトを作る機会があったので、その際に使用した技術についてまとめてみました!

 

目次

  • 自己紹介
  • 自己紹介サイト
  • Three.jsの基本的な使い方
  • 立方体(3Dオブジェクト)の描画
  • DOM要素を3D空間に配置

 

自己紹介

新卒エンジニアとして4月に入社しました。

情報系出身ではありませんが、プログラミングスクールのメンターアルバイトをやりながら1年半ほどプログラミングを学んでいました!新しいことを学び始めるときに一番ワクワクする人間です。どうぞよろしくお願いいたします。

自己紹介サイト

新卒研修で作成した自己紹介サイトでは、サイト上に立方体を描画して、各面を押すと自分の趣味や学生時代の情報がモーダル表示されるような機能をつけました。この機能をつけようと思った理由としては、「自分の情報をたくさん伝えたい」、「情報過多は避けたい」という2つの思いがあり、自分の情報の詰まったものをユーザーが任意で開けられるようにしようと考えたからです。あと、「ごきげんよう」という番組のサイコロを転がすシーンが好きだったので、サイコロがよぎりました。

 

実際に表示させた3Dオブジェクト

 

使用したのは、手軽に3Dコンテンツを作成・表示・操作できるJavaScriptライブラリのThree.jsです。

本投稿で紹介させていただくことは以下の通りです。

  • Three.jsの基本的な使い方
  • 立方体(3Dオブジェクト)の描画

サイト内で3Dモデルなどを利用しようと考えている方の参考になれば嬉しいです。

 

Three.jsの基本的な使い方

導入

npmパッケージをinstallするか、以下のようにHTMLファイル内の<head></head>タグ内にCDNからのインポートを記述します。

<script type="importmap">
        {
          "imports": {
            "three": "https://cdn.jsdelivr.net/npm/three@v0.149.0/build/three.module.js",
            "three/addons/": "https://cdn.jsdelivr.net/npm/three@v0.149.0/examples/jsm/"
          }
        }
</script>

次に<body></body>タグ内に以下のように記述し、Three.jsを使える環境にしたら準備完了です。

<body>
    <div id="3d_space"></div>
    <script type="module">
        import * as THREE from 'three';
    </script>
</body>

 

Three.jsでオブジェクトを描画させるには

大まかに以下の準備が必要です。

  • シーンの作成
    • 3Dオブジェクトを表示するための空間を作成します
  •  レンダラーの作成
    • WebGL()をレンダリングするためのものです
  •  カメラの作成
    • 3D空間を見る視点を決めます
  • メッシュの作成
    • 自分の表示させたいオブジェクトを作成するために必要なものです
  •  ライトの作成
    • シーンを照らすライトの位置や明るさの設定をします
  •  アニメーションの設定
    • 3Dオブジェクトをどのように動かすかを決めます

実際に立方体を表示させる過程で確認していきましょう。

 

立方体(3Dオブジェクト)の描画

シーンの作成

const scene = new THREE.Scene();

レンダラーの作成

レンダリング領域の大きさの他に背景の色なども設定できます。指定したDOM要素に対して子要素にcanvas領域を作成しレンダラーを追加します。

const renderer = new THREE.WebGLRenderer(); 
// レンダリングする領域の大きさを指定
renderer.setSize(window.innerWidth, window.innerHeight); 
// canvas領域にレンダラーを追加
document.getElementById('cube').appendChild(renderer.domElement);

カメラの作成

今回はPerspectiveCameraを使用し、第1引数では視野角、第2引数では画面のアスペクト比を指定します。第3,4引数ではカメラから見て一定距離区間の間に存在するオブジェクトだけをレンダリングするクリッピング機能のためのプロパティに値を指定します。そしてposition.setではカメラの位置を定めます。

// カメラを作成
const camera = new THREE.PerspectiveCamera(
    45,
    window.innerWidth / window.innerHeight,
    1,
    10000
);
// カメラの位置を指定
camera.position.set(0, 0, 2000);

メッシュの作成

メッシュの作成にはジオメトリとマテリアルの作成が必要です。ジオメトリは立方体(BoxGeometory)を指定し大きさを決めます。マテリアルはジオメトリの表面の材質などを指定できます。これらを用いてメッシュを作成し、シーンに追加します。

// ジオメトリを作成
const geometry = new THREE.BoxGeometry(500, 500, 500);
// マテリアルを作成
const material = new THREE.MeshStandardMaterial({
      color: 0x0000ff
});
// メッシュを作成
const box = new THREE.Mesh(geometry, material);
// シーンに追加
scene.add(box);

ライトの作成

今回はDirectionalLightで並行光源を再現し、引数で光の色や強さを指定できます。ライトの位置を指定してシーンに追加します。

// ライトを作成
const light = new THREE.DirectionalLight(0xffffff);
// 光の強さを2倍にする
light.intensity = 2; 
// ライトの位置を指定
light.position.set(1, 1, 1); 
// シーンに追加
scene.add(light);

アニメーション

requestAnimationFrameで画面のフレームが切り替わるたびにアニメーション関数(roll)を実行しスムーズなアニメーションを実現させます。アニメーション関数(roll)によりフレーム毎に3Dオブジェクトの位置とカメラの映像が変わるので、sceneとcameraのレンダリングを行います。

roll();

function roll() {
     requestAnimationFrame(roll);

     // 箱を回転させる
     box.rotation.x += 0.01;
     box.rotation.y += 0.01;

     // レンダリング
     renderer.render(scene, camera);
}

 

以下が立方体を表示させるための全コードです。

<body>
    <div id="cube"></div>
    <script type="module">
        import * as THREE from 'three';

        // シーンの作成
        const scene = new THREE.Scene();

        //レンダラーの設定
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.getElementById('cube').appendChild(renderer.domElement);

        // カメラを作成
        const camera = new THREE.PerspectiveCamera(
            30,
            window.innerWidth / window.innerHeight,
            1,
            10000
        );
        camera.position.set(0, 0, 2000);

        // 立方体を作成
        const geometry = new THREE.BoxGeometry(500, 500, 500);
        const material = new THREE.MeshStandardMaterial({
            color: 0x0000ff
        });
        const box = new THREE.Mesh(geometry, material);

        scene.add(box);

        const light = new THREE.DirectionalLight(0xffffff);
        light.intensity = 2; 
        light.position.set(1, 1, 1); 
        // シーンに追加
        scene.add(light);

        renderer.render(scene, camera);

        roll();

        function roll() {
            requestAnimationFrame(roll);

            // 箱を回転させる
            box.rotation.x += 0.01;
            box.rotation.y += 0.01;

            // レンダリング
            renderer.render(scene, camera);
        }
    </script>
</body>

実行結果がこちらになります。

立方体の描画はこれにて完了です。

ですが、立方体の各面に対して文字やボタンなどが含まれるDOM要素を配置するには、上記の内容とは少し異なる手法が必要になります。以下の「DOM要素を3D空間に配置」でその方法を説明します。

 

DOM要素を3D空間に配置

DOM要素を配置するには以下のような準備が必要です。

  • シーンの作成
  • レンダラーの作成
  • カメラの作成
  • メッシュの作成
  • CSS3Dオブジェクトの作成
  • アニメーションの設定

Three.jsが用意してくれている立方体や球体の3Dオブジェクトを描画する時とほとんど準備するものは一緒です。しかし、レンダラーの作成とCSS3Dオブジェクトの作成に関しては3Dオブジェクトの描画とは異なるので説明させていただきます。

 

導入

3D空間に配置するDOM要素をHTML内で記述します。

また、CSS3DObjectとCSS3DRendererはDOM要素を操作する上で必要になるので<script></script>内に以下のように追記し、importします。

<body>
    <div id="sample"></div>
    <div id="domElement">
        <div class="surface">
            DOM要素
        </div>
    </div>
    <script type="module">
        import * as THREE from 'three';
        import {CSS3DObject, CSS3DRenderer} from "three/addons/renderers/CSS3DRenderer.js"; // 追記
    </script>
</body>

レンダラーの作成

WebGLRendererではなくCSS3DRendererからレンダラーを作成します。

import {CSS3DObject, CSS3DRenderer} from "three/addons/renderers/CSS3DRenderer.js"; 

・・・

// CSS3DRendererからレンダラーを作成
const cssRenderer = new CSS3DRenderer();
cssRenderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById('sample').appendChild(cssRenderer.domElement);

CSS3Dオブジェクトを作成

まず、HTML内に用意したDOM要素を変数に格納し、必要なCSSを付与します。CSSに関しては、CSSファイル内に記述していても問題ありません。DOM要素が格納された変数からCSS3Dオブジェクトを作成し、立方体の面の位置に来るように位置設定をします。そしてシーンに追加するのではなく立方体オブジェクトにCSS3Dオブジェクトを追加(add)することで立方体に対してアニメーションを付与した時に動きを同期してくれます。

const domElement = document.getElementById("domElement"); 
domElement.style.backgroundColor = 'rgba(0, 200, 255, 0.5)'; 
domElement.style.width = '500px'; 
domElement.style.height = '500px'; 
domElement.style.fontSize = '4vh'; 
domElement.style.border = 'solid'; 
domElement.style.textAlign = 'center'; d
omElement.style.lineHeight = '500px'; 

// CSS3Dオブジェクトを作成
const cssObject = new CSS3DObject(domElement);
// 立方体の面に配置 
cssObject.position.set(0, 0, 250);
// 立方体にオブジェクトを追加 
box.add(cssObject);

以下がDOM要素を立方体の面に配置するための全コードです。

<body>
    <div id="sample"></div>
    <div id="domElement">
        <div class="surface">
            DOM要素
        </div>
    </div>
    <script type="module">
        import * as THREE from 'three';
        import {CSS3DObject, CSS3DRenderer} from "three/addons/renderers/CSS3DRenderer.js";

        // シーンの作成
        const scene = new THREE.Scene();

        // レンダラーの設定
        const cssRenderer = new CSS3DRenderer();
        cssRenderer.setSize(window.innerWidth, window.innerHeight);
        document.getElementById('sample').appendChild(cssRenderer.domElement);

        // カメラを作成
        const camera = new THREE.PerspectiveCamera(
            45,
            window.innerWidth / window.innerHeight,
            1,
            10000
        );
        camera.position.set(0, 0, 2000);

        // 立方体を作成
        const geometry = new THREE.BoxGeometry(500, 500, 500);
        const material = new THREE.MeshStandardMaterial({
            color: 0x0000ff
        });
        const box = new THREE.Mesh(geometry, material);

        scene.add(box);

                // DOM要素を取得しCSSを適応
        const domElement = document.getElementById("domElement");
        domElement.style.backgroundColor = 'rgba(0, 200, 255, 0.5)';
        domElement.style.width = '500px';
        domElement.style.height = '500px';
        domElement.style.fontSize = '4vh';
        domElement.style.border = 'solid';
        domElement.style.textAlign = 'center';
        domElement.style.lineHeight = '500px';

                 // CSS3Dオブジェクトを作成
        const cssObject = new CSS3DObject(domElement);
        cssObject.position.set(0, 0, 250); 
        box.add(cssObject);

        roll();
        
        // アニメーションの設定
        function roll() {
            requestAnimationFrame(roll);

            box.rotation.x += 0.01;
            box.rotation.y += 0.01;

            cssRenderer.render(scene, camera);
        }
    </script>
</body>

こちらが実行結果になります。CSS3DRendererでは3Dオブジェクトである立方体は可視化できませんが、立方体の動きに沿ってDOM要素が回転している状態です。

同じようなDOM要素を6つ用意して位置関係を考えながら同様の処理を施すと立方体が完成します!

おわりに

3Dオブジェクトを描画するためのライブラリThree.jsについて書かせていただきました。Three.jsを使えば、球体や多面体などのオブジェクトを比較的簡単に作成でき、サイト内を充実させることができます。ぜひ使ってみてください!

また、新しいライブラリに触れると簡単に開発の幅を広げられるなと感じました。とくにJavaScriptにはさまざまなライブラリが豊富にあるので自分に必要であるものを取捨選択しうまく活用していきたいなと思います。

 

Join Us !

ウエディングパークでは、一緒に働く仲間を募集しています!
ご興味ある方は、お気軽にお問合せください(カジュアル面談から可)

採用情報を見る