具有可拖动div的软件包布局不符合项目顺序

时间:2014-06-11 11:36:15

标签: javascript angularjs packery

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

总的来说,布局工作正常' ish:正确添加了div,可以通过在画布上拖动来更改它们的顺序,并且可以删除它们。问题是如果更改了div顺序并且在布局中添加了新div,则div将重新定位到旧位置。例如:

  1. 添加div A,B和C. A现在是画布上最左边的。
  2. 在A后面拖动A,因此新订单为B,C,A。
  3. 添加新div,D。
  4. 由于某种原因,新订单现在是div的A,B,C,D。我所期待的是,在布局中的新div之后,A的拖动位置会得到尊重。
  5. Packery指令:

    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)其他Packery方法需要调用这些DOM操作。

    有什么想法吗?我做错了什么?

1 个答案:

答案 0 :(得分:1)

这是在Github的Packery开发人员的帮助下解决的。

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