Creative Communities of the World Forums

The peer to peer support community for media production professionals.

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 pm

    Hi 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 pm

    you 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 pm

    Thanks 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 pm

    Kevin, 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 pm

    Hi 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 pm

    This is really fantastic work Kevin. Thanks again

  • Kevin Camp

    February 18, 2021 at 9:43 pm

    After 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 pm

    Yes 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 pm

    this 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

Viewing 1 - 9 of 9 posts

Log in to reply.

We use anonymous cookies to give you the best experience we can.
Our Privacy policy | GDPR Policy