(Flex) Flex (2012 год)

Flex-preloader.

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



В новом Флексе 4.6 библиотеки занимают адский размер - почти два мегабайта (даже без дополнительных наворотов - Flame, скинов, Embadded-ресурсов и проч.) - грузится такая страничка целую вечность. Поэтому чтобы сайт был хотя бы внешне живой в течении этих 30-ти секунд - особое значение приобретают прелоадеры.


Есть два пути создания прелоадера - подстыковатся к классу extend DownloadProgressBar (что проще) или реализовать в спрайте интерфейс IPreloaderDisplay : extends Sprite implements IPreloaderDisplay. Мне показалось что второй путь проще - по крайней мере для классов и интерфейсов в Adobe Flex Builder есть обозреватель с поиском, фантазировать не приходится - если помнишь примерное название - нажимаешь сначала обзор - потом тыкаешь в создание класса - и рыбка прелаадера готова.



Далее нужно понять порядок вызова событий прелоадера - я поставил Trace и посмотрел, общий порядок вызова - как вы видите ниже сначала идет инициализация, в процессе которой последнее событие вызывается в качестве параметра уже с большим модулем, который будет работать в полной виртуальной машине Flex. В этом вызове к большому модулю надо прицепится и слушать его события. В процессе инициализации болльго модуля (который должен работать в полной среде) идет серия событий ProgressEvent.PROGRESS (это загрузки библиотек), потом идут события FlexEvent.INIT_PROGRESS, в процессе которых среда Flex инициализируется (measure(), commitProperties(), or updateDisplayList()) - и когда инициализация завершена - нужно в прелоадере сформировать событие Event.COMPLETE - по которому виртуальная машина выгружает прелоадер и передает управление собственно большому модулю Flex.



Ниже вы видите прелоадер, который я в итоге родил для текущего своего сайта - обильно снабженный комментариями.


   1:  package 
   2:  {
   3:      import flash.display.GradientType;
   4:      import flash.display.Sprite;
   5:      import flash.events.Event;
   6:      import flash.events.ProgressEvent;
   7:      import flash.events.TimerEvent;
   8:      import flash.filters.DropShadowFilter;
   9:      import flash.geom.Matrix;
  10:      import flash.net.*;
  11:      import flash.text.TextField;
  12:      import flash.text.TextFormat;
  13:      import flash.utils.Timer;
  14:      
  15:      import mx.events.FlexEvent;
  16:      import mx.preloaders.IPreloaderDisplay;
  17:      
  18:   
  19:      public class INDIA_Preloader extends Sprite implements IPreloaderDisplay
  20:      {
  21:          private const STAGE_WIDTH:int = 654;
  22:          private const STAGE_HEIGHT:int = 336;
  23:          private const LOGO_URL:String="http://india.vb-net.com/Images/Load.png";
  24:          
  25:          private var _timer:Timer;                 // we have a timer for animation
  26:          private var _bytesLoaded:uint = 0;
  27:          private var _bytesExpected:uint = 1;   // we start at 1 to avoid division by zero errors.
  28:          private var _fractionLoaded:Number = 1;   // 0-1
  29:          private var _preloader:Sprite;
  30:          
  31:              
  32:          private var bar:Sprite = new Sprite();
  33:          private var mainBox:Sprite;               //контейнер в котором находитя прогрессбар
  34:          
  35:          private var barFrame:Sprite;
  36:          private var barShadow:DropShadowFilter = new DropShadowFilter(2, 45, 0x000000,0.5) // фильтр тени
  37:          private var barColors:Array = [ 0xC4E3AB, 0x89C858];
  38:          private var barBorderColor:uint = 0xdddddd;
  39:          private var barRadius:int = 20;
  40:          private var barWidth:int = STAGE_WIDTH;
  41:          private var barHeight:int = 30;
  42:          
  43:          private var loadingTextField:TextField;
  44:          private var textFont:String = "Tahoma";
  45:          private var textColor:uint = 0x31912A;
  46:          private var loading:String = "Loading ";
  47:          
  48:          /**
  49:           * первое событие - создание экземпляра этого класса - здесь надо создать сцену 
  50:           */
  51:          public function INDIA_Preloader() {
  52:              super();
  53:          }
  54:          
  55:          /**
  56:           * Здесь создается все на сцене, запускается таймер и все загрузки
  57:           */
  58:          private var LogoImage:flash.display.Loader;
  59:          virtual public function initialize():void {
  60:              _timer = new Timer(1);
  61:              _timer.addEventListener(TimerEvent.TIMER, timerHandler);
  62:              _timer.start();
  63:              
  64:              LogoImage = new flash.display.Loader();       
  65:              LogoImage.contentLoaderInfo.addEventListener(Event.COMPLETE, LogoImage_completeHandler);
  66:              LogoImage.load(new URLRequest(LOGO_URL));   
  67:              
  68:              Clear();  
  69:              CreateAllVisualElements();
  70:          }
  71:          
  72:          private function LogoImage_completeHandler(event:Event):void
  73:          {
  74:              addChild(LogoImage);
  75:              LogoImage.width = STAGE_WIDTH;
  76:              LogoImage.height= STAGE_HEIGHT;
  77:              LogoImage.x = 0;
  78:              LogoImage.y = 0;
  79:          }
  80:          
  81:          private function Clear():void {    
  82:              var bg:Sprite = new Sprite();
  83:              bg.graphics.beginFill(0xFFFFFF);
  84:              bg.graphics.drawRect(0, 0, stageWidth, stageHeight);
  85:              bg.graphics.endFill(); 
  86:              addChild(bg);
  87:          }
  88:          
  89:          private function CreateAllVisualElements():void {
  90:              // это спрайт внутри которого лежит прогрессбар
  91:              mainBox = new Sprite();
  92:              mainBox.graphics.beginFill(0xFFFFFF);
  93:              mainBox.graphics.drawRect(0,0,STAGE_WIDTH,STAGE_HEIGHT);
  94:              mainBox.graphics.endFill(); 
  95:              addChild(mainBox);
  96:              //собственно прогрессбар
  97:              bar = new Sprite();
  98:              bar.graphics.drawRoundRect(0, 0, barWidth, barHeight, barRadius, barRadius);
  99:              bar.x = 0;
 100:              bar.y = 290;
 101:              mainBox.addChild(bar);
 102:              //progress bar frame
 103:              barFrame = new Sprite();
 104:              barFrame.graphics.lineStyle(1, barBorderColor, 1)
 105:              barFrame.graphics.drawRoundRect(0, 0, barWidth, barHeight, barRadius, barRadius);
 106:              barFrame.graphics.endFill();
 107:              barFrame.x = bar.x;
 108:              barFrame.y = bar.y;
 109:              barFrame.filters = [ barShadow ];
 110:              mainBox.addChild(barFrame);
 111:              //создать текстовое поле и вписать его в средину прогресс бара
 112:              loadingTextField = new TextField()
 113:              loadingTextField.width = barWidth;
 114:              var tf:TextFormat = new TextFormat(textFont, null, textColor, true, null, null, null, null, "center");
 115:              loadingTextField.defaultTextFormat = tf;
 116:              loadingTextField.text = loading + " 0%";
 117:              loadingTextField.height = loadingTextField.textHeight + 8;
 118:              loadingTextField.x = barFrame.x;
 119:              loadingTextField.y = barFrame.y + Math.round((barFrame.height - loadingTextField.height) / 2);
 120:              mainBox.addChild(loadingTextField);
 121:          }
 122:          
 123:          /**
 124:           * Отрисовка градиентного прогресбара 
 125:           */
 126:          virtual protected function draw():void {
 127:              loadingTextField.text = loading + Math.round(_fractionLoaded * 100).toString() + "%";
 128:              var matrix:Matrix =  new Matrix();
 129:              matrix.createGradientBox(bar.width, bar.height, Math.PI/2);
 130:              bar.graphics.beginGradientFill(GradientType.LINEAR, barColors, [1, 1], [0, 255], matrix);
 131:              bar.graphics.drawRoundRect(0, 0, bar.width * _fractionLoaded, bar.height, barRadius, barRadius);
 132:              bar.graphics.endFill();
 133:          }
 134:          
 135:          /**
 136:          *здесь в параметрах пришел INDIA_swf (типа mx.preloaders.Preloader)
 137:          *это последнее событие этого класса по интерфейсным вызовам
 138:          *после вызова этого события начинается процесс загрузки большого SWF
 139:          *Здесь надо зацепится за события загрузки и инициализации главного SWF 
 140:          */
 141:          virtual public function set preloader(INDIA_swf:Sprite):void {
 142:              _preloader = INDIA_swf;
 143:              INDIA_swf.addEventListener(ProgressEvent.PROGRESS, ProgressBarProgress);    
 144:              INDIA_swf.addEventListener(Event.COMPLETE,  ProgressBarComplete);
 145:              INDIA_swf.addEventListener(FlexEvent.INIT_PROGRESS, FlexProgress);
 146:              INDIA_swf.addEventListener(FlexEvent.INIT_COMPLETE, FlexComplete);
 147:          }
 148:   
 149:          /**
 150:           * Эдесь до флекса еще не дошло - пока грузятся библиотеки 
 151:           */
 152:          virtual protected function ProgressBarProgress(event:ProgressEvent):void {
 153:              _bytesLoaded = event.bytesLoaded;
 154:              _bytesExpected = event.bytesTotal;
 155:              _fractionLoaded = Number(_bytesLoaded) / Number(_bytesExpected);
 156:              draw();
 157:          }
 158:          
 159:          virtual protected function ProgressBarComplete(event:Event):void {
 160:          }
 161:          
 162:            /**
 163:            * Dispatched when the Flex application completes an initialization phase, 
 164:          * as defined by calls to the measure(), commitProperties(), or updateDisplayList() methods.
 165:            */
 166:          virtual protected function FlexProgress(event:Event):void {
 167:              trace ("FlexProgress");
 168:              draw();
 169:          }
 170:          
 171:          /**
 172:           * Последнее событие обьекта INDIA_swf - среда FLEX полностью проинициализирована 
 173:           * Здесь нужно вызвать Event.COMPLETE и закончить в прогресс-баром
 174:           */
 175:          private var _IsInitComplete:Boolean = false;
 176:          virtual protected function FlexComplete(event:Event):void {
 177:              _IsInitComplete = true;
 178:          }
 179:          
 180:          virtual protected function timerHandler(event:Event):void {
 181:              if (_IsInitComplete) {    
 182:                  _timer.stop();
 183:                  dispatchEvent(new Event(Event.COMPLETE));
 184:              } else {
 185:                  draw();
 186:              }
 187:          }
 188:          
 189:          
 190:          /**
 191:           * Эти свойства вызываются как SET сразу после создания экземпляра класса (до initialise)
 192:           */ 
 193:          
 194:          public function set backgroundAlpha(alpha:Number):void{}
 195:          public function get backgroundAlpha():Number { return 1; }
 196:          
 197:          protected var _backgroundColor:uint = 0xffffffff;
 198:          public function set backgroundColor(color:uint):void { _backgroundColor = color; }
 199:          public function get backgroundColor():uint { return _backgroundColor; }
 200:          
 201:          public function set backgroundImage(image:Object):void {}
 202:          public function get backgroundImage():Object { return null; }
 203:          
 204:          public function set backgroundSize(size:String):void {}
 205:          public function get backgroundSize():String { return "auto"; }
 206:          
 207:          protected var _stageHeight:Number = STAGE_HEIGHT;
 208:          public function set stageHeight(height:Number):void { _stageHeight = height; }
 209:          public function get stageHeight():Number { return _stageHeight; }
 210:          
 211:          protected var _stageWidth:Number = STAGE_WIDTH;
 212:          public function set stageWidth(width:Number):void { _stageWidth = width; }
 213:          public function get stageWidth():Number { return _stageWidth; }
 214:          
 215:      }
 216:      
 217:  }

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



Общую документацию о построении прелоадеров вы можете почитать здесь.



Comments ( )
<00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19>  <20>  <21>  <22>  <23
Link to this page: //www.vb-net.com/Flex_Preloader/index.htm
<SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <CHAT ME>  <ABOUT ME>  < THANKS ME>