Building on my last article, Pretty Metaballs, I have seen a number of metaball examples that connect two circles, or that do so in a hub-and-spoke fashion.

However, I wanted to create a function that would generate a single SVG `path` representing a meta-metaball! The function `f(g) -> path` would take `g`, a group element containing two or more circle elements, and output a closed `path` (ends with the `Z` command) around these circles. The result would look as follows:

Here’s an example of an algorithm to do just that, as well as issues that might arise when building this tool:

Metaball `circles` to `path` algorithm

1. Traverse the DOM and get all `circle` elements with the group.
2. Sort circles (i.e. vertically, horizontally, by Euclidean distance, etc).
3. Find the 4 tangent points (TP) and 4 bezier curve handle points (see http://varun.ca/metaballs/)
4. Start the path with `M` (moveTo) at TP 1 between circles 1 & 2.
5. Draw a bezier curve, `C`, between TPs 1 & 2.
6. Draw an arc, `A`, between TP 2 (circles 1–2) and TP 1 (circles 2–3).
7. For terminal circles (`0` or `length-1`), draw an arc between TP 2 & 3.
8. Repeat twice (iterate once sorted and once reversed).
9. Close the path with `Z` (the final arc should close where we started).

To illustrate this algorithm, I’ve created a graphic to show tangent points in red, handle points in yellow, and labels for the various components of the path (i.e. arcs & curves).

Common issues when writing SVG algorithms

• `childNodes` doesn’t work for SVG elements and `children` for SVG isn’t widely supported. Instead, I use `querySelectorAll`, though `getElementsByTagName` should work as well.
• `document.createElement` doesn’t work for SVG elements, you have to `document.createElementNS` instead (and supply the SVG XML namespace).
• Pay attention to the largeArcFlag & sweepFlag!
• If you want to use SVG line animations, parameterize the starting point so the animation starts in a place of your choosing.

Where can we take it from here?

We can apply this algorithm to two or more partially-overlapping metaballs and use the CSS property `mix-blend-mode` to control how these paths blend together. In the above example, I’m using `mix-blend-mode: screen`.

That’s it for now, happy coding!

Written by