Be warned, this is going to be a potentially long post with lots of text and long clips to watch, so if you don’t have the time, you may wanna skip for now and read later.
Oooookay, a while ago I posted this little show-off piece and promised that I might one day share a little bit of insight on how I actually created it. Now before talking like blind people about colors, it would be best to start off by watching the first clip.
So what did you just see? As I told you back then, one of the coolest features in Plexus 2 is the addition of the Beams renderer and its Bèzier stuff based on spotlights. This opens up a plethora of design possibilities from fancy stuff like my Underwater Garden to more serious info and data graphics of all sorts, realistic or fictional. Now it’s easy to create one with a few manual tweaks, but infinitely more complicated to create the other due to the nature of the thing having to meet these requirements:
- Easy manipulation of large amounts of data either based on real data or dynamically generated (as per the example, random values).
- Easy ways to change the appearance based on the data in combination with the user’s input.
- Decouple it from other design aspects so you don’t end up with unnecessary pre-comps and layers.
- Make it failsafe so in case if there is no data present the entire network of expressions doesn’t collapse.
Of course some of these challenges are not that unusual – even if you plot Excel data to a chart, you need to think of some of that, but After Effects wouldn’t be the little bitch it is, if things were all that easy. Its scripting and expressions being plugged on as separate interpreters for internal commands rather than being at the core of the program and in addition those two things by themselves being hugely incongruent in terms of what you can do with each of them presented its own share of problems. As usual, the part that would have been most useful for my purposes is of course present in scripting, but not expressions, so I couldn’t rely on just grabbing the project structure and layer relationships with things like compItem. Therefore I once more ended up devising a system that is based on naming layers and effects in a specific manner. The basic rundown is illustrated in the picture.
The tough part was actually making it work. Regular expressions are one hell of a bitch to figure out at times (something which scares even serious programmers) and of course parsing strings and splicing them up on what potentially can amount to hundreds of layers and effects naturally doesn’t help performance. But eventually I got there and one day I might actually go back and clean up a little. and what is all the song and dance for? Essentially I was trying to find a clever way to avoid pre-composing or parenting. The value bars are laid out using some simple circle or linear array positioning expressions which are simply interpolated to convert from line to circle and back. That is easily done using the indices in the layer name and After Effects will help with mass duplication by incrementing numerals in names – create your prototype layer, name it Value Bar 01 and then duplicate it. So far so good.
The trickier part was defining the lights. Matching the index number and using the same circle math to move the light into position was easy enough. However, because Plexus connects the spotlights based on how they are stacked and thus the direction of the tangent handles changes if you swap start and end point there needed to be a way to fix that by letting the lights’ point of interest flip based on a criteria. Now a simple checkbox control could easily have taken care of this, but alas, lights cannot have effects applied and it was once more time to inflate the regex code. Another minor inconvenience is that Plexus‘ own group model will use every light that matches a specified name, which is okay for other scenarios, but not this time. Not only did I want to avoid more than two lights in a group so there would be no risk of inadvertent loops being drawn or multiple splines in the same location ruining semi-transparency, I also wanted the actual thickness to respond to the width of the value bar, which must be wired directly inside the effect. At the same time I wanted to retain the ability to add more Plexus stuff without interfering with the diagram, so yes, again more name-based smartness was needed. As a result, renaming stuff will almost magically make things snap to one another and as I already wrote 2 weeks ago, it would indeed not be too much trouble to create multiple such diagrams in relatively short time.
But wait, haven’t I forgotten something? Of course! How do we actually get the values for the bars? Wanting my designs to be responsive to changes in values, required decoupling them from the rest and using a predictable/ normalized value range that could be fed into all my fancy effects. In addition of course it’s one of the basic principles of “good” programming to isolate and compartmentalize functions and variables so any changes ripple through automatically to other stuff referencing them and you limit the damage in case something goes wrong and your code breaks down. This seems like stating the obvious, yet when you look at many tutorials even using the simplest wiggle(), you all too often see complete layer references hardwired into the frequency and amplitude controls. The tip of the day here is: Don’t! Define variables and even if it may seem trivial, sometimes adding a slider control even for such basic stuff can make your life a lot easier. It’s simply much more intuitive to adjust a slider value than constantly going in and hacking values. Granted, I’m not always adhering to this myself when I quickly throw together bits and pieces, but a complex project like this diagram is a good example why you should. Having a centralized slider for the value data makes it agnostic of its source. Just like I used a random function to generate the values while developing the other features I can manually dial in real values by disabling the expressions. On a chart with 1000 values this could still pretty tedious, so as an alternative, I could add an expression to this same slider that parses values from other sliders, a formula or a text layer and finally of course I could use a script to parse a CSV file. All this will allow fast turnarounds.
After I had a bit of fun geeking out on the code, I couldn’t quite let it rest. there’s an infinite number of ways to represent values in such datasets and it’s always good to have a few prototypes at hand. You never know when JJ Abrams knocks on your door, throws you a million and wants you to create fancy Borg interfaces for his next Star Trek movie… ;-)