Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sourceRectAtTime #300

Closed
SJMcGee86 opened this issue Mar 1, 2017 · 12 comments
Closed

sourceRectAtTime #300

SJMcGee86 opened this issue Mar 1, 2017 · 12 comments

Comments

@SJMcGee86
Copy link

Hey,

Loving this app so far, it's managed to open up a whole new way for us to develop broadcast graphics with ease from After Effects.

I'm struggling with an expression.

I want a bounding box to my text with padding. The current expression is.

s=thisComp.layer("Text");
paddingx=40;
paddingy=30;
x=s.sourceRectAtTime(time-s.inPoint,true).width;
y=s.sourceRectAtTime(time-s.inPoint,true).height;
[x+paddingx,y+paddingy]

This works fine in After effects, but I noticed in your notes that it disliked velocityAtTime and that this is probably the same situation.

If I have to find another way to write this, that's no problem, but I was wondering how I can implement this to work. So far it doesn't recognise it as a Java expression, specifying sourceRectAtTime.

Is there anyway I can incorporate this expression before I find an alternative work around in Java. I did notice you found a work around with the velocityAtTime and I was hoping you may have good news with this.

Kind Regards

@bodymovin
Copy link
Collaborator

Hi, I haven't considered yet supporting sourceRectAtTime.
I could try to see if it translates well to svg's getbbox.
But if it doesn't, it won't be trivial to have sourceRectAtTime supported correctly.
I need to finish a couple of things and I'll see how it goes.

@SJMcGee86
Copy link
Author

THANK YOU.

That would be awesome.

I've tried simpler expressions with no success

temp = thisComp.layer("TEXT").text.sourceText;
s = temp.length;
x = 100 * (s * .22);
[x, value[1]]

TypeError: thisComp.layer(...).text is undefined[Learn More]

or

fromComp(parent.effect('TEXTBOX_LT')('Point').value) + thisProperty.propertyGroup().size.value/2;

TypeError: fromComp is undefined[Learn More]

Always referring to

fn
bound
execute
m
BaseElement.prototype.prepareFrame
SVGRenderer.prototype.renderFrame
AnimationItem.prototype.renderFrame
AnimationItem.prototype.gotoFrame
AnimationItem.prototype.checkLoaded
t
bound t

I'll just have to be patient and work with IT to incorporate the svg getbbox for the time being.

But still...Kudos on this programme. Still an awesome piece of kit that can do many other things I am trying.

@royhs
Copy link

royhs commented Aug 22, 2017

Hey,

I'm new to bodymovin and loving it so far!
Just wanted to know if sourceRectAtTime support was ever added to bodymovin - or if anyone has a better alternative for creating a box that correlates to the size of a text box that works with bodymovin.

Thanks in advance!

@dtphase
Copy link

dtphase commented Sep 15, 2017

@royhs Did you ever find a solution for this? I'm desperate for this feature.

@royhs
Copy link

royhs commented Sep 18, 2017

@dtphase Unfortunately no, I've been working around it with expressions of number of characters and number of lines.

@bodymovin
Copy link
Collaborator

I will work on this very soon.

@royhs
Copy link

royhs commented Sep 22, 2017

@bodymovin awesome! thanks for that

@bodymovin
Copy link
Collaborator

sourceRectAtTime is now supported.
it only works with text layers and the svg renderer for now.

@royhs
Copy link

royhs commented Sep 25, 2017

@bodymovin thanks man!! will check it out today

@bitcloudTheFirst
Copy link

Hi, it seems there's an easily reproducible edge case bug on this feature (Thank you very much for implementing it btw). Unfortunately it breaks one animation method I use all the time.

To reproduce this bug:

  1. Create a text layer.
  2. Set the scale to utilise sourceRectAtTime() (eg as the x scale)
  3. Create a solid, and use the text Layer as the solid's Alpha Matte.

It seems that as soon as the Alpha Matte is turned on, the expression breaks in firefox. Even if the text layer is visible. This doesn't break in Chrome.

The Error is: NS_ERROR_FAILURE, and lands specifically on the text layer's sourceRectAtTime()
An example JSON can be found here:
https://ufile.io/w7pynx8c
The comp should look like this:
https://i.imgur.com/Aa6kpRP.png

Hope this helps narrow this down! Cheers

@goodwin74
Copy link

sourceRectAtTime is now supported.
it only works with text layers and the svg renderer for now.

Will there be support for sourceRectAtTime() Сanvas?
Canvas has a measureText() method that helps you calculate the width of the box on the text layer?! :)

@spider853
Copy link

spider853 commented Aug 6, 2024

Here is my fix for canvas:

CVTextElement.prototype.sourceRectAtTime = function () {
    this.validateText();

    if (!this.data.singleShape) {
      this.textAnimator.getMeasures(this.textProperty.currentData, this.lettersChangedFlag);
    }

    var letters = this.textProperty.currentData.l;
    var len = letters.length;
    var renderedLetters = this.textAnimator.renderedLetters;

    var minX = Number.MAX_SAFE_INTEGER, minY = Number.MAX_SAFE_INTEGER, maxX = Number.MIN_SAFE_INTEGER, maxY = Number.MIN_SAFE_INTEGER;

    for (var i = 0; i < len; i += 1) {
      var renderedLetter = renderedLetters[i];
      let offset = [0, 0];
      if (renderedLetter) {
        offset = [renderedLetter.p[12], renderedLetter.p[13]];
      }
      if (!letters[i].n) {
        var commands = this.textSpans[i].elem;
        var jLen = commands.length;

        for (var j = 0; j < jLen; j += 1) {
          var pathArr = commands[j];
          //kLen = pathArr.length;
          //this.globalData.canvasContext.moveTo(pathArr[0], pathArr[1]);
          minX = Math.min(minX, offset[0] + pathArr[0]);
          minY = Math.min(minY, offset[1] + pathArr[1]);
          maxX = Math.max(maxX, offset[0] + pathArr[0]);
          maxY = Math.max(maxY, offset[1] + pathArr[1]);

          /*
          for (k = 2; k < kLen; k += 6) {
            this.globalData.canvasContext.bezierCurveTo(pathArr[k], pathArr[k + 1], pathArr[k + 2], pathArr[k + 3], pathArr[k + 4], pathArr[k + 5]);
          }
          */
        }
      }
    }

    if (window.globalOffset) {
      minX += window.globalOffset[0];
      minY += window.globalOffset[1];
      maxX += window.globalOffset[0];
      maxY += window.globalOffset[1];
    }

    //console.log(minX, minY, maxX, maxY);

    return {
      top: minY,
      left: minX,
      width: maxX - minX,
      height: maxY - minY
    };
  };

it's not ideal as it might miss some curved shapes, as an improvement you could calculate the bezier shape at t=0.5 and add that point to cover most arcs cases. See commented code.

This replaces the implementation in node_modules\lottie-web\build\player\lottie.js

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants