如何在ReactJS环境中包含ScrollMagic的GreenSock插件?

Joh*_*ohn 3 reactjs scrollmagic

如何在我的ReactJS项目中包含ScrollMagic的Greensock插件?

ScrollMagic的作者制作了插件来整合像GreenSock和Velocity这样的库.当你将它们简单地包含在你的HTML文档中时,这些工作非常有用

<script type="text/javascript" src="js/lib/greensock/TweenMax.min.js"></script>
<script type="text/javascript" src="scrollmagic/uncompressed/ScrollMagic.js"></script>
<script type="text/javascript" src="scrollmagic/uncompressed/plugins/animation.gsap.js"></script>
Run Code Online (Sandbox Code Playgroud)

但是当你在ReactJS中时,你不会像这样导入javascript资源.实际上你必须通过像npm命令这样的进程导入它们,然后在你的反应项目中声明它们

import ScrollMagic from "scrollmagic"
Run Code Online (Sandbox Code Playgroud)

虽然我能够将ScrollMagic导入反应文件并开始使用scrollmagic,但我无法导入greensock插件.没有关于如何执行此操作的文档.我试图通过在animation.gsap.js中获取代码段并将其粘贴到node_modules/scrollmagic/scrollmagic.js文件中来破解事物(这不是编辑这些文件的好主意),但它要么破坏了webpack编译器,要么打破了我的项目码.

如何在反应环境中使用greensock插件进行scrollmagic?

Joh*_*ohn 7

我能够构建一个包装器.在高层次上,我所做的是研究代码plugins/animation.gsap.js,取出我需要的场景扩展属性,更改名称空间,并在导出之前将ScrollMagic的行为增加到单独的反应类中.

具体来说,我所做的是创建一个名为的新文件./ScrollMagic.js并粘贴以下内容:

import ScrollMagic from 'scrollmagic';
import {TweenLite as Tween,TimelineMax as Timeline} from 'gsap';

ScrollMagic.Scene.addOption("tweenChanges", // name
  false, // default

  function (val) { // validation callback
    return !!val;
});

ScrollMagic.Scene.extend(function () {
    var Scene = this,
      _tween;

    var log = function () {
      if (Scene._log) { // not available, when main source minified
        Array.prototype.splice.call(arguments, 1, 0, "(animation.gsap)", "->");
        Scene._log.apply(this, arguments);
      }
    };

    // set listeners
    Scene.on("progress.plugin_gsap", function () {
      updateTweenProgress();
    });
    Scene.on("destroy.plugin_gsap", function (e) {
      Scene.removeTween(e.reset);
    });

    /**
     * Update the tween progress to current position.
     * @private
     */
    var updateTweenProgress = function () {
      if (_tween) {
        var
        progress = Scene.progress(),
          state = Scene.state();
        if (_tween.repeat && _tween.repeat() === -1) {
          // infinite loop, so not in relation to progress
          if (state === 'DURING' && _tween.paused()) {
            _tween.play();
          } else if (state !== 'DURING' && !_tween.paused()) {
            _tween.pause();
          }
        } else if (progress != _tween.progress()) { // do we even need to update the progress?
          // no infinite loop - so should we just play or go to a specific point in time?
          if (Scene.duration() === 0) {
            // play the animation
            if (progress > 0) { // play from 0 to 1
              _tween.play();
            } else { // play from 1 to 0
              _tween.reverse();
            }
          } else {
            // go to a specific point in time
            if (Scene.tweenChanges() && _tween.tweenTo) {
              // go smooth
              _tween.tweenTo(progress * _tween.duration());
            } else {
              // just hard set it
              _tween.progress(progress).pause();
            }
          }
        }
      }
    };

    /**
     * Add a tween to the scene.  
     * If you want to add multiple tweens, add them into a GSAP Timeline object and supply it instead (see example below).  
     * 
     * If the scene has a duration, the tween's duration will be projected to the scroll distance of the scene, meaning its progress will be synced to scrollbar movement.  
     * For a scene with a duration of `0`, the tween will be triggered when scrolling forward past the scene's trigger position and reversed, when scrolling back.  
     * To gain better understanding, check out the [Simple Tweening example](../examples/basic/simple_tweening.html).
     *
     * Instead of supplying a tween this method can also be used as a shorthand for `TweenMax.to()` (see example below).
     * @memberof! animation.GSAP#
     *
     * @example
     * // add a single tween directly
     * scene.setTween(TweenMax.to("obj"), 1, {x: 100});
     *
     * // add a single tween via variable
     * var tween = TweenMax.to("obj"), 1, {x: 100};
     * scene.setTween(tween);
     *
     * // add multiple tweens, wrapped in a timeline.
     * var timeline = new TimelineMax();
     * var tween1 = TweenMax.from("obj1", 1, {x: 100});
     * var tween2 = TweenMax.to("obj2", 1, {y: 100});
     * timeline
     *    .add(tween1)
     *    .add(tween2);
     * scene.addTween(timeline);
     *
     * // short hand to add a TweenMax.to() tween
     * scene.setTween("obj3", 0.5, {y: 100});
     *
     * // short hand to add a TweenMax.to() tween for 1 second
     * // this is useful, when the scene has a duration and the tween duration isn't important anyway
     * scene.setTween("obj3", {y: 100});
     *
     * @param {(object|string)} TweenObject - A TweenMax, TweenLite, TimelineMax or TimelineLite object that should be animated in the scene. Can also be a Dom Element or Selector, when using direct tween definition (see examples).
     * @param {(number|object)} duration - A duration for the tween, or tween parameters. If an object containing parameters are supplied, a default duration of 1 will be used.
     * @param {object} params - The parameters for the tween
     * @returns {Scene} Parent object for chaining.
     */
    Scene.setTween = function (TweenObject, duration, params) {
      var newTween;
      if (arguments.length > 1) {
        if (arguments.length < 3) {
          params = duration;
          duration = 1;
        }
        TweenObject = Tween.to(TweenObject, duration, params);
      }
      try {
        // wrap Tween into a Timeline Object if available to include delay and repeats in the duration and standardize methods.
        if (Timeline) {
          newTween = new Timeline({
            smoothChildTiming: true
          }).add(TweenObject);
        } else {
          newTween = TweenObject;
        }
        newTween.pause();
      } catch (e) {
        log(1, "ERROR calling method 'setTween()': Supplied argument is not a valid TweenObject");
        return Scene;
      }
      if (_tween) { // kill old tween?
        Scene.removeTween();
      }
      _tween = newTween;

      // some properties need to be transferred it to the wrapper, otherwise they would get lost.
      if (TweenObject.repeat && TweenObject.repeat() === -1) { // TweenMax or TimelineMax Object?
        _tween.repeat(-1);
        _tween.yoyo(TweenObject.yoyo());
      }
      // Some tween validations and debugging helpers
      if (Scene.tweenChanges() && !_tween.tweenTo) {
        log(2, "WARNING: tweenChanges will only work if the TimelineMax object is available for ScrollMagic.");
      }

      // check if there are position tweens defined for the trigger and warn about it :)
      if (_tween && Scene.controller() && Scene.triggerElement() && Scene.loglevel() >= 2) { // controller is needed to know scroll direction.
        var
        triggerTweens = Tween.getTweensOf(Scene.triggerElement()),
          vertical = Scene.controller().info("vertical");
        triggerTweens.forEach(function (value, index) {
          var
          tweenvars = value.vars.css || value.vars,
            condition = vertical ? (tweenvars.top !== undefined || tweenvars.bottom !== undefined) : (tweenvars.left !== undefined || tweenvars.right !== undefined);
          if (condition) {
            log(2, "WARNING: Tweening the position of the trigger element affects the scene timing and should be avoided!");
            return false;
          }
        });
      }

      // warn about tween overwrites, when an element is tweened multiple times
      if (parseFloat(TweenLite.version) >= 1.14) { // onOverwrite only present since GSAP v1.14.0
        var
        list = _tween.getChildren ? _tween.getChildren(true, true, false) : [_tween],
          // get all nested tween objects
          newCallback = function () {
            log(2, "WARNING: tween was overwritten by another. To learn how to avoid this issue see here: https://github.com/janpaepke/ScrollMagic/wiki/WARNING:-tween-was-overwritten-by-another");
          };
        for (var i = 0, thisTween, oldCallback; i < list.length; i++) { /*jshint loopfunc: true */
          thisTween = list[i];
          if (oldCallback !== newCallback) { // if tweens is added more than once
            oldCallback = thisTween.vars.onOverwrite;
            thisTween.vars.onOverwrite = function () {
              if (oldCallback) {
                oldCallback.apply(this, arguments);
              }
              newCallback.apply(this, arguments);
            };
          }
        }
      }
      log(3, "added tween");

      updateTweenProgress();
      return Scene;
    };

    /**
     * Remove the tween from the scene.  
     * This will terminate the control of the Scene over the tween.
     *
     * Using the reset option you can decide if the tween should remain in the current state or be rewound to set the target elements back to the state they were in before the tween was added to the scene.
     * @memberof! animation.GSAP#
     *
     * @example
     * // remove the tween from the scene without resetting it
     * scene.removeTween();
     *
     * // remove the tween from the scene and reset it to initial position
     * scene.removeTween(true);
     *
     * @param {boolean} [reset=false] - If `true` the tween will be reset to its initial values.
     * @returns {Scene} Parent object for chaining.
     */
    Scene.removeTween = function (reset) {
      if (_tween) {
        if (reset) {
          _tween.progress(0).pause();
        }
        _tween.kill();
        _tween = undefined;
        log(3, "removed tween (reset: " + (reset ? "true" : "false") + ")");
      }
      return Scene;
    };

  });

export default ScrollMagic; 
Run Code Online (Sandbox Code Playgroud)

您会注意到这看起来几乎完全一样plugins/animation.gsap.js,例外情况是:

  • 我在顶部添加了自己的导入行,因此请确保你已经提前安装了rpm的scrollmagic和gsap
  • 我将ScrollMagic对象导出到最后
  • plugins/animation.gsap.js 有一些其他代码将插件转换为我排除的工厂,因为它不适用于此处

现在我可以.setTween()在我的反应项目中使用.用法示例:

import React, {Component} from "react";
import ScrollMagic from "./ScrollMagic"; // my own wrapper for scrollmagic that includes greensock

export default class Home extends Component {

    componentDidMount()
    {
        var controller = new ScrollMagic.Controller();
        var item = "#whateverstuffselector";
        var scene = new ScrollMagic.Scene({triggerElement:item})
                .setTween(item, 0.5, {backgroundColor: "red", scale: 3})
                .addTo(controller);

    }

    render()
    {
        return (<div id="whateverstuffselector">stuff</div>);
    }
}
Run Code Online (Sandbox Code Playgroud)