I created a sketch that generates poems from images as my computational letterforms assignment. This sketch transforms sampled pixels from an image into characters to create a poem randomly!
After finishing this project, I thought it would be super cool to make the circles draggable and have the poem refresh while dragging! Using d3-force would be the ideal way to implement this. Since we were learning about forces this week, and I was curious about how it works, I decided to implement a simple version myself. This also gave me a great opportunity to shape Charming.js. Here's the result, and you can find the code here.
Although there's plenty of room for improvement, I'm happy I implemented this effect with minimal code. This example also helped me find and fix a memory leak in Charming's garbage collection! While I didn't need to apply this effects to my previous sketch, I plan to do so in the future.
First, I looked through Dan's example for two-body attraction. I quickly implemented it with Charming.js. When I added multiple bodies to the canvas, they kept moving endlessly! I realized we shouldn't apply forces from every other body—only from nearby ones. However, detecting nearby bodies around a circle is tricky. While a quadtree would solve this, it would be too complex for this project.
Then I looked through the source code of d3-force. It confirmed my suspicions—it uses a quadtree to find neighbors and apply forces from them. The forces turned out to be more complex than expected. To achieve what I wanted, I needed to implement three forces:
I decided to look for a simpler solution, even if not perfect. I remembered seeing a similar effect on OpenProcessing called Wobbly Swarm by Konstantin Makhmutov.
After reading its source code, I was amazed to find it used such a simple force to create the effect! I immediately adapted this force for my own work. While running my sketch, it got slower and slower until the browser crashed due to running out of memory. This revealed a memory leak in Charming, so I opened a PR to fix it.
Although I didn't apply d3-force's algorithm in my work, I drew many inspirations from its API design. I especially liked how it decouples visual elements and methods. Most importantly, this pattern will be applied across all Charming's official examples! Let's say goodbye to classes!
With Charming.js, the implementation is straightforward.