🐥
Reactによる3Dプロフィール画面の作成
React + Three.js で作る美しい 3D プロフィールサイト
こんにちは!今回は、ReactとThree.jsを使って、インタラクティブな 3D プロフィールサイトを作成する方法をご紹介します。
🎯 完成イメージ
- 回転する 3D アバター球体
- 浮遊するスキルボックス
- マウス操作でのインタラクティブな回転・ズーム
- 美しいグラデーション背景
- レスポンシブ対応
🛠 使用技術
- React 18 + TypeScript
- Three.js - 3D グラフィックスライブラリ
- React Three Fiber - React で Three.js を使用するためのライブラリ
- React Three Drei - 便利な 3D コンポーネント集
📋 前提条件
まず、開発環境のバージョンを確認しましょう:
# バージョン確認
node --version # v20.17.0
npm --version # 11.6.2
npx --version # 11.6.2
🚀 プロジェクトセットアップ
1. React アプリの作成
# TypeScriptテンプレートでReactアプリを作成
npx create-react-app 3d-profile --template typescript
# プロジェクトディレクトリに移動
cd 3d-profile
2. 必要なライブラリのインストール
# 3D関連ライブラリをインストール
npm install three @react-three/fiber @react-three/drei @types/three
💻 実装
3D プロフィールコンポーネントの作成
src/components/Profile3D.tsxを作成します:
import React, { useRef } from "react";
import { Canvas, useFrame } from "@react-three/fiber";
import { OrbitControls, Text, Box, Sphere, Torus } from "@react-three/drei";
import * as THREE from "three";
// 回転するアバター球体
function Avatar() {
const meshRef = useRef<THREE.Mesh>(null!);
useFrame((state, delta) => {
meshRef.current.rotation.x += delta * 0.5;
meshRef.current.rotation.y += delta * 0.2;
});
return (
<Sphere ref={meshRef} args={[1, 32, 32]} position={[0, 2, 0]}>
<meshStandardMaterial color="#4f46e5" roughness={0.3} metalness={0.7} />
</Sphere>
);
}
// 浮遊するスキルボックス
function SkillBox({
position,
color,
skill,
}: {
position: [number, number, number];
color: string;
skill: string;
}) {
const meshRef = useRef<THREE.Mesh>(null!);
useFrame((state) => {
meshRef.current.position.y =
position[1] + Math.sin(state.clock.elapsedTime + position[0]) * 0.2;
meshRef.current.rotation.y += 0.01;
});
return (
<group>
<Box ref={meshRef} args={[0.8, 0.8, 0.8]} position={position}>
<meshStandardMaterial color={color} />
</Box>
<Text
position={[position[0], position[1] - 1, position[2]]}
fontSize={0.3}
color="white"
anchorX="center"
anchorY="middle"
>
{skill}
</Text>
</group>
);
}
// 装飾的なリング
function DecorativeRing() {
const ringRef = useRef<THREE.Mesh>(null!);
useFrame((state, delta) => {
ringRef.current.rotation.z += delta * 0.3;
});
return (
<Torus ref={ringRef} args={[3, 0.1, 16, 100]} position={[0, 0, -2]}>
<meshStandardMaterial color="#10b981" wireframe />
</Torus>
);
}
// メインの3Dプロフィールコンポーネント
export default function Profile3D() {
const skills = [
{
position: [-3, 1, 0] as [number, number, number],
color: "#ef4444",
skill: "React",
},
{
position: [3, 1, 0] as [number, number, number],
color: "#3b82f6",
skill: "TypeScript",
},
{
position: [-2, -1, 2] as [number, number, number],
color: "#f59e0b",
skill: "Three.js",
},
{
position: [2, -1, 2] as [number, number, number],
color: "#8b5cf6",
skill: "Node.js",
},
];
return (
<div
style={{
width: "100%",
height: "100vh",
background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
}}
>
<Canvas camera={{ position: [0, 0, 8], fov: 75 }}>
{/* 照明設定 */}
<ambientLight intensity={0.5} />
<pointLight position={[10, 10, 10]} intensity={1} />
<spotLight
position={[-10, -10, -10]}
angle={0.15}
penumbra={1}
intensity={0.5}
/>
{/* メインのプロフィール要素 */}
<Avatar />
{/* プロフィール名 */}
<Text
position={[0, 4, 0]}
fontSize={1}
color="white"
anchorX="center"
anchorY="middle"
>
あなたの名前
</Text>
{/* 職業/タイトル */}
<Text
position={[0, 3.2, 0]}
fontSize={0.4}
color="#e5e7eb"
anchorX="center"
anchorY="middle"
>
フロントエンド開発者
</Text>
{/* スキルボックス */}
{skills.map((skill, index) => (
<SkillBox
key={index}
position={skill.position}
color={skill.color}
skill={skill.skill}
/>
))}
{/* 装飾リング */}
<DecorativeRing />
{/* カメラコントロール */}
<OrbitControls
enableZoom={true}
enablePan={false}
enableRotate={true}
autoRotate={true}
autoRotateSpeed={0.5}
/>
</Canvas>
{/* UI オーバーレイ */}
<div
style={{
position: "absolute",
top: "20px",
left: "20px",
color: "white",
fontFamily: "Arial, sans-serif",
zIndex: 1000,
}}
>
<h2 style={{ margin: "0 0 10px 0", fontSize: "24px" }}>
3D プロフィール
</h2>
<p style={{ margin: "0", fontSize: "14px", opacity: 0.8 }}>
マウスでドラッグして回転、スクロールでズーム
</p>
</div>
{/* 連絡先情報 */}
<div
style={{
position: "absolute",
bottom: "20px",
right: "20px",
color: "white",
fontFamily: "Arial, sans-serif",
textAlign: "right",
zIndex: 1000,
}}
>
<p style={{ margin: "5px 0", fontSize: "14px" }}>
📧 your.email@example.com
</p>
<p style={{ margin: "5px 0", fontSize: "14px" }}>
🐙 github.com/yourusername
</p>
<p style={{ margin: "5px 0", fontSize: "14px" }}>
💼 linkedin.com/in/yourprofile
</p>
</div>
</div>
);
}
App.tsx の更新
import React from "react";
import Profile3D from "./components/Profile3D";
import "./App.css";
function App() {
return (
<div className="App">
<Profile3D />
</div>
);
}
export default App;
スタイリングの調整
src/App.cssを更新:
.App {
margin: 0;
padding: 0;
width: 100%;
height: 100vh;
overflow: hidden;
}
/* 3Dプロフィール用のグローバルスタイル */
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
"Helvetica Neue", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* レスポンシブ対応 */
@media (max-width: 768px) {
.App {
height: 100vh;
}
}
🎮 実行
# 開発サーバーを起動
npm start
ブラウザで http://localhost:3000 にアクセスすると、美しい 3D プロフィールサイトが表示されます!
🔧 主要機能の解説
1. useFrame フック
Three.js のアニメーションループを管理し、毎フレーム実行される処理を定義します。
2. useRef + THREE.Mesh
3D オブジェクトへの参照を保持し、直接操作できるようにします。
3. OrbitControls
マウス操作でのカメラ制御を簡単に実装できます。
4. 照明設定
-
ambientLight: 全体的な環境光 -
pointLight: 特定の点からの光源 -
spotLight: スポットライト効果
🎨 カスタマイズのポイント
色の変更
// スキルボックスの色を変更
{ position: [-3, 1, 0], color: "#your-color", skill: "Your Skill" }
アニメーション速度の調整
// 回転速度を変更
meshRef.current.rotation.y += delta * 0.5; // 0.5を変更
スキルの追加
const skills = [
// 既存のスキル...
{ position: [0, -2, 1], color: "#ff6b6b", skill: "New Skill" },
];
📱 レスポンシブ対応
モバイルデバイスでも快適に動作するよう、CSS でレスポンシブ対応を実装しています。
🚀 デプロイ
Vercel でのデプロイ
# ビルド
npm run build
# Vercel CLIでデプロイ
npx vercel --prod
Netlify でのデプロイ
# ビルド
npm run build
# build フォルダをNetlifyにドラッグ&ドロップ
🎯 まとめ
React Three Fiber を使うことで、React の宣言的な書き方で 3D グラフィックスを実装できました。
メリット
- ✅ React の知識があれば学習コストが低い
- ✅ コンポーネント化で再利用しやすい
- ✅ TypeScript で型安全な開発
- ✅ 豊富な Drei コンポーネントで開発効率 UP
応用例
- ポートフォリオサイト
- 商品の 3D プレビュー
- インタラクティブなデータ可視化
- ゲームの UI
ぜひ、あなたのプロフィールサイトに 3D 要素を取り入れて、訪問者に印象的な体験を提供してみてください!
🔗 参考リンク
この記事が役に立ったら、ぜひ「いいね」をお願いします!🌟
Discussion