Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
RolandSoos

Custom GSAP plugin unexpected behavior

Recommended Posts

Hi,

Few months ago I needed a solution for a very special case. I needed to add custom class to the element with custom animated property which I can use everywhere. Related topic: 

 

So I ended up with the following plugin, which adds visibility hidden to the element when we reach opacity 0, and removes the visibility property when opacity is not 0. (No, I can not use GSAP inbuilt autoAlpha as that adds visibility visible, but my elements might be hidden with CSS selector)

_gsScope._gsDefine.plugin({
    propName: "n2AutoAlpha",
    API: 2,
    version: "1.0.0",
    overwriteProps: ["n2AutoAlpha"],
    init: function (target, value, tween, index) {
        var start = window.getComputedStyle(target)["opacity"];
        if (typeof value === "function") {
            value = value(index, target);
        }
        this._tween = this._addTween(target.style, "opacity", start, value, "n2AutoAlpha");

        return true;
    },
    set: function (ratio) {
        this._super.setRatio.call(this, ratio);

        if (this._tween) {
            if (ratio === 0 && this._tween.s === 0) {
                this._tween.t.visibility = "hidden";
            } else if (ratio === 1 && this._tween.s + this._tween.c === 0) {
                this._tween.t.visibility = "hidden";
            } else if (this._tween.t.visibility === "hidden") {
                this._tween.t.removeProperty("visibility");
            }
        }
    }
});

 

 

It works like a charm in most cases. 

 

The following scenario is just the simplified version of the production code. The timelines and such are fixed and I can only change the GSAP plugin itself.

I have two timelines and both can contain several tween and all tween applies to the same element. When tl1 ends, it starts to play tl2, when tl2 ends, it plays tl1 again. 

tl1 is an x animation, which also reset the opacity value to the original one.

tl2 animates the opacity from 1 to 0

 

GSAP autoAlpha -> Everything works, expect the animated box do not get hidden when the browser is smaller than 600px.

See the Pen JZdzwK by anon (@anon) on CodePen

 

Custom plugin -> The visibility status does not change on when tl1 runs from the second time.

 

When tl2 ends with opacity 0, it sets the visibility to hidden, but somehow the custom plugin skipped in tl1 and visibility hidden is not removed and opacity is not set to 1.

 

Solution would be that the plugin set opacity and adjust the visibility as the core autoAlpha works.

 

How can I reach that in my plugin?

 

 

 

See the Pen dKorrv by anon (@anon) on CodePen

Link to comment
Share on other sites

I have a possible workaround, but it would be great to hear you thoughts.

 

When _addTween does not return an object, there is no tween added for that property. So I create a custom object which I use to fake the tween data to the set function. The only thing what I do not like about that is that I need to set the opacity manually in the set function.

 

See the Pen yENWab by anon (@anon) on CodePen

 

Link to comment
Share on other sites

Yep, the problem was that when the tween is initializing, the start & end opacity match, so there's no need for a tween. GSAP saves CPU cycles by skipping that then (it'd be wasteful to constantly set opacity to the same value over and over during the tween). But in your scenario, you've got something else that then alters the opacity later on but you're replaying the same tween and expecting it to do something different. There are certainly ways to handle that by changing your tween/timeline code, but you said you only have access to the plugin itself, so we can also solve it there. Here's what I'd probably do: 

 

_gsScope._gsDefine.plugin({
    propName: "n2AutoAlpha",
    API: 2,
    version: "1.0.1",
    overwriteProps: ["n2AutoAlpha"],
    init: function (target, value, tween, index) {
        var start = window.getComputedStyle(target)["opacity"];
        if (typeof value === "function") {
            value = value(index, target);
        }
        this._style = target.style;
        this._tween = this._addTween(target.style, "opacity", start, value, "n2AutoAlpha");
        if (!this._tween) { //if the start & end values are identical, no tween gets created because it's not needed (save CPU cycles), but we still want to force this value to be set during the tween in case something else outside of the tween changed the value.
          this._opacity = start;
        }
        return true;
    },
    set: function (ratio) {
        this._super.setRatio.call(this, ratio);
        if (!this._tween && this._opacity != this._style.opacity) {
          this._style.opacity = this._opacity;
        }
        if (this._style.opacity == "0") {
          this._style.visibility = "hidden";
        } else if (this._style.visibility === "hidden") {
          this._style.removeProperty("visibility");
        }
    }
}); 

 

Does that help? 

Link to comment
Share on other sites

3 minutes ago, GreenSock said:

Does that help? 

 

Yes Jack, thank you! Good to see how you approach the problem. 

 

Also can you answer why the inbuilt opacity and autoAlpha works fine with my special scenario? Is there some kind of magic in the background which is not available for plugins?

Link to comment
Share on other sites

22 minutes ago, RolandSoos said:

can you answer why the inbuilt opacity and autoAlpha works fine with my special scenario? Is there some kind of magic in the background which is not available for plugins?

 

Well, I wouldn't say there's any "magic" involved, no, but CSSPlugin doesn't use _addTween() like you do in your plugin. It does set the value regardless of if there's a change. 

  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×