Web Development

My Web Project: 3D Atom & Interactive Periodic Table

Discover the journey behind creating a stunning 3D atom model and interactive periodic table with Three.js and React. A deep dive into the tech and challenges.

L

Liam Carter

A front-end developer and creative technologist passionate about interactive 3D web experiences.

6 min read14 views

Remember high school chemistry class? For me, it was a mix of fascinating concepts and... well, pretty static learning tools. The periodic table was a flat, lifeless chart on the wall, and the structure of an atom was a diagram in a textbook that looked more like a tiny solar system than a dynamic, energetic entity. It worked, but it never felt truly intuitive or exciting.

As a web developer with a passion for visual storytelling, I kept coming back to one question: can we do better? Can we leverage the power of modern web technologies to transform how we visualize and interact with fundamental scientific concepts? This question became the seed for my latest passion project: a fully interactive periodic table connected to a dynamic, 3D atom viewer built with Three.js and React.

This post is a deep dive into that journey. I’ll walk you through the initial spark of inspiration, the tech stack I chose, the design and development challenges I faced, and the key lessons I learned while trying to bring the building blocks of our universe to life in the browser. Let's get into the code, the concepts, and the creative process.

The Spark of an Idea: Beyond Static Charts

The project began not with a line of code, but with a simple goal: to create a learning tool that I wished I had. I wanted something that wasn't just a reference but an exploratory experience. Imagine clicking on 'Gold' (Au) and not just seeing its atomic number, but watching a 3D model of a gold atom assemble before your eyes—79 protons and 118 neutrons forming a dense nucleus, with 79 electrons zipping around their respective shells. The idea was to make the abstract tangible.

My core objectives were clear:

  • Interactivity: Users should be able to filter, search, and select elements with ease.
  • Visualization: The 3D atom model needed to be clear, accurate (within the simplified Bohr model), and performant.
  • Information: Key atomic data should be presented cleanly alongside the visual model.
  • Responsiveness: The experience should be seamless on both desktop and mobile devices.

Choosing the Right Tools: The Tech Stack

With a clear vision, the next step was selecting the technologies. This is always a critical phase, as the right tools can accelerate development, while the wrong ones can lead to roadblocks. I needed a robust combination for a dynamic UI and a complex 3D scene.

Here's a breakdown of my choices and the rationale behind them:

Component Technology Chosen Reasoning
3D Rendering Three.js The de-facto standard for WebGL. It has a massive community, extensive documentation, and the flexibility to handle everything from simple shapes to complex, high-performance scenes. Libraries like Babylon.js are also great, but my familiarity with Three.js made it the faster choice.
UI Framework React Its component-based architecture is perfect for building a modular UI like a periodic table. Managing the state of the selected element and updating the 3D scene in response to UI events is straightforward with React's lifecycle and state management.
React/Three.js Bridge React Three Fiber (R3F) This library is a game-changer. It lets you build your Three.js scene declaratively with reusable React components. Instead of imperative commands like scene.add(mesh), you can just write <mesh />. This simplifies code, improves readability, and integrates perfectly with the React ecosystem.
State Management Zustand While React's built-in state is powerful, I needed a simple way to share state between the UI (the table) and the 3D canvas. Zustand is a minimal, fast, and unopinionated state management solution that doesn't require wrapping your app in context providers, making it perfect for this use case.

Building the Periodic Table: A UI/UX Challenge

The periodic table itself was the first major component. It’s not just a grid; it has a unique, staggered shape. I used CSS Grid Layout to create the structure, which is perfectly suited for this kind of non-standard layout. Each element is a button component that, when clicked, updates the global state with its atomic data.

Advertisement

Data and Interactivity

I sourced the element data from a public JSON file, which contains everything from atomic mass and electron configuration to discovery year. When the app loads, this data is used to populate the grid. I added filter buttons that allow users to color-code the table by element category (e.g., 'alkali metal', 'noble gas', 'lanthanide'), which immediately highlights relationships between elements.

The core interaction is simple: you click an element, and the app's central state (managed by Zustand) updates. The 3D canvas component is subscribed to this state, and upon change, it triggers a re-render of the atom model with the new element's properties. This decoupled approach keeps the UI and the 3D logic clean and separate.

Crafting the Atom: A Deep Dive into Three.js

This was the most exciting and challenging part. How do you programmatically build an atom? I broke it down into three parts: the nucleus, the electron shells, and the electrons themselves.

The Nucleus: Protons and Neutrons

The nucleus is a cluster of protons and neutrons. Creating a single sphere in Three.js is easy. Creating up to 294 of them (for Oganesson) and arranging them in a somewhat spherical cluster without killing performance is hard. My first attempt, a simple loop creating new Mesh objects, was a disaster for performance. The solution? InstancedMesh. This powerful Three.js feature lets you render a huge number of identical objects with different positions and colors in a single draw call. I used one InstancedMesh for all the protons and another for the neutrons, dramatically improving frame rates.

The Shells and Electrons

For the electron shells, I opted for the classic Bohr model representation: simple circular orbits. I used a TorusGeometry for each shell, making them semi-transparent to maintain a clean look. The radius of each torus corresponds to the energy level of the shell.

The electrons are small spheres that need to animate along these orbital paths. This is where a little bit of trigonometry comes in handy. Inside the animation loop provided by React Three Fiber's useFrame hook, I update the position of each electron using sine and cosine functions:


useFrame((state, delta) => {
  // For each electron in its shell
  const angle = initialAngle + (speed * state.clock.elapsedTime);
  const x = orbitalRadius * Math.cos(angle);
  const z = orbitalRadius * Math.sin(angle);
  electronRef.current.position.set(x, 0, z);
});
        

By giving each electron a slightly different speed and initial angle, I could create a mesmerizing, dynamic dance that feels much more alive than any static diagram.

Overcoming Hurdles: Performance and Precision

As mentioned, performance was the biggest hurdle. Beyond using InstancedMesh, I implemented a few other optimizations:

  • Geometry Sharing: All protons share a single SphereGeometry, as do all neutrons and electrons. This saves memory.
  • Level of Detail (LOD): While not fully implemented yet, a future step is to simplify the model when it's viewed from a distance or on the main grid view, and only render the full, detailed atom when it's the main focus.
  • Avoiding Unnecessary Re-renders: By using React.memo for UI components and carefully structuring my state, I ensured that only the necessary parts of the app re-render when the selected element changes.

Another challenge was scientific representation. The Bohr model is a simplification; in reality, electrons exist in complex probability clouds called orbitals. I made a conscious decision to stick with the Bohr model because it's more intuitive and visually clear for a general audience. I added a small disclaimer in the UI to acknowledge this, striking a balance between educational clarity and scientific accuracy.

Key Features and What I Learned

After weeks of coding, debugging, and tweaking, the project came together. The final product includes:

  • A responsive, interactive periodic table with element filtering.
  • A dynamic 3D viewer that constructs an atom for any selected element.
  • Smooth animations for electrons orbiting the nucleus.
  • A clean UI displaying essential data like atomic mass, electron configuration, and more.

This project was an incredible learning experience. My biggest takeaway was the power of declarative 3D with React Three Fiber. It completely changed my workflow for web-based 3D projects, making scene management feel as natural as building a web UI. I also gained a much deeper appreciation for performance optimization in WebGL. It’s not an afterthought; it has to be part of the design process from day one.

What's Next for This Atomic Explorer?

This project is by no means 'finished'. Science is about continuous exploration, and so is development. I have a list of features I'd love to add in the future:

  • Orbital View: A mode to visualize the more accurate (and much more complex) s, p, d, and f electron orbitals.
  • Isotopes: Allowing users to add or remove neutrons to see how isotopes are formed.
  • Compound Builder: A far-future idea to let users combine atoms to see simple molecular structures.

Building this interactive atom viewer has been one of the most rewarding projects I've ever worked on. It's a perfect marriage of my interests in science, design, and technology. It transformed a static chart from my memory into a living, breathing digital playground. I hope it can serve as a small inspiration for how we can make learning more visual, interactive, and fun.

Feel free to check out the live project and dive into the source code on my GitHub. I'd love to hear your feedback!

Tags

You May Also Like