(Flex) Flex (2012 год)

Модуль векторной графики для построения графов.

To view this page ensure that Adobe Flash Player version 10.0.0 or greater is installed.

Ниже я покажу код одного своего теста, без которого у меня не получилось сдвинутся в одной моей коммерческой проге. Этот тест был написан для того, чтобы еще раз вникнуть в тригонометрические функции - в без них никуда при векторном рисовании. Когда в коммерческой проге нагромоздились горы кода - у меня не получилось с разбегу сообразить, какая из тригонометрических функций мне тут нужна в моей проге - котангенс, арктангенс, тангенс, арккотенгенс. Пришлось выделить нужный фрагмент кода - так получился тест, который вы видите.

Потом я добавил в тестик пульсацию - чтобы придать тесту более симпатичный вид. Хотя вариантов облагородить тест вокруг функции можно придумать миллион. Если бы у меня было свободное время - я бы сделал вокруг функции Koleso вращающееся, подпрыгивающее и деформируемое на кочках колесо. Ну или например вылазящие из орбит глаза в которых вращаются от удивления зрачки. Но, увы... времени нет совершенно - единственное что я успел - сделать для другого топика пример на этих же графических примитивах - Шаблон Flex/Air приложений со вкладками - ViewStack.

НумерикБокс с количеством спиц (сверху клипа) можно менять на ходу - это и есть проверка корректности тригонометрической функции - иначе это было бы простейшее матричное преобразование.


Есть много дорогих пакетов для построения графов. Разбираться с ними мне дольше, чем написать свой пакет. Поэтому я покажу тут свой небольшой фреймворк для построения графов. Я не стал оформлять этот фреймворк в виде библиотеки SWZ, а покажу тут прототип кода, который можно дальше гнуть в любую сторону.

Итак, тест рабочих функций моего фреймворка для работы с графами выглядит так: главный MXML содержит определения двух рабочих коллекций для работы на графах - PLACE и LINK, обьекта Stage2 - в котором производится отрисовка графа, линкует три модуля этого теста - graphics.as, EnterFrame.as, GrafLogic.as и содержит функию запуска отрисовки DrawGraf и функцию перерисовки.


   1:  <?xml version="1.0" encoding="utf-8"?>
   2:  <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
   3:                 xmlns:s="library://ns.adobe.com/flex/spark" 
   4:                 xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="900" minHeight="600" creationComplete="application1_creationCompleteHandler(event)" width="900" height="600" enterFrame="application1_enterFrameHandler(event)" backgroundColor="#FDF5E6">
   5:      
   6:      <fx:Script>
   7:          <![CDATA[
   8:              import flash.display.Graphics;
   9:              mport flash.text.TextField;
  10:              import mx.controls.Alert;
  11:              import mx.core.UIComponent;
  12:              import mx.events.FlexEvent;
  13:              import mx.managers.PopUpManager;
  14:              
  15:              
  16:              protected function application1_creationCompleteHandler(event:FlexEvent):void
  17:              {
  18:   
  19:                  //produce test data
  20:                  var k:int=0;
  21:                  for (var j:int=1;j<11;j++){
  22:                      for (var i:int=0;i<100;i++){
  23:                          //разместили узлы с состоянием K в координатах X и Y (place nodes)
  24:                          PLACE.addItem(new OnePlace(i*30+j*50+50,i*50+50,k++ ));
  25:                      }
  26:                  }
  27:                  
  28:                  for (var j:int=0;j<10;j++){
  29:                      for (var i:int=1;i<100;i++){
  30:                          //содинили состояния линиями (crete link with nodes)
  31:                          LINK.addItem(new OneLink(i+(j*100),(i+100)+(j*100)));
  32:                          LINK.addItem(new OneLink(i+(j*100),(i-1)+(j*100)));
  33:                          LINK.addItem(new OneLink(i+(j*100),(i+99)+(j*100)));
  34:                      }
  35:                  }
  36:                  
  37:                  button1_clickHandler(null);
  38:              }
  39:              
  40:              
  41:              protected function button1_clickHandler(event:MouseEvent):void
  42:              {
  43:                  try{            
  44:                      if (Stage2.numChildren==0){
  45:                          //на сцене пока ничего (canvas is clear)
  46:                          GRAF = new UIComponent();
  47:                          Stage2.addChild(GRAF);  
  48:                          DrawGraf();
  49:                      }
  50:                      else if (Checkbox1.selected) {
  51:                          //нужна новая перерисовка (need redraw) 
  52:                          Stage2.removeAllChildren();
  53:                          GRAF = new UIComponent();
  54:                          PLACE.filterFunction=null;
  55:                          PLACE.refresh();
  56:                          Stage2.addChild(GRAF);  
  57:                          DrawGraf();
  58:                      }
  59:                      else {
  60:                          GRAF = Stage2.getChildAt(0) as UIComponent;
  61:                          //не нужна перерисовка (no need redraw)
  62:                      }
  63:                  }                
  64:                  catch (e){
  65:                      Alert.show(e.toString());
  66:                  }
  67:              }
  68:              
  69:              
  70:              protected function DrawGraf():void {
  71:                  //это запуск EnterFrame
  72:                  DrawCircleStartIndex = 0;
  73:                  GRAF.x=0;
  74:                  GRAF.y=0;
  75:                  GRAF.width=5000;
  76:                  GRAF.height=5000;
  77:              }
  78:              
  79:   
  80:          ]]>
  81:      </fx:Script>
  82:      
  83:      
  84:      <fx:Script source="graphics.as" />
  85:      <fx:Script source="EnterFrame.as" />
  86:      <fx:Script source="GrafLogic.as" />
  87:      
  88:      <fx:Declarations>
  89:          <s:ArrayCollection id="PLACE"/>
  90:          <s:ArrayCollection id="LINK"/>
  91:          <mx:UIComponent id="GRAF" />
  92:      </fx:Declarations>
  93:      
  94:      <mx:Canvas id="Stage2" left="10" top="50" bottom="10" right="10"   contentBackgroundColor="#F99999" />
  95:      <s:Button x="76" y="15" label="Refresh" click="button1_clickHandler(event)"/>
  96:      <s:CheckBox id="Checkbox1" x="24" y="16" label="New" selected="true" visible="false"/>
  97:      
  98:  </s:Application>

Файл grafics.as - в приниципе для этого примера я взял отрисовку элументарных графических примитивов из топика - Векторное рисование в полярных координатах и арктангенс.

Собственно логика графа, которая соединяет узлы графа - содержится в модуле logic.as:


   1:  // моя логика графа - My logic
   2:  // PLACE - месторасположение узлов ( Node Place)
   3:  // LINK - связи между узлами графа ( Link nodes)
   4:   
   5:  private function GetPlace(State:int):OnePlace {
   6:      PLACE.filterFunction =    function(One:OnePlace):Boolean {
   7:          return One.state == State;
   8:      }
   9:      PLACE.refresh();
  10:      return (PLACE.length>0 ? PLACE[0]: null);
  11:  }
  12:   
  13:   
  14:  //соединить состояние From и To линией (draw line on From node to To node)
  15:  private function DrawLink1 (Sprite:Graphics, FromState:int,ToState:int):void{
  16:      //найти координаты состояний From и To
  17:      var From:OnePlace = GetPlace(FromState);
  18:      var To:OnePlace = GetPlace(ToState);
  19:      //соединить их линией
  20:      if (From!==null && To !==null){
  21:          return DrawLine3(Sprite, From.x , From.y , To.x , To.y);
  22:      }
  23:  }

Кроме того, я сделал коллекции, писывающие координаты узлов не в виде анонимных колекций (в стиле JavaScript), а в виде типизированных коллекций (с тиле Бейсика и Явы):


   1:      public class OnePlace
   2:      {
   3:          public var x:Number;
   4:          public var y:Number;
   5:          public var state:int;
   6:          
   7:          public function OnePlace(X:Number, Y:Number, State:int)        {
   8:              x=X;
   9:              y=Y;
  10:              state=State;
  11:          }
  12:      }
  13:   
  14:      public class OneLink
  15:      {
  16:          public var fromState:int;
  17:          public var toState:int;
  18:          
  19:          public function OneLink(FromState:int,ToState:int)
  20:          {
  21:              fromState=FromState;
  22:              toState=ToState;
  23:          }
  24:      }

И, наконец, главный компонент фрейморка - рендер, который отрисовывает по частям граф в событии EnterFrame:


   1:  //требование отрисовки этого количества объектов
   2:  //
   3:  private var DrawCircleStartIndex:int = -1;
   4:  private var DrawTextStartIndex:int = -1;
   5:  private var DrawLinkStartIndex:int = -1;
   6:  //
   7:  //шаг отрисовки в одном EnterFrame
   8:  //
   9:  private var DrawCircleStep:int = 10;
  10:  private var DrawLinkStep:int = 5;
  11:  //
  12:  protected function application1_enterFrameHandler(event:Event):void
  13:  {
  14:      
  15:      //отрисовали узлы состояний (draw nodes)
  16:      if (DrawCircleStartIndex >= 0)
  17:      {
  18:          for (var i:int=DrawCircleStartIndex; i<PLACE.length; i++){
  19:              
  20:              DrawCircle1(GRAF.graphics, PLACE[i].x, PLACE[i].y);
  21:              
  22:              if (i-DrawCircleStartIndex >= DrawCircleStep+DrawCircleStartIndex-1){
  23:                  if (i==PLACE.length-1){
  24:                      DrawCircleStartIndex=-1;
  25:                  }
  26:                  else {
  27:                      DrawCircleStartIndex=i;
  28:                      return;
  29:                  } 
  30:              }
  31:          }
  32:          
  33:          DrawCircleStartIndex=-1;
  34:          DrawTextStartIndex = 0;
  35:          
  36:      }
  37:      
  38:      //отрисовали номера состояний (draw nodes number)
  39:      if (DrawTextStartIndex >= 0)
  40:      {
  41:          for (var i:int=0;i<PLACE.length;i++){
  42:              if ((i % 100)  == 0 || i>900){
  43:                  var Text1:TextField= DrawText(PLACE[i].x - Circle_Radius,PLACE[i].y - Circle_Radius - Text_size - 5 , PLACE[i].state);
  44:                  if (Text1 !== null){
  45:                      GRAF.addChild(Text1);
  46:                  }
  47:              }
  48:          }
  49:          DrawTextStartIndex=-1;
  50:          DrawLinkStartIndex =0;
  51:      }
  52:      
  53:      
  54:      //отрисовали связи (draw link with nodes)
  55:      if (DrawLinkStartIndex >= 0)
  56:      {
  57:          for (var i:int=DrawLinkStartIndex; i<LINK.length; i++){
  58:              
  59:              DrawLink1(GRAF.graphics, (LINK[i] as OneLink).fromState,(LINK[i] as OneLink).toState);
  60:              
  61:              if (i-DrawLinkStartIndex >= DrawLinkStep+DrawLinkStartIndex-1){
  62:                  if (i==LINK.length-1){
  63:                      DrawLinkStartIndex=-1;
  64:                  }
  65:                  else {
  66:                      DrawLinkStartIndex=i;
  67:                      return;
  68:                  } 
  69:              }
  70:          }
  71:          DrawLinkStartIndex=-1;
  72:      }
  73:  }

Если вас интересует FLASH, AIR и FLEX - то вы можете посмотреть и другие мои заметки, которые собрались у меня на сайте в прошлом году:




Comments ( )
Link to this page: //www.vb-net.com/GraphFramework/index.htm
< THANKS ME>