Next.jsでのWebサイト制作 #3 では、トップページ紹介とThree.jsによる3Dモデルの実装紹介をしたいと思います。
トップページ紹介
トップページは以下のようになっています。(ぜひアクセスしてご覧ください。)
メイン画像+メインメッセージ 部分
この部分では、画像スライドショーとアニメーションによるメッセージの出現を実装しています。
ここで使用している技術は、以下過去記事にて紹介させていただいておりますので、ここでの説明は割愛させていただきます。
ブログ最新記事部分
ブログ最新記事部分では、Blogページ(microCMSからデータを取得)にて掲載している記事のうち、最新のものを表示する仕様となっています。
ここで使用している技術は、Blogページの回で紹介予定ですので、今回は割愛させていただきます。
メッセージ部分
今回の記事は、このメッセージ部分における、3Dモデル「動く地球」の実装方法をメインに紹介します。
3Dモデルは、Three.jsという Javascriptライブラリを用いて実装しています。
Three.jsとは?
Three.jsは、Webブラウザ上で3Dモデルを簡単に表示できるJavaScriptライブラリです。
JavaScriptの基本的な知識があれば、Three.jsを用いてWebブラウザ上に3Dモデルや3Dアニメーションを簡単に表示できるようになります。
もともと、WebGLという3Dモデルを扱う技術があったそうですが、かなり難易度が高いようです。(私は全く学んだことありません。。)
Three.jsを使うことでWebGLを使うよりも圧倒的に簡単に実装できます。
実装方法
3Dモデルのダウンロード
今回は以下サイトから3Dモデルを「GLTF」フォーマットでダウンロードし、public/modelsに格納しました。
インストール
npm install three
TypeScript使用時は型ファイルのインストールも必要
npm install @type/three
実装
以下が実際のコードです。
処理ごとの意味、説明は、コメントに記載してあります。
私自身、初めてThree.jsを扱ったため、わからないことが多く、「ググって。。。うまく動かないところを修正して。。。」の繰り返しでした。
そのため、あまり詳しい説明ができていませんが、ご了承ください。。。。
import { useEffect, useRef } from "react";
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
// 3Dモデル
function Earth() {
// 3Dモデルを表示したい部分のDOM要素をuseRefでもってくる
const canvasRef = useRef<HTMLCanvasElement | null>(null);
// useEffect内に3Dモデルの設定を書くことで、レンダリング時に3Dモデルが生成されるようになる。
// Three.jsで3Dモデルを出力するには、以下に定義する、scene, camera, rendererの3つのオブジェクトが最低限必要となる。
useEffect(() => {
const canvas = canvasRef.current as HTMLCanvasElement;
const sizes = {
width: 350,
height: 370,
};
// scene(3D空間全体の情報をもつオブジェクト)
const scene = new THREE.Scene();
// camera(3Dモデルをどのように画面に映すかを、カメラをのぞいた時のようなイメージで定義できるオブジェクト)
const camera = new THREE.PerspectiveCamera(
85, //垂直視野
sizes.width / sizes.height, //アスペクト比
0.1, //Near(奥行きの手前側)
1000 //Far(奥行きの最奥)→NearとFarの間にあるものが画面に映し出される。
);
camera.position.set(0, 0, 2); //カメラ自体の位置(x軸, y軸, z軸)
// renderer(レンダリング設定)
const renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer({
canvas: canvas, //useRefでとってきた要素。ここに3Dモデルがレンダリングされる。
antialias: true, //3Dモデルの端を滑らかにする。
alpha: true, //背景の設定(透明にしたい場合はtrue)
});
renderer.setSize(sizes.width, sizes.height); //ここの記述はお決まり。
renderer.setPixelRatio(window.devicePixelRatio); //ここの記述はお決まり。
// ライトの設定(この設定がないと映らない3Dモデルがある)
const light = new THREE.PointLight(0xffffff, 1); //特定の方向からのライト(第1引数:光の色、第2引数:光の強さ)
light.position.set(0, 1, 1); //sceneから見たライトの位置 (第1引数:x軸、第2引数:y軸、第3引数:z軸)
scene.add(light); //sceneにライトを紐付け
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); //全方向からのライト≒モデルそのものの光度(第1引数:光の色、第2引数:光の強さ)
scene.add(ambientLight); //sceneにライトを紐付け
// GLTFモデルのインポート
let model: THREE.Object3D<THREE.Object3DEventMap>; // モデルを格納する変数
const gltfLoader = new GLTFLoader();
gltfLoader.load("/models/earth.gltf", (gltf) => {
model = gltf.scene;
model.scale.set(0.14, 0.14, 0.14); //modelの大きさ(スケール)を設定
scene.add(model); //sceneにmodelを紐付け
});
// アニメーション
const tick = () => {
if (model) {
// modelを回転させる
model.rotation.y += 0.0025; // Y軸周りに毎フレーム回転(数字はスピード)
}
renderer.render(scene, camera); // 現在のシーンをカメラの視点からレンダリング(描画)(ここの記述はお決まり。)
requestAnimationFrame(tick); // ブラウザに次の再描画のフレームでtick関数を呼び出すように要求(ここの記述はお決まり。)
};
tick(); //初回のアニメーションフレームを開始するためにtick関数を一度呼び出す(ここの記述はお決まり。)
}, []);
return (
<canvas
id="canvas"
ref={canvasRef}
className=" mx-auto xl:ml-[67%]"
></canvas>
);
}
export default Earth;
上記実装により、3DモデルをWebブラウザに表示することができます。
最後に
今回は、トップページ(特に3Dモデル部分)について紹介させていただきました。
Three.jsはWebGLに比べると簡単にかけるものとは言われていますが、私としては十分難しかったです。。笑
次回は、Garalleyページ、Blogページについて、紹介させていただきたいと思います。
最後までお読みいただきありがとうございました!!
p.s.
Qiitaの記事をより多くの人に読んでもらう方法を教えてください!
タイトルを検索されやすいようなタイトルにする、くらいはやってみようと思っていますが、その他何かありましたらご教授いただければ幸いです!!!