Home
JavaScript
【Three.js】スクロールにあわせてメッシュを動かす方法

【Three.js】スクロールにあわせてメッシュを動かす方法

【Three.js】スクロールにあわせてメッシュを動かす方法

どうも!かけちまるです!

Three.jsを少し触れるようになると、様々な図形を描画できると思います。

その図形をスクロールによって動かす方法を解説します。

この記事では、

  • ・スクロールイベントでのアニメーション

がわかります。

今回のテンプレート

次のコードを元にスクロールアニメーションを加えていきます。

ディレクトリ構成
開く&閉じるコピー
index.html css/ -style.css js/ -main.js
index.html
開く&閉じるコピー
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" href="./css/style.css"> <script async src="https://unpkg.com/es-module-shims@1.5.8/dist/es-module-shims.js"></script> <script type="importmap"> { "imports": { "three": "https://unpkg.com/three@0.142.0/build/three.module.js" } } </script> <script src="./js/main.js" type="module"></script> </head> <body> <section class="section">main</section> <section class="section">about</section> <section class="section">works</section> <section class="section">contact</section> </body> </html>
style.css
開く&閉じるコピー
*{ margin: 0; padding: 0; box-sizing: border-box; } html, body{ height: 100%; } canvas{ position: fixed; top: 0; left: 0; z-index: -1; } .section{ color: #fff; display: flex; align-items: center; justify-content: center; font-size: 32px; width: 100%; height: 100%; }
main.js
開く&閉じるコピー
import * as THREE from 'three'; /** * シーン・カメラ・レンダラーを用意する */ const fov = 50; const fovRad = (fov / 2) * (Math.PI / 180); // 視野角をラジアンに変換 let distance = (window.innerHeight / 2) / Math.tan(fovRad); // カメラ距離を求める const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.z = distance; const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); document.body.appendChild(renderer.domElement); /** * ジオメトリ+マテリアル=メッシュを用意する */ const coneGeometry = new THREE.ConeGeometry( 100, 200, 64 ); const lambertMaterial = new THREE.MeshPhysicalMaterial({ reflectivity: 0, roughness: 0.2, metalness: 0, clearcoat: 0.3, clearcoatRoughness: 0.25, color: new THREE.Color(0x3da8e6), ior: 1.2, thickness: 10.0, }); let coneMesh = new THREE.Mesh(coneGeometry, lambertMaterial); coneMesh.rotation.x = -0.1; coneMesh.rotation.z = -0.2; scene.add(coneMesh); /** * ライトを追加する */ let pointLight = new THREE.PointLight(0xffffff, 2, 0, 0.1); pointLight.position.set(200, 100, 300); scene.add(pointLight); let pointLight02 = new THREE.PointLight(0xffffff, 2, 0, 0.1); pointLight02.position.set(-300, 300, -300); scene.add(pointLight02); // アニメーション function animate() { renderer.render(scene, camera); requestAnimationFrame(animate); } animate(); // ブラウザのリサイズに対応させる window.addEventListener('resize', onWindowResize); function onWindowResize() { renderer.setSize(window.innerWidth, window.innerHeight); camera.aspect = window.innerWidth / window.innerHeight; distance = (window.innerHeight / 2) / Math.tan(fovRad); camera.position.z = distance; camera.updateProjectionMatrix(); }

ここまで次のようになっていればオッケーです。

スクロールにあわせてアニメーションさせる方法

ブラウザを読み込んだ時にメッシュの位置を維持するためにスクロール量をy座標に設定します。(13行目)
スクロールしたときにスクロール量をy座標に設定することでメッシュを動かします。(14~16行目)

main.js
開く&閉じるコピー
・・・ // ブラウザのリサイズに対応させる window.addEventListener('resize', onWindowResize); function onWindowResize() { renderer.setSize(window.innerWidth, window.innerHeight); camera.aspect = window.innerWidth / window.innerHeight; distance = (window.innerHeight / 2) / Math.tan(fovRad); camera.position.z = distance; camera.updateProjectionMatrix(); } coneMesh.position.y = window.pageYOffset; window.addEventListener('scroll', () => { coneMesh.position.y = window.pageYOffset; });

こんな感じになったらOKです。

慣性をつける方法

慣性をつけるには、スクロール量に任意の値をかけてあげればできます。
0に近づくほどスクロール量より少なく動きます。
1より大きくなるとスクロール量より大きく動きます。

main.js
開く&閉じるコピー
coneMesh.position.y = window.pageYOffset * 0.4; window.addEventListener('scroll', () => { coneMesh.position.y = window.pageYOffset * 0.4; });

スクロール量より少なく動くようになりました。

main.js
開く&閉じるコピー
coneMesh.position.y = window.pageYOffset * 1.5; window.addEventListener('scroll', () => { coneMesh.position.y = window.pageYOffset * 1.5; });

スクロール量より大きく動くようになりました。

まとめ

スクロールアニメーションは使える場面が多いと思いますのでマスターしておくと応用が効くのではないかと思います。

おわり

かけちまる
かけちまる
Webエンジニアをしています。
HTML/CSS/JavaScript/jQuery/PHPができます。
WEB制作を中心に日々学びになったこと、興味が沸いたことについて初心者の方でもわかりやすいようにアウトプットしていくブログです。

関連記事

CSSだけでぷよぷよしたアニメーションの実装方法

CSSだけでぷよぷよしたアニメーションの実装方法

Contact Form 7の基本設定

Contact Form 7の基本設定

【PHP】json_encode()とjson_decode()でJSONを操る

【PHP】json_encode()とjson_decode()でJSONを操る

【CSSのみ】指定行数を超えたテキストを非表示にする方法

【CSSのみ】指定行数を超えたテキストを非表示にする方法

【macOS】よく使うターミナルコマンド一覧

【macOS】よく使うターミナルコマンド一覧

【縦横比を保つ】YouTube埋め込みをレスポンシブ対応にする

【縦横比を保つ】YouTube埋め込みをレスポンシブ対応にする