I recently wrote an article on some things you can do with converting Text to Shape Layers. One of the examples added multiple strokes to the shape outlines using the Shape Layers' built in stroke effect which was just duplicated.
While this is very easy to set up it can be a very lengthly process to manipulate all your stroke widths and colors manually. If you have 20 strokes that are based on a blue color and you want them all to be based on green and double the width it can be a real pain to change!
So is it possible to do this dynamically? Well, yes! By linking stroke width and color to some expression sliders on the first stroke any subsequent duplicated stroke will also be linked to the sliders allowing you to control them all at once.
Wouldn't it be great if you could also offset each stroke so every duplicate stroke got a bit wider, darker or lighter, or even to be able to randomize the width and brightness of each stroke! Well you can do that too!
The problem is how do you target the contents of a Shape Layer and find the index of each Stroke effect? Here's what I mean.
Each Layer in an After Effects composition has an Index number. The top Layer has an Index of 1. It could be any type of Layer, a Solid, an Adjustment Layer or Null object.
The Layer below it has an Index of 2 and so on and so on. You can see this in the image below. The Index number is on the right hand side by the Layer color.
A common trick with index numbers is to offset a duplicate of the original Layer by adding, multiplying or dividing its position, opacity, etc by its Index number.
By adding an expression to Position and Opacity that says if the Index is equal to one do nothing but if it's not then multiply the X position by the Layer Index and divide the Opacity by the Layer Index.
I get this when I duplicate the Layers.
This type of thing is used to create faux 3D text by offsetting the Z position of a duplicate 3D text layer by its Index number. Standard stuff!
Now Shape Layers are kind of like mini compositions in the fact that they can hold many different elements. They can contain single or multiple Paths, Fills, Strokes and Vector Effects like Pucker and Bloat, Offset Path, Twist, Zig Zag, Rounded Corners and Wiggle Path (an animated version of Illustrators Roughen Edges).
These elements can be grouped together using the Add > Group and a Shape Layer can contain multiple groups each with its own independent hierarchy and effects, even nested groups. This can lead to very complex structures. So how do we find the Index numbers of these elements within these structures for duplication offset effects?
Let's start from the top. Here's an empty Shape Layer. It contains two items Contents and Transform.
When you create a Layer > New > Shape Layer the Contents folder is empty. This is where all new items (or Properties) go, so let's put something into the Contents folder.
I'm going to add three shapes clicking the Add button. I'll add an Ellipse, a Circle and a Poly Star.
Now I need a Fill and Stroke so I'll add these too using the Add button.
Now I have have a basic structure.
Here's the problem. I want to duplicate my Stroke effect and have the new Stroke automatically increase in size based on an Index number like my Comp Layer example.
But does my Stroke effect even have an Index number? Well, yes it does but it's a bit harder to find than Layer Index.
To find an Index number that I can increase my Stroke Width with I'm going to use this clever expression on Stroke 1's width.
value = thisProperty.propertyGroup(1).propertyIndex
How does this work then? Here's a breakdown...
value = The value of Stroke Width.
thisProperty - the actual '˜Stroke 1' effect.
propertyGroup(1) - The '˜container' that holds thisProperty (Stroke 1) which is Contents.
propertyIndex - Give me the Index of thisProperty (Stroke 1) inside Contents.
You can see propertyGroup() lets me drill backwards up the hierarchy from my start point to find the container for the Stroke effect. The (1) is the first level up from the Stroke effect. propertyGroup(2) would be the container that holds Contents, two levels up from thisProperty, i.e the actual Shape Layer! Lets add this to Stoke Width and see what happens.
Well you can see my Stroke Width is now 5px!
This is because '˜Stroke 1' is the 5th item inside Contents!
OK, so that's cool, I have an index number! But what if I choose to get rid of a shape later it will throw out my index numbers!
Well I can get round this by placing all my shapes in a Group. Go to Add and choose Group and move the shapes into it. I'll even move my Fill into it incase I decide to add a different fill for each Shape later. I've named it '˜My Shapes'.
Now my Stroke is 2px as it's the 2nd item in Contents.
Now I have a more consistent structure I can simply subtract one from my expression to make my first stroke 1 pixel!
value = thisProperty.propertyGroup(1).propertyIndex - 1
Now I can do some stuff!! First I'll add a Master Width control to the Shape Layer using an Expression Slider. 1 - 100 pixels.
Then I'll wrap my expression in some brackets and add a multiply sign and Pick Whip to the slider value. This way I can control the relative value of my stroke width.
Before I duplicate I'll divide the Stroke Opacity by the propertyIndex as well.
Each duplicate will become more transparent as it's divided by a higher index number! So if I raise the Master Width slider my Stroke expands.
And if I duplicate each Stroke increases and the Opacity fades! Horray!
If I enlarge the Stroke it works for each duplicate!
Here you can see all the expressions working.
And if I delete some Shapes it still works because of that Group we put them in!
Now you can take this as far as you want to go. I made myself a really handy animation preset using this technique that lets me create multi stroke design elements with a click of a button, I just add a Shape or Path.
It has random or linear options for Lightness and Stroke Width with random seed control. Controls for Start and End Lightness which you can Invert etc etc.
Once you know this technique Shape Layers take on a whole new meaning! Try it for yourself!!