Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Forums Adobe After Effects Expressions Auto-FontSizing Text that Also Auto-Line Breaks?

  • Auto-FontSizing Text that Also Auto-Line Breaks?

  • Will Batchelor

    April 15, 2021 at 6:44 pm

    Hello! Been trying to figure this out for a while and just keep coming up short.

    Is there a way to have a text layer that will line break after a specified width (not character count), like when you draw the text bounding box, and also have the font size automatically scale down so nothing gets clipped/cropped out?

    I tried using for loops/while loops and set my fontSize variable to “i”, with the thinking being that it would count up until it exceeded a set max size. However it doesn’t work or (more likely) I’m doing it wrong.

    I do a lot of spreadsheet driven templates so it’d be great if I could just set the text bounding area and not have to worry that parts of the text are getting lost.

    Thanks!

  • Filip Vandueren

    April 16, 2021 at 9:38 am

    What would be the logic on when to line break and when to scale down ?

  • Robert Womack

    April 16, 2021 at 2:12 pm

    Is this for a script, or an expression? If it’s a script, can you not set the width of the text layer, and have it break automatically?

  • Tomas Bumbulevičius

    April 16, 2021 at 6:55 pm

    Will, coming from a data-driven automation I would say that setting auto-scale would be easier than figuring out a font size. UNLESS you have restrictions on font-size due to branding requirements.

    1. You need a function to define, which, after certain amount of characters would add a line break.
    2. Second thing to take into account – whenever a word is longer and assuming its non-breakable into next line, you must downscale the layer when width X is reached.

    Last but not least, when doing such calculations, always pre-compose the text phrase before using it. Will save you A LOT of headaches in the process.

  • Will Batchelor

    April 16, 2021 at 7:51 pm

    Edit- Sorry posted this before seeing replies

    My setup is drawing a text bounding box which automatically adds line breaks. It scales to fit when you manually change the font size. My goal is to create an expression that automates the action of changing the font size.

    In theory I would draw the bounding box to the desired width and then make the height very large and set the maximum height in the expression.

    Here is my current code that does not work. I am trying to create a forLoop that will increase the font size by 1 until the font size causes the sourceRectAtTime Height value to exceed the set maximum height.

    posterizeTime(0);

    const maxHeight = 400;

    var n;

    for(var i = 1; i < 1000; i++){

    thisLayer.text.sourceText.style.setFontSize(i);

    if(thisLayer.sourceRectAtTime().height < maxHeight){

    continue;

    }else{

    i = n;

    break;

    }

    }

    thisLayer.text.sourceText.style.setFontSize(n);

  • Will Batchelor

    April 16, 2021 at 8:08 pm

    Thank you Tomas! I recently learned how to set up the autoscaling constraints on a 1 line text layer doing something like this:

    maxWidth = 500;

    currentWidth = sourceRectAtTime().width;

    s = Math.min(maxWidth / sourceRectAtTime().width * 100, 100);

    [s,s]

    So you’re suggesting trying to work this in while adding in a line break expression driven from a set character limit? I will try that!

    I was trying to avoid any code for manipulating the sourceText (like adding line breaks) since I don’t really know how to do that other than copy/paste Mr. Dan Ebberts code. So thought I could use the text bounding box to line break for me, but the scale parameter doesn’t work the same on those, which is why I was targeting fontSize.

  • Filip Vandueren

    April 17, 2021 at 6:53 am

    Hi Will,

    I would make a second invisible text layer with an expression that copies the text and that ramps up the font size every frame:

    style.setFontsize(timeToFrames(time));

    and then in a second text layer loop through the frames to look up at what point the sourcRect height exceeds your threshold.

    And alternative but a lot more convoluted approach is to do it on 1 layer band hiding the font size ramp up in negative time, not sure if that would work in this case.

  • Will Batchelor

    April 19, 2021 at 7:37 pm

    Very, very cool idea and I was able to get it running! However after effects really chugs even with posterizeTime(0) thrown in when applicable. Will probably not be able to use this right now. but still quite happy with the result! Thank you so much!

    Here’s the code I ended up using:

    On the Source Text layer for the hidden text layer (layer name “ramptext”):

    const sourcetext = thisComp.layer(“bounding box text”).text.sourceText;

    const fontSize = timeToFrames(time);

    style.setText(sourcetext).setFontSize(fontSize);

    On the Source Text for the visible text layer (layer name “bounding box text”):

    posterizeTime(0);

    const maxHeight = 300;

    const ramptext = thisComp.layer(“ramptext”);

    const defaultsize = 100;

    try{

    for(i = 1; i <= timeToFrames(thisComp.duration) ; i++){

    if(ramptext.sourceRectAtTime(framesToTime(i)).height < maxHeight)

    n = i;

    }

    }catch(err){

    n = defaultsize;

    }

    style.setFontSize(n)

  • Filip Vandueren

    April 20, 2021 at 8:16 am

    This one runs smoother for me:

    posterizeTime(0);
    const maxHeight = 400;
    const rampText = thisComp.layer("ramptext");
    n=50;
    if (rampText.sourceRectAtTime().height!=0) {
    t=0;
    while (rampText.sourceRectAtTime(t).height < maxHeight) {
    t+=thisComp.frameDuration;
    }
    n=timeToFrames(t)-1;
    }
    style.setFontSize(n).setText(rampText.text.sourceText);
  • Filip Vandueren

    April 20, 2021 at 8:46 am

    Here’s how to make it run the fastest:

    Add a slider control to your ramptext. layer and give it this expression:

    posterizeTime(0);
    const maxHeight = 400;
    n=50;
    if (sourceRectAtTime(1).height!=0) {
    t=0;
    while (sourceRectAtTime(t).height < maxHeight) {
    t+=thisComp.frameDuration;
    }
    n=timeToFrames(t)-1;
    }
    n;

    Give your visible layer’s sourceText this expression:

    posterizeTime(0);

    n=thisComp.layer("ramptext").effect("Slider Control")("Slider");

    style.setFontSize(n).setText(thisComp.layer("ramptext").text.sourceText);

    posterizeTime(0) does recalculate everytime something changes in the comp while you’re working in it. So dragging a layer can be super slow because it is recalculating the expression while you drag, but when you would render or ram preview, the expression will be evaluated only once.

    So for the fastest workflow while tweaking animations in after effects, you can check what number is the result of the calculation on the slider, disable the expression and manually enter the same value in the slider.

    The don’t forget to re-enable it when you make a template out of it.

Viewing 1 - 10 of 10 posts

Log in to reply.

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