2

我在 Angular.js 应用程序中使用 Packery & Draggabilly 来创建类似仪表板的设置,用户可以在其中动态创建添加到 Packery 布局的窗口。我认为,我遇到的问题与将 Packery 和 Angular.js 正确地结合在一起有关。

总体而言,布局工作正常:div 被正确添加,它们的顺序可以通过在画布上拖动来更改,并且可以删除。问题是如果改变了 div 的顺序并在布局中添加了一个新的 div,那么这些 div 就会重新定位到旧位置。例如:

  1. 添加 div A、B 和 C。A 现在是画布上的最左侧。
  2. 将 A 拖到 C 后面,所以新的顺序是 B、C、A。
  3. 添加新的 div,D。
  4. 出于某种原因,div 的新顺序现在是 A、B、C、D。我所期望的是,在布局中的新 div 之后,将尊重 A 的拖动位置。

包装指令:

win.controller('PackeryController', ['$scope', '$rootScope', '$timeout',
  function($scope, $rootScope, $timeout) {
    console.log("packery controller");
    $scope.$onRootScope('packery.add', function(event, selection, type) {
      $scope.add(selection, type);
    });

    $scope.windows = [];
    $scope.windowRunningNumber = 0;

    // remove from grid
    $scope.remove = function(number, element) {
      $scope.windows = _.reject($scope.windows, function(obj) {
        return obj.number === number;
      });
      $scope.packery.remove(element[0]);
      $scope.packery.layout();
    };

    // adds window to grid
    $scope.add = function(selection, type) {
      $scope.windows.push({
        number: (++$scope.windowRunningNumber),
        type: type,
        variables: selection
      });
    };
  }
]);
win.directive('packery', [

  function() {
    return {
      restrict: 'C',
      templateUrl: 'vis/windowing/packery.tpl.html',
      replace: true,
      controller: 'PackeryController',
      scope: {},
      link: function(scope, elm, attrs, controller) {
        scope.packery = new Packery(elm[0], {
          isResizeBound: true,
          // see https://github.com/metafizzy/packery/issues/7
          rowHeight: 410,
          itemSelector: '.window',
          gutter: '.gutter-sizer',
          columnWidth: 500
        });
      }
    };
  }
]);

包装画布上单个 div/窗口的指令:

win.directive('window', ['$compile', '$injector',
 function($compile, $injector) {
  return {
   scope: false,
   require: '^packery',
   restrict: 'C',
   templateUrl: 'vis/windowing/window.tpl.html',
   replace: true,
   link: function($scope, ele, iAttrs, controller) {
    $scope.element = ele;
    var draggable = new Draggabilly($scope.element[0], {
     handle: '.handle'
    });
    $scope.$parent.packery.bindDraggabillyEvents(draggable);

    $scope.packery.reloadItems();
    $scope.packery.layout();

    // catch dragging operations
    $scope.element.find('.handle').mousedown(function() {
     $(window).mousemove(function() {
      $scope.isDragging = true;
      $(window).unbind("mousemove");
     });
    })
     .mouseup(function() {
      var wasDragging = $scope.isDragging;
      $scope.isDragging = false;
      $(window).unbind("mousemove");
      if (!wasDragging) { //was clicking
       return;
      }
      console.log("was dragging");
      setTimeout(function() {
       $scope.packery.reloadItems();
       // $scope.packery.layout();
      }, 900);
     });

    // catch window destroys
    $scope.$on('$destroy', function() {
     $scope.packery.reloadItems();
     // $scope.packery.layout();
    });
   }
  };
 }
]);

我怀疑要么

a) 我没有捕获所有必要的 DOM 操作(除了通过拖动添加、删除和更改顺序之外还有其他操作吗?)这会导致 Packery 实例不同步,或者

b) 需要在这些 DOM 操作上调用其他 Packery 方法。

有任何想法吗?我究竟做错了什么?

4

1 回答 1

1

这在Github中 Packery 的开发者的帮助下得到了解决。

有关它的要点,请参阅此 Codepen。基本上你想避免.reloadItems(),并且不需要在拖动事件之后进行布局(无论如何这些都可以更好地处理,请参阅Draggabilly文档中的事件)。

于 2014-07-04T19:41:28.290 回答