Three.js インタラクティブエフェクト

2023-05-22

Three.js

Next.js

Math

参考

https://goworkship.com/magazine/interactive-effect-threejs/

https://github.com/iondrimba/interactive-repulsive-effect/tree/master/second-demo/src

デモ

https://tympanus.net/Tutorials/InteractiveRepulsionEffect/index2.html

コアコンセプト、数学的な部分もろもろ鬼難しそうだがやってみる

とりあえず既存のThree.jsコンポーネントにぶち込んでいく形

クラスで作成していく

ヘルパー関数を作成

2点間の距離を計算し、値をマッピングして、角度をラジアンに変換するための関数を作成する

え?わけわからん

const radians = (degrees) => { // 度数を引数にとりラジアンで角度を返す return degrees * Math.PI / 180; } const distance = (x1, y1, x2, y2) => { // 中心とマウスとの2点間の距離を計算 return Math.sqrt(Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2)); } const map = (value, start1, stop1, start2, stop2) => { return (value - start1) / (stop1 - start1) * (stop2 - start2) + start2 }

https://ics.media/entry/10657/

上記が三角関数の数式と概念について

概念は難しそうなのでざっくり仕組みだけ抑える

3D空間においてx, y, zから2つとって平面としたときx座標、y座標の決定方法は

x, y = 半径 x Math.cos(ラジアン), 半径 x Math.sin(ラジアン)

つまりラジアンを求めてこれにぶっこめば座標を指定できる

そのラジアンの求め方は上にもある

度数 x 円周率(π) / 180

で求めることができる

よって、度数と半径の2つの要素があれば問題ない

2点間距離は始点座標、終点座標を引数に

2点間の距離公式&三平方の定理をもとに求める。

以下が分かりやすい

二点間の距離を求める公式(2次元、3次元) - 具体例で学ぶ数学 (mathwords.net)

x, yごとに絶対値を求めてそれぞれ2乗して平方根(ルート)を計算する

Math.sqrt();は平方根の計算、Math.powは第二引数が乗数

mapに関してはよくわからん

公式として覚える

const map = (value, start1, stop1, start2, stop2) => { return (value - start1) / (stop1 - start1) * (stop2 - start2) + start2 }

valueを元範囲である[start1, stop1]の範囲から[start2, stop2]の範囲へ変化しマッピングを行う

グリッドエレメント

使用するオブジェクトの定義

割愛

https://github.com/pailhead

import RoundedBoxGeometry from 'roundedBox'; class Box { constructor() { this.geom = new RoundedBoxGeometry(.5, .5, .5, .02, .2); this.rotationX = 0; this.rotationY = 0; this.rotationZ = 0; } }

三次元設定

ん~わからん。。。

setup() { // handles mouse coordinates mapping from 2D canvas to 3D world this.raycaster = new THREE.Raycaster(); this.gutter = { size: 1 }; // コンテンツ間のスペース this.meshes = []; // オブジェクトの格納用配列 this.grid = { cols: 14, rows: 6 }; // オブジェクトの配置設定 this.width = window.innerWidth; // Heightともに要調整、offsetのほうがいいかも this.height = window.innerHeight; this.mouse3D = new THREE.Vector2(); // マウス操作にかかわる座標 this.geometries = [ new Box(), // 生成するオブジェクト ]; window.addEventListener('mousemove', this.onMouseMove.bind(this), { passive: true }); // thisコンテキストに保持 // we call this to simulate the initial position of the mouse cursor this.onMouseMove({ clientX: 0, clientY: 0 }); // マウスの初期位置設定 }

マウスホバー、マウスクリック判定はTHREE.Raycaster();を利用

https://ics.media/tutorial-three/raycast/

mousemoveイベントでマウスの位置を監視する

全体的にsetup()で情報をまとめて設定する

0 → 1で書けって言われたら無理かな~

基本形として覚えるというか参照する

canvas幅がinnerWidthでない場合

event.offsetX,Yの罠...どこが原点の座標値なのかを理解する (currentTargetとtarget) - Qiita

マウス移動ハンドラの設定

onMouseMove({ clientX, clientY }) { this.mouse3D.x = (clientX / this.width) * 2 - 1; this.mouse3D.y = -(clientY / this.height) * 2 + 1; }

-1 ~ +1の範囲でマウス座標を登録している

GPTに説明してもらったけど全然理解できない。

ので、とりあえず位置とそれに対応する幅と高さにxは x2 - 1、yは x(-1) x2 +1 して座標に保存することで上記の機能を実現できる

3Dシーン、カメラの作成

実装済みなので割愛

shadow設定も今回いらないので省略

ランダムオブジェクトヘルパー

getRandomGeometry() { return this.geometries[Math.floor(Math.random() * Math.floor(this.geometries.length))];

setupで作成したgeometriesからランダムで返す

とりあえず使わない

メッシュヘルパー

実装済み

エレメントをグリッドに配置する

TOP PAGE