Hi Tom,
I propose giving all the character layers another colour-label than other Nulls and layers in your comp, so it’s easy to quickly select them all by clicking on the coloured square in front of one layer’s name and choosing “Select Layer Group”. That makes it quick to paste an expression to multiple layers.
I’m assuming the character’s anchorpoints are not all perfectly on their baseline, as they would be when the outlines are created in the first place ?
Then we need some extra steps:
Add a “Control Null”, position it at [0,0].
Select all the character layers and center their anchorPoints (Layer -> Transform -> Center AnchorPoint in Layer Content);
Add a Point Control “firstChar”, and position it under your first Character, where you want it to attach to the Path (so, on the baseline)
Add this expression to all of their anchorPoints:
value - [0,position.valueAtTime(-1)[1]-thisComp.layer("Control Null").effect("firstChar")("Point")[1]];
The characters will now all have crazy vertical offsets, don’t mind about that for now.
To the control-nulll add a slider named “spacing” (set to about 30), and a second slider named “offset” (keep at 0).
Give all the Characters this expression for position, it is based on the position expression that the “Trace” option of Paths to nulls made:
The main thing you need to adjust is to make sure the name of the pathLayer and the name of pathToTrace is correct for your composition, you should copy those from the “trace” Null’s position expression.
var pathLayer = thisComp.layer("Shape Layer 1");
var progress = thisComp.layer("Control Null").effect("offset")("Slider")/100;
var spacing = thisComp.layer("Control Null").effect("spacing")("Slider")/100;
hPos = position.valueAtTime(-1)[0] - thisComp.layer("Control Null").effect("firstChar")("Point")[0];
progress += (hPos*spacing)/1000;
progress = ((progress%1)+1)%1;
if (time<=-1) { value } else {
var pathToTrace = pathLayer("ADBE Root Vectors Group")(1)("ADBE Vectors Group")(1)("ADBE Vector Shape");
pathLayer.toComp(pathToTrace.pointOnPath(progress));
}
Add this expression to each character’s rotation:
var pathToTrace = thisComp.layer("Shape Layer 1")("ADBE Root Vectors Group")(1)("ADBE Vectors Group")(1)("ADBE Vector Shape");
var progress = thisComp.layer("Control Null").effect("offset")("Slider")/100;
var spacing = thisComp.layer("Control Null").effect("spacing")("Slider")/100;
hPos = position.valueAtTime(-1)[0] - thisComp.layer("Control Null").effect("firstChar")("Point")[0];
progress += (hPos*spacing)/1000;
progress = ((progress%1)+1)%1;
var pathTan = pathToTrace.tangentOnPath(progress);
radiansToDegrees(Math.atan2(pathTan[1],pathTan[0]));
Also based on the original Trace expression.
You don’t need the Trace Null anymore.
Now you can finetune the character spacing and animate the offset. (The exact value is dependent on the length of your PathToTrace, the length of the line, the width of each character,… but the result should be perfectly proportional to your original layout and easy to dial in)
If you notice a bit of offset from the path to the characters, check to see that in your Shape Group the position <i style=”font-weight: bold;”>of the Contents (not the layer transform) is set to [0,0], then reposition the layer, not the Contents.