janpaepke / ScrollMagic

The javascript library for magical scroll interactions.
http://ScrollMagic.io
Other
14.9k stars 2.17k forks source link

Using ScrollMagic as an AMD module or shim #160

Closed gabriel-amram closed 10 years ago

gabriel-amram commented 10 years ago

Hello, Is there a way to use the ScrollMagic plugin as an AMD module? I see it defines two variables in the window level : window.ScrollScene = ScrollScene; window.ScrollMagic = ScrollMagic;

but using it with requirejs requires these to be defined otherwise.

Using requirejs shim syntax doesn't work because ScrollMagic exports 2 variables as far as I know. Is there a way to use ScrollMagic as an AMD module?

janpaepke commented 10 years ago

Without knowing too much about AMD it should go something like this:

define('ScrollMagic', ['ScrollScene'], function (ScrollScene) {
    return window.ScrollMagic;
});
define('ScrollScene', ['ScrollMagic'], function (ScrollMagic) {
    return window.ScrollScene;
});

I dunno - that's just a guess. Feel free to figure it out and let me know.

gabriel-amram commented 10 years ago

Hey, Thanks for the reply! The problem with that approach as far as I know is that it makes me load jQuery, TweenMax and ScrollMagic outside of the requirejs loop.

Instead, I asked that question on StackOverflow and answered myself: http://stackoverflow.com/questions/25867893/using-scrollmagic-js-as-amd-module

I forked the repo and hope to send you a pull request with full support for AMD modules soon (including module.exports for node hopefully).

Thanks again for the reply and that wonderful plugin!

janpaepke commented 10 years ago

All right, I'll leave this open for now. :) Thanks for investigating this!

krnlde commented 10 years ago

Here is my scrollmagic require config:

;(function (window) {
  "use strict";
  require.config({
    waitSeconds: 360,
    baseUrl: '/tour/js/',
    paths: {
      when: 'lib/vendor/cujojs/when',
      TweenMax: 'lib/vendor/TweenMax.min'
    },
    shim: {
      IScroll: {
        exports: 'IScroll'
      },
      ScrollMagic: {
        deps: ['lib/vendor/jquery.scrollmagic.min', 'lib/vendor/animationFrame'],
        exports: 'ScrollMagic',
        init: function() {
          var instance;
          return {
            ScrollMagic: ScrollMagic,
            ScrollScene: ScrollScene,
            controller: function () {
              return instance || (instance = new ScrollMagic());
            }
          };
        }
      }
    }
  });
  require(['app']);
}(window));

Require ScrollMagic in your module like so:

require(['ScrollMagic', 'TweenMax', 'IScroll'], function (S, TweenMax, IScroll) {
  var controller = new ScrollMagic();
  // you can call "new ScrollMagic();" because it's a global variable.
});

There might be some improvement involved with this, since ScrollMagic is a global variable. Preferably extend it with the UMD pattern: https://github.com/umdjs/umd . Any thoughts Jan?

janpaepke commented 10 years ago

I will have to look into this some more. So far I haven't really used require.js or the like. Although I do understand the advantages... I'll look into it...

janpaepke commented 10 years ago

ScrollMagic now uses the UMD pattern. It can be used as a browser global or defined with the AMD pattern. Here's the code I used to get requirejs to load it:

require.config({
    baseUrl: '../ScrollMagic/js',
    paths: {
        TweenMax: '_dependent/greensock/TweenMax.min',
        TimelineMax: '_dependent/greensock/TweenMax.min',
        ScrollMagic: 'jquery.scrollmagic',
        ScrollScene: 'jquery.scrollmagic',
        "ScrollMagic.debug": 'jquery.scrollmagic.debug',
        jquery: '_dependent/jquery.min'
    }
});

require(['jquery', 'ScrollMagic', 'ScrollScene', 'ScrollMagic.debug'], function( $, ScrollMagic, ScrollScene, debug) {
    // do stuff
});

Have fun! :)

krnlde commented 10 years ago

Dear good Sir. You. Are. Awesome.

janpaepke commented 10 years ago

Haha - you're the one that made me learn about it. I didn't have a clue about UMD and AMD, now I do and I understand them and see their value.

So thank you for that. :)

If you have tested it out I'd love some feedback that it works for you as well. Just to make sure...

krnlde commented 10 years ago

Seems to work great at a first glance. I only find it a bit annoying that ScrollMagic is now begging for jQuery as a require-module, which is (together with require.js itself) the only module I load synchronously. But I know there is already a TODO which will remove these kinda dependencies so no offense!

In the meantime my solution will be the following, suggested by this saviour:

define('jquery', function() {
    return jQuery;
});
janpaepke commented 10 years ago

Actually there's also an even bigger TODO on my list which is to remove the jQuery dependency all together. It's actually only in there for convenience reasons but not out of necessity. So stay tuned for a module version of ScrollMagic, where both jQuery and possibly TweenMax are optional additional AddOns to the core functionality.

krnlde commented 9 years ago

As of ScrollMagic v1.3.0 the behavior for require.js has changed a bit. You only need to load ScrollMagic as a single module which'll itself provide the ScrollMagic Controller and Scene Constructors.

Here's an example

require.config({
    baseUrl: '../ScrollMagic/js',
    paths: {
        TweenMax: '_dependent/greensock/TweenMax.min',
        TimelineMax: '_dependent/greensock/TweenMax.min',
        ScrollMagic: 'jquery.scrollmagic',
        jquery: '_dependent/jquery.min'
    }
});

require(['ScrollMagic'], function (ScrollMagic) {
    var controller = new ScrollMagic.Controller(/*...*/);
    var scene = new ScrollMagic.Scene(/*...*/);
});

Further information are described here: https://github.com/janpaepke/ScrollMagic/wiki/Getting-Started-:-Using-AMD

colinory commented 9 years ago

I'm trying to use ScrollMagic 1.3.0 with RequireJS. I've followed the getting started wiki. Still not working..

I get this error in the console: Uncaught TypeError: Cannot read property 'Controller' of undefined

This is my requirejs config:

requirejs.config({
    "baseUrl": wp_path,
    "paths": {
      "app": "../app",
      "jquery": "//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min",
        "TweenMax": "//cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min",
        "TimelineMax": "//cdnjs.cloudflare.com/ajax/libs/gsap/latest/TimelineMax.min",
        "TweenLite": "//cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenLite.min",
        "cssplugin": "//cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/CSSPlugin.min",
        "jqueryui": "//code.jquery.com/ui/1.11.1/jquery-ui.min",
        "ScrollMagic": "jquery.scrollmagic.min",
        "intense": "intense",
        "videobg": "jquery.videoBG",
        "placeholders": "placeholders",
        "viewportbuggyfill": "viewport-units-buggyfill"
    }
});

This is how I define them:

define(["jquery","jqueryui","intense","videobg","placeholders","viewportbuggyfill","TweenMax","TimelineMax","cssplugin","ScrollMagic"], function($, ScrollMagic) {

This is how I init the controller

        // init the controller
        var controller = new ScrollMagic.Controller({
            globalSceneOptions: {
                triggerHook: "onEnter"
            }, loglevel: 0

        });
        var intro_icon = new TimelineMax();
        intro_icon.add([
            TweenMax.to(".intro .icons", 2, { bottom:0, autoAlpha: 1, ease: Back.easeInOut, force3D: true})
        ]);
        var scene1 = new ScrollMagic.Scene({
            triggerElement: ".columns_container"
        })
            .setTween(intro_icon)
            .addTo(controller);

Am I doing something wrong?

krnlde commented 9 years ago

You have to fill every required module into the params of the callback like so:

define(["jquery","jqueryui","intense","videobg","placeholders","viewportbuggyfill","TweenMax","TimelineMax","cssplugin","ScrollMagic"], function($, jqueryui, intense, videobg, placeholders, viewportbuggyfill, TweenMax, TimelineMax, cssplugin, ScrollMagic) {
  // ...
});

The parameters of the callback have to match the length of the dependency array, since these values are linked/mapped to each other.

If there are libs you don't need as a param, just require them at the end and leave the param out, in your case for example jquery ui:

define(['jquery', 'jqueryui'], function ($) {
  // ...
});
colinory commented 9 years ago

Thanks! It's working. A bit off topic. I'm also using this line:

window.viewportUnitsBuggyfill.init();

Do I need to add window as well as a parameter? Because I'm getting this error :

Uncaught TypeError: Cannot read property 'init' of undefined

krnlde commented 9 years ago

Leave out the window. part when using requirejs, and write the variable the same way you wrote the function parameter.

colinory commented 9 years ago

It's working! Thanks!