<p>Looks like Adobe have come to the party on this one. A new update as of After Effects CC 2014.2 (13.2) has a sourceRectAtTime() method that does exactly what I'm wanting. To quote <a href="http://blogs.adobe.com/aftereffects/2014/12/after-effects-cc-2014-2-13-2.html" rel="nofollow">their blur</a>b:</p>

<blockquote>
  <p>You can now read the rectangle bounds of a layer’s content, including
  the corrected bounds of a text layer, for any time in a composition.
  The sourceRectAtTime() method from the After Effects scripting API is
  now accessible in expressions as a read-only layer object attribute.</p>
</blockquote>

<p>Yee-hah!</p>

CC BY-SA 3.0
2014-12-21T20:12:10.487Z
Oh cool finally. Thanks for updating the question with this info.
timonsku
CC BY-SA 3.0
2014-12-19T06:16:04.410Z
2014-12-19T06:16:04.410Z
stib
<p>So you want the width of the whole text object no single characters?
In that case you could use this: <a href="http://motionboutique.com/text-bounds-expresssion-580/" rel="nofollow">http://motionboutique.com/text-bounds-expresssion-580/</a>
A tutorial plus sample project on how to get the bounding box of a text layer.</p>

<p>In case the link dies, here is the complete expression they use to determine the bounding box.</p>

<pre><code>step = 1.0; // higher values speed things up (2 means two times faster) but reduce precision
L = thisComp.layer("MyTextLayer"); // text layer whose size must be evaluated

w = thisComp.width;
h = thisComp.height;
halfW = w / 2;
halfH = h / 2;
halfStep = step / 2;

left = w;
right = 0;
top = h;
bottom = 0;

// find left
found = false;
for (x = 0; !found &amp;&amp; x &lt; w; x+=step)
{
    if (L.sampleImage([x,halfH], [halfStep,halfH], true)[3] &gt; 0)
    {
        found = true;
        if (x &lt; left) 
            left = x;
    }
}
// find right
found = false;
for (x = w; !found &amp;&amp; x &gt;= 0; x-=step)
{
    if (L.sampleImage([x,halfH], [halfStep,halfH], true)[3] &gt; 0)
    {
        found = true;
        if (x &gt; right) 
            right = x;
    }
}
// find top
found = false;
for (y = 0; !found &amp;&amp; y &lt; h; y+=step)
{
    if (L.sampleImage([halfW,y], [halfW,halfStep], true)[3] &gt; 0)
    {
        found = true;
        if (y &lt; top) 
            top = y;
    }
}
// find bottom
found = false;
for (y = h; !found &amp;&amp; y &gt;= 0; y-=step)
{
    if (L.sampleImage([halfW,y], [halfW,halfStep], true)[3] &gt; 0)
    {
        found = true;
        if (y &gt; bottom) 
            bottom = y;
    }
}

/*"Size of text\n" + (right-left) + "x" + (bottom-top)*/
left + "," + top + "," + (right-left) + "," + (bottom-top)
</code></pre>

CC BY-SA 3.0
2014-11-14T09:07:04.080Z
Thanks for that. This looks like it samples the pixels to see if there's any opacity and determines the size that way. Good thinking outside the square. I'll have to test to see if it works on animated text.
stib
CC BY-SA 3.0
2014-11-14T18:51:01.780Z
Expressions evaluate per frame so animation shouldn't be any issue. It will just slow your rendertime down a little as the sampleImage function is quite CPU heavy.
timonsku
CC BY-SA 3.0
2017-10-26T12:15:09.097Z
Expressions evaluate each time the frame is *rendered*. If you have motion blur on, the layer can get rendered dozens of time per-frame. So an expression that slows down the playback a little while you're working on it can suddenly become a beast when you turn on MB in the render.
stib
CC BY-SA 3.0
2014-11-13T17:05:49.043Z
2014-11-13T17:05:49.043Z
timonsku
<p>I have a type effect that requires a couple of layers, one with the type, and another moving behind the letters as they appear (simulating the little text bubbles you get when typing on an iPhone). It's very tedious animating the position of the bottom layer to match the text, so I'm wondering if it's possible to use any javascript tools to measure the characters and drive the position value.</p>

<p>Currently I have an expression driving the opacity like this, to automatically turn the background off for spaces:</p>

<pre><code>theOffset=thisComp.layer(1).text.animator("Animator 1").selector("Range Selector 1").offset;
if (thisComp.layer(1).text.sourceText.substr(theOffset, 1) == " " ){0} else {100}
</code></pre>

<p>and another that folows the text animator range selector so that I can retime if I want without having to nudge keyframes till doomsday:</p>

<pre><code>theOffset=thisComp.layer(1).text.animator("Animator 1").selector("Range Selector 1").offset;
try {
    transform.position.key(theOffset + 1).value
}
catch(error){[-10000,0]}//effectively hide it on errors (like the index going out of bounds)
</code></pre>

<p>…but this relies on me going through and creating keyframes to match the spacing of all the letters in the text, and frankly I'd rather be doing something else with the time that takes. so I'm trying to find a string method that I could use like this:</p>

<pre><code>xOffset = thisComp.layer(1).text.sourceText.substr(1, theOffset).getTextWidth()
</code></pre>

<p>but <strong>getTextWidth</strong> obviously isn't a valid method. Is there a JS method that can get the size of a string on screen? There seems to be several solutions for this when the client is a web browser, but I can't find any that work for AE expressions.</p>

CC BY-SA 3.0
2014-12-19T06:19:26.900Z
No, I'm talking expressions. A lot of undocumented javascript creeps into expressions; for example many of the javascript string methods are there, like regex and so on.
stib
CC BY-SA 3.0
2014-11-13T10:24:49.450Z
As you are asking for JavaScript, I'm assuming you are using ExtendScript and not the limited After Effects expressions you apply directly to layers?
timonsku
<after-effects><after-effects-expressions>
Can you measure the width of a character in an AE expression?
stib
# Can you measure the width of a character in an AE expression?

(Asked by: username_0 on 2014-11-12)

I have a type effect that requires a couple of layers, one with the type, and another moving behind the letters as they appear (simulating the little text bubbles you get when typing on an iPhone). It's very tedious animating the position of the bottom layer to match the text, so I'm wondering if it's possible to use any javascript tools to measure the characters and drive the position value.
Currently I have an expression driving the opacity like this, to automatically turn the background off for spaces:
theOffset=thisComp.layer(1).text.animator("Animator 1").selector("Range Selector 1").offset;
if (thisComp.layer(1).text.sourceText.substr(theOffset, 1) == " " ){0} else {100}

and another that folows the text animator range selector so that I can retime if I want without having to nudge keyframes till doomsday:
theOffset=thisComp.layer(1).text.animator("Animator 1").selector("Range Selector 1").offset;
try {
    transform.position.key(theOffset + 1).value
}
catch(error){[-10000,0]}//effectively hide it on errors (like the index going out of bounds)

…but this relies on me going through and creating keyframes to match the spacing of all the letters in the text, and frankly I'd rather be doing something else with the time that takes. so I'm trying to find a string method that I could use like this:
xOffset = thisComp.layer(1).text.sourceText.substr(1, theOffset).getTextWidth()

but getTextWidth obviously isn't a valid method. Is there a JS method that can get the size of a string on screen? There seems to be several solutions for this when the client is a web browser, but I can't find any that work for AE expressions.

**Tags:** after-effects, after-effects-expressions

> **Comments:**
> **username_1**: As you are asking for JavaScript, I'm assuming you are using ExtendScript and not the limited After Effects expressions you apply directly to layers?  
> **username_0**: No, I'm talking expressions. A lot of undocumented javascript creeps into expressions; for example many of the javascript string methods are there, like regex and so on.  

---

## 2 answers

### Answer by username_0 on 2014-12-19. Score: 2 | Accepted answer

Looks like Adobe have come to the party on this one. A new update as of After Effects CC 2014.2 (13.2) has a sourceRectAtTime() method that does exactly what I'm wanting. To quote [their blur](http://blogs.adobe.com/aftereffects/2014/12/after-effects-cc-2014-2-13-2.html)b:

> You can now read the rectangle bounds of a layer’s content, including
> the corrected bounds of a text layer, for any time in a composition.
> The sourceRectAtTime() method from the After Effects scripting API is
> now accessible in expressions as a read-only layer object attribute.

Yee-hah!

> **Comments:**
> **username_1**: Oh cool finally. Thanks for updating the question with this info.  

---

### Answer by username_1 on 2014-11-13. Score: 2

So you want the width of the whole text object no single characters?
In that case you could use this: http://motionboutique.com/text-bounds-expresssion-580/
A tutorial plus sample project on how to get the bounding box of a text layer.
In case the link dies, here is the complete expression they use to determine the bounding box.
step = 1.0; // higher values speed things up (2 means two times faster) but reduce precision
L = thisComp.layer("MyTextLayer"); // text layer whose size must be evaluated

w = thisComp.width;
h = thisComp.height;
halfW = w / 2;
halfH = h / 2;
halfStep = step / 2;

left = w;
right = 0;
top = h;
bottom = 0;

// find left
found = false;
for (x = 0; !found && x < w; x+=step)
{
    if (L.sampleImage([x,halfH], [halfStep,halfH], true)[3] > 0)
    {
        found = true;
        if (x < left) 
            left = x;
    }
}
// find right
found = false;
for (x = w; !found && x >= 0; x-=step)
{
    if (L.sampleImage([x,halfH], [halfStep,halfH], true)[3] > 0)
    {
        found = true;
        if (x > right) 
            right = x;
    }
}
// find top
found = false;
for (y = 0; !found && y < h; y+=step)
{
    if (L.sampleImage([halfW,y], [halfW,halfStep], true)[3] > 0)
    {
        found = true;
        if (y < top) 
            top = y;
    }
}
// find bottom
found = false;
for (y = h; !found && y >= 0; y-=step)
{
    if (L.sampleImage([halfW,y], [halfW,halfStep], true)[3] > 0)
    {
        found = true;
        if (y > bottom) 
            bottom = y;
    }
}

/*"Size of text\n" + (right-left) + "x" + (bottom-top)*/
left + "," + top + "," + (right-left) + "," + (bottom-top)

> **Comments:**
> **username_0**: Thanks for that. This looks like it samples the pixels to see if there's any opacity and determines the size that way. Good thinking outside the square. I'll have to test to see if it works on animated text.  
> **username_1**: Expressions evaluate per frame so animation shouldn't be any issue. It will just slow your rendertime down a little as the sampleImage function is quite CPU heavy.  
> **username_0**: Expressions evaluate each time the frame is *rendered*. If you have motion blur on, the layer can get rendered dozens of time per-frame. So an expression that slows down the playback a little while you're working on it can suddenly become a beast when you turn on MB in the render.  

---

