Search code examples
javascriptecmascript-6gsapscrollmagic

disabling a scrollmagic controller in an object literal es6


i am having an issue trying to reenable a scrollmagic controller if it has been disabled before.

i want to have the logo color change only triggered if its a narrow viewport (if the logo is in the colored area) and disabled if its wide..that works so far

but if i resize the window to narrow again it won't reenable the controller..i tried to destroy and reset the controller as well but somehow it won't reenable the controller...

codepen (gsap and scrollmagic used): https://codepen.io/HendrikEng/pen/owyBYz?editors=0011

js:

const mobile = {
  controller: new ScrollMagic.Controller(),

  changeLogo: {
    init: () => {
      console.log("init tweens an scrollmagic");
      const tweens = {
        enterOuter: () => {
          TweenMax.fromTo(
            ".c-logo__outer",
            1,
            { fill: "#4dabfc" },
            { fill: "#fff" }
          );
        },
        enterInner: () => {
          TweenMax.fromTo(
            ".c-logo__inner",
            1,
            { fill: "#fff" },
            { fill: "#4dabfc" }
          );
        },
        leaveOuter: () => {
          TweenMax.fromTo(
            ".c-logo__outer",
            1,
            { fill: "#fff" },
            { fill: "#4dabfc" }
          );
        },
        leaveInner: () => {
          TweenMax.fromTo(
            ".c-logo__inner",
            1,
            { fill: "#4dabfc" },
            { fill: "#fff" }
          );
        }
      };
      const trigger = document.querySelectorAll(".js-change-logo");

      trigger.forEach(id => {
        const scene = new ScrollMagic.Scene({
          triggerElement: id,
          reverse: true,
          triggerHook: 0.065,
          duration: id.clientHeight
        })
          .on("enter", () => {
            tweens.enterOuter();
            tweens.enterInner();
          })
          .on("leave", () => {
            tweens.leaveOuter();
            tweens.leaveInner();
          })
          .addIndicators()
          .addTo(mobile.controller);
      });
    },
    destroyTweens: () => {
      console.log("kill tweens");
      TweenMax.killTweensOf(".c-logo__outer");
      TweenMax.killTweensOf(".c-logo__inner");
      TweenMax.set(".c-logo__outer", { clearProps: "all" });
      TweenMax.set(".c-logo__inner", { clearProps: "all" });
    }
  }
};

$(window).on("resize", function() {
  var win = $(this); //this = window
  if (win.width() <= 450) {
    // reanble controller if disabledbed before - doesnt work 
    mobile.controller.enabled(true);
    mobile.changeLogo.init();
  } else {
    // disable scrollmagic controller
    mobile.controller.enabled(false);
    // destroy tweens
    mobile.changeLogo.destroyTweens();
  }
}).resize();

Solution

  • @hendrikeng I hope you don't mind, but I changed your code quite a lot. I've found myself needing to do this exact thing numerous times recently, so I based a lot of it on my own work.

    I think the largest issue was that you were running a lot of functions on every resize which is not very performant and also makes it difficult to keep track of what's initialised and what's not. Mine relies on an init_flag so that it is only setup once.

    There are then methods to update (duration on resize if needed) and destroy.

    https://codepen.io/motionimaging/pen/848366af015cdf3a90de5fb395193502/?editors=0100

    const mobile = {
    
    init_flag: false,
    
    init: () => {
    
        $(window).on('resize', function(){
    
            const width = $(window).width();
    
            if( width <= 450 ){
    
                if(! mobile.init_flag ){
    
                    mobile.setup();
    
                } else {
    
                    mobile.update();
                }
    
            } else {
    
                if( mobile.init_flag ){
    
                    mobile.destroy();
                }
            }
        });
    },
    
    setup: () => {
    
        mobile.init_flag = true;
    
        mobile.triggers = document.querySelectorAll('.js-change-logo');
    
        const tweens = {
            enterOuter: () => {
                TweenMax.fromTo(
                    '.c-logo__outer',
                    1,
                    { fill: '#4dabfc' },
                    { fill: '#fff' }
                );
            },
            enterInner: () => {
                TweenMax.fromTo(
                    '.c-logo__inner',
                    1,
                    { fill: '#fff' },
                    { fill: '#4dabfc' }
                );
            },
            leaveOuter: () => {
                TweenMax.fromTo(
                    '.c-logo__outer',
                    1,
                    { fill: '#fff' },
                    { fill: '#4dabfc' }
                );
            },
            leaveInner: () => {
                TweenMax.fromTo(
                    '.c-logo__inner',
                    1,
                    { fill: '#4dabfc' },
                    { fill: '#fff' }
                );
            }
        };
    
        mobile.controller = new ScrollMagic.Controller();
    
        mobile.triggers.forEach(el => {
            el.scene = new ScrollMagic.Scene({
                triggerElement: el,
                reverse: true,
                triggerHook: 0.065,
                duration: el.clientHeight
            })
            .on('enter', () => {
                tweens.enterOuter();
                tweens.enterInner();
            })
            .on('leave', () => {
                tweens.leaveOuter();
                tweens.leaveInner();
            })
            .addIndicators()
            .addTo(mobile.controller);
        });
    },
    
    update: () => {
    
        if( mobile.init_flag ){
    
            mobile.triggers.forEach(el => {
                el.scene.duration(el.clientHeight);
            });
        }
    },
    
    destroy: function(){
    
        mobile.controller.destroy(true);
    
        mobile.init_flag = false;
    
        $('.c-logo > *').attr('style', '');
    },
    };
    mobile.init();