2013-04-10 110 views
1

我有一个以.ai格式显示的美国地图。我想在我的Flex应用程序中使用它。
问题是地图切片状态线,我想操纵应用程序内的状态。Adob​​e Illustrator到Flash Builder 4.6

说明:在我的应用程序中,我希望能够点击一个国家来突出显示它,并将所有其他国家赶出现场,然后再将所有国家带回来使整个国家。就像一个拼图游戏。

我将Adobe Illustrator中的FXG文件导入到了Flash Builder 4中的Flex应用程序中,但我无法一次处理每个状态!

会真的很感谢帮助! 欢呼声

+2

在Flex应用程序,如果你想以不同的方式处理它们,你需要个人资产为每个地图件。否则,你将不得不做一些位图处理,这听起来像一条非常复杂的路线。 – JeffryHouser 2013-04-11 00:30:34

+0

感谢您的建议!我已经开始走下去了... :( – 2013-04-11 00:40:55

回答

1

我最终转换到FXG MXML ...

我用下面的代码来做到这一点:

FXG to MXML Converter

我改变

d:userlabel

到属性ID和它的工作非常好!...

+0

不知道,感谢分享(+1) – 2013-04-17 20:19:47

1

有一个FxgParser库,但它似乎没有输出状态名称,如果它们在.fxg文件中标记为d:userLabel属性。你可以修改源代码来解决这个问题。

下面是如何::

编辑fxgparser.parser.Path.as然后在类的顶部添加此命名空间:

public static const aab:Namespace = new Namespace("aab", "http://ns.adobe.com/fxg/2008/dt"); 

然后在解析()方法的末尾添加此:

target.name = [email protected]::userLabel; 

为插画CS6似乎增加,而不是ID或其他东西,并FxgParser在默认情况下会忽略这个编号userLabel属性。

代码将是非常类似上面:

package { 

    import flash.display.*; 
    import flash.events.*; 
    import flash.geom.Point; 
    import flash.net.*; 
    import flash.utils.Dictionary; 

    import com.greensock.*; 
    import fxgparser.FxgDisplay; 

    [SWF(width='1368', height='936', backgroundColor='#ffffff', frameRate='30')] 
    public class FXGTest extends Sprite{ 

     private var states:Sprite;//container holding each state Shape 
     private var positions:Dictionary = new Dictionary();//original position to restore states to 

     public function FXGTest() { 
      addEventListener(Event.ADDED_TO_STAGE,init); 
     } 
     private function init(e:Event):void{ 
      new URLLoader(new URLRequest("usa-wikipedia.fxg")).addEventListener(Event.COMPLETE,fxgLoaded); 
     } 
     private function fxgLoaded(e:Event):void{ 
      //trace(e.target.data); 
      var map:FxgDisplay = addChild(new FxgDisplay(new XML(e.target.data))) as FxgDisplay; 
      trace(listChildren(map)); 
      //map.item.item.item.* 
      states = Sprite(Sprite(Sprite(map.getChildAt(0)).getChildAt(0)).getChildAt(0)); 
      for(var i:int = 0 ; i < states.numChildren; i++){ 
       var s:DisplayObject = DisplayObject(states.getChildAt(i));//can't add mouse listeners because the states are Shape instances 
       positions[s.name] = new Point(s.x,s.y);//store the positions in a hash to get the state position by name 
      } 
      stage.addEventListener(MouseEvent.CLICK,handleClick); 
     } 
     private function handleClick(e:MouseEvent):void{ 
      if(e.target is Stage) restore(); 
      else blast(getObjectsUnderPoint(new Point(mouseX,mouseY))[0].name);//named shapes are stored in a sprite so use getObjetsUnderPoint 
     } 
     private function blast(name:String):void{ 
      var blastRadius:Number = stage.stageWidth+stage.stageHeight;//or some other number 
      var c:DisplayObject = states.getChildByName(name);//selected 
      for(var i:int = 0 ; i < states.numChildren; i++){ 
       var s:DisplayObject = states.getChildAt(i); 
       if(s != c){//everything else goes except this 
        var angle:Number = Math.atan2(s.y-c.y,s.x-c.x);//direction relative to the clicked state 
        var x:Number = s.x + (Math.cos(angle) * blastRadius);//get a position offset from the clicked state (blast centre) 
        var y:Number = s.y + (Math.sin(angle) * blastRadius);//outwards at a random angle 
        TweenLite.to(s,1+Math.random() * 2,{x:x,y:y});//tween with different speeds for a bit of depth 
       } 
      } 
     } 
     private function restore():void{ 
      for(var i:int = 0 ; i < states.numChildren; i++){ 
       var s:DisplayObject = DisplayObject(states.getChildAt(i)); 
       TweenLite.to(s,.5+Math.random() * .5,{x:positions[s.name].x,y:positions[s.name].y});//tween states back into the original positions 
      } 
     } 
     private function listChildren(d:DisplayObjectContainer):String{ 
      var result = 'parent: '+d.name+'\n\t'; 
      for(var i:int = 0 ; i < d.numChildren; i++){ 
       var c:DisplayObject = d.getChildAt(i); 
       result += '\tchild: '+c.name+'\n'; 
       if(c is DisplayObjectContainer) result += listChildren(DisplayObjectContainer(c)); 
      } 
      return result; 
     } 


    } 

} 

您也可以下载上面的类,改性fxgparser图书馆和国家FXG 01​​,看到正在运行的演示here 或者您可以使用SVG而不是FXG 。同样的开发商也有一个SvgParser库,你可以像这样:

svn export http://www.libspark.org/svn/as3/SvgParser 

您可以将您的文件。爱易保存为.svg文件。 下面是使用一个简单的例子US map from wikipedia

package { 
    import flash.display.*; 
    import flash.events.*; 
    import flash.geom.Point; 
    import flash.net.*; 
    import flash.utils.Dictionary; 

    import svgparser.SvgDisplay; 
    import com.greensock.*; 

    [SWF(width='1368', height='936', backgroundColor='#ffffff', frameRate='30')] 
    public class SVGTest extends Sprite { 

     private var states:Sprite;//container holding each state Shape 
     private var positions:Dictionary = new Dictionary();//original position to restore states to 

     public function SVGTest() { 
      addEventListener(Event.ADDED_TO_STAGE,init);//make sure we have the stage ready 
     } 
     private function init(e:Event):void{ 
      removeEventListener(Event.ADDED_TO_STAGE,init);//stage ready, load the svg 
      new URLLoader(new URLRequest("http://upload.wikimedia.org/wikipedia/commons/3/32/Blank_US_Map.svg")).addEventListener(Event.COMPLETE,svgLoaded); 
     } 
     private function svgLoaded(e:Event):void{//svg loaded 
      var map:SvgDisplay = addChild(new SvgDisplay(new XML(e.target.data))) as SvgDisplay;//use the parser 
      trace(listChildren(map));//quick debug of the maps display list 
      states = Sprite(map.getChildAt(0));//we want to access the main container 
      for(var i:int = 0 ; i < states.numChildren; i++){ 
       var s:DisplayObject = DisplayObject(states.getChildAt(i));//can't add mouse listeners because the states are Shape instances 
       positions[s.name] = new Point(s.x,s.y);//store the positions in a hash to get the state position by name 
      } 
      stage.addEventListener(MouseEvent.CLICK,handleClick); 
     } 
     private function handleClick(e:MouseEvent):void{ 
      if(e.target is Stage) restore(); 
      else blast(getObjectsUnderPoint(new Point(mouseX,mouseY))[0].name);//named shapes are stored in a sprite so use getObjetsUnderPoint 
     } 
     private function blast(name:String):void{ 
      var blastRadius:Number = stage.stageWidth+stage.stageHeight;//or some other number 
      for(var i:int = 0 ; i < states.numChildren; i++){ 
       var s:DisplayObject = states.getChildAt(i); 
       if(s.name != name){//everything else goes except this 
        var angle:Number = Math.random() * Math.PI * 2;//pick a random angle 
        var x:Number = s.x + Math.cos(angle) * blastRadius;//get a position offset from the clicked state (blast centre) 
        var y:Number = s.y + Math.sin(angle) * blastRadius;//outwards at a random angle 
        TweenLite.to(s,1+Math.random() * 2,{x:x,y:y});//tween with different speeds for a bit of depth 
       } 
      } 
     } 
     private function restore():void{ 
      for(var i:int = 0 ; i < states.numChildren; i++){ 
       var s:DisplayObject = DisplayObject(states.getChildAt(i)); 
       TweenLite.to(s,.5+Math.random() * .5,{x:positions[s.name].x,y:positions[s.name].y});//tween states back into the original positions 
      } 
     } 
     private function listChildren(d:DisplayObjectContainer):String{//recursively traverse a display list and list children names 
      var result = 'parent: '+d.name+'\n\t'; 
      for(var i:int = 0 ; i < d.numChildren; i++){ 
       var c:DisplayObject = d.getChildAt(i); 
       result += '\tchild: '+c.name+'\n'; 
       if(c is DisplayObjectContainer) result += listChildren(DisplayObjectContainer(c)); 
      } 
      return result; 
     } 

    } 

}