2010-03-24 12 views
2

Je construis un outil de schématisation avec Adobe Flex 3. Je suis sur le point de mettre en œuvre des lignes de connexion et j'ai une question.Flex: tracer une ligne de connecteur entre les formes

Imaginez que j'ont 2 places à des positions aléatoires sur la toile. Je dois tracer une ligne de connecteur fléché entre eux. J'en ai besoin pour tendre vers le centre de la cible mais finir sur sa bordure. alt text http://i44.tinypic.com/25tw4n4.jpg

Comment puis-je trouver les points précis entre lesquels tracer la ligne?

Merci

Répondre

-1

la chose la plus simple utilise probablement flash.geom.Point. prendre les deux centres c1 et c2. Prenez le vecteur d qui est leur différence. en fonction de son angle (315 à 45, 45 à 135, 135 à 225, 225 à 315), vous saurez quels côtés sont concernés (respectivement: droite et gauche, haut et bas, gauche et droite, bas et haut).

calculer ensuite les intersections entre chaque côté et la ligne reliant les centres.

la ligne reliant les centres peuvent être représentés comme p=t*v+c1 (parlant en vecteurs). représentent le côté comme une ligne, puis calculer t de telle sorte que les deux équations donnent le même point p, qui est l'intersection que vous recherchez.

5

Voici un exemple de faire ce que vous voulez.

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

Ce code est pas totalement optimisé. L'idée est plutôt d'expliquer comment cela fonctionne. Fondamentalement, nous définissons deux carrés (aléatoires), et tracer une ligne entre eux. Pour tracer la ligne, nous calculons un angle entre le centre du premier carré et le centre du second, et nous utilisons une méthode spéciale (getSquareBorderPointAtAngle) pour extraire un point sur la bordure carrée dans la bonne direction.

Cette méthode est le premier point clé de cet extrait. Nous calculons cela en utilisant une géométrie de cercle simple, avec un peu de complexification sur la façon dont nous faisons correspondre le point à la frontière au lieu de faire correspondre un cercle autour ou à l'intérieur du carré.

Ensuite, nous tirons une tête de flèche. Pour cela, nous utilisons la classe Flash Matrix, car c'est beaucoup plus facile que de le calculer à partir de zéro.

Et nous sommes fait.

+0

C'est tout à fait impressionnant, l'homme, je vous remercie! Je suis maintenant un peu distrait donc je ne l'ai pas encore essayé, mais je le ferai. Merci beaucoup – artemb

Questions connexes