Существует библиотека FxgParser, но она, похоже, не выводит имена состояний, если они помечены как атрибут d:userLabel
в файле .fxg. Однако вы можете изменить источник, чтобы исправить это.
Вот как ::
Редактировать fxgparser.parser.Path.as затем добавить это пространство имен в верхней части класса:
public static const aab:Namespace = new Namespace("aab", "http://ns.adobe.com/fxg/2008/dt");
затем в конце метода синтаксического анализа() Добавить :
target.name = [email protected]::userLabel;
в Illustrator CS6, кажется, добавить атрибут userLabel, а не идентификатор или что-то еще и FxgParser по умолчанию игнорирует это.
код будет очень похож на выше:
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 here и увидеть бегущую демо here В качестве альтернативы вы можете использовать SVG вместо FXG .The же разработчик также имеет SvgParser библиотеку, которую вы можете получить так:
svn export http://www.libspark.org/svn/as3/SvgParser
вы можете легко сохранить ваш .ai файл как .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;
}
}
}
В Заявке Flex вам нужны отдельные активы для каждой карты части, если вы хотите, чтобы манипулировать ими по-разному. Или вам придется делать некоторую растровую обработку, которая просто звучит как очень сложный маршрут. – JeffryHouser
Благодарю вас за предложение! Я уже начал спускаться по этой дороге ... :( –