编写鱼眼组件


  编写鱼眼组件
  如果你看过苹果那的停靠栏也许你会很惊讶,现在用脚本来实现一下鱼眼。
  设计鱼眼组件,我们可以使用Group作为容器组件。需要两个渲染器,定义两个接口(渲染器必须实现这两个接口),另外需要为子组件自定义一个事件。然后我们再侦听鼠标移动,根据鼠标与各个组件之间的距离计算各个组件的大小。基本原理就是这样。
  容器代码:
  package
  {
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.geom.Point;
  import flash.utils.Dictionary;
  import mx.collections.ArrayCollection;
  import mx.controls.Alert;
  import mx.core.FlexGlobals;
  import mx.core.IFactory;
  import mx.core.UIComponent;
  import mx.events.FlexEvent;
  import spark.components.Application;
  import spark.components.Group;
  import spark.layouts.HorizontalLayout;
  import spark.layouts.VerticalLayout;
  import spark.layouts.supportClasses.LayoutBase;  [Event(name="item_click", type="MyDockItemEvent")]
  [Event(name="item_rollover", type="MyDockItemEvent")]
  [Event(name="item_rollout", type="MyDockItemEvent")]
  /**
  * Dock container
  * @author 黄记新
  */
  public class MyDock extends Group
  {
  private var _itemRender:IFactory;
  private var _labelRender:IFactory;
  [Bindable]
  private var _itemWidth:Number;
  /**
  *
  * @default
  */
  protected var itemWidthChanged:Boolean;
  [Bindable]
  private var _itemHeight:Number;
  /**
  *
  * @default
  */
  protected var itemHeightChanged:Boolean;
  [Bindable]
  private var _itemSize:Number=40;
  protected var itemSizeChanged:Boolean;
  [Bindable]
  private var _labelPosition:String;
  protected var labelPositionChanged:Boolean;
  [Bindable]
  private var _maximumSize:Number=_itemSize * 1.5;
  [Bindable]
  private var _scaleRange:Number=_maximumSize * 1.5;
  private var _labelGap:Number=10;
  private var _dataProvider:ArrayCollection;
  /**
  *
  * @default
  */
  protected var dataProviderChanged:Boolean;
  /**
  *
  * @default
  */
  protected var renderToItemMap:Dictionary;
  /**
  *
  * @default
  */
  protected var renderToLabelMap:Dictionary;
  /**
  *
  * @default
  */
  protected var itemToRenderMap:Dictionary;
  /**
  *
  * @default
  */
  public var labelField:String="";
  /**
  *
  */
  public function MyDock()
  {
  //TODO: implement function
  super();
  //Set defaults;
  renderToItemMap=new Dictionary();
  renderToLabelMap=new Dictionary();
  itemToRenderMap=new Dictionary();
  addEventListener(FlexEvent.CREATION_COMPLETE, onComplete);
  }
  /**
  *
  * @param event
  */
  protected function onComplete(event:FlexEvent):void
  {
  removeEventListener(FlexEvent.CREATION_COMPLETE, onComplete);
  FlexGlobals.topLevelApplication.addEventListener(M ouseEvent.MOUSE_MOVE, onMouseMove);
  }
  protected function onMouseMove(e:MouseEvent):void
  {
  var point:Point=globalToLocal(new Point(e.stageX, e.stageY));
  var minimumSize:Number=this.itemSize;
  var maximumSize:Number=this.maximumSize;
  var scaleRange:Number=this.scaleRange;
  /* the distance the mouse must be in to make the item full size */
  var insideDistance:Number=maximumSize / Math.SQRT2;
  // set the width and height of the icons appropriately based on their distance from the mouse
  for each (var render:UIComponent in itemToRenderMap)
  {
  if (render == null)
  continue;
  var renderPoint:Point=new Point(render.x + render.width / 2, render.y + render.height / 2);
  var distance:Number=Math.sqrt(Math.pow(renderPoint.x - point.x, 2) + Math.pow(renderPoint.y - point.y, 2));
  /* the radius the of smallest circle to totally encompass the current item */
  var outerDistance:Number=render.width / Math.SQRT2;
  // make it the largest size if the mouse inside the inside distance
  if (distance  scaleRange + outerDistance)
  {
  render.width=render.height=minimumSize;
  continue;
  }
  // scale it proportionally in the scale region
  var scale:Number=1 - ((distance - outerDistance) / scaleRange);
  var size:Number=minimumSize + (maximumSize - minimumSize) * scale;
  render.width=render.height=size;
  }
  }
  //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ _/_/_/_/_/_/_/_/_/
  //_/_/
  //_/_/  getter and setter
  //_/_/
  //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ _/_/_/_/_/_/_/_/_/
  public function get labelPosition():String
  {
  return _labelPosition;
  }
  [Inspectable(defaultValue="top", enumeration="top,bottom,left,right")]
  public function set labelPosition(value:String):void
  {
  if (_labelPosition == value)
  {
  return;
  }
  _labelPosition=value;
  labelPositionChanged=true;
  invalidateProperties();
  }
  public function get scaleRange():Number
  {
  return _scaleRange;
  }
  public function set scaleRange(value:Number):void
  {
  _scaleRange=value;
  }
  public function get maximumSize():Number
  {
  return _maximumSize;
  }
  public function set maximumSize(value:Number):void
  {
  _maximumSize=value;
  }
  public function get itemSize():Number
  {
  return _itemSize;
  }
  public function set itemSize(value:Number):void
  {
  if (_itemSize == value)
  {
  return;
  }
  _itemSize=value;
  itemSizeChanged=true;
  invalidateProperties();
  }
  /**
  *
  * @return
  */
  public function get labelGap():Number
  {
  return _labelGap;
  }
  /**
  *
  * @param value
  */
  public function set labelGap(value:Number):void
  {
  _labelGap=value;
  }
  /**
  *
  * @return
  */
  public function get itemHeight():Number
  {
  return _itemHeight;
  }
  /**
  *
  * @param value
  */
  public function set itemHeight(value:Number):void
  {
  if (_itemHeight == value)
  {
  return;
  }
  _itemHeight=value;
  itemHeightChanged=true;
  invalidateProperties();
  }
  /**
  *
  * @return
  */
  public function get itemWidth():Number
  {
  return _itemWidth;
  }
  /**
  *
  * @param value
  */
  public function set itemWidth(value:Number):void
  {
  if (_itemWidth == value)
  {
  return;
  }
  _itemWidth=value;
  itemWidthChanged=true;
  invalidateProperties();
  }
  /**
  *
  * @return
  */
  public function get dataProvider():ArrayCollection
  {
  return _dataProvider;
  }
  /**
  *
  * @param value
  */
  public function set dataProvider(value:ArrayCollection):void
  {
  if (_dataProvider == value)
  {
  return;
  }
  _dataProvider=value;
  dataProviderChanged=true;
  invalidateDisplayList();
  invalidateSize();
  invalidateParentSizeAndDisplayList();
  }
  /**
  *
  * @return
  */
  public function get labelRender():IFactory
  {
  return _labelRender;
  }
  /**
  *
  * @param value
  */
  public function set labelRender(value:IFactory):void
  {
  _labelRender=value;
  }
  /**
  *
  * @return
  */
  public function get itemRender():IFactory
  {
  return _itemRender;
  }
  /**
  *
  * @param value
  */
  public function set itemRender(value:IFactory):void
  {
  _itemRender=value;
  }
  /**
  *
  * @param object
  */
  protected function removeItem(object:Object):void
  {
  var render:UIComponent=itemToRenderMap[object];
  if (!render)
  {
  return;
  }
  itemToRenderMap[object]=null;
  renderToItemMap[render]=null;
  renderToLabelMap[render]=null;
  removeElement(render);
  }
  /**
  *
  * @param e
  */
  protected function itemClickHandler(e:MouseEvent):void
  {
  var render:UIComponent=e.currentTarget as UIComponent;
  if (render == null)
  return;
  var item:Object=renderToItemMap[render];
  if (!item)
  {
  return;
  }
  this.dispatchEvent(new MyDockItemEvent("item_click", render, dataProvider.getItemIndex(item)));
  }
  /**
  *
  * @param e
  */
  protected function itemRollOverHandler(e:MouseEvent):void
  {
  var render:UIComponent=e.target as UIComponent;
  if (render == null)
  return;
  var item:Object=renderToItemMap[render];
  if (!item)
  {
  return;
  }
  var label:UIComponent=renderToLabelMap[e.target] as UIComponent;
  if (label == null)
  return;
  label.visible=true;
  this.dispatchEvent(new MyDockItemEvent("item_rollover", render, dataProvider.getItemIndex(item)));
  }
  /**
  *
  * @param e
  */
  protected function itemRollOutHandler(e:MouseEvent):void
  {
  var render:UIComponent=e.target as UIComponent;
  if (render == null)
  return;
  var item:Object=renderToItemMap[render];
  if (!item)
  {
  return;
  }
  var label:UIComponent=renderToLabelMap[e.target] as UIComponent;
  if (label == null)
  return;
  label.visible=false;
  this.dispatchEvent(new MyDockItemEvent("item_rollout", render, dataProvider.getItemIndex(item)));
  }
  /**
  *
  * @param event
  */
  protected function positionChangeHandler(event:Event):void
  {
  var render:UIComponent=event.target as UIComponent;
  if (render == null)
  return;
  var label:UIComponent=renderToLabelMap[event.target] as UIComponent;
  if (label == null)
  return;    var midPoint:Point=this.localToGlobal(new Point(render.x + render.width / 2, render.y + render.height / 2));    var horizontalOffset:Number=-label.width / 2;
  var verticalOffset:Number=-label.height / 2;    trace(labelPosition);
  if (labelPosition == "top")
  {
  label.x=midPoint.x - label.width / 2;
  label.y=midPoint.y - render.width / 2 - label.height - labelGap;
  }
  else if (labelPosition == "bottom")
  {
  label.x=midPoint.x - label.width / 2;
  label.y=midPoint.y + render.width / 2 + label.height + labelGap;
  }
  else if (labelPosition == "left")
  {
  label.x=midPoint.x - render.width / 2 - label.width - labelGap;
  label.y=midPoint.y - label.height / 2;
  }
  else
  {
  label.x=midPoint.x + render.width / 2 + labelGap;
  label.y=midPoint.y - label.height / 2;
  }
  }   /**
  *
  * @param object
  * @return
  */
  protected function createInstance(object:Object):UIComponent
  {
  var render:UIComponent=itemRender.newInstance() as UIComponent;
  if (render is IMyItemRender)
  {
  IMyItemRender(render).data=object;
  IMyItemRender(render).myDock=this;
  }    render.addEventListener(MouseEvent.CLICK, itemClickHandler);
  render.addEventListener(MouseEvent.ROLL_OVER, itemRollOverHandler);
  render.addEventListener(MouseEvent.ROLL_OUT, itemRollOutHandler);
  render.addEventListener("move", positionChangeHandler);
  //   render.addEventListener("yChanged", positionChangeHandler);    if (labelField == "" || !labelRender)
  {
  return render;
  }    var label:UIComponent=labelRender.newInstance() as UIComponent;
  if (label is IMyLabelRender)
  {
  IMyLabelRender(label).text=object[this.labelField] ;
  }    label.visible=false;
  renderToLabelMap[render]=label;    FlexGlobals.topLevelApplication.addElement(label);
  return render;
  }   /**
  *
  */
  protected function ChangeWH():void
  {    for each (var render:UIComponent in itemToRenderMap)
  {
  render.height=render.width=itemSize;
  }   }   //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ _/_/_/_/_/_/_/_/_/
  //_/_/
  //_/_/  override functions
  //_/_/
  //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ _/_/_/_/_/_/_/_/_/   /**
  *
  * @param value
  */
  override public function set layout(value:LayoutBase):void
  {
  super.layout=value;    if (value is HorizontalLayout)
  {
  trace("我是横向布局");
  }
  else if (value is VerticalLayout)
  {
  trace("我是纵向布局");
  }
  }
  /**
  *
  */
  override protected function commitProperties():void
  {
  super.commitProperties();
  if (dataProviderChanged)
  {
  dataProviderChanged=false;
  for each (var object:Object in itemToRenderMap)
  {
  removeItem(object);
  }
  var length:int=dataProvider.length;
  var render:UIComponent;
  for (var i:int=0; i 
  flex/spark"
  xmlns:mx="library://ns.adobe.com/flex/mx"
  implements="IMyItemRender"
  rollOutEffect="{rollOutEffect}"
  rollOverEffect="{rollOverEffect}">
  
  
  
  
  
  
  
            width="{this.width}"             height="{this.height}"/>   flex/spark"         xmlns:mx="library://ns.adobe.com/flex/mx"         implements="IMyLabelRender"         showEffect="{showEffect}"         hideEffect="{hideEffect}">                               
  
  
  
  
  
  
  事件:
  package
  {
  import flash.events.Event;
  import mx.core.UIComponent;
  /**
  * The DockItemEvent is the event fired to indicate mouse interaction has happened with an item in the Dock.
  * Interaction comes in the form of clicking an individual item or having the mouse move over or leave the item.
  * @author jixin_huang
  */
  publicclassMyDockItemEventextends Event
  {
  privatevar _render:UIComponent;
  privatevar _index:int;        publicstaticconst ITEM_CLICK:String="item_click";        publicstaticconst ITEM_ROLLOVER:String="item_rollover";        publicstaticconst ITEM_ROLLOUT:String="item_rollout";        /**         * Constructor         * @param type         * @param bubbles         * @param cancelable         */        publicfunctionMyDockItemEvent(type:String, render:UIComponent, index:int, bubbles:Boolean=false, cancelable:Boolean=false)        {            //TODO: implement function            super(type, bubbles, cancelable);            this._index=index;            this._render=render;        }        /**         * Get the index of the item of the event         * @return         */        publicfunctionget index():int        {            return _index;        }        /**         * Get the render of the event;         * @return         */        publicfunctionget render():UIComponent        {            return _render;        }     } } 主文件: 
  flex/spark"
  xmlns:mx="library://ns.adobe.com/flex/mx"
  minWidth="955"
  minHeight="600"
  xmlns:view="view.*"
  creationComplete="application1_creationCompleteHan dler(event)"
  xmlns:ns1="*"
  backgroundColor="0x000000">
  
  
  
  
  
  
  width="268"
  height="155"
  dataProvider="{dataProvider}"
  itemRender="{itemRenderer}"
  labelRenderer="{labelRenderer}"
  labelField="title">
  
  width="100%"
  height="500"
  itemSize="{hslider.value}"
  maximumSize="{maximumHSlider.value}"
  scaleRange="{scaleRangeHSlider.value}"
  dataProvider="{dataProvider}"
  itemRender="{myItemRenderer}"
  labelRender="{mylabelRenderer}"
  labelField="title"
  item_click="myDock_item_clickHandler(event)"
  labelPosition="top">
  
  
  
  
  
  
  
  

猜你喜欢

转载自wangangie19.iteye.com/blog/1573940