简体   繁体   English

Flex:在形状之间绘制连接线

[英]Flex: drawing a connector line between shapes

I am building a diagramming tool using Adobe Flex 3. I am about to implement connector lines and I have a question. 我正在使用Adobe Flex 3构建图表工具。我即将实现连接线,我有一个问题。

Imagine I have 2 squares at random positions on the canvas. 想象一下,我在画布上的随机位置有2个正方形。 I need to draw an arrowed connector line between them. 我需要在它们之间画一条箭头连接线。 I need it to tend to the target square's center but end on its border. 我需要它倾向于目标广场的中心,但结束于它的边界。 替代文字

How do I find out the exact points between which to draw the line? 如何找出绘制线的确切点?

Thank you 谢谢

Here is an example doing what you want. 这是一个做你想要的例子。

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;
        }
    }
}

This code isn't totally optimized. 此代码未完全优化。 The idea is more to explain how it works. 这个想法更多的是解释它是如何工作的。 Basically, we are defining two (random) squares, and tracing a line between them. 基本上,我们定义了两个(随机)方块,并在它们之间描绘了一条线。 To trace the line, we calculate an angle from the center of the first square to the center of the second one, and we use a special method ( getSquareBorderPointAtAngle ) to extract a point on the square border in the right direction. 为了跟踪线,我们计算从第一个正方形的中心到第二个正方形的中心的角度,我们使用一个特殊的方法( getSquareBorderPointAtAngle )在正确的方向上提取方形边界上的一个点。

This method is the first key point of this snippet. 此方法是此代码段的第一个关键点。 We calculate that using simple circle geometry, with a little complexification on how we make the point match the border instead of matching a circle around or inside the square. 我们使用简单的圆几何计算,稍微复杂化我们如何使点匹配边框而不是匹配方形周围或内部的圆。

Then, we draw an arrow head. 然后,我们画一个箭头。 For that, we're making use of the Flash Matrix class, because it's much easier this way than to calculate it from the scratch. 为此,我们正在使用Flash Matrix类,因为这种方式比从头开始计算要容易得多。

And here we're done. 在这里我们已经完成了。

I was reading the answers here a month ago as I need the same thing. 我一个月前在这里阅读答案,因为我需要同样的东西。 Found this connector drawing example in the meantime, and thought i'd share the link. 在此期间找到此连接器绘图示例,并认为我将共享链接。

The example draws connector lines between uicomponents, and updates the lines as the connectors are dragged. 该示例在uicomponents之间绘制连接线,并在拖动连接器时更新线。 Nice one! 好东西!

替代文字
(source: sammyjoeosborne.com ) (来源: sammyjoeosborne.com

http://sammyjoeosborne.com/Examples/Connector/ConnectorExample.html http://sammyjoeosborne.com/Examples/Connector/ConnectorExample.html

the most simple thing is probably using flash.geom.Point . 最简单的事情可能是使用flash.geom.Point take both centers c1 and c2 . 取两个中心c1c2 take the vector d that is their difference. 采取矢量d ,这是他们的差异。 depending on its angle (315 to 45, 45 to 135, 135 to 225, 225 to 315) you will know which sides are involved (respectively: right and left, top and bottom, left and right, bottom and top). 根据其角度(315至45,45至135,135至225,225至315),您将知道涉及哪些侧面(分别为:右侧和左侧,顶部和底部,左侧和右侧,底部和顶部)。

then calculate intersections between each side and the line connecting the centers. 然后计算每一边和连接中心的线之间的交叉点。

the line connecting the centers can be represented as p=t*v+c1 (speaking in vectors). 连接中心的线可以表示为p=t*v+c1 (以向量表示)。 represent the side as a line and then calculate t such that both equations yield the same point p , which is the intersection you are looking for. 将边表示为一条线然后计算t使得两个方程产生相同的点p ,这是您正在寻找的交点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM