Forums › Adobe After Effects Expressions › Finding the position of the last character
-
Finding the position of the last character
-
Adam Greenberg
February 18, 2021 at 7:03 pmHi everyone, please see the attached pic. I have a multi line text layer, and I want another layer to appear at the end. I cannot use sourcerectattime width because a line higher up may be wider than the last line. This seems like it exists, but I haven’t found it yet.
Thanks
-
Kevin Camp
February 18, 2021 at 7:50 pmyou could do it with two different text layers, but the smaller text layer would only be used to add text to the main text layer, and then you could use a text animator to make the ‘added’ text smaller…. and it will be a little easier if the main line is paragraph text rather than point text (ie, you would not use hard returns to make lines break, the lines just break as they wrap to the area).
try this:
Create a text layer as paragraph text (use the text tool and create a box for the text), then create another text layer (point text is fine, this layer will not be seen, we will just take the sourceText from it) and make that layer a guide layer.
In the sourceText property of the main layer add an expression like this:
value + ' ' + thisComp.layer("small text").text.sourceText ; // set the 'small text' layer to your second text layer
This should add the text from the second layer to the end of the main layer.
On the main text layer, add a text animator for scale and set the scale to 50% (or whatever scale you want). Then in the Start property of the Range Selector add an expression like this:
txt1 = text.sourceText ;
txt2 = thisComp.layer("small text").text.sourceText ; // set this layer to your second text layer
100 - ( 100 * txt2.length / txt1.length )
Now your second text should be added to the main text and be smaller, but the characters may not have the tracking you’d like. To adjust that, simply add a Tracking animator to that same text animator from the ‘add’ menu to the right of the Animator in the timeline and adjust as needed.
-
Adam Greenberg
February 18, 2021 at 8:28 pmThanks very much Kevin. I will try this, but let me add one more thing I forgot to mention.
Let us assume the small text is not a text layer but a precomp. so the size does not need to change, it has been predetermined.
would anything change in this workflow ?
-
Adam Greenberg
February 18, 2021 at 8:39 pmKevin, I should also note that the above expression is forcing after effects to consider this added text in the auto – centering. It should not. It is almost like a trademark, it should not be considered at all in the design.
-
Kevin Camp
February 18, 2021 at 8:43 pmHi Adam, this method would only work with text… if the precomp had text in it, and you only needed the text (not other layers) from that precomp, then it could work. You’d need to direct the expression to find the ‘small text’ text layer in the precomp… it would be something like:
comp("my precomp").layer("small text").text.sourceText ;
However if there are other non-text layers in the precomp, this method would not work.
-
Adam Greenberg
February 18, 2021 at 8:50 pmThis is really fantastic work Kevin. Thanks again
-
Kevin Camp
February 18, 2021 at 9:43 pmAfter looking a bit more closely at your example, my solution may not give you what you described… your example has ‘multi lines of text’ all centered to itself with ‘xyz’ hanging off to the right. Since my solution is injecting the ‘xyz’ text into the other text, the last line ‘text –xyz’ will recenter.
If that is a problem, then you can make separate text layers for each line (the text for those lines will can come from a single text layer by using expressions). Then you could use sourceRectAtTime() to add the ‘xyz’ to the end of the last text line. It would be a bit more complicated since you may need to evaluate which line is the last line with text in it, assuming not all 3 lines would always have text.
-
Adam Greenberg
February 18, 2021 at 9:50 pmYes Kevin, my thoughts exactly for that particular example. But I have to say your solution s perfect for a different problem I had where the text is aligned to the right.
Because when I dont need this extra text, i need the last part of that line to move back into proper position so I added an if layer active else statement looking for that other layer to be active or not. Even though we technically never see that actual layer, I just left the opacity at 0 and it works as a switch. Works like a charm, here is the exact code thanks to you;
on source text
if(thisComp.layer(“small text”).active) value + ‘ ‘ + thisComp.layer(“small text”).text.sourceText else value
on range selector 1 start
txt1 = text.sourceText ;
txt2 = thisComp.layer(“small text”).text.sourceText ;
if(thisComp.layer(“small text”).active) (100 – 100 * txt2.length / txt1.length ) else 100
on tracking amount
if(thisComp.layer(“small text”).active) -17 else 0
-
Adam Greenberg
May 20, 2022 at 1:52 pmthis has been finally solved. I’d like to give credit to Laurent Lavergne. I am including a copy of the project and the 3 lines of code;
on the multiline text layer this needs to be added to the sourcetext;
const theText = text.sourceText.value;
const lines = theText.split(/\r/);
(time < inPoint) ? lines[lines.length-1] : theText
and on the other layer which could be anything ( a precomp, a text layer, an imported logo ), add to the position x this code;
const posRef = thisComp.layer(“text”).transform.xPosition;
const widthRef = thisComp.layer(“text”).sourceRectAtTime(-1, false).width;
value + widthRef
and to the y position this code;
const layerRef = thisComp.layer(“text”);
const theText = layerRef.text.sourceText;
const lines = theText.split(/\r/);
const numLines = lines.length -1;
const textLeading = theText.style.leading;
value + numLines * textLeading
Log in to reply.