锁定老帖子 主题:FLEX WEB流程设计器线条、箭头的绘制
精华帖 (8) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-06-05
流程设计器里面,最复杂的其实不是拖来拖去的图片,而是线条的绘制包括锚点、箭头,如果把线条绘制好了,那设计器就没什么难度了。 绘制线条会涉及到一些数学知识,主要是三角函数、极坐标等,如果不记得了,赶紧恶补一下吧,这个是必须的。 线条绘制又分多种场景: 1 在一个节点和鼠标所在坐标之间绘制(寻找目标节点过程),这个线条要跟随鼠标的移动而不断重绘。线条的起点为节点中心点坐标与鼠标位置的连线再与节点边缘的交点(有点抽象,等会看图就明白) 可能很多人都以为是在拖动线条,其实这是一个假象,当鼠标移动时,会先擦除线条,然后重新绘制一条节点和鼠标当前位置的连线,当鼠标移动一段距离后,实际上重绘了无数次,这样线条的“拖动”就有连贯性,如果只在鼠标移动结束之后再绘制一条也可以,这样只需要重绘一次,但视觉上的效果要查很多。 2 在两个节点之间绘制,起点和终点坐标分别为两个节点中心点坐标之间的连线分别与节点边缘的交点。 3 拖动锚点(一条线条被分成几段时,子线条之间的交点)绘制,和第1点有些类似,稍微复杂点。 下面举第1种场景中节点在鼠标左上方的例子进行说明:
X坐标的计算过程: 计算X坐标的代码如下(考虑了各种场景):
/** * 获取起始点与图片边框的交点坐标 * 需按矩形对角线划分四个区域(此处为正方形,每90度为一个边界) * acrossNode 参照节点对象(为上图中的节点对象) */ public static function getLinkPoint(fromPoint:Point,targetPoint:Point,acrossNode:BaseNode):Point { var angle:Number=getAngel(fromPoint,targetPoint); /**计算交点与中心点的垂直和水平距离*/ var distanceX:Number=Math.abs((targetPoint.x-fromPoint.x)*(acrossNode.width/2)/(targetPoint.y-fromPoint.y)); var distanceY:Number=Math.abs((targetPoint.y-fromPoint.y)*(acrossNode.width/2)/(targetPoint.x-fromPoint.x)); if(targetPoint.x<fromPoint.x) { distanceX=-distanceX; } if(targetPoint.y<fromPoint.y) { distanceY=-distanceY; } /**最终xy坐标*/ var x:Number=0; var y:Number=0; if(angle>=45&&angle<135) { x=fromPoint.x+distanceX; y=acrossNode.y; } else if(angle>=135&&angle<225) { x=acrossNode.x; y=fromPoint.y+distanceY; } else if(angle>=225&&angle<315) { x=fromPoint.x+distanceX; y=fromPoint.y+acrossNode.height/2; } else { x=fromPoint.x+acrossNode.width/2; y=fromPoint.y+distanceY; } return new Point(x,y); } /**获取两点夹角的角度*/ private static function getAngel(fromPoint:Point,targetPoint:Point):Number { /**为了与三角坐标一致,y坐标的值要反过来*/ /**通过反正切计算弧度*/ var radian:Number=Math.abs(Math.atan((targetPoint.x-fromPoint.x)/(targetPoint.y-fromPoint.y))); /**计算角度*/ var angle:Number=radian*180/Math.PI; if((targetPoint.x>=fromPoint.x)&&(targetPoint.y<=fromPoint.y))//0~90区域 { angle=90-angle; } else if((targetPoint.x<=fromPoint.x)&&(targetPoint.y<=fromPoint.y))//90~180区域 { angle=90+angle; } else if((targetPoint.x<=fromPoint.x)&&(targetPoint.y>=fromPoint.y))//180~270区域 { angle=270-angle; } else if((targetPoint.x>=fromPoint.x)&&(targetPoint.y>=fromPoint.y))//270~360区域 { angle=270+angle; } return angle; }
具体绘制线条还有一个技巧,线条绘制出来不仅是摆看的,还要加事件,可以被选取,太细了选择太困难,太粗了又太难看,一个很简单的办法就是绘制两条线,一条1个像素的实线,一条比较粗的透明线,透明线实际上是为了扩大选择区域。
graphics.clear(); graphics.moveTo(fromPoint.x,fromPoint.y); graphics.lineStyle(8,color,0,true,LineScaleMode.NORMAL,CapsStyle.NONE); graphics.lineTo(targetPoint.x,targetPoint.y); graphics.moveTo(fromPoint.x,fromPoint.y); graphics.lineStyle(DesignerConstances.LINE_THICKNESS,color); graphics.lineTo(targetPoint.x,targetPoint.y);
绘制箭头 为了简化可绘制等边三角形
平分后的弧度各为PI/6。
/** * 根据线条起始点绘制三角形 */ public function draw(ui:UIComponent,fromPoint:Point,toPoint:Point,color:uint):void { var vDistance:Number= toPoint.y-fromPoint.y;//起始点垂直距离 var sDistance:Number=Point.distance(fromPoint,toPoint);//起始点直线距离 var sinValue:Number=vDistance/sDistance;//起始点间的夹角的sin值 /**两点间直线与水平线的角度(弧度)*/ var radian:Number=Math.asin(sinValue); /**用于计算三角形顶点与目标点水平距离的夹角(弧度)*/ var hRadian:Number=radian-Math.PI/6; /**用于计算三角形顶点与目标点垂直距离的夹角(弧度)*/ var vRadian:Number=radian+Math.PI/6; /**上顶点与目标点的垂直距离*/ var topYDis:Number=8*Math.sin(vRadian); /**上顶点与目标点的水平距离*/ var topXDis:Number=8*Math.cos(vRadian); /**下顶点与目标点的垂直距离*/ var botYDis:Number=8*Math.sin(hRadian); /**下顶点与目标点的水平距离*/ var botXDis:Number=8*Math.cos(hRadian); /**计算三角形上下顶点坐标*/ var topPointX:Number=toPoint.x-topXDis; var topPointY:Number=toPoint.y-topYDis; var botPointX:Number=toPoint.x-botXDis; var botPointY:Number=toPoint.y-botYDis; if(toPoint.x<fromPoint.x) { topPointX=toPoint.x+topXDis; botPointX=toPoint.x+botXDis; } ui.graphics.beginFill(color); ui.graphics.moveTo(topPointX,topPointY); ui.graphics.lineTo(toPoint.x,toPoint.y); ui.graphics.lineTo(botPointX,botPointY); ui.graphics.lineTo(topPointX,topPointY); }
绘制锚点 以下列出开始节点在结束节点左上方时,起始位置的锚点为例,所有锚点坐标通过极坐标换算(x = r*cos(θ) y = r*sin(θ),r为半径)
计算四个顶点值
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-06-19
我也在做,用flex 4 spark skin 渲染组件,界面和逻辑分开 ,效果不错
有空一起探讨探讨 |
|
返回顶楼 | |
发表时间:2011-07-01
最后修改:2011-07-01
你的演示图做的不错,不过,这个我之前已经做过了,:)
http://shlei.iteye.com/blog/809023 http://shlei.iteye.com/blog/808939 |
|
返回顶楼 | |
发表时间:2011-07-01
这个貌似搞的复杂啊
|
|
返回顶楼 | |
发表时间:2011-07-01
shlei 写道 你的演示图做的不错,不过,这个我之前已经做过了,:)
http://shlei.iteye.com/blog/809023 http://shlei.iteye.com/blog/808939 哥也是去年做的,只不过今年才发 |
|
返回顶楼 | |
发表时间:2011-07-04
zean 写道 shlei 写道 你的演示图做的不错,不过,这个我之前已经做过了,:)
http://shlei.iteye.com/blog/809023 http://shlei.iteye.com/blog/808939 哥也是去年做的,只不过今年才发 哥 去年也做了,前 两天才上图。呵呵 |
|
返回顶楼 | |
发表时间:2011-07-20
出了三个哥……
好吧,其实哥前几年就做了。 |
|
返回顶楼 | |
发表时间:2011-07-20
漏打了一个“想”字,改正如下:
其实哥前几年就想做了。 |
|
返回顶楼 | |
发表时间:2011-07-21
觉得flex好玩,想学习一下,弱问一下锚点是什么意思?
|
|
返回顶楼 | |
发表时间:2011-07-21
liangjiesd 写道 觉得flex好玩,想学习一下,弱问一下锚点是什么意思?
在这里主要指控制线条的点,用来点击并拖动时改变线条的形状和连接目标。 |
|
返回顶楼 | |