效果图如下:
1、根据数据源的层级关系构造 树型的数据,并根据层次给每层数据赋于TREE_LEVEL数据
protected function convertToTree(startData:Object,level:Number=0):void
{
if(startData != null)
{
level++ ;
var children:Array = getChildrenNode(startData) ;
startData.children = children ;
for each(var data:Object in children)
{
convertToTree(data,level) ;
}
startData.TREE_LEVEL = level ;
}
}
2、根据数据,创建对应的节点,并把节点与数据进行绑定
protected function mapDataToNode(startData:Object,startNode:BinaryTreeNode):void
{
if(startData == null || startNode == null)
{
return ;
}
var dataArray:Array = startData.children ;
if(dataArray.length == 1 )
{
var newNode:BinaryTreeNode = createNode(startNode);
newNode.data = dataArray[0] ;
startNode.children.itemUpdated(newNode,"data") ;
mapDataToNode(dataArray[0],newNode) ;
}
if(dataArray.length == 2 )
{
var leftNode:BinaryTreeNode = createNode(startNode);
var rightNode:BinaryTreeNode = createNode(startNode);
leftNode.data = dataArray[0] ;
rightNode.data = dataArray[1] ;
startNode.children.itemUpdated(leftNode,"data") ;
startNode.children.itemUpdated(rightNode,"data") ;
mapDataToNode(dataArray[0],leftNode) ;
mapDataToNode(dataArray[1],rightNode) ;
}
}
3、获取最后一级的节点
protected function getVirtualLast(last:Array,startNode:BinaryTreeNode):Array
{
if(startNode != null)
{
if(startNode.children && startNode.children.length == 0)
{
startNode.isLeaf = true ;
last.push(startNode) ;
}
for each (var child:BinaryTreeNode in startNode.children)
{
getVirtualLast(last,child) ;
}
}
return last ;
}
4、比较很容易的定位最后一级的位置
如果是垂直排列,则
Y坐标为(level - 1) * (VERTICAL_HEIGHT + lastNode.defaultHeight) + TOP_PADDING
如果前一个节点为它的兄弟节点,则 X坐标为preNode.vx + BROTHER_GAP + node.defaultWidth ;
否则X坐标为LEFT_PADDING
if(_direction == "vertical")
{
lastNode.x = LEFT_PADDING ;
lastNode.y = (level - 1) * (VERTICAL_HEIGHT + lastNode.defaultHeight) + TOP_PADDING ;
for (var i:int=1;i<last.length;i++)
{
var node:BinaryTreeNode = last[i] as BinaryTreeNode ;
var preNode:BinaryTreeNode = last[i-1] as BinaryTreeNode ;
var nodeParent:BinaryTreeNode = node.superNode ;
if(nodeParent == null)
{
return ;
}
if(ArrayUtil.arrayContainsValue(nodeParent.children.toArray(),preNode))
{
node.x = preNode.x + BROTHER_GAP + node.defaultWidth ;
}
else
{
node.x = preNode.x + GAP + node.defaultWidth ;
}
node.y = (node.level - 1) * (VERTICAL_HEIGHT + node.defaultHeight) + TOP_PADDING ;
}
}
5、根据最后一层的位置,推算出其他层的位置
先对最后一层,按level进行排序,先推算最底层的父节点
如果父节点有两个小孩,则父节点的 X坐标为 parentNode.x = ((parentNode.children[0] as BinaryTreeNode).x + ((parentNode.children[1] as BinaryTreeNode).x)) / 2 ;;
如果只有一个小孩,则父节点的 X坐标为parentNode.x = childNode.x;
Y坐标为parentNode.y = childNode.y - childNode.defaultHeight - VERTICAL_HEIGHT ;
var fixArray:Array = new Array() ;
fixedArray.sortOn("level", Array.DESCENDING | Array.NUMERIC);
if(_direction == "vertical")
{
for(var i:int=0;i<fixedArray.length ; i++)
{
var childNode:BinaryTreeNode = fixedArray[i] as BinaryTreeNode ;
var parentNode:BinaryTreeNode = childNode.superNode ;
if(parentNode == null)
{
continue; //return ;
}
if(parentNode.children.length == 2)
{
parentNode.x = ((parentNode.children[0] as BinaryTreeNode).x + ((parentNode.children[1] as BinaryTreeNode).x)) / 2 ;
//两个孩子 确定一个父,所以他兄弟 不需要再循环了
i++ ;
}
else if(parentNode.children.length == 1)
{
parentNode.x = childNode.x;
}
parentNode.y = childNode.y - childNode.defaultHeight - VERTICAL_HEIGHT ;
fixArray.push(parentNode) ;
}
if(fixArray.length > 0)
{
fixPostion(fixArray) ;
}
}
6、根据位置设置节点是在左边还是右边
if(_direction == "vertical")
{
for each(var n:BinaryTreeNode in children)
{
if(n.data)
{
if(n.x < node.x)
{
n.position = "left" ;
}
if(n.x > node.x)
{
n.position = "right" ;
}
if(n.x == node.x)
{
n.position = "direct" ;
}
children.itemUpdated(n) ;
validatePostion(n) ;
}
}
}
7、锁定线的位置
var children:ArrayCollection = startNode.children ;
var searchReuslt:Array = ArrayUtil.getItemsByField(children.toArray(),null,"data") as Array;
if(searchReuslt && searchReuslt.length == 1)
{
var node:BinaryTreeNode = (children[0].data == null ? children[1] : children[0]) as BinaryTreeNode ;
if(node.line &&_canvas.contains(node.line))
{
_canvas.removeChild(node.line) ;
}
node.line = new BinaryTreeLine() ;
if(_direction == "vertical")
{
node.line.position = BinaryTreeLine.POSITION_L ;
node.line.height = VERTICAL_HEIGHT - Locker.LOCKER_HEIGHT ;
node.line.width = 0 ;
node.line.x = node.x + node.defaultWidth / 2 ;
node.line.y = node.y - VERTICAL_HEIGHT + Locker.LOCKER_HEIGHT ;
node.line.direction = "VERTICAL" ;
node.direction = "VERTICAL" ;
}
else
{
node.line.position = BinaryTreeLine.POSITION_D ;
node.line.width = HORIZONAL_WIDTH - Locker.LOCKER_HEIGHT ;
node.line.height = 0 ;
node.line.y = node.y + node.defaultHeight / 2 ;
node.line.x = node.x - HORIZONAL_WIDTH + Locker.LOCKER_HEIGHT ;
node.line.direction = "HORIZONAL" ;
node.direction = "HORIZONAL" ;
}
if(lineField && lineField != "" && node.data)
{
node.line.text = node.data[lineField] ;
}
fixLinePosition(node) ;
}
8、根据最大和最小的X Y值设置 measuredWidth measuredHeight 以便出现滚动条
并加入到舞台中。
_canvas.x = 0 ; _canvas.y = 15 ; _canvas.measuredWidth = maxX - minX + startNode.defaultWidth + TOP_PADDING ; _canvas.measuredHeight = maxY - minY + startNode.defaultHeight + LEFT_PADDING ; _canvas.setActualSize(_canvas.measuredWidth,_canvas.measuredHeight) ; addChildrenToContainer(startNode) ; _canvas.addChild(startNode) ;