TWaver - 专注UI技术

http://twaver.servasoft.com/
posts - 171, comments - 191, trackbacks - 0, articles - 2
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

利用Layer优化Group显示

Posted on 2012-08-07 09:53 TWaver 阅读(1055) 评论(0)  编辑  收藏
每天逛逛TWaver论坛已经成为一种习惯,今天看到一个非常有意思的帖子:http://twaver.servasoft.com/forum/viewtopic.php?f=14&t=3129
当两个Group重叠时,Group中的Node会始终显示在两个Group之上,呈现结果如下图(引用了帖子中的图片):

这简直是无法忍受的,如果把这样的呈现效果拿给客户看,不被骂死才怪。我们要的是这种效果(引用了帖子中的图片):

帖子中给出的解决方案是:为每个Group生成一个layer,当选中Group中,将对应的layer置顶。想法很美好,现实却很残酷:帖子最后给出的代码虽然可以部分实现这种效果,但是在我看来仍然不够完美,甚至说有瑕疵。大家可以把代码copy下来,然后运行测试:先将所有的Group展开,然后点击group1,再点击group2_2并拖动与group1重合,你看到了什么?
group2_2虽然被置顶,但是它的parent:group2却仍然被group1和group1_1遮挡了。这是因为帖子中的解决方案只是处理了当前点击Group自身和的child Group(将child Group置顶),却没有处理parent Group,所以group2_2的parent:group2仍然显示在后面。下图是测试的结果(group1是group1_1的parent;group2是group2_2的parent;group1和group2是平级,同是group_root1的children):

可以很明显地看到,group2_2确实被置顶了,但是group2却仍然被遮挡,理想的状况下,当我们点击group2_2的时候,group2应该紧紧跟随在group2_2下面,并遮挡group1和group1_1,效果如下图:

这样就好看多了,当我们拖动group2_2的时候,group2应该仅仅跟随在group2_2下边,并且遮挡住group1和group1_1。
我把帖子中的代码改造了一下,最终实现了这种效果,独乐乐不如众乐乐,下面我把我的实现代码贴到此博客上与大家分享,如果有错误或可以优化的地方希望大家可以批评指正,感激不尽!
我们仍然沿用帖子中的设计思路:为每个Group生成一个layer,点击Group时将layer置顶,但是我们还要考虑Group的parent Group和child Group:将child Group置顶,parent Group紧随其后。
首先Group可以嵌套多层,而且我们也不确定可能会嵌套几层,所以递归是不可避免的了。对于这种比较复杂的算法,直观的代码远远要比语言描述有力的多,直接贴上代码:

 1 private function init():void {
 2                 this.initBox();
 3                 network.elementBox = box;
 4                 network.addInteractionListener(function(e:InteractionEvent):void {
 5                     if(e.kind == InteractionEvent.CLICK_ELEMENT){
 6                         var g:Group = null;
 7                         if(e.element is Group){
 8                             g = Group(e.element);
 9                         }else if(e.element.parent is Group){
10                             g = Group(e.element.parent);
11                         }
12 
13                         var ele:Element=e.element as Element;
14                         var rootGroup:Group=g;
15                         var parentArr:ArrayCollection=new ArrayCollection;
16                         parentArr.addItem(g);
17                         while(ele.parent){
18                             if(ele.parent is Group){
19                                 rootGroup=ele.parent as Group;
20                                 parentArr.addItem(rootGroup);
21                             }
22                             ele=ele.parent as Element;
23                         }
24                         iterator(rootGroup,parentArr);
25                     }
26                 });
27             }
28 private function iterator(parentGroup:Group,parentArr:ArrayCollection):void{
29                 var nextParentGroup:Group=null;
30                 var layer:Layer = box.layerBox.getLayerByID(parentGroup.id) as Layer;
31                 if(layer){
32                     box.layerBox.moveToBottom(layer);
33                 }
34                 for(var i=0;i<parentGroup.children.count;i++){
35                     var ele:Element=parentGroup.getChildAt(i) as Element;
36                     if(ele is Group){
37                         var g:Group=Group(ele);
38                         if(parentArr.contains(g)){
39                             nextParentGroup=g;
40                             continue;
41                         }
42                         var layer:Layer = box.layerBox.getLayerByID(g.id) as Layer;
43                         if(layer){
44                             box.layerBox.moveToBottom(layer);
45                         }
46                         iterator(Group(ele),parentArr);
47                     }
48                 }
49                 if(nextParentGroup)
50                     iterator(nextParentGroup,parentArr);
51             }

尽管语言乏力,但是为了方便大家理解,我还是尽力描述一下:
当我点击一个Group的时候,获取这个Group的根Group,称之为rootGroup,将rootGroup传入iterator方法递归遍历,把所有的Group置顶一遍,但是越是靠后置顶的,就越靠前显示。所以为了让我们点击的Group能够靠前显示,我们需要先遍历无关Group(例子中的group1和group1_1),最后再遍历group2和group2_2(其中group2_2要最后遍历)。这个遍历先后顺序怎么控制呢,通过这段代码来控制: 

1 if(parentArr.contains(g)){
2     nextParentGroup=g;
3     continue;
4 }

parentArr集合里包含了我们点击的Group的所有的parent Group,我们判断如果当前遍历到的group在parentArr集合中,就跳过循环,直到for结束后再遍历它。
这是大致的思路,我觉得这些描述+代码应该可以让大家理解,不知道这样频繁的置顶对效率有没有影响,希望大家能提出优化方案。最后附上完整的代码见原文最下方

只有注册用户登录后才能发表评论。


网站导航: