angular的splitter案例學習,都有注釋了,作為自己的備忘。
<!DOCTYPE html> <html ng-app="APP"> <head> <meta charset="UTF-8"> <title>Angular pane splitter example</title> <link type="text/css" rel="stylesheet" href="split.css" /> </head> <body> <!-- //主要流程是根據dom的包裹節點從外部到內部 //先是界面的渲染是先把指令轉換成template, 然后為每一個指令定義controller控制器, 然后進行link; --> <bg-splitter orientation="horizontal"> <bg-pane min-size="100">Pane 1</bg-pane> <bg-pane min-size="150"> <bg-splitter orientation="vertical"> <bg-pane min-size="50">Pane 2</bg-pane> <bg-pane min-size="50">Pane 3</bg-pane> </bg-splitter> </bg-pane> </bg-splitter> <script src="http://cdn.bootcss.com/angular.js/1.3.0-beta.12/angular.min.js"></script> <script> //依賴模塊; angular.module("APP",["bgDirectives"]) </script> </body> <script> //新建模塊; angular.module('bgDirectives', []) .directive('bgSplitter', function() { return { //使用 標簽(tag)的方式 restrict: 'E', //替換節點 replace: true, //替換內容 transclude: true, //獨立作用域, 并引用屬性 scope: { orientation: '@' }, //包裹的節點; template: '<div class="split-panes {{orientation}}" ng-transclude></div>', controller: 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) { //因為這個組件沒有進行雙向綁定, 鏈接階段就對dom進行更改, 也都沒什么事情; //把分隔線添加進來; 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); //為這個元素添加事件(不給document添加事件嗎?); 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是這個事件的; 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'); } 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'); } }); //為分割線添加事件; handler.bind('mousedown', function (ev) { ev.preventDefault(); //添加了拖拽的標志; drag = true; }); angular.element(document).bind('mouseup', function (ev) { //刪除拖拽的標志; drag = false; }); } }; }) /* 就是說指令的順序是外部包裹節點到內部子節點; // */ .directive('bgPane', function () { return { restrict: 'E', //依賴bgSplitter這個controller; require: '^bgSplitter', replace: true, transclude: true, scope: { minSize: '=' }, //主要流程是根據dom的包裹節點從外部到內部 //先是界面的渲染是先把指令轉換成template, 然后為每一個指令定義controller控制器, 然后進行link; template: '<div class="split-pane{{index}}" ng-transclude></div>', link: function(scope, element, attrs, bgSplitterCtrl) { scope.elem = element; scope.index = bgSplitterCtrl.addPane(scope); } }; }); </script>
<style>
.split-panes
{
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
position: absolute;
}
.split-panes > .split-handler
{
background: transparent;
position: absolute;
z-index: 999;
}
/* Horizontal */
.split-panes.horizontal > .split-handler
{
width: 4px;
top: 0px;
left: 50%;
bottom: 0px;
cursor: ew-resize;
}
.split-panes.horizontal > .split-pane1,
.split-panes.horizontal > .split-pane2
{
position: absolute;
height: 100%;
}
.split-panes.horizontal > .split-pane1
{
width: 50%;
}
.split-panes.horizontal > .split-pane2
{
left: 50%;
right: 0px;
border-left: 1px solid #aaa;
}
/* Vertical */
.split-panes.vertical > .split-handler
{
height: 4px;
top: 50%;
left: 0px;
right: 0px;
cursor: ns-resize;
}
.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;
border-top: 1px solid #aaa;
}
</style>
</html>
文章列表