🌏概要
OS Yamatoでは、各カテゴリに保存されたデータをを3D惑星の周囲に“花”として可視化しています。写真1000枚などという数字だけでは、どこか味気なく感じるものです。よって、詩的なOSに相応しいデータの可視化を実装しました。
本記事では、Vue 3 + Three.jsで構築したその仕組みを分解しながら紹介します。
🌍 1. 地球モデルの生成
SphereGeometryで球体を生成
テクスチャは5種類(photo, video, message, memo, contact)に対応
MeshBasicMaterialで表面に貼り付け
OrbitControlsを用いてカメラ操作(回転のみ可能)
const geometry = new THREE.SphereGeometry(1.0, 192, 192)
const material = new THREE.MeshBasicMaterial({ map: texture })
planetMesh = new THREE.Mesh(geometry, material)
scene.add(planetMesh)
🌸 2. 投稿数を花で表現する
PlaneGeometry + 花の画像テクスチャで“花びら”を作成
投稿数に応じて球面上にランダム配置
投稿数が増えるほど色が変化する
青 → 紫 → 黄 → オレンジ → 赤
function createSingleFlower(color) {
const geometry = new THREE.PlaneGeometry(0.25, 0.25)
const material = new THREE.MeshBasicMaterial({
map: flowerTexture,
color: color,
transparent: true,
side: THREE.DoubleSide
})
const flower = new THREE.Mesh(geometry, material)
}
✨3. 背景に星と流星
ランダムな座標に背景の星を配置(CSS)
shooting-stars クラスで流星エフェクトを実現
アニメーションはCSSで制御
4. メモリリーク対策とクリーンアップ
onUnmountedで geometry, material, renderer, controls すべてを破棄
isMounted フラグで animate() の暴走も防止
onUnmounted(() => {
if (renderer) {
renderer.dispose()
if (renderer.forceContextLoss) renderer.forceContextLoss()
renderer.domElement = null
}
if (planetMesh) {
planetMesh.geometry?.dispose()
planetMesh.material?.dispose()
scene.remove(planetMesh)
}
controls?.dispose()
flowerMeshes.forEach(f => {
f.geometry?.dispose()
f.material?.dispose()
})
Object.keys(textures).forEach(key => {
textures[key]?.dispose?.()
})
if (flowerTexture?.dispose) flowerTexture.dispose()
clearInterval(meteorInterval)
})
⸻
💬 5. Vueとの組み合わせが強い理由
Vueの再活動性とi18nの統合で、国際対応や状態管理がしやすい
単一ファイルコンポーネント(.vue)でThree.jsのスコープを安全に封じ込め可能
⸻
✅ まとめ
Three.jsでの地球表現は単なるビジュアル以上に、詩的なUI/UX表現の手段となる
Vueとの相性も良く、コンポーネント単位で完結できるのが魅力
🔗 プロジェクト情報
• 試してみる:
https://hanaco875.com
メールアドレスで簡単にサインアップ!!
• ソースコード: GitHub - osyamato/os-yamato
https://github.com/osyamato/os-yamato
🌱 OS Yamato / 花子天気は オープンソース です。
技術や思想に共鳴する方は、気軽に触れてみてください。
PR・Issue・コメントも大歓迎です。