Three.jsでマウスに合わせて動かす

以前に実装した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()は線形補間を行う関数で、滑らかに移動させるために使用しています。
マウスに合わせてカメラを動かすデモページ

参考サイト

このエントリーをはてなブックマークに追加

関連記事

コメントを残す

メールアドレスが公開されることはありません。
* が付いている欄は必須項目です

CAPTCHA


コメントが承認されるまで時間がかかります。

2025年5月
 123
45678910
11121314151617
18192021222324
25262728293031