planets

a three.js display of planets by notchris

by notchris

HTML

<div id="render"></div>
<div class="pallete">
  <div class="sun"></div>
  <div class="a"></div>
  <div class="b"></div>
  <div class="c"></div>
  <div class="d"></div>
  <div class="e"></div>
  <div class="f"></div>
  <div class="g"></div>
  <div class="h"></div>
</div>

SCSS

* {
    box-sizing: border-box;
    text-rendering: optimizeLegibility;
    font-kerning: auto;
  }
  
  html {
    font-family: sans-serif;
  }
  
  body {
    margin: 0;
  }
  
  html,
  body {
    width: 100%;
    height: 100%;
  }

  .label {
    margin-top: -2em;
    text-align: center;
  }

  .label .planet-distance::after {
    content: '';
    font-size: 0.1em;
    position: absolute;
    top: 24px;
    left: 50%;
    width: 1px;
    height: 16px;
    background: rgba(0, 0, 0, 0.5);
  }

  .planets {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }

  .planet-title {
    font-family: 'Arial', sans-serif;
    font-size: 0.6em;
    font-weight: 600;
    display: block;
    width: 100%;
    text-transform: uppercase;
    padding-bottom:0.3em;
  }

  .planet-distance {
    font-family: 'Arial', sans-serif;
    font-size: 0.5em;
    font-weight: 400;
    display: block;
    width: 100%;
  }

  #render {
    width: 100%;
    height: 100%;
    min-height: 200px;
    max-height: 200px;
    max-width: 100%;
    position: relative;
  }

.pallete {
  display: flex;
  align-items: center;
  flex-direction: row;
  justify-content: center;
  padding: 0.5em 0;
}

.pallete div {
  width: 30px;
  height: 30px;
  margin-right: 1em;
  opacity: 0.5;
  border-radius: 30px;
  cursor: pointer;
}

.pallete div:hover {
  border: 2px solid rgba(0, 0, 0, 0.5);
  opacity: 1;
}

.pallete div:last-child {
  margin-right: 0 !important;
}

.pallete {
  & .sun {
    background: #FFE600
  }
  & .a {
    background: #C2D0FF
  }
  & .b {
    background: #FF9900
  }
  & .c {
    background: #00A3FF
  }
  & .d {
    background: #FF5C00
  }
  & .e {
    background: #E59700
  }
  & .f {
    background: #FFCF72
  }
  & .g {
    background: #61D9FF
  }
  & .h {
    background: #0047FF
  }
}

JavaScript

/* Planets by notchris */

import * as THREE from "https://cdn.skypack.dev/[email protected]";

import {
	CSS2DRenderer,
	CSS2DObject
} from 'https://cdn.skypack.dev/[email protected]/examples/jsm/renderers/CSS2DRenderer.js'

import gsap from "https://cdn.skypack.dev/[email protected]";

import {
  OrbitControls
} from "https://cdn.skypack.dev/[email protected]/examples/jsm/controls/OrbitControls";


		let renderer,
			labelRenderer,
			scene,
			camera,
			clock,
			planets,
			controls,
			mainObj,
			activePlanet
		const el = document.querySelector('#render')
		const { width, height } = el.getBoundingClientRect()
		const size = new THREE.Vector3()
		const center = new THREE.Vector3()
		const box = new THREE.Box3()
		init()

		const planetArr = [
			'sun',
			'mercury',
			'venus',
			'earth',
			'mars',
			'jupiter',
			'saturn',
			'uranus',
			'neptune'
		]

		const planetEls = document.querySelectorAll('.pallete > div')
		planetEls.forEach((p, i) => {
			p.addEventListener('mouseover', () => {
				activePlanet = planetArr[i]

				gsap.to(mainObj.rotation, {
					duration: 0.3,
					x: Math.PI / 2,
					ease: 'none',
					paused: false
				})
				gsap.to(mainObj.position, {
					duration: 0.3,
					z: 200,
					ease: 'none',
					paused: false
				})

				const mesh = scene.getObjectByName(planetArr[i])
				mesh.children[0].visible = true
				activePlanet = mesh
			})
			p.addEventListener('mouseleave', () => {
				gsap.to(mainObj.rotation, {
					duration: 0.3,
					x: 0.1,
					ease: 'none',
					paused: false
				})
				gsap.to(mainObj.position, {
					duration: 0.3,
					z: 0,
					ease: 'none',
					paused: false
				})
				const mesh = scene.getObjectByName(planetArr[i])
				mesh.children[0].visible = false
				activePlanet = null
			})
		})

		animate()

		function fitCameraToSelection(camera, controls, selection, fitOffset) {
			box.makeEmpty()
			for (const object of selection)...