Creating a lava lamp in React (Web)

I’ve been working with Next.JS (a React framework) for the last few months and I decided make something more interesting than a simple webpage. I wanted to create a lava lamp using only SVG paths. (It might not look like a proper lava lamp, but it will probably melt your CPU/GPU because it’s not the most optimized piece of software).

  1. Procedurally generated shapes by using only few generated points
  2. Creating smoothened SVG path from points.
  3. Adding shadow and gradient to the shapes.
  4. Create multiple stages while slightly moving points around (hence creating a morphing shape)
  5. Applying shape morphing
  6. Multiply the same logic and enjoying the result

This one is quite easy, I wanted a hump in the middle of the screen, so I looked for function that resulted in the desired shape. I ended up using a frequency curve but I found other that could be useful in the future. (Except hyperbola, because I’d have to update the whole plot render to handle two shapes on one layer.)

Visualization of selected functions

It’s only a short for loop to get our array of x:y coordinates (from -5 to 5 in my case). At this point, we don’t have to worry about getting the SVG path definition yet.

I found this wonderful article from François Romain about exactly what I needed. Based on the knowledge in this article, it’s fairly easy to implement a solid path smoothing.

Adding linear gradients are simple but shadow looks a little tricky to me. But hey, it works and looks better than without it.

To achieve the morphing effect, I simply created 5 different versions of the initial shape coordinate array (see point 1) by changing every single point slightly in a given radius. We can do this by using Pythagoras theorem (a²+b²=c²)

My main issue with this part was that many SVG animation tool is not available in React or poorly implemented. Thankfully I don’t have to deal with different number of points in the different stages but that can be an issue while doing SVG animations using automatic interpolation.

I started off by trying to use Paper.js because it has a smoothing and morphing example not too far from my goal but unfortunately I couldn’t get it working in React.

So, after a little research, I found an article about react-spring on CSS tricks. It perfect, they basically done it for me. I just had to add the previously generated stages to the output value and changing the x valued using a setInterval. The CSS tricks example has only 2 stages, so instead of using “active” I used “stage” because I had n stage instead of just A and B. Be careful though, while we have multiple stages (eg 5) the range of x is still from 0 to 1 so will need to use float values otherwise the animation will be jumpy.

12 hours later, my creation is alive! Check it out on https://onet.dev

Choosing the unknown