EarthChart's JavaScript Report

目次

初めに

このページでは、JavaScriptの基本的な説明と、Canvas APIを使用したアニメーションの作成方法について説明します。
また、3Dモデルの花を作成する方法についても触れます。

JavaScriptの基本説明

JavaScriptとは、Webブラウザ上で動作するスクリプト言語の一つで、動的なWebページを作成するために使用されるプログラミング言語のことです。
Webブラウザの機能を制御し、動的な操作やアニメーション、ユーザーとのインタラクション、データの検証や処理などを実現できます。
JavaScriptは、HTMLやCSSと組み合わせて使用されることが多く、Webページに高度な対話性や視覚効果を追加することができます。

Three.jsの導入について

Three.jsは、WebGLを使用して3Dグラフィックスを描画するためのJavaScriptライブラリです。
これにより、ブラウザ上でリアルタイムの3Dアニメーションやインタラクティブなコンテンツを作成することができます。

cdnの利用方法

<script type="importmap"> { "imports": { "three": "https://cdn.jsdelivr.net/npm/three@0.167.0/build/three.module.js", "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.167.0/examples/jsm/" } } </script> <script type="module"> import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; </script>

Canvas API について

Canvas APIは、HTML5で導入された2Dグラフィックスを描画するためのAPIです。JavaScriptを使用して、
動的なグラフィックスやアニメーションを作成することができます。

canvasの利用方法

<canvas> id="petalCanvas" width="600" height="480"></canvas>

アニメーション

JavaScriptを使用したアニメーションの作成方法について学びます。Three.jsでは`requestAnimationFrame()`を使用して、
スムーズな回転や移動アニメーションを実現することができます。

アニメーションループの基本

// アニメーションループ function animate() { requestAnimationFrame(animate); // 次のフレームを要求 // オブジェクトを回転 petal.rotation.z += 0.01; // Z軸回転 // カメラコントロールを更新 controls.update(); // シーンを描画 renderer.render(scene, camera); } // アニメーション開始 animate();

カメラ・光源について

Three.jsでは、カメラと光源の設定が重要です。カメラはシーンをどのように見るかを決定し、光源はオブジェクトの見え方に影響を与えます。
ここでは、基本的なカメラと光源の設定方法について説明します。

カメラ・光源の基本

// カメラの設定 const camera = new THREE.PerspectiveCamera( 60, // fov: 視野角(度) canvas.width / canvas.height, // aspect: アスペクト比 0.1, // near: 近クリップ面 1000 // far: 遠クリップ面 ); camera.position.set(0, 0.5, 1.5); // 光源の設定 const sunLight = new THREE.DirectionalLight(0xffffff, 0.8); sunLight.position.set(3, 5, 2); sunLight.castShadow = true; scene.add(sunLight);

3Dの花を作成する

3Dの花を作成するために、Three.jsを使用して立体的な花のモデルを作成します。花びらや茎、葉っぱを個別に作成し、
組み合わせて1つの花を形成します。

Three.js 3D花園

桜の花びら
マウスでドラッグして回転できます

このセクションでは、桜の花びらを描画するためのJavaScriptコードを示します。
花びらはCanvas APIを使用して描画され、マウスでドラッグして回転させることができます。
「quadraticCurveTo()」を使って桜の花びら特有の曲線を描画しました。

花びら生成関数

// 花びら生成関数 function createSakuraPetal(size, color, position) { const shape = new THREE.Shape(); // 桜の花びらの形状を描画 shape.moveTo(0, 0); // 開始点 shape.quadraticCurveTo(size * 0.5, size * 0.2, size, size * 0.6); // 右の曲線 shape.quadraticCurveTo(size * 0.9, size * 1.0, size * 0.5, size * 1.2); // 先端の右側 shape.quadraticCurveTo(size * 0.2, size * 1.3, 0, size * 1.0); // 先端のくぼみ shape.quadraticCurveTo(-size * 0.2, size * 0.7, -size * 0.1, size * 0.3); // 左の曲線 shape.quadraticCurveTo(-size * 0.05, size * 0.1, 0, 0); // 元の位置に戻る }

2D形状を3Dに変換

// 2D形状を3Dに変換 const extrudeSettings = { depth: 0.01, // 厚み bevelEnabled: true, // 面取りを有効 bevelThickness: 0.005, // 面取りの厚み bevelSize: 0.005, // 面取りのサイズ bevelSegments: 2 // 面取りの分割数 }; const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);

花びらに自然な湾曲を追加

// 花びらに自然な湾曲を追加 const positionAttribute = geometry.attributes.position; const vertex = new THREE.Vector3(); for (let i = 0; i < positionAttribute.count; i++) { vertex.fromBufferAttribute(positionAttribute, i); // 中心からの距離に応じて湾曲(Z方向に曲げる) const dist = Math.sqrt(vertex.x ** 2 + vertex.y ** 2); const curveStrength = 0.1; // 湾曲の強さ vertex.z = Math.sin(dist * Math.PI) * curveStrength; positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z); }

花びらの材質設定

// 花びらの材質設定 const material = new THREE.MeshStandardMaterial({ color: color, // 色 transparent: true, // 透明度を有効 opacity: 0.9 // 透明度(90%不透明) }); const petal = new THREE.Mesh(geometry, material);

桜の花
マウスでドラッグして回転できます

このセクションでは、先ほどの桜の花びらを組み合わせて、一輪の桜の花を作成します。 上記の花びらを放射状に配置し、雄蕊と雌蕊を追加して、よりリアルな桜の花を表現します。
花びらの色や形状を調整することで、より自然な見た目を実現しています。

桜の花の構成要素の組み立て

// 桜の花全体を作成 const sakuraFlower = new THREE.Group(); // 5枚の花びらを放射状に配置 for (let i = 0; i < 5; i++) { const angle = (i / 5) * Math.PI * 2; // 72度ずつ配置 const petal = createRealisticSakuraPetal(0.2, 0xff69b4, angle, i); sakuraFlower.add(petal); } // 雄蕊と雌蕊を追加 const stamens = createStamen(15); const pistil = createPistil(); sakuraFlower.add(stamens); sakuraFlower.add(pistil);

雄蕊の作成

// 雄蕊を作成する関数 function createStamen(count = 15, sizeScale = 2.0) { // 15本の雄蕊を円形に配置 for (let i = 0; i < count; i++) { // 軸(stalk): 細い円柱 const stalkGeometry = new THREE.CylinderGeometry( 0.002 * sizeScale, // 上端半径 0.003 * sizeScale, // 下端半径 0.08 * sizeScale // 高さ ); // 葯(anther): 花粉を含む球体 const antherGeometry = new THREE.SphereGeometry( 0.008 * sizeScale, 8, 8 ); // 円形配置の計算 const angle = (i / count) * Math.PI * 2; const radius = (0.03 + Math.random() * 0.02) * sizeScale; } }

雌蕊の作成

// 雌蕊を作成する関数 function createPistil(sizeScale = 2.0) { // 雌蕊の軸: 円柱 const pistilGeometry = new THREE.CylinderGeometry( 0.004 * sizeScale, // 均一な太さ 0.004 * sizeScale, 0.06 * sizeScale // 高さ ); // 柱頭(受粉部分): 白い球体 const stigmaGeometry = new THREE.SphereGeometry( 0.006 * sizeScale, 8, 8 ); }

がくの作成

// がくを1つ追加 const calyxGeometry = new THREE.ConeGeometry( 0.08 * calyxScale, // ★がくの底面半径 0.03 * calyxScale, // ★がくの高さ 5 ); const calyxMaterial = new THREE.MeshStandardMaterial({ color: 0x228b22 }); const calyx = new THREE.Mesh(calyxGeometry, calyxMaterial); calyx.position.set(0, -0.02 * calyxScale, 0); // ★位置もスケールに合わせる calyx.rotation.x = Math.PI; completeFlower.add(calyx);

桜の枝
マウスでドラッグして回転できます

このセクションでは、桜の枝を作成します。
枝の形状や配置を工夫することで、より自然な桜の木を表現します。

桜の枝の節

// ★節の情報を定義 const nodes = [ { position: new THREE.Vector3(0, 0, 0), direction: new THREE.Vector3(1, 0, 0) }, { position: new THREE.Vector3(0.4, 0.1, 0.05), direction: new THREE.Vector3(0.8, 0.6, -0.1) }, { position: new THREE.Vector3(0.7, 0.35, 0), direction: new THREE.Vector3(0.6, 0.8, 0.2) }, { position: new THREE.Vector3(0.9, 0.7, 0.15), direction: new THREE.Vector3(0.3, 0.9, -0.1) }, { position: new THREE.Vector3(1.0, 1.1, 0.1), direction: new THREE.Vector3(0.2, 1.0, 0.1) } ];

桜の枝の接続

// ★節間のセグメントを作成 for (let i = 0; i < nodes.length - 1; i++) { const startNode = nodes[i]; const endNode = nodes[i + 1]; // セグメントの長さ const segmentLength = startNode.position.distanceTo(endNode.position); // ★適度に真っ直ぐなセグメント作成 const segmentGeometry = new THREE.CylinderGeometry( 0.02 * (1 - i * 0.15), // 先端に向かって細くなる 0.025 * (1 - i * 0.1), segmentLength, 12 );

桜の枝の階層分岐

// ★節(ふし)を作成 for (let i = 1; i < nodes.length - 1; i++) { const node = nodes[i]; // 節の膨らみ const nodeGeometry = new THREE.SphereGeometry(0.018, 12, 12); const nodeSwelling = new THREE.Mesh(nodeGeometry, barkMaterial); nodeSwelling.position.copy(node.position); // ★節から小枝を追加(1-2本) const subBranchCount = Math.random() > 0.5 ? 1 : 2; for (let j = 0; j < subBranchCount; j++) { createSubBranch(node.position, branchGroup, barkMaterial, i); } }

桜の小枝の構造

// ★小枝のセグメント数(2-4個に増加) const segments = 2 + Math.floor(Math.random() * 3); // ★小枝の節の位置を定義 const subNodes = []; for (let i = 0; i <= segments; i++) { const t = i / segments; const position = new THREE.Vector3() .copy(nodePosition) .add(branchDirection.clone().multiplyScalar(branchLength * t)); // 小さなランダムな変化を追加 position.add(new THREE.Vector3( (Math.random() - 0.5) * 0.02, (Math.random() - 0.5) * 0.02, (Math.random() - 0.5) * 0.02 )); subNodes.push(position); }

桜の小枝の三次分岐

// ★新しい関数:三次分岐(小枝から更に分岐) function createTertiaryBranch(nodePosition, parentGroup, material, generation) { // より細い枝の方向 const branchDirection = new THREE.Vector3( (Math.random() - 0.5) * 2, Math.random() * 0.6 + 0.1, // 上向き傾向を弱める (Math.random() - 0.5) * 2 ).normalize(); // より短い枝 const branchLength = 0.08 + Math.random() * 0.15; const segments = 1 + Math.floor(Math.random() * 2); // 1-2セグメント


マウスでドラッグして回転できます

このセクションでは、今まで作成した桜の花、枝を使い、1本の枝付き桜を作成しました。
javascriptのexportを使用して、各コンポーネントをモジュール化し、再利用可能な形に整えます。

exportの例

export function createSakuraFlower(scale = 1) { // 花びらを1つだけ作成 const petal = createSakuraPetal(0.5, 0xff69b4, new THREE.Vector3(0, 0, 0)); petal.rotation.x = Math.PI / 2; return petal; }

importの例

import { createRealisticPlumBranch, createSubBranch, getBranchNodes, createTertiaryBranch, createTinyTwig } from './cherry-parts/brunch_export.js'; import {createSakuraFlower} from './cherry-parts/petals_export.js'; import {OrbitControls} from 'three/addons/controls/OrbitControls.js';

本コンテンツの作成時間

約18時間

参考資料

↑ Top