📦
Three.jsで3Dの立方体が埋め込まれたButtonを作る
完成したもの
作り方
Viteでプロジェクト作成。
npm init vite@latest my-vite-3dbutton --template vanilla-ts
Three.jsとその型定義ファイルをインストール。
npm install --save three @types/three
index.htmlファイルを開き、buttonとCanvasを追加。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app">
<button>
<canvas />
</button>
</div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
main.tsファイルを開き、1行目以外を消して書き換える。
main.ts
import './style.css'
import * as THREE from 'three';
function init() {
// Button取得, Buttonの縦幅・横幅をwidth,height変数に代入
const button = document.querySelector('button') as HTMLButtonElement;
const width = button.clientWidth;
const height = button.clientHeight;
// Three.js側の処理
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('canvas') as HTMLCanvasElement
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
// シーン作成
const scene = new THREE.Scene();
// カメラ作成
const camera = new THREE.PerspectiveCamera(45, width / height);
camera.position.set(0, 0, 1000);
// 立方体の3Dモデルを作ってシーンに追加
const geometry = new THREE.BoxGeometry(400, 400, 400);
const material = new THREE.MeshNormalMaterial();
const box = new THREE.Mesh(geometry, material);
scene.add(box);
// レンダリングする用のTick関数
function Tick() {
requestAnimationFrame(Tick);
renderer.render(scene, camera);
}
Tick();
}
window.onload = init;
こんな感じでボタンの中に3Dモデルの立方体が表示される。
発展
これだけだとあまり面白くないので、中の立方体を回転させてみる。
まずは回転される角度を入れる変数を準備。
let rotaion: number = 0.005;
Tick関数を実行するたびにboxを回転させていく。
// レンダリングする用のTick関数
function Tick() {
requestAnimationFrame(Tick);
box.rotation.y += rotaion;
renderer.render(scene, camera);
}
さらにボタンにカーソルを当てると回転速度が変わるようにしてみる。
ついでにボタンの大きさも変わるようにCSSを変えてみる。
button.onmouseenter = () => {
rotaion = 0.01;
}
button.onmouseleave = () => {
rotaion = 0.005;
}
style.css
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
button {
transition-property: transform;
transition-duration: 0.5s;
}
button:hover {
transform: scale(1.1);
}
Discussion