我正在使用Adobe Flex 3构建图表工具。我即将实现连接线,并且我有一个问题。Flex:在形状之间绘制连接线
想象一下,我在画布上的随机位置有2个方格。我需要在它们之间绘制一个带箭头的连接线。我需要它倾向于目标广场的中心,但结束于其边界。 alt text http://i44.tinypic.com/25tw4n4.jpg
如何找出画线的确切点?
我正在使用Adobe Flex 3构建图表工具。我即将实现连接线,并且我有一个问题。Flex:在形状之间绘制连接线
想象一下,我在画布上的随机位置有2个方格。我需要在它们之间绘制一个带箭头的连接线。我需要它倾向于目标广场的中心,但结束于其边界。 alt text http://i44.tinypic.com/25tw4n4.jpg
如何找出画线的确切点?
最简单的事情可能是使用flash.geom.Point
谢谢。采取两个中心c1
和c2
。采取矢量d
这是他们的区别。根据其角度(315至45,45至135,135至225,225至315),您将知道涉及哪些侧面(分别为:左侧,左侧,上下和左侧,左侧,底部和顶部)。
然后计算每边和连接中心的线之间的交点。
连接中心的线可以表示为p=t*v+c1
(以向量表示)。将该边表示为一条线,然后计算t
,使得两个方程式产生相同的点p
,这是您正在寻找的交点。
下面是一个做你想做的例子。
package
{
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.ui.Mouse;
/**
* Sample class to draw squares and arrows between them.
*/
public class SquareArrows extends Sprite
{
/**
* Initialize the scene as soon as we can.
*/
public function SquareArrows()
{
if(stage) {
init();
}
else {
addEventListener(Event.ADDED_TO_STAGE, init);
}
}
/**
* Draw two squares and an arrow between them.
*/
private function init(e : Event = null) : void
{
if(hasEventListener(Event.ADDED_TO_STAGE)) {
removeEventListener(Event.ADDED_TO_STAGE, init);
}
// Drawing random-sized squares.
var squareOne : Shape =
getSquareShape((Math.random() * 50) + 20, 0xBBBBBB);
var squareTwo : Shape =
getSquareShape((Math.random() * 50) + 20, 0xDDDDDD);
addChild(squareOne);
addChild(squareTwo);
// Draw the connector.
var connector : Shape = getConnectorShape(squareOne, squareTwo);
addChild(connector);
}
/**
* Draw a connector arrow between two square shapes.
*/
private function getConnectorShape(connectFrom : Shape, connectTo : Shape) : Shape
{
// Getting the center of the first square.
var centerFrom : Point = new Point();
centerFrom.x = connectFrom.x + (connectFrom.width/2);
centerFrom.y = connectFrom.y + (connectFrom.height/2);
// Getting the center of the second square.
var centerTo : Point = new Point();
centerTo.x = connectTo.x + (connectTo.width/2);
centerTo.y = connectTo.y + (connectTo.height/2);
// Getting the angle between those two.
var angleTo : Number =
Math.atan2(centerTo.x - centerFrom.x, centerTo.y - centerFrom.y);
var angleFrom : Number =
Math.atan2(centerFrom.x - centerTo.x, centerFrom.y - centerTo.y);
// Getting the points on both borders.
var pointFrom : Point = getSquareBorderPointAtAngle(connectFrom, angleTo);
var pointTo : Point = getSquareBorderPointAtAngle(connectTo, angleFrom);
// Calculating arrow edges.
var arrowSlope : Number = 30;
var arrowHeadLength : Number = 10;
var vector : Point =
new Point(-(pointTo.x - pointFrom.x), -(pointTo.y - pointFrom.y));
// First edge of the head...
var edgeOneMatrix : Matrix = new Matrix();
edgeOneMatrix.rotate(arrowSlope * Math.PI/180);
var edgeOneVector : Point = edgeOneMatrix.transformPoint(vector);
edgeOneVector.normalize(arrowHeadLength);
var edgeOne : Point = new Point();
edgeOne.x = pointTo.x + edgeOneVector.x;
edgeOne.y = pointTo.y + edgeOneVector.y;
// And second edge of the head.
var edgeTwoMatrix : Matrix = new Matrix();
edgeTwoMatrix.rotate((0 - arrowSlope) * Math.PI/180);
var edgeTwoVector : Point = edgeTwoMatrix.transformPoint(vector);
edgeTwoVector.normalize(arrowHeadLength);
var edgeTwo : Point = new Point();
edgeTwo.x = pointTo.x + edgeTwoVector.x;
edgeTwo.y = pointTo.y + edgeTwoVector.y;
// Drawing the arrow.
var arrow : Shape = new Shape();
with(arrow.graphics) {
lineStyle(2);
// Drawing the line.
moveTo(pointFrom.x, pointFrom.y);
lineTo(pointTo.x, pointTo.y);
// Drawing the arrow head.
lineTo(edgeOne.x, edgeOne.y);
moveTo(pointTo.x, pointTo.y);
lineTo(edgeTwo.x, edgeTwo.y);
}
return arrow;
}
/**
* Utility method to get a point on a square border at a certain angle.
*/
private function getSquareBorderPointAtAngle(square : Shape, angle : Number) : Point
{
// Calculating rays of inner and outer circles.
var minRay : Number = Math.SQRT2 * square.width/2;
var maxRay : Number = square.width/2;
// Calculating the weight of each rays depending on the angle.
var rayAtAngle : Number = ((maxRay - minRay) * Math.abs(Math.cos(angle * 2))) + minRay;
// We have our point.
var point : Point = new Point();
point.x = rayAtAngle * Math.sin(angle) + square.x + (square.width/2);
point.y = rayAtAngle * Math.cos(angle) + square.y + (square.height/2);
return point;
}
/**
* Utility method to draw a square of a given size in a new shape.
*/
private function getSquareShape(edgeSize : Number, fillColor : Number) : Shape
{
// Draw the square.
var square : Shape = new Shape();
with(square.graphics) {
lineStyle(1);
beginFill(fillColor);
drawRect(0, 0, edgeSize, edgeSize);
endFill();
}
// Set a random position.
square.x = Math.random() * (stage.stageWidth - square.width);
square.y = Math.random() * (stage.stageHeight - square.height);
return square;
}
}
}
此代码并未完全优化。这个想法更多的是解释它是如何工作的。基本上,我们正在定义两个(随机)正方形,并在它们之间追溯一条线。为了追踪线条,我们计算从第一个方块的中心到第二个方块的中心的角度,并且我们使用特殊方法(getSquareBorderPointAtAngle
)以正确的方向提取方形边界上的点。
此方法是此片段的第一个关键点。我们计算出使用简单的圆形几何体,对于如何使点与边界相匹配而不是匹配方形周围或内部的圆有点复杂化。
然后,我们画一个箭头。为此,我们正在使用Flash类,因为它比从头开始计算要容易得多。
然后我们就完成了。
我在一个月前在这里看到答案,因为我需要同样的东西。同时发现这个连接器绘图示例,并认为我会分享链接。
该示例在uicomponents之间绘制连接线,并在连接器被拖动时更新线。好一个!
alt text http://sammyjoeosborne.com/Images/connectorImage.jpg
http://sammyjoeosborne.com/Examples/Connector/ConnectorExample.html
这是完全真棒,人,谢谢!我现在有点分心,所以我还没有尝试过,但我会。非常感谢你 – artemb 2010-04-09 18:21:19