Angular JS 可调整大小的 div 指令

Posted

技术标签:

【中文标题】Angular JS 可调整大小的 div 指令【英文标题】:Angular JS resizable div directive 【发布时间】:2013-08-21 22:04:11 【问题描述】:

我的网站将有多个部分,我打算调整每个部分的大小。为此,我制作了一个“可调整大小”的指令,例如:

<div class="workspace" resize="full" ng-style="resizeStyle()">
<div class="leftcol" resize="left" ng-style="resizeStyle()">

使用如下所示的指令:

lwpApp.directive('resize', function ($window) 
    return 
        scope: ,

        link: function (scope, element, attrs) 
            scope.getWinDim = function () 
                return 
                    'height': window.height(),
                    'width': window.width()
                ;
            ;

            // Get window dimensions when they change and return new element dimensions
            // based on attribute
            scope.$watch(scope.getWinDim, function (newValue, oldValue) 
                scope.resizeStyle = function () 
                    switch (attrs.resize) 
                    case 'full':
                        return 
                            'height': newValue.height,
                            'width': (newValue.width - dashboardwidth)
                        ;

                    case 'left':
                        return 
                            'height': newValue.height,
                            'width': (newValue.width - dashboardwidth - rightcolwidth)
                        ;

                    etc...
                ;
            , true);

            //apply size change on window resize
            window.bind('resize', function () 
                scope.$apply(scope.resizeStyle);
            );
        
    ;
);

如您所见,这只在窗口调整大小时调整每个 div 的大小,并且每个指令都有一个隔离范围。这适用于它的构建目标,但最终我想通过一个可拖动的栏来调整 div 的子集。比如

div1     div2
----------------
|     ||       |
|     ||       |
|     ||       |
|     ||       |
----------------
    draggable bar in middle

在可拖动条的移动(水平方向)上,我可能需要通过父控制器的范围访问 div1、div2 的宽度(?)。我的问题是:

    这是在 Angular 中制作可调整大小的 div 的“正确”方法吗?特别是当一个 div 的大小影响另一个时?

    我个人认为 (1) 的答案是“不,我没有正确执行它,因为当每个指令都有一个隔离范围时,我无法在指令之间进行通信。”如果这是真的,我该如何考虑 div 之间的窗口和可拖动大小调整?

【问题讨论】:

我没有明确的答案,但我会检查 BootstrapUI Accordion 或类似的东西,其中有一个使用其他指令的主指令并在它们之间“传达”适当的信息打开和关闭相应的部分。我相信您将使用指令定义对象的 require 属性,请参阅此处的长版本 docs.angularjs.org/guide/directive 谢谢!我认为您的要求可能是正确的。这将使我可以访问另一个控制器... 我一直在尝试这个。正如 jayflo 建议的那样,我尝试了 jQuery-Splitter,但我对此感到很苦恼,并且也得到了代码不受支持的印象。我再次尝试使用JQueryUI resizable,效果很好。下一步是与Angular集成,我将使用AngularJS-JQueryUI 【参考方案1】:

这个问题很老,但对于任何正在寻找解决方案的人,我构建了一个简单的指令来处理这个问题,用于垂直和水平调整大小。

Take a look at the Plunker

angular.module('mc.resizer', []).directive('resizer', function($document) 

    return function($scope, $element, $attrs) 

        $element.on('mousedown', function(event) 
            event.preventDefault();

            $document.on('mousemove', mousemove);
            $document.on('mouseup', mouseup);
        );

        function mousemove(event) 

            if ($attrs.resizer == 'vertical') 
                // Handle vertical resizer
                var x = event.pageX;

                if ($attrs.resizerMax && x > $attrs.resizerMax) 
                    x = parseInt($attrs.resizerMax);
                

                $element.css(
                    left: x + 'px'
                );

                $($attrs.resizerLeft).css(
                    width: x + 'px'
                );
                $($attrs.resizerRight).css(
                    left: (x + parseInt($attrs.resizerWidth)) + 'px'
                );

             else 
                // Handle horizontal resizer
                var y = window.innerHeight - event.pageY;

                $element.css(
                    bottom: y + 'px'
                );

                $($attrs.resizerTop).css(
                    bottom: (y + parseInt($attrs.resizerHeight)) + 'px'
                );
                $($attrs.resizerBottom).css(
                    height: y + 'px'
                );
            
        

        function mouseup() 
            $document.unbind('mousemove', mousemove);
            $document.unbind('mouseup', mouseup);
        
    ;
);

【讨论】:

有 Angular >= 2 的版本【参考方案2】:

我知道我参加聚会有点晚了,但我发现了这一点,需要我自己的解决方案。如果您正在寻找一个适用于 flexbox 且不使用 jquery 的指令。我在这里扔了一个:

http://codepen.io/Reklino/full/raRaXq/

只需声明您希望元素调整大小的方向,以及您是否使用 flexbox(默认为 false)。

<section resizable r-directions="['right', 'bottom']" r-flex="true">

【讨论】:

非常有帮助!对于那些想要让它真正快速工作的人来说,这是一个超级简单的 plunker(使用 angular-resizable)。看看index.htmlplnkr.co/edit/ww3axpDkBTJuGX1gfIlA?p=preview【参考方案3】:

为了我的项目的需要,我添加了对最小值的支持,以便面板可以保持一些宽度或高度 - (这里是要点) - Github

另外,我创建了Github repo,我在其中添加了对位于主页面轴右侧的面板的支持以及对最小/最大值的支持。它现在处于示例阶段,但我愿意将它变成一个完整的 Angular 指令

【讨论】:

处理最小值/最大值的百分比值可能是另一个很好的补充。 @Mutant 当然,我会调查一下,谢谢你的建议【参考方案4】:

这并不能完全回答问题,但更改 scope: true 解决了隔离范围问题。特别是,在我的 html 中,我有:

<div ng-controller="WorkspaceCtrl">
  <div class="workspace" resize="full" ng-style="resizeStyle()">
    <div class="leftcol" resize="left" ng-style="resizeStyle()">
      <ul class="filelist">
        <li ng-repeat="file in files" id=file.id ng-bind=file.name></li>
      </ul>
      <div contenteditable="true" ng-model="content" resize="editor" ng-style="resizeStyle()">
        Talk to me
      </div>
    </div>
</div>

并且ng-repeat="file in files" 仍然可以访问控制器 WorkspaceCtrl 中定义的数组$scope.files。所以scope: 将指令的作用域与父控制器的作用域截断,而scope: true 只是为指令的每个实例创建一个新作用域,并且指令的每个实例及其子控制器保留对父范围。

我还没有实现调整这些 div 大小的可拖动栏,但是当我这样做时会报告。

【讨论】:

实施这个有什么好运气吗? 不,抱歉。在窗口调整大小时使 div 调整大小很简单。我已经被其他事情分心了,并且没有尝试让 div 本身可调整大小。但是,我确信这将通过使用位于 div 之间的可拖动“垫片”来完成。此外,请确保您没有隔离任何您希望以这种方式调整大小的指令的范围。 自从我昨天问这个问题以来,我找到了一个相当不错的解决方案。查看这个 jQuery Splitter 的分叉版本:github.com/e1ven/jQuery-Splitter。要让它与 jQuery 1.9+ 一起工作,您需要恢复 jQuery.browser(我使用 this code)。将其与链接功能挂钩,您应该一切顺利。

以上是关于Angular JS 可调整大小的 div 指令的主要内容,如果未能解决你的问题,请参考以下文章

为啥手动调整 Visjs 时间线图的高度(可调整大小)不起作用?

如何创建多个受容器 div 约束的可调整大小的同级 div 元素

在可拖动和可调整大小的 Jquery div 中删除

外部 jquery 可拖动/可调整大小的 div 不允许我选择内部跨度的文本

CSS:使 div 可调整大小

将 jquery 可调整大小的句柄移出 div