Codementor Events

How I fell in love with atoms and built a 3D periodic table in Javascript

Published Dec 23, 2017Last updated Jun 21, 2018
How I fell in love with atoms and built a 3D periodic table in Javascript

I'll tell you right off the bat: making Victor's Periodic Table was super fun. But also hard. Love's like that.

Good thing I was taking chemistry and calculus, and that I'm a front-end and Javascript geek. Warning: this post contains some very science-geeky stuff, if you didn't guess it from the title.

I'm going to break down the process of building a complex 3D viewer like this in ThreeJS. It'll be from a bird's-eye view -- I'm going to avoid code, mostly, at least. It's just too hard to fit all of it into one post. Go look at the source, if you're that kind of person.

But if you want ThreeJS tutorials or code from this project... just leave me a comment. I'll definitely make a post if you do.

I'm a nerd

I'm 30, I have a Master's (in Religious Studies, of all things), and I'm a web developer, but last year I got the urge to take some science classes. I live right next to a community college so I went and took first year Chem, Bio, and Calc. It was really fun. Yeah, calculus is fun, I said it. Once you start getting a bit older, it's nice to find a new way to look at the world: and for me, that was math.

Chemistry really appealed to me, and I love thinking about atoms and electrons. It's freaking unreal that our world, everything, is made of them. I wanted to be able to visualize an atom better, and I couldn't find any really good model viewers online. There were some pictures in our textbooks, and some good 3D periodic tables, but they weren't what I wanted. They helped, though -- especially this orbital viewer.

Screen Shot 2017-12-23 at 12.09.59 AM.png

What I really wanted to see was not only the nuclei and the protons/neutrons, but the electrons... yeah, the electrons! Sparking randomly in their orbitals, in a 3D model that was fully interactive. That's what I wanted. And I was going to build it.

I've built stuff using WebGL in ThreeJS before, nothing crazy, but I had a feeling I could try it out and see how far I could get. Rolled up my sleeves. Working in ThreeJS is no joke, my friends, believe you me.

Begin the Coding

Screen Shot 2017-12-23 at 12.09.16 AM.pngThere is a process to building any web app or new project, especially if it's complex. Think from a high level first. What do you really need to actually start getting somewhere?

For me, hydrogen was the starting point. I know the 1s orbital is just a sphere, so I really just needed to make a few different spheres in ThreeJS: one that represented the nucleus, and a larger semi-transparent one that represented the orbital. Easy, right?

What you think is simple isn't always simple -- that's most definitely true in ThreeJS. Placing an object in the center of the screen, lighting the scene properly, and making it possible to zoom and rotate around ... these are not as easy as they might seem at first. But eventually I got it, with the help of many online tutorials. Adding text is also remarkably difficult, as a beginner.

One problem with ThreeJS is that it's highly version-dependent, and it has many, many versions. Tutorials that you'll find could be in any version, and you have no idea if you can adapt the code or if it'll never work. There's more trial and error than almost any other framework or library I've used.

Anyway, I eventually got the scene lit, and my spheres. It was nice. But I immediately wanted to do more. Helium next -- then the more complex p-orbitals.

Increasing complexity

I had to adapt some of my growing calculus knowledge to help me calculate the possible positions of an electron randomly appearing and disappearing inside an orbital. My formula looks complex in code but is really simple:

   var shellRadius = Math.abs((shellConstraints.x2-shellConstraints.x1)/2);
   var angleTheta = Math.acos(Math.abs(xPosition)/shellRadius);
   var maxValues = Math.sin(angleTheta);
   if(Math.abs(yPosition)>maxValues) {
       yPosition = (maxValues * Math.sign(yPosition)) + shellConstraints.offset.y;
   }
   if(Math.abs(zPosition)>maxValues) {
       zPosition = (maxValues * Math.sign(zPosition)) + shellConstraints.offset.z;
   }

Essentially, I set up the electron to randomly run through a function that defined position variables according to the radius of the relevant orbital. It was a little tricky to get, but once I got it it deployed perfectly from then on.

There is also a lot of touchy positioning going on with the orbitals in order to have them ballooning and stretching out in the right directions. I had to experiment and play around a lot with scale and position, but look at the totally gorgeous atoms that ended up being generated!

At some point, I began to carefully split up my files into a series: Atomic Stage, Atomic Functions, Interface, and so on. I kept my really mathematical and complex work in Functions, and moved the scene, lighting, and showing/hiding type work to Stage.
Screen Shot 2017-12-23 at 12.11.16 AM.png

I also had to build out an interface eventually, and make it work with switching and clearing the stage. I used jQuery, just to trigger the events necessary to show and hide the elements. It was not at all easy to constantly clean up and re-re-re-revise my code, to try to make it manageable and scalable for larger and larger atoms. But at this point I was dying to share it with someone, and I needed it to work!

Where to now?

I shared the site with my chemistry teacher, and much to my embarrassment (or delight?) she shared it with the class. It worked, bug free -- which was pretty sweet. People were impressed, in a kind of pitying way. 😃

Further development of it? I haven't promoted it at all. I'm not so good at marketing. I guess it could be turned into a larger educational tool, if I wanted to email around to professors and stuff. Do you have any ideas?

But also, at this point, I'm not sure how much WebGL can reliably take more complex orbitals. I could drop some earlier shells, or only allow outer shells, but I'm also a little less interested in this project than before. But my computer definitely gets hot once the shells get thick on those heavier elements.

I've tried to just give you a very quick look at how I went through a complicated ThreeJS project like this. I wish I could have gotten more into the guts of the code, but it's honestly a behemoth to go through. I will, though -- if you want to learn how to make something like this yourself!

I'll always be a huge nerd. Get in touch with me about your nerdy projects and let's do something together!

Discover and read more posts from Victor Gerard Temprano
get started
post commentsBe the first to share your opinion
DongYi
2 years ago

good job. feeling very inspirational

Show more replies