Jump to content
Search Community

RolandSoos last won the day on January 18 2019

RolandSoos had the most liked content!

RolandSoos

Members
  • Posts

    200
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by RolandSoos

  1. 10 minutes ago, GreenSock said:

    Again, GSAP is optimized to only render when it MUST, so if a tween has already rendered when its playhead is at a particular spot it won't render again unless its playhead moves elsewhere. Solution in your case: you could rewind to progress 0, jump to 1 and then back to your time:

    
    tl.invalidate().progress(0, true).progress(1, true).time(t, true);

     

    Thanks, but I do not see how your logic applies for this example: 

    See the Pen jOmLgRd by mm00 (@mm00) on CodePen

     

    With this line  tl.invalidate().progress(1, true).time(t, true);we are at the end of the animation as t is equal with the totalDuration of the timeline. 

     

    Then we pause and seek back to 0 with the line tl.pause(0). Should I invalidate here again jump to progress(0) and progress(1) and back to progress(0) again?

     

    My problem is that the playhead is at the end and then I move the playhead back to the start and GSAP is not redering the changes.

  2. I see your point. I think there would be an optimized way to make my suggestion work:

    When invalidate({...}) called with my option:

    • If playhead is inside a tween -> If start or end value is a function or arithmetic string ("+=100"), initialize the tween again and render its current state
    • If playhead after a tween (tween is at progress === 1)-> If end value is a function or arithmetic string ("+=100"), initialize the tween again and render its current end state
    • If playhead before a tween (tween is at progress === 0)-> If start value is a function or arithmetic string ("+=100"), initialize the tween again and render its current start state

     

  3. In the following example, the x starting point a function which returns the value where should the tween start from. I use function as I have a variable which might change for some events and when this variable changes, I can inform the timeline with the .invalidate() to evaluate the function again for the new value. 

    The problem is that when the timeline is paused, this invalidate is not working and the new values are not rendered. The expected behavior for me that the red box is jumping on the X axis when the random number changes. 

     

    Using tl.time(0.000001); instead of tl.time(0); solves this issue, but maybe you have a better solution for this case.

    See the Pen ExmvGZq?editors=1010 by mm00 (@mm00) on CodePen

  4. The problem is that I'm developing a software where a lot of things are possible and there is no way to know everything about the environment (normal/hover colors and such.) This is why I tried to use clearing properties with .set() on the timeline as it would guarantee in this case that the HOVER works as expected.

     

    Right now I feel the need for a feature like:

    tl.call(function(isSeekingBack){
      if(isSeekingBack){
        // remove background and style
      } else {
        // add background and style
      }
    })

     

  5. It's a 1 second duration timeline as the .set's position arguments is 1. 

     

    I made a real world example which shows my problem: 

    See the Pen xxRJMbR by mm00 (@mm00) on CodePen

     

    It's a typewriter effect with text selection and removal effect. Also it should change the background and color on HOVER when the animation is not in the selection part. 

     

    The HOVER on the first part of the animation only works on the first run. The second run is not clearing the properties, instead is uses the cached values. 

    You can emulate this by commenting "tl.play();" and uncommenting the two lines lines at the same time:

    tl.progress(1);
    tl.progress(0.3);

     

  6. There is a timeline with a set. The set is changing a property in the object and the value of the property is empty string. When we jump to the end of the timeline, the color property set to #ffffff, but when we jump back to .progress(0), the value become RGBA(0,0,0,0). It seems like GSAP tries to interpret the target value as color and decides to use RGBA(0,0,0,0) as the original value. 

     

    I think in this case GSAP should reset the value back to empty string on .progress(0).

    See the Pen VwmBeyb?editors=1010 by mm00 (@mm00) on CodePen

  7. Does the license allow to use custom builds of GSAP? For example, if I do not need the CSSPlugin, am I allowed to build GSAP without it and use it in end product?

     

    In the license I think this point is related, but I'm not sure how to interpret "for your own use" and "originally intended". I'm sure this is not originally intended :)

    C. You may make modifications to the source code exclusively for your own use in order to perform bug fixes or other minor edits required to operate the PROGRAM as originally intended.

  8. 15 hours ago, ZachSaucier said:

     

    @RolandSoos If you need to use getters and setters with undefined properties, using a proxy is the way to go. There is no other way to my knowledge to do it. Side note: I recommend using real getters and setters.

    I was able to find what I needed. I know how GSAP animates the attributes. If I made animated data to look like attributes for GSAP, then I can use the getAttribute/setAttribute methods of the object.

     

    class HelloWorld {
      constructor() {
        this._abc = {};
      }
    
      getAttribute(key) {
        if (this._abc[key] === undefined) {
          this._abc[key] = 0;
        }
        return this._abc[key];
      }
    
      setAttribute(key, value) {
        this._abc[key] = value;
      }
    }
    
    var obj = new HelloWorld();
    
    gsap.to(obj, 0.4, {
      attr: {
        a: 5,
        k: 10,
        z: -5
      },
      onUpdate() { console.log( obj._abc.a)}
    });

     

    • Like 2
  9. 15 hours ago, tailbreezy said:

     

     

    Not sure what you mean by "any". 

     

    However, your code works as it is. You only have to pass in the actual obj from your constructor ( obj._abc )

     

    
    gsap.to(obj._abc, 0.4, {
      a: 5,
      k: 10,
      z: -5,
      onUpdate() { console.log( obj._abc.a)}
    });

     

     

    Thank you, but I think it is not the right solution for me. In this case GSAP alerts on the console that I use invalid property and your solution only works if the initial value is 0:

    image.png.0516699f3ec0774e174da5ca820e309a.png

     

    That would not work for this one:

    class HelloWorld{
      constructor(){
        this._abc = {
        }
      }
      
      getData(key){
        if(this._abc[key] === undefined){
          this._abc[key] = 2;
        }
        return this._abc[key];
      }
      
      setData(key, value){
        this._abc[key] = value;
      }
    }
    
    var obj = new HelloWorld;
    
    gsap.to(obj, 0.4, {
      a: 5,
      k: 10,
      z: -5
    });

     

  10. I have an object which has a getter and a setter function. I would like to force GSAP to animate any unknown property through these getter/setter functions of the object. Is it possible?

     

    I know GSAP can animate object's properties, but that means that the possible keys must be defined before GSAP can use it. What I want is similar how GSAP can animate any attribute names or CSS variables. 

     

    Proxy might be the right solution, but maybe GSAP has such feature out of the box: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

     

    Example:

    The class itself does not specify its properties, it only defines that any unknow property start value is 0.

    class HelloWorld{
      constructor(){
        this._abc = {
        }
      }
      
      getData(key){
        if(this._abc[key] === undefined){
          this._abc[key] = 0;
        }
        return this._abc[key];
      }
      
      setData(key, value){
        this._abc[key] = value;
      }
    }
    
    var obj = new HelloWorld;
    
    gsap.to(obj, 0.4, {
      a: 5,
      k: 10,
      z: -5
    });
  11. Yes, I totally understand these aspects. So I'm not sure what could be the solution :) 

     

    I'm struggling to optimize the page load which contains several animated elements. On emulated 4x CPU slowdown the site takes 4 seconds until LCP, but 25-30% (1-1.5 sec) used for GSAP to create the timelines. I was only able to optimize one thing in my code:

    adding display:none or not-attached dom elements to the timeline hugely slowing down the processing as GSAP display them or attach to the dom to be able to use getcomputed style, which cause multiple style recalculation and layout.

  12. I have another idea. A cache method in GSAP which could provide the required values what normally red from getComputedStyle.

    gsap.cache("h1", {
      opacity: 1
    });
    gsap.set("h1", {
      opacity: 0.5
    });
    gsap.cache("p", {
      transform: none
    });
    gsap.set("p", {
      x: 100
    });
    gsap.cache("#a", {
      transform: none,
      opacity: 1
    });
    gsap.fromTo("#a", 0.4, {
     opacity: 1,
     x: 0
    }, {
     opacity: 0.5,
     x: 100
    });

    The flow is (when all required values are provided in the cache method)

    • h1: Read opacity from [cache]
    • h1: Render opacity
    • p: Read and prepare transform from [cache]
    • p: render transform
    • #a: Read opacity from [cache]
    • #a: Render opacity
    • #a: Read and prepare transform from [cache]
    • #a: render transform
    • Style recalculation and layout
  13. @GreenSock I have a theory which creates two pipelines: one for property initialization/reading and one for rendering.

     

    So if I have the following:

    gsap.set("h1", {
      opacity: 0.5
    });
    gsap.set("p", {
      x: 100
    });
    gsap.fromTo("#a", 0.4, {
     opacity: 1,
     x: 0
    }, {
     opacity: 0.5,
     x: 100
    });

    The current flow is:

    • h1: Read opacity [might have style recalculation]
    • h1: Render opacity
    • p: Read and prepare transform cache [style recalculation + layout <- caused by opacity change]
    • p: render transform
    • #a: Read opacity [style recalculation <- caused by transform change p]
    • #a: Render opacity
    • #a: Read and prepare transform [style recalculation + layout <- caused by opacity #a]
    • #a: render transform
    • Style recalculation [caused by transform change #a ] 

    My idea:

    • Init Pipeline:
      • h1: Read opacity [might have style recalculation][optional <- set is exactly telling what opacity value]
      • p: Read and prepare transform cache
      • #a: Read opacity [optional <- from part is exactly telling what opacity value]
      • #a: Read and prepare transform cache
    • Render pipeline [Maybe in the next requestAnimationFrame]:
      • h1: Render opacity
      • p: render transform cache
      • #a: render opacity
      • #a: render transform
      • Style recalculation + layout

     

  14. Thank you Jack!

     

    One interesting addition for this topic. Just added some measurement codes to GSAP:

    _getComputedProperty = (target, property, skipPrefixFallback) => {
    	console.time(property);
    	let cs = getComputedStyle(target);
    	const ret = cs[property] || cs.getPropertyValue(property.replace(_capsExp, "-$1").toLowerCase()) || cs.getPropertyValue(property) || (!skipPrefixFallback && _getComputedProperty(target, _checkPropPrefix(property) || property, 1)) || ""; //css variables may not need caps swapped out for dashes and lowercase.
    	console.timeEnd(property);
    	return ret;
    },

     

    It seems like getting transform origin results a Layout while getting transform is not and those transform origin reading calls sometimes took more than 10ms. Getting transform is cheap and took 0.2ms and getting the opacity was around 2ms.

     

    image.thumb.png.8138f2eacacdf83e4f44933f2dc9dc30.png

     

    • Thanks 1
×
×
  • Create New...