原生angularjs实现拖拽布局功能

今天给大家带来一个很有用原生angularjs的拖拽布局功能,可以说是相当丝滑。
先来个效果动态图:

具体实现:
HTML模板:
 

<div>
    <bg-splitter orientation="horizontal">
        <bg-pane min-size="101" style="max-width:400">
            <div class="pane-container" ng-init="h=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]">
             <p ng-repeat="i in h">Left{{i}}</p>
            </div>
        </bg-pane>
        <bg-pane min-size="150">
          <bg-splitter orientation="vertical">
            <bg-pane min-size="100" class="pane-container">
                <div ng-init="h=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]">
                <p ng-repeat="i in h">RightTop{{i}}</p>
                </div>
            </bg-pane>
            <bg-pane min-size="150" class="pane-container">
                <div ng-init="h=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]">
                <p ng-repeat="i in h">RightBottom{{i}}</p>
                </div>
            </bg-pane>
          </bg-splitter>
        </bg-pane>
      </bg-splitter>
</div>

指令定义:

'use strict';

app.directive('bgSplitter', function() {
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    scope: {
        orientation: '='
      },      
      template: '<div class="split-panes {{orientation}}" ng-transclude></div>',
      controller: ['$scope', function ($scope) {
        $scope.panes = [];
        
        this.addPane = function(pane){
          if ($scope.panes.length > 1)
            throw 'splitters can only have two panes';
          $scope.panes.push(pane);
          return $scope.panes.length;
        };
      }],
      link: function(scope, element, attrs) {
        var handler = angular.element('<div class="split-handler"></div>');
        var pane1 = scope.panes[0];
        var pane2 = scope.panes[1];
        var vertical = scope.orientation == 'vertical';
        var pane1Min = pane1.minSize || 0;
        var pane2Min = pane2.minSize || 0;
        var drag = false;
        
        pane1.elem.after(handler);
        
        element.bind('mousemove', function (ev) {
          if (!drag) return;
          
          var bounds = element[0].getBoundingClientRect();
          var pos = 0;
          
          if (vertical) {

            var height = bounds.bottom - bounds.top;
            pos = ev.clientY - bounds.top;

            if (pos < pane1Min) return;
            if (height - pos < pane2Min) return;

            handler.css('top', pos + 'px');
            pane1.elem.css('height', pos + 'px');
            pane2.elem.css('top', pos + 'px');
            scope.verPos = pos;
      
          } else {

            var width = bounds.right - bounds.left;
            pos = ev.clientX - bounds.left;

            if (pos < pane1Min) return;
            if (width - pos < pane2Min) return;

            handler.css('left', pos + 'px');
            pane1.elem.css('width', pos + 'px');
            pane2.elem.css('left', pos + 'px');
            scope.horPos = pos;
          }
          scope.$emit('bgSplitterChanged', {
            orientation:vertical?"vertical":"horizontal",
            bounds:bounds,
            pos:pos
          });

        });
    
        handler.bind('mousedown', function (ev) {
          ev.preventDefault();
          drag = true;
        });
    
        angular.element(document).bind('mouseup', function (ev) {
          drag = false;
        });
      }
  };
})
.directive('bgPane', function () {
    return {
      restrict: 'E',
      require: '^bgSplitter',
      replace: true,
      transclude: true,
      scope: {
        minSize: '='
      },
      template: '<div class="split-pane{{index}}" ng-transclude></div>',
      link: function(scope, element, attrs, bgSplitterCtrl) {
        scope.elem = element;
        scope.index = bgSplitterCtrl.addPane(scope);
      }
    };
  });


CSS样式:
 

<style>
    .split-panes
{
  overflow: hidden;
  left: 0px;
  right: 0px;
  top: 0px;
  bottom: 0px;
  position: absolute;
}

.split-panes > .split-handler
{
  position: absolute;
  z-index: 999;
}

/* Horizontal */

.split-panes.horizontal > .split-handler
{
  width: 6px;
  top: 0px;
  left: 232px;
  bottom: 0px;
  border-left: solid 1px #B3B3B3;
  border-right: solid 1px #B3B3B3;
  cursor: ew-resize;
  background: #B3B3B3 0 50%;
}

.split-panes.horizontal > .split-pane1,
.split-panes.horizontal > .split-pane2
{
  position: absolute;
  height: 100%;
}

.split-panes.horizontal > .split-pane1
{
  width: 232px;
}

.split-panes.horizontal > .split-pane2
{
  left: 230px;
  right: 0px;
}


/* Vertical */

.split-panes.vertical > .split-handler
{
  height: 6px;
  top: 50%;
  left: 0px;
  right: 0px;
  border-top: solid 1px #B3B3B3;
  border-bottom: solid 1px #B3B3B3;
  cursor: ns-resize;
  background: #B3B3B3 50% 0;
}

.split-panes.vertical > .split-pane1,
.split-panes.vertical > .split-pane2
{
  position: absolute;
  width: 100%;
}

.split-panes.vertical > .split-pane1
{
  height: 50%;
}

.split-panes.vertical > .split-pane2
{
  top: 50%;
  bottom: 0px;
  margin-top: 8px;
}
.split-pane1,.split-pane2{
    overflow:auto;
}
.split-panes.vertical{
    left:8px;
}
</style>

猜你喜欢

转载自blog.csdn.net/shoushou71/article/details/87458939