TWaver - 专注UI技术

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

最近用户有个比较“变态”的需求:从工具栏上将节点拖入拓扑图中时,如果鼠标下面是Link,就将节点插入这条Link之间;而且鼠标在拖拽过程中,鼠标下面的link呈现凸起效果。

在Link之间插入节点好说,可以删除这条Link再添加两条Link,不过凸起效果就有点费劲了。这里用TWaver Flex的ShapeLink实现比较满意的效果:


大概思路是:
1. 监听network的DragEvent.DRAG_OVER事件,用network#getElementsByDisplayObject方法判断鼠标下面是否有Link。如果有就将这个Link变成透明(link.setStyle(Styles.LINK_ALPHA, 0);),然后加入一条ShapeLink;如果没有就将之前变成透明的Link还原,并删除ShapeLink。具体代码见updateMark以及removeMark方法:

 1 private function updateMark(link:Link, data:Object, point:Point):void {
 2     if(!network.elementBox.contains(markLink)){
 3         markLink.fromNode = link.fromNode;
 4         markLink.toNode = link.toNode;
 5         markLink.setStyle(Styles.SHAPELINK_TYPE, Consts.SHAPELINK_TYPE_QUADTO);
 6         markLink.setStyle(Styles.LINK_WIDTH, link.getStyle(Styles.LINK_WIDTH));
 7         markLink.setStyle(Styles.LINK_COLOR, link.getStyle(Styles.LINK_COLOR));
 8         markLink.setStyle(Styles.LINK_ALPHA, link.getStyle(Styles.LINK_ALPHA));
 9 
10         network.elementBox.add(markLink);
11         lastLink = link;
12         link.setStyle(Styles.LINK_ALPHA, 0);
13     }
14 
15     var points:Collection = new Collection();
16 
17     var fromCenter:Point = markLink.fromNode.centerLocation;
18     var toCenter:Point = markLink.toNode.centerLocation;
19     var radius:Number = Math.sqrt(data.width*data.width + data.height*data.height)/2;
20     var crossPoints:Object = getCrossPoints(fromCenter, toCenter, point, radius*2);
21     if (crossPoints){
22         if(fromCenter.x<toCenter.x){
23             points.addItem(crossPoints.p2);
24             points.addItem(crossPoints.p2);
25         }else{
26             points.addItem(crossPoints.p1);
27             points.addItem(crossPoints.p1);
28         }
29 
30         var crossPoint:Point = new Point(crossPoints.p1.x + (crossPoints.p2.x-crossPoints.p1.x)/2,
31             crossPoints.p1.y + (crossPoints.p2.y-crossPoints.p1.y)/2);
32         var controlPoints:Object = getCrossPoints(crossPoint, point, point, radius*3);
33         if(controlPoints){
34             if(crossPoint.y >= point.y){
35                 points.addItem(controlPoints.p2);
36             }else{
37                 points.addItem(controlPoints.p1);
38             }
39         }else{
40             if(point.y>=fromCenter.y){
41                 point.y = point.y - radius * 3;
42             }else{
43                 point.y = point.y + radius * 3;
44             }
45             points.addItem(point);
46         }
47         if(fromCenter.x<toCenter.x){
48             points.addItem(crossPoints.p1);
49             points.addItem(crossPoints.p1);
50         }else{
51             points.addItem(crossPoints.p2);
52             points.addItem(crossPoints.p2);
53         }
54     }else{
55         points.addItem(fromCenter);
56     }
57     markLink.points = points;
58 }
59 
60 private function removeMark(moving:Boolean):void {
61     if(network.elementBox.contains(markLink)){
62         var fromNode:Node = markLink.fromNode;
63         var toNode:Node = markLink.toNode;
64         network.elementBox.remove(markLink);
65         if(lastLink && moving){
66             lastLink.setStyle(Styles.LINK_ALPHA, markLink.getStyle(Styles.LINK_ALPHA));
67             lastLink = null;
68         }
69     }
70 }
71 

 

2. 最关键的是如何确定ShapeLink的points。这里的核心是计算圆和直线的交点。具体代码见getCrossPoints方法:

 1 private function getCrossPoints(p1:Point, p2:Point, circleCenter:Point, radius:Number):Object{
 2     var line_p1_x:Number = p1.x;
 3     var line_p1_y:Number = p1.y;
 4     var line_p2_x:Number = p2.x;
 5     var line_p2_y:Number = p2.y;
 6     var circle_center_x:Number = circleCenter.x;
 7     var circle_center_y:Number = circleCenter.y;
 8     var circle_radius:Number = radius;
 9     var line_k:Number =(line_p2_y-line_p1_y)/(line_p2_x-line_p1_x);
10     var line_b:Number =line_p1_y-line_k*line_p1_x;
11     var a:Number =1+line_k*line_k;
12     var b:Number =-2*circle_center_x+2*line_k*line_b-2*line_k*circle_center_y;
13     var c:Number =circle_center_x*circle_center_x+(line_b-circle_center_y)*(line_b-circle_center_y)-circle_radius*circle_radius;
14     var delta:Number =b*b-4*a*c;
15     var x1:Number =(-b+Math.sqrt(delta))/(2*a);
16     var x2:Number =(-b-Math.sqrt(delta))/(2*a);
17     var y1:Number =line_k*x1+line_b;
18     var y2:Number =line_k*x2+line_b;
19 
20     if(delta>=0){
21         return {p1: new Point(x1, y1), p2: new Point(x2, y2)};
22     }else{
23         return null;
24     }
25 }
26 

 

3. 在DragEvent.DRAG_DROP事件里,删除ShapeLink并创建两条Link。

源码下载

 


评论

# re: Flex下实现拖动节点时,连线拱起的效果  回复  更多评论   

2011-02-17 22:34 by 奇幻修真小说
最关键的是如何确定ShapeLink的points。这里的核心是计算圆和直线的交点。

# re: Flex下实现拖动节点时,连线拱起的效果  回复  更多评论   

2011-02-20 17:09 by 好店8
确实是比较变态的要求。。。项目做多了,总会碰到各样奇怪的要求。。

# re: Flex下实现拖动节点时,连线拱起的效果  回复  更多评论   

2011-02-21 09:50 by qiuyunanjichong
这需求不是一般变态

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


网站导航: