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. 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

     

  2. 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

  3. Our software is a visual slider builder. Slider contains several slides. Slides has background image and layers.

    We have two animated groups at slide level: slide background transitions in the back and layers in the front.

     

    Simple example: https://smartslider3.com/free-image-slider/

     

    Here is the real purpose why we need to separate slide backgrounds and layers: https://smartslider3.com/static/


     

    • .slide-layers are visibility:hidden while .slide-layer is visibility:visible which allows to right click and save the .slide-background image. (It needed for several user)
    • .slide-layer are animated by the user, so autoAlpha does not work as inherit value for visibility gets the parent hidden value.
    • Playing with z-index is not an option. User can change the z-index of the layers in the editor, I do not want to play with the defined z-index as it might result in overlay with an other layer which is not intended by the user. (Imagine my previous example with a third image which should overlay both the appearing image. )

    Here is a very raw example about a slider structure: 

    <div class="canvas" style="width:800px;height:600px;position:relative;">
      <div class="slide-background-container">
        <div class="slide-background slide-active" data-slide="1"></div>
        <div class="slide-background" data-slide="2"></div>
        <div class="slide-background" data-slide="3"></div>
      </div>
    
      <div class="slide-layers" data-slide="1">
        <div class="slide-layer"></div>
      </div>
      <div class="slide-layers" data-slide="2">
        <div class="slide-layer"></div>
      </div>
      <div class="slide-layers" data-slide="2">
        <div class="slide-layer"></div>
      </div>
    </div>
    
    <style>
      .slide-background-container{
        z-index:1;
        position:absolute;
        width:100%;
        height:100%;
        left:0;
        top:0; 
      }
      .slide-background{
        position:absolute;
        left: -100%;
        top: 0;
        width: 100%;
        height: 100%;
      }
      
      .slide-background.slide-active{
        left: 0;
      }
      
      .slide-layers{
        position:absolute;
        left: -100%;
        top: 0;
        width: 100%;
        height: 100%;
        z-index: 2;
        visibility: hidden;
      }
      
      .slide-layers.slide-active{
        left: 0;
      }
      
      .slide-layer{
        position: absolute;
      }
      
      .slide-layers > *{
       visibility: visible; 
      }
    </style>

     

     

  4. User can place several layers on the canvas which overlays each other. They can add timelines on their own which can be triggered with events. For example you have 2 buttons and when you click on the first button, it shows an image. If you click on the second button, it shows a different image at the same place as the first image. But, when you click on the image, each has its own url. If you do not set the opacity:0; image to visibility:hidden, you might open the link of the invisible image. Here is a quick example with the applied visibility:hidden -> https://smartslider3.com/bugs/gsap/2/

     

    As the user can create timelines, it is very hard to implement your original solution with the events as the animated properties  are not predestined. There might be opacity change or there might not be. So, I'm always trying to come up something universal :)

  5. Based on the official attribute plugin, I made it work. The code adds the current opacity value as an attribute, so I can style when the attribute value is 0. I would be better if I would be able to toggle the attribute 0/1 based on the not-visible/visible state as it might reduce the overhead instead of writing the attribute on every frame.

     

    See the Pen oqGKEo?editors=0010 by anon (@anon) on CodePen

     

  6. Your first solution is close enough, so I started to work on that idea as a plugin to GSAP. It creates a custom property: nAutoAlpha which currently adds and removes the class on the parent. The .container should be green when the box visible and grey when it is hidden. That only issue what I have it that when I reset the timeline in "hidden - grey background" state, it does not removes the class on the .container.

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

     

  7. I have a special case when my layers sits in a container element which must be visibility:hidden. The elements in the container are visibility:visible, but I need to make them visibility:hidden when the opacity is 0.

     

    I tried autoAlpha, but it fails for me as it applies visibility:inherit; which inherits the hidden from the parent.

     

    The best would be if I could toggle a class when the element's opacity is 0 or not 0.

     

    I'm looking for a solution which works without labels or events and I need to be able to specify progess and such on the timeline.

     

    Any suggestion would be apreciated!

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

  8.  

    21 minutes ago, OSUblake said:

    I guess I'm kind of struggling to understand why the variable swap would cause any problems. It's doing pretty much the same thing as jQuery's noConflict method. 

     

    I'm not telling you that it will cause problems. It will work fine. I use that method in my files too. We should also forget my specific use-case.

     

    In my opinion my described method with _gsScope.window is a much more elegant way to access to the properties and services of window as GSAP's code depends on that several places. You shouldn't use _gsScope.navigator, you should use _gsScope.window.navigator as it results more understandable code. It probably be slower, I do not doubt it.

     

    Then if you does this change you could suggest the following instead of the variable swapping. I think it is much more cleaner, don't you think?

    var myScope = {window: window};
    (function(){
      //Here comes GSAP
    }).call(myScope);

     

     

    Here is my loader, but I think it is not related with or discussion. It is just an example when _gsScope is not a window. 

     

    The code might be messy, but it does a great job for me.

    window.N2Classes is my scope

    variable n2 holds jQuery and this class loader runs when jQuery is available on the page.

        window.N2Classes = {};
        (function ($, undefined) {
            "use strict";
            var a = {};
    
            window.N2Require = function (name, dependencies, fn) {
                var deps = [];
                if (name && a[name] == undefined) {
                    a[name] = $.Deferred();
                }
    
                if (arguments.length == 2) {
                    fn = arguments[1];
                    dependencies = undefined;
                }
    
                if (dependencies !== undefined && dependencies) {
                    for (var i = 0; i < dependencies.length; i++) {
                        if (a[dependencies[i]] == undefined) {
                            a[dependencies[i]] = $.Deferred();
                        }
                        deps.push(a[dependencies[i]]);
                    }
                }
                $.when.apply($, deps).done(function () {
                    var args = [$];
    
                    if (name) {
                        if (typeof fn == 'function') {
                            N2Classes[name] = fn.apply(N2Classes, args);
                        } else {
                            N2Classes[name] = true;
                        }
                        a[name].resolve();
                    } else {
                        fn.apply(N2Classes, args);
                    }
                });
            };
    
            for (var i = 0; i < window.n2require.length; i++) {
                window.N2Require.apply(window, window.n2require[i]);
            }
        })(n2);

     

    In my application JS files made in build process and I have several different JS files which holds classes for specific areas. backend.min.js frontend.min.js gsap.min.js etc...

     

    Every file starts with, so if the module loader is not loaded yet, the resources added to a global array for later evaluation:

    window.n2require = window.n2require || [];
    window.N2Require = window.N2Require || function() {
        window.n2require.push(arguments)
    };

     

    And here is a class definition:

    N2Require('MyClass', function ($, undefined) {
      
      function MyClass(){};
      
      return MyClass;
    });

     

    Class definition with dependecy:

    N2Require('Hello', ['MyClass', 'MyOtherClass'], function ($, undefined) {
      
      function Hello(){};
      
      return Hello;
    });

     

     

    Then I can use this class as:

    new N2Classes.MyClass();
    
    //Or if there is chance that the gived class is not loaded yet. 
    //For example when you start the application as inline script, you can not be sure that resources are loaded as async or not
    
    N2Require(0,['MyClass' /* dependencies */], function(){
      // It runs when MyClass available
      new N2Classes.MyClass();
    });

     

    • Like 1
  9. My module loader is nothing special, it just does what I told, creates a new scope for my stuff and loads there the required things. Custom jQuery, GSAP etc...

     

    But, my enviroment is special. We are creating WordPress plugins and we have to make sure that our thing runs in every different environment. Async, not async, other plugin combines every JS files put them into the head with/without async, put to the end of the body, loads it with AJAX and just eval the JS codes.

     

    I'm sure that I can use your solution with the variable exchange.You won't be able to convince me that this is the BEST solution, but you convinced me that this is the official solution.

     

     

    I know that people want to use GSAP even in CLI environment where window is not available only global (like my scope, but I have window too). So you can even look for window that it is optional and you should prepare the code in that way. What I suggest could work and you would be able to know that you are in a non-window-ed context.

    _gsScope.window = _gsScope.window || false;

    Then you can use _gsScope.window when you need window and for example you can skip the runtime of CSSPlugin when _gsScope.window is false.

     

    I think in theory it should work. Also I accept if you want to close the discussion on topic as this is your code and who am I to push anything :)

  10. 22 hours ago, OSUblake said:

    Using _gsScope instead of window is faster, and sometimes the window object doesn't exists, like in a node or server environment.

     

    Ok, I understand. I take the risk. Hopefully this topic will help others who encounter the same issue.

     

    Another idea. If you do not mind I would like to continue the converstation, maybe we will figure out something good for GSAP :)

    window.window holds the window object. Why don't you use _gsScope.window.navigator and such instead of _gsScope.navigator

     

    Then we can use:

    var obj = {};
    (function ($, undefined) {
        this.window = window;
        // Here comes GSAP
    }).call(obj);

     

    If _gsScope.window is undefined, you could throw an error for the developers.

     

  11. I have a custom module loader which creates a custom scope for the modules. I load GSAP into this module loader, so this is why this issue popped up. (It worked fine with with an older version of GSAP) 

     

    If GSAP really needs window object for specific tasks then it should use directly, I think:

    _gsScope.document => window.document
    _gsScope.navigator => window.navigator
    _gsScope.console => window.console

     

     

  12. 11 hours ago, OSUblake said:

     

    What conflicts? You're creating problems, not solving any. If you want your GSAP stuff to be part of a certain scope, create an object for GreenSockGlobals, like here.

     

     

    I do not see why do you think that playing with temporary variables is a good solution instead of creating a new scope:

    21 hours ago, RolandSoos said:

    var myScope = {};

    (function(){

        // Here comes the source code of GSAP

    }).call(myScope);

     

     

    I went through the source code and the following needed to make GSAP to work as expected in custom scope:

    _gsScope.document
    _gsScope.navigator
    _gsScope.console
     
  13. 13 hours ago, GreenSock said:

    Hm, sorry to hear about the trouble. It's super difficult for us to troubleshoot on a live site with thousands of lines of minified code. It looks like maybe that's the part of the code that's specific to old version of IE for handling "opacity" (IE8 didn't support "opacity", so a Microsoft-specific filter had to be used). 

     

    I really wish I could do more to help without a reduced test case, but I'm at a loss. There's no way to reproduce this in Codepen or a simpler test that doesn't use minified code? 

     

     

    Thank you, you gave me an idea :)

     

    I create a custom scope for GSAP to prevent conflicts. 

    var myScope = {};
    (function(){
        // Here comes the source code of GSAP
    }).call(myScope);

     

    Then GSAP creates _gsScope with the following definition:

    var _gsScope = (typeof(module) !== "undefined" && module.exports && typeof(global) !== "undefined") ? global : this || window;

     

    So the _gsScope variable will be equal with myScope.

     

    Then GSAP tries to find the navigator in the _gsScope which is not there as it assumes it is a Window object:

    _agent = (_gsScope.navigator || {}).userAgent || "",

     

    As _agent is empty string, GSAP is unable to find which browser it is and it assumes that opacity not supported, then it tries to use filter as opacity not supported :)

     

    Solution:

     

    Define navigator in the custom scope:
     

    myScope.navigator = window.navigator;

     

     

    Jack:

    Do you know any other variable what GSAP presume in _gsScope?

  14. Hi!

     

    After I updated my application to the latest GASP version I run into strange errors. I'm pretty sure that GSAP is fine and the issue is with my application, but I'm unable to find the cause. Maybe the following error message will ring a bell and you will be able to tell me where to look.

     

    Error message: 

    TypeError: c.removeAttribute is not a function at S.CSSPropTween.Ua [as setRatio]

     

     

    And here are a screenshot of the clues from the call stack: https://i.imgur.com/FI6SDHg.png

     

    I tried to recreate the issue on CodePen, but it does not happen there with the same parameter to the timeline's fromTo method. Here you can the error in real environment: https://smartslider3.com/bugs/gsap/1/index.html

  15. Hi,

     

    I have this example located: https://smartslider3.com/video-slider/#four

    When you switch slides - in Safari 11.0.1 the animated slides start the flickering until the animation ends. Do you see any issue on the applied transforms or is it a Safari bug which I should report?

     

    I will try to create a Codepen on Monday, but currently I do not have the time for that.

     

     

    What fixed the example:

    z axis 1px to the slides or rotationX or rotationY 1 deg

  16. Noticed a bug in your code, so here is a fixed version.
    In your code the _filterCSSProp variable was "webkit-filter", but it should be "-webkit-filter".
    
    
    
        (function () {
            var _div = document.createElement("div"),
                _filterProp = /Edge\/\d./i.test(navigator.userAgent) ? false : (_div.style.webkitFilter !== undefined) ? "webkitFilter" : (_div.style.filter !== undefined) ? "filter" : false,
                _filterCSSProp = _filterProp ? (_filterProp == 'filter' ? _filterProp : '-' + _filterProp.replace(/([A-Z])/g, "-$1").toLowerCase()) : "";
            _gsScope._gsDefine.plugin({
                propName: "n2blur",
                API: 2,
                version: "1.1.0",
                overwriteProps: ["n2blur"],
                init: function (target, value, tween, index) {
                    if (!_filterProp) { //browser doesn't support filters
                        return true;
                    }
                    if (typeof(value) === "function") { //accommodate function-based values
                        value = value(index, target);
                    }
                    var start = window.getComputedStyle(target)[_filterProp],
                        end = "blur(" + value + "px)";
                    if (start === "none") {
                        start = "blur(0px)";
                    }
                    this._style = target.style;
                    this._remove = !value;
                    this._addTween(target.style, _filterProp, start, end, "n2blur");
                    return true;
                },
                set: function (ratio) {
                    this._super.setRatio.call(this, ratio);
                    console.trace(_filterProp, ratio, this._remove);
                    //ratio is typically 1 when tween is done.
                    if (ratio === 1 && this._remove) {
                        this._style.removeProperty(_filterCSSProp);
                    }
                }
            });
        })();

     

×
×
  • Create New...