使用stellar.js的Angular.js指令多次使用 - 只有第一个工作

时间:2015-02-01 23:20:02

标签: javascript angularjs angularjs-directive angularjs-scope stellar.js

我写了一个angular.js指令,该指令使用stellar.js进行视差效果。当我一个接一个地多次调用同一个指令时,stellar.js只能在第一个指令上工作。 我读到了$.stellar('refresh');,它应该在DOM中注入元素后重新初始化恒星,但这对我没有影响。在窗口上调用stellar也没有效果。

以下是我的指令的代码:

angular.module('ClientApp')
    .directive('parallaxModule', function () {
        return {
            templateUrl: 'views/parallax-module.html',
            restrict: 'E',
            scope: {
                data: '='
            },
            controller: function() {
               $(function(){
                   $(this).stellar({
                        horizontalScrolling: false,
                        verticalScrolling: true,
                        verticalOffset: 50
                   });
                });
            }
        };
    });

这就是我使用指令的方式:

<parallax-module data="sectionData.para"></parallax-module>
<parallax-module data="sectionData.para"></parallax-module>

这是我的模板:

<div class="parallax-module" data-stellar-background-ratio="0.2">
    <div class="wrapper" data-stellar-ratio="2.5">
        <div class="title">{{data.title}}</div>
        <div class="caption">{{data.caption}}</div>
    </div>
</div>

这里是一名掠夺者:http://plnkr.co/edit/TJbPL3dhSsiitZQWm9Qe?p=preview

3 个答案:

答案 0 :(得分:1)

$timeout有效,因为应该应用恒星插件,而不是应用于每个视差元素,而是应用于滚动容器。在文档示例中,它适用于window$(window).stellar();

因此,使用$timeout,代码“等待”摘要队列的结束,并在执行时,加载所有指令。不幸的是,它不必要地为每个指令执行。

解决方案是将指令应用于容器。然后就变得如此简单:

.directive("parallaxContainer", function(){
  return {
    link: function(scope, element){
      element.stellar({
          horizontalScrolling: false,
          verticalScrolling: true,
          verticalOffset: 0
        });
    }
  }
})

此解决方案依赖于在该容器中存在一个与恒星兼容的元素(例如data-stellar-background-ratio):

<body parallax-container>
  <div data-stellar-background-ratio="0.2">
    ...
  </div>

  <div data-stellar-background-ratio="0.2">
    ...
  </div>
</body>

plunker

修改

如果动态加载视差元素,上述代码将无效。这使事情变得复杂,但并不多。在这种安排中,我们需要负责触发插件的容器指令,以及实际的parallax elements指令,它们将自己注册到容器并在容器加载时通知容器。

元素指令可以使用ng-include在内容加载时获取通知。该指令使用require: "^parallaxContainer"

app.directive('parallaxModule', function() {
    return {
      template: '<div ng-include="\'parallax-module.html\'" onload="notifyLoaded()"></div>',
      restrict: 'E',
      scope: {
        data: '='
      },
      require: "^parallaxContainer",
      link: {
        pre: function(scope, element, attrs, parallaxContainer){
          parallaxContainer.registerElement();
          scope.notifyLoaded = parallaxContainer.notifyElementLoaded;
        }
      }
    };
  })

parallaxContainer指令添加了一个控制器,用于公开要注册和通知的方法。当所有孩子都加载

时它会触发插件
app.directive("parallaxContainer", function() {
    var parallaxElementCount = 0;
    var parallaxElementLoaded = 0;
    return {
      controller: function($element){

        this.registerElement = function(){
          parallaxElementCount++;
        };

        this.notifyElementLoaded = function(){
          parallaxElementLoaded++;

          if (parallaxElementCount !== 0 && parallaxElementCount === parallaxElementLoaded){

            $element.stellar({
              horizontalScrolling: false,
              verticalScrolling: true,
              verticalOffset: 0
            });
          }
        }
      },
    }
  })

plunker

请注意,stellar在多次激活时不会起作用(出于某种原因 - 可能在恒星文档中有一些信息),因此一旦触发,加载更多子元素将不会改变任何东西。

答案 1 :(得分:0)

我找到了一个解决方案:因为stellar不是角度框架的一部分,所以我必须使用$ apply()来执行恒星表达式。但由于$ digest已经在我的指令中进行,我必须使用$ timeout来获取另一个摘要周期中的stellar()调用。 $ timeout隐式调用$ apply。我还必须在angular.element($ window)上调用stellar()以使多个指令正确运行 所以这是我的工作代码:

angular.module('ClientApp')
    .directive('parallaxModule', function ($timeout, $window) {
        return {
            templateUrl: 'views/parallax-module.html',
            restrict: 'E',
            scope: {
                data: '='
            },
            link: function() {
                $timeout(function () {
                    angular.element($window).stellar({
                        horizontalScrolling: false,
                        verticalScrolling: true,
                        verticalOffset: 50
                    });
                });
            }
        };
    });

答案 2 :(得分:0)

对Angular2 / Angular4使用NG-PARALLAX指令非常简单。

链接:https://www.npmjs.com/package/ng2-parallaxscroll

GIT中:https://github.com/tyrantwave/ng2-parallaxscroll

示例1:

<div parallax [config]="{axis: x, speed: -.3}" style=" background-image: url('/parallax_img.jpg');"></div>

示例2:

<ng-parallax img="img/img.jpg" [config]="{axis: x, speed: -.3}" class="some-class"></ng-parallax>