2

Я написал директиву angular.js, который использует stellar.js для эффектов параллакса. Когда я вызываю одну и ту же директиву несколько раз один за другим, stellar.js будет работать только на первом. Я прочитал около $.stellar('refresh');, который должен повторно инициализировать звездный элемент после инъекции в DOM, но это не повлияло на меня. Также звёзд звезд в окне не имел никакого эффекта.Директива Angular.js, использующая stellar.js, используется несколько раз - только первый работает

Вот код моей директивы:

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> 

Вот plunker: http://plnkr.co/edit/TJbPL3dhSsiitZQWm9Qe?p=preview

+0

Вы можете создать plunker? –

+0

Вот плункер: http://plnkr.co/edit/TJbPL3dhSsiitZQWm9Qe?p=preview – dorthrithil

+0

@ dorthrithil ли мой ответ решает вашу проблему? – Rebornix

ответ

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

EDIT :

Приведенный выше код не работает, если элементы параллакса загружаются динамически. Это немного усложняет ситуацию, но не так много. В этой схеме нам понадобится директива контейнера, ответственная за запуск плагина, и фактические директивы элементов параллакса, которые будут регистрироваться в контейнере и уведомлять контейнер, когда они загрузились.

Директива элемента может использовать 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 директив The добавляет контроллер, который предоставляет методы для регистрации и уведомить. И это вызывает плагин, когда все дети загружены

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 не работает (по какой-то причине - возможно, есть некоторая информация об этом в звездных Документах), когда она активирована более одного раза, поэтому после запуска, загрузка более дочерних элементов ничего не изменит.

+0

Это правильный ответ. – Rebornix

+0

Я протестировал это в своем проекте, но когда я загружаю parallaxModules динамически, parallaxContainer не является решением, так как инициализируется звездным get, прежде чем модули будут загружены и вставлены в DOM. Но я думаю, один звездный вызов _after_ модули загружаются, чтобы реализовать вашу идею избежать ненужных вызовов в моем конкретном контексте. Я не так далеко, но я сообщу вам, если это сработает. Благодарю. :] – dorthrithil

+0

@ dorthrithil, true, если вы загружаете динамически, это усложняет ситуацию. Для простоты ваше решение может быть лучше, поэтому я предложил вам разместить его в качестве ответа. –

0

Я нашел решение: поскольку звездный элемент не является частью угловой структуры, я должен использовать $ apply() для выполнения звездных выражений. Но поскольку в моей директиве уже выполняется $ digest, я должен использовать $ timeout, чтобы получить вызов stellar() в другом цикле дайджеста. $ timeout неявно вызывает $ apply. Мне также нужно вызвать звездную() на angular.element ($ window), чтобы правильно запустить несколько директив.
Так вот мой рабочий код:

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 
        }); 
       }); 
      } 
     }; 
    }); 
0

Использование NG-ПАРАЛЛАКСА директива для Angular2/Angular4 очень легко.

Ссылка: https://www.npmjs.com/package/ng2-parallaxscroll

Гит: 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> 
Смежные вопросы