以前に実装したThree.jsで複数のランダム配置をした記事のコードに、マウスに合わせて動作する処理を追加してみます。
サンプルコード
まずはマウスの動きに合わせて、画面内に配置した要素を回転させてみます。
import * as THREE from 'three';
// シーンの作成
const scene = new THREE.Scene();
// カメラの作成
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 10);
// レンダラーの作成
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor("white");
document.body.appendChild(renderer.domElement);
// ライトの作成
const directionalLight = new THREE.DirectionalLight("white", 3);
directionalLight.position.set(0, 0, 10);
scene.add(directionalLight);
// オブジェクトの作成
const objectCount = 150;
const objects = [];
for (let i = 0; i < objectCount; i++) {
// ランダムなサイズ設定
const geometry = new THREE.DodecahedronGeometry(
Math.random() * 1 + 1 // 1~2
);
// ランダムな色設定
const color = new THREE.Color().setRGB(Math.random(), Math.random(), Math.random());
const material = new THREE.MeshStandardMaterial({
color
});
const object = new THREE.Mesh(geometry, material);
// ランダムな位置設定
object.position.set(
Math.random() * 40 - 20, // X: -20~20
Math.random() * 30 - 15, // Y: -15~15
Math.random() * 20 - 20 // Z: -20~0
);
scene.add(object);
objects.push(object);
}
renderer.render(scene, camera);
// リサイズの対応
const resize_canvas = () => {
const w = window.innerWidth;
const h = window.innerHeight;
renderer.setSize(w, h);
camera.aspect = w / h;
camera.updateProjectionMatrix();
renderer.render(scene, camera);
}
window.addEventListener('resize', resize_canvas);
// マウスの位置を取得
let mouseX = 0, mouseY = 0;
document.addEventListener('mousemove', (e) => {
mouseX = (e.clientX / window.innerWidth - 0.5) * 2; // x: -1〜1
mouseY = (e.clientY / window.innerHeight - 0.5) * 2; // y: -1〜1
});
// アニメーション設定
const animate = () => {
requestAnimationFrame(animate);
objects.forEach((object) => {
const speedFactor = Math.random() * 0.065 + 0.005;// 0.07~0.005
object.rotation.y += (mouseX * Math.PI) * speedFactor;
object.rotation.x += (-mouseY * Math.PI) * speedFactor;
});
renderer.render(scene, camera);
}
animate();
次にマウスに合わせてカメラも同時に動かしてみます。
import * as THREE from 'three';
// シーンの作成
const scene = new THREE.Scene();
// カメラの作成
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 10);
// レンダラーの作成
const renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor("white");
document.body.appendChild(renderer.domElement);
// ライトの作成
const directionalLight = new THREE.DirectionalLight("white", 3);
directionalLight.position.set(0, 0, 10);
scene.add(directionalLight);
// オブジェクトの作成
const objectCount = 150;
const objects = [];
for (let i = 0; i < objectCount; i++) {
// ランダムなサイズ設定
const geometry = new THREE.DodecahedronGeometry(
Math.random() * 1 + 1 // 1~2
);
// ランダムな色設定
const color = new THREE.Color().setRGB(Math.random(), Math.random(), Math.random());
const material = new THREE.MeshStandardMaterial({
color
});
const object = new THREE.Mesh(geometry, material);
// ランダムな位置設定
object.position.set(
Math.random() * 40 - 20, // X: -20~20
Math.random() * 30 - 15, // Y: -15~15
Math.random() * 20 - 20 // Z: -20~0
);
scene.add(object);
objects.push(object);
}
renderer.render(scene, camera);
// リサイズの対応
const resize_canvas = () => {
const w = window.innerWidth;
const h = window.innerHeight;
renderer.setSize(w, h);
camera.aspect = w / h;
camera.updateProjectionMatrix();
renderer.render(scene, camera);
}
window.addEventListener('resize', resize_canvas);
// マウスの位置を取得
let mouseX = 0, mouseY = 0;
document.addEventListener('mousemove', (e) => {
mouseX = (e.clientX / window.innerWidth - 0.5) * 2; // x: -1〜1
mouseY = (e.clientY / window.innerHeight - 0.5) * 2; // y: -1〜1
});
// アニメーション設定
const animate = () => {
requestAnimationFrame(animate);
objects.forEach((object) => {
const speedFactor = Math.random() * 0.065 + 0.005;// 0.07~0.005
object.rotation.y += (mouseX * Math.PI) * speedFactor;
object.rotation.x += (-mouseY * Math.PI) * speedFactor;
});
camera.rotation.y = THREE.MathUtils.lerp(camera.rotation.y, mouseX * 0.1, 0.05);
camera.rotation.x = THREE.MathUtils.lerp(camera.rotation.x, -mouseY * 0.1, 0.05);
renderer.render(scene, camera);
}
animate();
MathUtils.lerp()は線形補間を行う関数で、滑らかに移動させるために使用しています。
マウスに合わせてカメラを動かすデモページ
コメントが承認されるまで時間がかかります。