Crafting an Interactive Galaxy with Three.js for an Eye-Catching Homepage

Kaiser Keenmon
7 min readJan 2, 2024

--

I’ve been working on digital content that I plan to release soon, with plans of releasing more in time. While working on a particular piece, it became apparent that I‘d need a website. Naturally, one of the first questions I asked was, “What would the home page be like?” I wanted something eye-catching for sure, and the first thing that came to mind was Three.js!

Three.js space scene including a ship and planets.

Inspiration: “Nerding Out”

Galaga Atari game.

But then I also had to ask, “What to build with Three.js, and how might it enhance my site?” So, I brainstormed ideas like an interactive seascape, town, or village. Ultimately, being a fan of Atari space-themed classics like Asteroids and Space Invaders, I was more intrigued by visions of an interactive space scene — à la Galaga!

Tech Stack: A Few of the Technologies Leveraged for This Project

I’m building the site on Laravel/Vue.js, which will streamline my development. With it, I’ll be able to leverage its wide array of first and third-party tools, like Inertia, Breeze, Spark, and Socialite, to name a few. Leveraging Inertia, I’ll be able to get up and running with creating dynamic UIs very quickly using Vue or React. I’m leaning toward Vue, which I have more experience with but haven’t settled on. For the home page, I’m using Three.js for an interactive and visually appealing entry point to the site. Finally, to ease the development process of the Three.js scene, I’m using Express.js.

Setting the Scene

Low poly space alien worlds 3D asset pack by syomapozdeev.

My thinking for the space scene was to create a galaxy where users could journey to different planets to discover different areas of the site. For that, I needed planets and a ship; in other words, 3D models were essential! So, I could either build the needed models or, much more conveniently, source them. And given time constraints, I quickly opted for the latter. A few Google searches and 3D model marketplace shopping sessions later, I settled on this clean, low-poly space object set on CGTrader, created by syomapozdeev. It’s chock full of ships, planets, landforms, space stations, and other things you might find in space.

With the model downloaded, I isolated and exported the planets and ships I needed using Blender. The original model file was a composite of many space-related elements, so I carefully separated and exported only the components required for my scene.

Isolating needed objects from composite model in Blender.

After that, I only needed to modify the position of each exported object within the 3D viewport. In the original model, each element was positioned relative to the composite model’s center. Modifying the position of each extracted object so that its geometric center was aligned with the center of the 3D viewport enabled me to rotate the objects around their centers in the Three.js scene.

Modifying origin point of a model in Blender.

With the planets loaded into the scene, I positioned them randomly on page load, providing a unique appearance each visit. Additionally, I opted to rotate each planet around its center to provide an extra layer of motion to the environment.

For the background and to give the scene an immersive space environment-like feel, I added a skybox that I generated with this sweet online cube map generator here, which brought the scene together nicely. I also added a floating star field, adding yet another layer of motion and realism to the environment.

Cubemap generator from wwwtyro.netw.

Additionally, I planned a few necessary and informative UI elements for the page.

  1. I planned to load a modal popup containing site information and a CTA each time the user journeys to a planet that’s linked to modal data.
  2. I planned a hamburger pop-out navigation menu so users can navigate the site without using the space scene.
  3. I added a key-map to aid users in navigating the ship.
  4. And for further visual coherence and thematic effect, I opted to style all UI elements to resemble a spaceship’s HUD, tying together the look and feel of the scene.

Enhancing the User Experience

With the ship loaded, I configured keybindings to control its movements: forward, backward, up, down, left, right, roll-left, roll-right, level reset, and position reset. I also added a ‘warp back’ function to reset the ship back to its original position in the scene. The user can press a key to ‘warp back’ to this position at any time. Additionally, if the ship travels too far outside the ‘safe zone,’ a HUD will appear with a blinking warning that it is nearing the warp threshold. Once the threshold is reached, the ship will automatically be ‘warped back.’

Warning warp threshold HUD added to scene.

At this point, the scene looked very nice, crispy even. The environment appeared super space-like; the planets and the ship looked killer, and the ship’s controls and movement worked smooth like butter.

However, I still needed to incorporate links to other site areas with brief descriptions so that the scene/page functions as a useful site component. To accommodate this, I added a JSON file for storing data for each modal. I then modified the planet-loading method to randomly associate each data item from the JSON file with one of the planets on page load. Adding this randomness further keeps the scene unique on each visit, as the planets are not only randomly positioned but also randomly associated with data on each page load. Finally, I added collision detection to trigger the modals to display whenever the ship collides with a planet linked to data.

Popup modals display when the ship collides with a planet.

Additionally, because there are 9 planets but currently only 4 data items, I needed to enhance the linked planets. To achieve this, I implemented a shader to add a soft glow around the linked planets to serve as a visual indicator to users that they should visit these unique planets.

Planets linked to data appear with a soft glow.

Finally, I added the popup navigation and the key-legend, and I also wired up the key-legend so that the active key is highlighted as the user navigates.

Popout navigation and key-legend added to scene.

Future Updates:

The next steps for me are to adjust the layout of the UI elements and enable ship navigation on mobile. Controlling the ship on mobile could be approached in several ways, but I have yet to settle on one. Whatever the case, it should be fun. Additionally, I’ll need to add branding and load actual modal data.

Possible Future Updates:

Envisioning the future of this interactive galaxy, I’m considering a few possible enhancements. A few possible feature adds are:

  1. An asteroid field that could destroy the user’s ship to add an increased level of challenge.
  2. An enemy ship that could destroy the user’s ship to add an increased level of challenge.
  3. A firing mechanism could be added to the ship, adding an offensive capability.
  4. The scene could also be gamified with a point system, and specific goals could increase user engagement.

Any of these would create a richer and more immersive user experience. Exploring these possibilities is what makes working on projects like this incredibly rewarding.

I’d love to hear from you! Visit machinelrn.com, take the helm and let your curiosity guide you through the stars. Seriously though, I’d love to hear your thoughts, suggestions, and overall experience with the current state of the home page. Did the scene load quickly enough? Was it intuitive enough? How were the interactions? What features would you like to see added? Your feedback is the stardust that will help drive the evolution of this galactic interface!

If you found this article interesting, please share it with others who might also enjoy or benefit from it. Thank you for your support!

Current state of the three.js scene.

--

--

Kaiser Keenmon

Experienced PHP Developer specializing in Laravel/Vue, Drupal, WordPress, and Magento2. Past work in ASP.net. Currently learning Python.