5

我有点击时展开和收缩的 div。Masonry 库非常适合初始化页面。我遇到的问题是,通过 Masonry 的绝对定位和下面的指令,当 div 展开时,它们与下面的 div 重叠。我需要让扩展 div 下面的 div 向下移动以处理扩展。

我的来源是: http: //masonry.desandro.com/

https://github.com/passy/angular-masonry/blob/master/src/angular-masonry.js

/*!
* angular-masonry <%= pkg.version %>
* Pascal Hartig, weluse GmbH, http://weluse.de/
* License: MIT
*/
(function () {
  'use strict';

angular.module('wu.masonry', [])
.controller('MasonryCtrl', function controller($scope, $element, $timeout) {
  var bricks = {};
  var schedule = [];
  var destroyed = false;
  var self = this;
  var timeout = null;

  this.preserveOrder = false;
  this.loadImages = true;

  this.scheduleMasonryOnce = function scheduleMasonryOnce() {
    var args = arguments;
    var found = schedule.filter(function filterFn(item) {
      return item[0] === args[0];
    }).length > 0;

    if (!found) {
      this.scheduleMasonry.apply(null, arguments);
    }
  };

  // Make sure it's only executed once within a reasonable time-frame in
  // case multiple elements are removed or added at once.
  this.scheduleMasonry = function scheduleMasonry() {
    if (timeout) {
      $timeout.cancel(timeout);
    }

    schedule.push([].slice.call(arguments));

    timeout = $timeout(function runMasonry() {
      if (destroyed) {
        return;
      }
      schedule.forEach(function scheduleForEach(args) {
        $element.masonry.apply($element, args);
      });
      schedule = [];
    }, 30);
  };

  function defaultLoaded($element) {
    $element.addClass('loaded');
  }

  this.appendBrick = function appendBrick(element, id) {
    if (destroyed) {
      return;
    }

    function _append() {
      if (Object.keys(bricks).length === 0) {
        $element.masonry('resize');
      }
      if (bricks[id] === undefined) {
        // Keep track of added elements.
        bricks[id] = true;
        defaultLoaded(element);
        $element.masonry('appended', element, true);
      }
    }

    function _layout() {
      // I wanted to make this dynamic but ran into huuuge memory leaks
      // that I couldn't fix. If you know how to dynamically add a
      // callback so one could say <masonry loaded="callback($element)">
      // please submit a pull request!
      self.scheduleMasonryOnce('layout');
    }

    if (!self.loadImages){
      _append();
      _layout();
    } else if (self.preserveOrder) {
      _append();
      element.imagesLoaded(_layout);
    } else {
      element.imagesLoaded(function imagesLoaded() {
        _append();
        _layout();
      });
    }
  };

  this.removeBrick = function removeBrick(id, element) {
    if (destroyed) {
      return;
    }

    delete bricks[id];
    $element.masonry('remove', element);
    this.scheduleMasonryOnce('layout');
  };

  this.destroy = function destroy() {
    destroyed = true;

    if ($element.data('masonry')) {
      // Gently uninitialize if still present
      $element.masonry('destroy');
    }
    $scope.$emit('masonry.destroyed');

    bricks = [];
  };

  this.reload = function reload() {
    $element.masonry();
    $scope.$emit('masonry.reloaded');
  };


}).directive('masonry', function masonryDirective() {
  return {
    restrict: 'AE',
    controller: 'MasonryCtrl',
    link: {
      pre: function preLink(scope, element, attrs, ctrl) {
        var attrOptions = scope.$eval(attrs.masonry || attrs.masonryOptions);
        var options = angular.extend({
          itemSelector: attrs.itemSelector || '.masonry-brick',
          columnWidth: parseInt(attrs.columnWidth, 10) || attrs.columnWidth
        }, attrOptions || {});
        element.masonry(options);
        var loadImages = scope.$eval(attrs.loadImages);
        ctrl.loadImages = loadImages !== false;
        var preserveOrder = scope.$eval(attrs.preserveOrder);
        ctrl.preserveOrder = (preserveOrder !== false && attrs.preserveOrder !== undefined);

        scope.$emit('masonry.created', element);
        scope.$on('$destroy', ctrl.destroy);
      }
    }
  };
}).directive('masonryBrick', function masonryBrickDirective() {
  return {
    restrict: 'AC',
    require: '^masonry',
    scope: true,
    link: {
      pre: function preLink(scope, element, attrs, ctrl) {
        var id = scope.$id, index;

        ctrl.appendBrick(element, id);
        element.on('$destroy', function () {
          ctrl.removeBrick(id, element);
        });

        scope.$on('masonry.reload', function () {
          ctrl.scheduleMasonryOnce('reloadItems');
          ctrl.scheduleMasonryOnce('layout');
        });

        scope.$watch('$index', function () {
          if (index !== undefined && index !== scope.$index) {
            ctrl.scheduleMasonryOnce('reloadItems');
            ctrl.scheduleMasonryOnce('layout');
          }
          index = scope.$index;
        });
      }
    }
  };
});
}());
4

2 回答 2

1

您可以使用 Angular 的 $emit、$broadcast 和 $on 功能。

在您的masonry指令链接函数内部:

scope.$on('$resizeMasonry', ctrl.scheduleMasonryOnce('layout'));

在您的masonryBrick指令链接函数或任何其他子元素中:

scope.$emit('$resizeMasonry');

使用 $emit 将事件向上发送范围树,使用 $broadcast 将事件向下发送范围树。

于 2014-06-06T03:43:12.443 回答
1

与许多非 Angular 库一样,答案似乎在于将库包装在 Angular 指令中。

我还没有尝试过,但似乎这就是这个人所做的

于 2014-06-03T00:19:28.877 回答