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制作を中心に日々学びになったこと、興味が沸いたことについて初心者の方でもわかりやすいようにアウトプットしていくブログです。

関連記事

【Contact Form7】ログインユーザーのためにテキスト項目にデフォルト値を設定する

【Contact Form7】ログインユーザーのためにテキスト項目にデフォルト値を設定する

【GSAP入門】使い方となにができるのか

【GSAP入門】使い方となにができるのか

Linuxパーミッションの変更方法

Linuxパーミッションの変更方法

【Contact Form 7】ログインユーザーのためにselectのデフォルト値を設定する

【Contact Form 7】ログインユーザーのためにselectのデフォルト値を設定する

【CSS】mix-blend-modeで乗算などを表現する方法

【CSS】mix-blend-modeで乗算などを表現する方法

bxSliderのデザインカスタムと不具合の対処

bxSliderのデザインカスタムと不具合の対処