利用Layer优化Group显示

每天逛逛TWaver论坛已经成为一种习惯,今天看到一个非常有意思的帖子:http://twaver.servasoft.com/forum/viewtopic.php?f=14&t=3129

当两个Group重叠时,Group中的Node会始终显示在两个Group之上,呈现结果如下图(引用了帖子中的图片):

利用Layer优化Group显示

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

利用Layer优化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):

利用Layer优化Group显示

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

利用Layer优化Group显示

这样就好看多了,当我们拖动group2_2的时候,group2应该仅仅跟随在group2_2下边,并且遮挡住group1和group1_1。

我把帖子中的代码改造了一下,最终实现了这种效果,独乐乐不如众乐乐,下面我把我的实现代码贴到此博客上与大家分享,如果有错误或可以优化的地方希望大家可以批评指正,感激不尽!

我们仍然沿用帖子中的设计思路:为每个Group生成一个layer,点击Group时将layer置顶,但是我们还要考虑Group的parent Group和child Group:将child Group置顶,parent Group紧随其后。

首先Group可以嵌套多层,而且我们也不确定可能会嵌套几层,所以递归是不可避免的了。对于这种比较复杂的算法,直观的代码远远要比语言描述有力的多,直接贴上代码:

private function init():void {

				this.initBox();

				network.elementBox = box;

				network.addInteractionListener(function(e:InteractionEvent):void {

					if(e.kind == InteractionEvent.CLICK_ELEMENT){

						var g:Group = null;

						if(e.element is Group){

							g = Group(e.element);

						}else if(e.element.parent is Group){

							g = Group(e.element.parent);

						}



						var ele:Element=e.element as Element;

						var rootGroup:Group=g;

						var parentArr:ArrayCollection=new ArrayCollection;

						parentArr.addItem(g);

						while(ele.parent){

							if(ele.parent is Group){

								rootGroup=ele.parent as Group;

								parentArr.addItem(rootGroup);

							}

							ele=ele.parent as Element;

						}

						iterator(rootGroup,parentArr);

					}

				});

			}

private function iterator(parentGroup:Group,parentArr:ArrayCollection):void{

				var nextParentGroup:Group=null;

				var layer:Layer = box.layerBox.getLayerByID(parentGroup.id) as Layer;

				if(layer){

					box.layerBox.moveToBottom(layer);

				}

				for(var i=0;i<parentGroup.children.count;i++){

					var ele:Element=parentGroup.getChildAt(i) as Element;

					if(ele is Group){

						var g:Group=Group(ele);

						if(parentArr.contains(g)){

							nextParentGroup=g;

							continue;

						}

						var layer:Layer = box.layerBox.getLayerByID(g.id) as Layer;

						if(layer){

							box.layerBox.moveToBottom(layer);

						}

						iterator(Group(ele),parentArr);

					}

				}

				if(nextParentGroup)

					iterator(nextParentGroup,parentArr);

			}

尽管语言乏力,但是为了方便大家理解,我还是尽力描述一下:

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

if(parentArr.contains(g)){

	nextParentGroup=g;

	continue;

}

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

你可能感兴趣的:(group)