2022 January 05

Constructing Polyhedrons with JavaScript


I wanted to know if I could program and animate SVGs without the assistence of a third-party software such as Adobe Illustrator. Don't get me wrong, I still use Adobe Creative Suite, but I want to bridge the gap between design and development.

Ambitiously, I wanted to construct polyhedrons by math and translate vertices into <point> elements. The answer I kept finding was, I have to use a library such as ThreeJS which is not a problem. However, I have seen so many times the temptation in Front End Devs to answer one problem with a library that likely introduces more problems such as bloat (a good example of this is MomentJS). So ThreeJS is the way to go, but only if we are going to use it to it's fullest potential. If it's for one thing only, a more light-weight approach is required - which means it's going to require one to think.

The good news is, someone already did the thinking for me! I want to thank Xah for publishing their 1-hour demonstration on YouTube.

Here is my version of this on CodePen

polyhedrons as SVGs

For each polyhedron we wish to construct, we begin with initSolid. We could hard code these calculations, but where's the fun in that? But a good arguement for doing this is it does require us to be precise such as calculating the golden ratio.

What's amazing to me, I did not know before, is there are many vertices that share the same values - as you will see v, vo, and gr repeated in the data. Here we set the data for each polyhedron.

I made it easier to set what type of polyhedron we want by classname: '.tetrahedron', '.cube', '.octahedron', '.icosahedron'

I wanted to first check if the element with a matching className exists first - that's where solidMatch comes in before we try to append any new elements. If there is a match, then set a <svg> tag inside each target element. The render function is what contructs each <polygon> and is appended in the newly created SVG.

Because this is a 2D representation of a 3D object, I learned we can simply leave out the z coordinates and it will work just fine. .map(([x, y, _z]) => [x, y]) But the issue is it's hard to tell that it's actually 3D without movement. So I wrote another function that rotates by x and z coordinates by 5 degree increments, to give us the impression.

And there you have it! It's amazing to me how little code it took to get this accomplished. You can also control the rotation during an event if you want such as scrolling up and down. GSAP's ScrollTrigger makes it incredibly easy without going through the hassle of configuring an IntersectionObserver.

Copyright © 2022. Jake Wantulok