【JavaScript 3D 入門講座】HTMLでここまでできる!3D表現の入口 Three.jsをつかってみよう

1. はじめに

ゲーム開発をしていく中で、色々なアイデア出しをしてるのですが、その中の一つで、3Dの話題が出て「Three.js」を触って見て、どうせなら記事にしようと思い、 本講座を企画。

「3Dって難しそう…」「JavaScriptでそこまでやるの?」

そう思っていた自分が、わずか十数行のコードで画像を回転させて、“立体的に浮かぶカード” を表示できた時── 思わず「これ、本当にHTMLだけで動いてるの?」と驚きました。

この記事では、3Dライブラリ「Three.js(スリー・ジェイエス)」を使って、 Webページ上に軽量な3D空間を表示する最初の一歩を解説します。

👣 この記事でできること

  • CDN読み込みでThree.jsを動かす
  • HTML+JavaScriptだけで3Dオブジェクトを表示する
  • カード画像を「空間に浮かべて、回転」させる
  • よくあるエラーの回避方法も解説

💡 読者対象

  • JavaScriptで3Dを「ちょっと試してみたい」人
  • Webで3DのUIや演出を取り入れたい人
  • Three.jsに興味はあるけど、どこから触っていいか分からない人

🔰 難易度

超入門(HTML・JSの基礎知識があればOK)

2. Three.jsを読み込んでみよう

Three.js(スリー・ジェイエス)は、WebGLを簡単に扱えるようにした JavaScript製の3Dライブラリです。

まずは、Webページに読み込んで、最小構成で動かすところから始めましょう。

📦 方法①:CDNで読み込む(最も手軽な方法)

以下のコードを <script type="module"> の形で使います。

Three.js は近年「モジュール(ESM)」として使うのが推奨されており、type=“module” が必要です。

<!-- HTMLファイルのどこか<body>の最後に貼り付けてOK -->
<script type="module">
  import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.152.0/build/three.module.js";

  // Three.js を使ったコードはこの中に書いていきます
</script>

✅ 解説

内容
type="module" モジュールとして読み込むための宣言。最近のThree.jsでは必須。
import * as THREE from ... THREE.SceneTHREE.Mesh などを使えるように読み込みます。

💡 注意点

  • 古い記事では three.min.js を読み込む例もありますが、それでは THREE is not defined のエラーが出ることがあります。
  • モジュール構成に対応していないCDNや、type=“module” を省略すると正しく動きません。
  • ファイルをローカル(file://)で開くと一部制限がかかるため、なるべくローカルサーバ(VSCode + Live Serverなど)で開くのがおすすめです。

🧪 ここまでで準備OK!

次のステップでは、実際に「画像を貼った3Dカード」を表示してみましょう。

自分の好きな画像を浮かせて回すだけでも、3Dの楽しさを実感できます。

3. 初めての3Dカード表示

さて、Three.js の読み込みができたら、いよいよ本格的に「3D空間にカード画像を浮かべて回す」ことに挑戦してみましょう。

最小構成なので、たったの十数行のコードで立体的な表現が可能です。

📷 表示する画像

ここでは、カードの表として使う画像をひとつ用意してください。

画像ファイル名は card-back.webp(または .png, .jpg)として、

HTMLと同じ階層に assets/img/ フォルダを用意し、その中に画像を置くとスムーズです。

サンプル

Stable Diffusion checkpoint + 著作権フリーのnovaAnimeXLで作成したサンプル画像を置いておきます。

サンプル:Stable Diffusion checkpoint + novaAnimeXL

💻 フルコード(コピーしてそのまま使えます)

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <title>3Dカード表示サンプル</title>
  <style>
    body { margin: 0; overflow: hidden; background: #000; }
    canvas { display: block; }
  </style>
</head>
<body>
  <script type="module">
    import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.152.0/build/three.module.js";

    // シーン(空間)を作る
    const scene = new THREE.Scene();

    // カメラ(視点)を作る
    const camera = new THREE.PerspectiveCamera(
      75,                     // 視野角
      window.innerWidth / window.innerHeight, // アスペクト比
      0.1, 1000               // 描画範囲(手前〜奥)
    );
    camera.position.z = 5; // カメラのZ位置を少し後ろへ

    // レンダラー(描画エンジン)
    const renderer = new THREE.WebGLRenderer({ alpha: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // テクスチャ画像の読み込み
    const texture = new THREE.TextureLoader().load("card-back.webp");

    // カードの形(平面)を作る
    const geometry = new THREE.PlaneGeometry(2, 3); // 幅2, 高さ3

    // マテリアル(表面の材質)
    const material = new THREE.MeshBasicMaterial({ map: texture, transparent: true });

    // カードを作ってシーンに追加
    const card = new THREE.Mesh(geometry, material);
    scene.add(card);

    // アニメーション処理
    function animate() {
      requestAnimationFrame(animate);
      card.rotation.y += 0.01; // Y軸(左右)に回転
      renderer.render(scene, camera);
    }
    animate();
  </script>
</body>
</html>

✅ 実行するとどうなる?

  • 黒い画面に、カード画像がふわっと浮かび、ゆっくり回転し始めます。
  • マウスやキーボードでの操作はまだありませんが、視覚的に“3D空間”を感じられます。

🎯 補足:コードの役割ざっくりまとめ

パート 内容
scene 3Dの世界そのもの(オブジェクトを入れる箱)
camera その世界をどの角度・距離で見るか
renderer 描画エンジン(canvasに表示)
geometry カードの形(2D平面)
material 表面のテクスチャ(画像)
Mesh 形+材質=1枚のカード
animate() 毎フレーム回転させて描画

🛠️ トラブル時のチェックリスト

  • 画像が表示されない?
    • パスが “assets/img/…” で正しいか
    • card-back.webp が存在するか
    • サーバで実行してるか(Live Server推奨)

🌟 ここまででできたこと

  • Three.jsをCDNで読み込む
  • 平面に画像を貼って、回転アニメーションを加える
  • 「HTMLとJavaScriptだけで、ここまでできるんだ」という感覚を体験

4. よくあるエラーとその回避方法

Three.js は非常に強力なライブラリですが、初めて使うときにハマりやすいエラーがいくつかあります。

この章では、あなたが実際に体験したつまずきも含めて、よくあるエラーと対処法を丁寧に紹介します。

❌ エラー①:Uncaught ReferenceError: THREE is not defined

🔍 原因:

Three.js の読み込み方法が古いため、THREE オブジェクトがグローバルで使えなくなっています。

💡 解決法:

以下のように type=“module” を指定して読み込むのが正しい方法です。

<script type="module">
  import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.152.0/build/three.module.js";
</script>

⚠️ three.min.js のような古いCDNを <script src=…> で読み込む方法は非推奨です。

❌ エラー②:画像が表示されない / 真っ白なカードになる

🔍 原因の例:

  • ファイルのパスが間違っている
  • 画像ファイルが存在しない
  • ローカル環境でセキュリティ制限がかかっている

💡 解決法:

  • 画像パスが assets/img/card-back.webp のように正しいか確認
  • ブラウザの「ネットワーク」タブで 404(ファイルがない)になっていないか確認
  • ローカルサーバ(Live Serverなど)で開くことを推奨
    • file:// では画像の読み込みやWebGLが正常に動かないことがあります

❌ エラー③:Cross origin requests are only supported…

🔍 原因:

ローカルのHTMLファイルを file:// 経由で開いているため、画像の読み込みに制限がかかっている。

💡 解決法:

ローカルにWebサーバを立てる。

🔧 例:VSCode + Live Server 拡張機能

  1. HTMLファイルを VSCode で開く
  2. 右クリック → 「Open with Live Server」
  3. http://127.0.0.1:5500/… のようなURLで安全に実行されます

⚠️ 警告:WebGL fallback to software renderer…

🔍 意味:

  • GPUによる描画がうまく使えず、ソフトウェアレンダリングに切り替わったことを示す警告。
  • 特にローカルファイルや古い環境でよく出ます。

💡 解決法:

  • **基本は無視してOK。**実行自体に問題がなければ警告です。
  • 気になる場合は Chrome をハードウェアアクセラレーション有効で起動してください。

✅ まとめ:困ったらまずここをチェック

症状 チェックポイント
THREEが使えない type="module"で読み込んでるか?
画像が出ない パス、拡張子、ファイルの存在を再確認
ローカルで動かない Live Server等のHTTPサーバで実行
意味不明な警告が出る 無視して問題ない場合が多い

🧪 補足:ブラウザの「コンソール(Console)」を活用しよう

  • Chrome の DevTools(F12)→「Console」タブでエラー内容を確認
  • console.log() を使って、scene, camera, texture の状態を出力するのも有効です

5. 3Dの広がり方を実感するテクニック

回転するカードを表示できたら、次は「空間の深み」や「立体感」をもっと感じられる工夫を加えてみましょう。

Three.js では、たった数行の追加で印象が一気に変わることがあります。

✨ テクニック①:ライト(光源)を追加する

光がないと、3Dオブジェクトはのっぺりした見た目になります。

以下のように環境光や平行光を追加することで、立体感や陰影が生まれます。

📌 追加コード(カード作成後に追記)

// 環境光(全体にほんのり光を当てる)
const ambientLight = new THREE.AmbientLight(0xffffff, 0.4); // 色、強さ
scene.add(ambientLight);

// 平行光(方向のある光、影もできる)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 10, 7); // 光の位置
scene.add(directionalLight);

🔍 結果:

  • カードの一部が明るくなり、影ができて奥行きが感じられるようになります。
 テクニック①:ライト(光源)を追加する  テクニック①:ライト(光源)を追加する

※THREE.MeshStandardMaterial にした方が効果が出やすいようです。

🌀 テクニック②:複数カードを配置する

オブジェクトを複数置くだけで「空間にいる」感覚が増します。

📌 複数配置サンプル

for (let i = -2; i <= 2; i++) {
  const cardClone = card.clone();
  cardClone.position.x = i * 2.5;
  scene.add(cardClone);
}

🔍 結果: カードが横に5枚並び、カメラ視点の移動や回転がより楽しくなる

📷 テクニック③:カメラの視点を動かしてみる

マウス連動などはまだ先として、カメラの位置をゆっくり動かすだけでも雰囲気が変わります。

📌 アニメーション内で追加

let t = 0;
function animate() {
  requestAnimationFrame(animate);
  t += 0.01;
  camera.position.x = Math.sin(t) * 2; // 横にスイング
  camera.lookAt(0, 0, 0); // 常に中心を向く
  renderer.render(scene, camera);
}

🔍 結果: カメラがスライドしながらカードを眺めるようになり、「空間に入った」印象が強まる

🌫️ テクニック④:フォグ(霧)で奥行きを演出

霧を追加すると、奥にあるものがぼんやりとし、距離感がリアルに感じられます。

📌 フォグの追加

scene.fog = new THREE.Fog(0x000000, 5, 15); // 色, 開始, 終了距離

💡 黒背景でやると「深淵」っぽくなって雰囲気が出ます。

🧠 補足:これらを組み合わせるだけで…

  • 複数のカードが並び、
  • 光が差し込み、
  • カメラがゆっくり動き、
  • 背景が霞んで見える

ただの「回転する画像」だったはずのシーンが、一気に“世界”として立ち上がってきます。

🏁 まとめ:3Dの広がりは「少しの工夫」で変わる

工夫 効果
ライト 立体感・陰影
複数オブジェクト 空間的スケール感
カメラ移動 奥行き・没入感
フォグ 距離・ミステリアスな雰囲気演出

6. Three.jsでできること・ひろがる未来

回転する1枚のカードから始まった3D表現。

しかし Three.js の力は、その先の創造を支える拡張性にこそあります。

「画像を表示する」だけでなく、Three.js でできることは、想像以上に多彩で柔軟です。

🌐 あなたが今やっているのは、“3D表現”の入り口にすぎない

ここでは、「カード表示」からどんな世界が広がるのか、その具体例と可能性を紹介します。

🎴 1. カードコレクション・ギャラリー

  • 収集したカードを 3D空間の壁に飾る
  • 美術館や個展のような 静かな体験空間 を作る
  • PointerLockControls や OrbitControls を使って、自由に見回せるようにも

📊 2. データ可視化(情報を魅せる)

  • スコアや履歴、感情グラフなどを3Dで表示
  • three.meshline, three-charts, d3.jsとの連携も可能
  • ゲーム開発だけでなく、日常のUIにも3Dの発想を取り入れられる

🧍‍♂️ 3. 歩ける世界(簡易3Dアドベンチャー)

  • 地面・壁・空を用意して、自由に歩く
  • キャラクターを読み込んで動かす
  • 対話イベントやギミックも実装可能
Three.js + PointerLockControls + GLTFLoader

🧩 Three.jsは「世界を持てる」ツール

  • HTML+JS だけで構成できるため、Webアプリにも統合しやすい
  • スマホ・PC・VRにも対応(WebXR)
  • 重くなりすぎずに、印象深い体験が作れる

🧭 あなたのプロジェクトにも活かせるかもしれない

今回のように「カード画像を回す」といった一見シンプルな機能も、
ゲーム、UI、アート表現など、さまざまなコンテキストで応用できます。

“面白さは、コード行数じゃない。”
1枚のカードに、世界観が宿ることもある。

📝 まとめ:Three.jsは「始めやすく、終わりがない」

特徴 内容
始めやすさ HTML+JSだけで3Dが扱える。CDNで即動作。
表現の広がり 空間、光、時間、データ──あらゆる表現を持ち込める
あなたの感性に応える アート・ストーリー・没入体験を支える構造が揃っている

🎁 最後に

ここまで読んでくれたあなたへ。 Three.js はただの技術ではなく、あなたの「描きたいもの」を支えるキャンバスです。

1枚のカードから始まったあなたの世界が、 誰かの記憶に残る空間になることを願って──