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).
Basic idea
- Procedurally generated shapes by using only few generated points
- Creating smoothened SVG path from points.
- Adding shadow and gradient to the shapes.
- Create multiple stages while slightly moving points around (hence creating a morphing shape)
- Applying shape morphing
- Multiply the same logic and enjoying the result
1. Generating shape
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.)
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.
2. Creating smoothened SVG path
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.
3. Adding shadows and gradients
Adding linear gradients are simple but shadow looks a little tricky to me. But hey, it works and looks better than without it.
4. Adding noise
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²)
5. Morphing
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.
6. Laying back
12 hours later, my creation is alive! Check it out on https://onet.dev