Creative Communities of the World Forums

The peer to peer support community for media production professionals.

Activity Forums Adobe After Effects Expressions Changing Source Text: Resize layer at each frame to fit comp width

  • Changing Source Text: Resize layer at each frame to fit comp width

    Posted by Mac Ward on August 14, 2009 at 11:41 pm

    Hi,

    I’m using the Buzzword animation preset to make the source text for a layer change at every x number of frames. What I’d like to do is make the width of that layer (which changes as often as the source text) fit the comp width at every frame. Can this be done with an expression? Or do I need a script that goes frame by frame and fits to comp width?

    Thanks,

    Mac

    Mac Ward replied 16 years, 11 months ago 3 Members · 10 Replies
  • 10 Replies
  • Filip Vandueren

    August 14, 2009 at 11:56 pm

    Unless its’ a fixed WIdth font, and you can count the letters, this can only be achieved with a script.

  • Mac Ward

    August 15, 2009 at 12:02 am

    Well, I’m getting familiar with Photoshop Scripting and would be happy to give it an attempt in the ESTK. Do you happen to know how to access the Fit to Comp Width command?

  • Dan Ebberts

    August 15, 2009 at 4:27 am

    There is a way to use an expression to detect the width of a text layer by using sampleImage() to sample an area 1 pixel wide by the height of the layer. You movie in from the left edge, column by column until you get back a non-zero alpha and then do the same from the right edge. It’s a little messy and can be a little slow.

    I think you might be better off with a script though. Use sourcRectAtTime() to get the extents of the text layer at each frame.

    Either way, you still have a little math to do to calculate the scale value required for the layer to fill the comp.

    Dan

  • Filip Vandueren

    August 15, 2009 at 12:33 pm

    Here’s a script I did a few weeks ago that does something like this,
    it constrains the first TXTlayer of the comp to a max of 1400*130 px

    This should set you on your way.

  • Mac Ward

    August 15, 2009 at 5:18 pm

    Filip, Thank you for offering your script. I am not seeing it attached, though. Am I missing it?

  • Filip Vandueren

    August 16, 2009 at 3:47 am

    Oh,

    apparently there’s something wrong with the expressions code box. Nothing I paste there gets posted ?


    {
    ai=app.project.activeItem;

    for (l=1; l<=ai.layers.length; l++) { if (ai.layers[l].matchName=="ADBE Text Layer") { break; } } txtLayer=ai.layers[l]; w=txtLayer.sourceRectAtTime(0,true).width*txtLayer.scale.value[0]/100;; maxWidth=1400; if (w>maxWidth) {
    initScale=100*maxWidth/w;
    txtLayer.scale.setValue([initScale,initScale,initScale]);
    }

    h=txtLayer.sourceRectAtTime(0,true).height*txtLayer.scale.value[1]/100;
    maxHeight=130;

    if (h>maxHeight) {
    initScale=100*maxHeight/h;
    txtLayer.scale.setValue([initScale,initScale,initScale]);
    h=maxHeight;
    }
    w=w*txtLayer.scale.value[0]/100;
    }

  • Mac Ward

    August 18, 2009 at 9:41 pm

    Well Filip, I’m close.

    I got this to work, which is very specific to the particular comp I’m working on:

    compW = app.project.activeItem.width
    compH = app.project.activeItem.height

    g = "frames per second"
    g = 30

    ai=app.project.item(1);

    txtLayer=ai.layer("ngngv");

    for (i=0; i<500; i++){

    w=txtLayer.sourceRectAtTime(i/g,true).width//*txtLayer.scale.value[0]/100;;
    maxWidth= compW;

    if (w

    But I'm trying to make a varsion that's not comp specific, and that fits to a given layer's width, rather than to the comp width. But it keeps giving me an error at the first "sourceRectAtTime" line, saying "Null is not an object". What am I doing wrong?

    show_prompt1()
    var src;

    function show_prompt1()
    {
    src=prompt("Enter the Layer # you wish to resize","");

    }

    show_prompt2()
    var goal;

    function show_prompt2()
    {
    goal=prompt("Enter the Layer # you wish to match in size","");

    }

    ai = app.project.item(1);
    srcLayer = ai.layer(src);
    goalLayer = ai.layer(goal);

    g = "frames per second";
    g = 30;

    for (var i = 0; i<50 /*switch to lsrc layer length in frames*/; i++){
    srcWidth = app.project.item(1).layer(src).sourceRectAtTime(i/g,true).width;
    goalWidth = goalLayer.sourceRectAtTime(0, true).width;

    if(srcWidth != goalWidth){
    initScale = 100*goalWidth/srcWidth;
    srcLayer.scale.setValueAtTime(i/g, [initScale,initScale,initScale]);
    srcLayer.property("scale").addKey(i/g);
    }
    }

  • Mac Ward

    August 18, 2009 at 9:44 pm

    PS

    In my for loops I’m using 500 and 50 for the number of frames to Keyframe, only because I haven’t figured out how to say ‘layer length in frames’.

  • Mac Ward

    August 20, 2009 at 6:50 pm

    It seems that in the sourceRectAtTime line, src is not being seen as an integer. Does anyone know how to force it to be an integer? Because this does return the desired value:
    show_prompt1();

    ai = app.project.activeItem;
    srcLayer = ai.layer(src);

    function show_prompt1(){
    source=prompt("Enter the Layer # you wish to resize","");
    if (source!=null ){
    src = 1} //substituting the integer for source

    }

    alert(ai.layer(src).name)

    but this does not:

    show_prompt1();

    ai = app.project.activeItem;
    srcLayer = ai.layer(src);

    function show_prompt1(){
    source=prompt("Enter the Layer # you wish to resize","");
    if (source!=null ){
    src = source}

    }

    alert(src)

    alert(ai.layer(1).name)

    alert(ai.layer(src).name)

  • Mac Ward

    August 20, 2009 at 7:52 pm

    Got it!

    /* seed: https://forums.creativecow.net/thread/227/13876
    Thank you Filip Vandueren and Dan Ebberts

    This takes the 'Layer you wish to Resize' and matches its width, at every frame to the width
    of the 'Layer you wish to match

    */show_prompt1()
    var src;

    function show_prompt1()
    {
    src=prompt("Enter the Layer # you wish to resize","");
    src = parseInt(src)
    //~ if (src!=null )
    //~ {
    //~ src -= 1
    //~ }
    }

    show_prompt2()
    var goal;

    function show_prompt2()
    {
    goal=prompt("Enter the Layer # you wish to match in size","")
    goal = parseInt(goal)
    //~ if (goal!=null)
    //~ {
    //~ goal -= 1;
    //~ }
    }

    ai = app.project.activeItem;
    srcLayer = ai.layer(src);
    goalLayer = ai.layer(goal);
    //alert(srcLayer)
    g = "frames per second";
    g = 30;

    //~ srcWidth = srcLayer.srcRectAtTime(20/g,true).width;
    //~ alert(srcWidth)

    for (var i = 0; i<500 /*switch to lsrc layer length in frames*/; i++){
    srcWidth=srcLayer.sourceRectAtTime(i/g,true).width;
    goalWidth = goalLayer.sourceRectAtTime(0, true).width;

    if(srcWidth != goalWidth){
    initScale = 100*goalWidth/srcWidth;
    srcLayer.scale.setValueAtTime(i/g, [initScale,initScale,initScale]);
    srcLayer.property("scale").addKey(i/g);
    }
    }

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