现在的位置: 首页 > 综合 > 正文

利用Degrafa框架在FLEX中动态显示和操作SVG文档

2013年09月10日 ⁄ 综合 ⁄ 共 7489字 ⁄ 字号 评论关闭

 

利用degrafa框架在FLEX中动态显示和操作SVG文档
Degrafa框架已经非常接近在FLEX中动态显示和操作SVG文档了,通过一些简单的转换, 基本上能够实现对SVG图形进行显示和操作。这样大量的SVG图形资源就可以直接在FLEX应用程序中使用了。
 
基本思路如下:
       在MXML添加degrafa Surface对象, 读取SVG文档, 将其中的图形表示为degrafa图形对象, 动态添加到Surface中. 然后通过对象ID可以操作这些图形元素。
       由于SVG文档为XML格式, 可以方便的读取这些图形元素.
 
首先在MXML中增加degrafa surface作为显示图形的画布
              <degrafa:Surface id="surface1" x="0" y="0" >
           </degrafa:Surface>
 
然后在装载SVG图形文件后遍历其图形对象
 
 // A recursive function that reaches every element in an XML tree
              private    static function searchPath( node:XML ):void
              {
                     // Loop over all of the child elements of the node
                   for each ( var element:XML in node.elements( ) )
                   {
                          if(element.name().toString() == (svgNameSpace + "::path"))
                          {
                                var newPath:SvgPath = new SvgPath(element, ct);
                                newPath.show();
                         }
              ………………
注意到为每个SVG对象建立了一个相应的FLEX对象,其父类为一个图形类SvgGraphic, 然后派生出SvgRect, SvgPath等具体的子类。每个子类负责完成自己的属性设置和显示操作。
例如SvgPath在创建时读取了相应节点的属性, 包括fill, stroke等
public function SvgPath(element:XML, container:Surface):void
              {
                     surface = container;
                    
                     for each ( var attr:XML in element.attributes() )
                     {
                            //Alert.show(attr.name().toString());
                          switch(attr.name().toString())
                          {
                                 case "id":
                                 id = attr.toString();
                                 //Alert.show(id);
                                 break;
                                
                                 case "d":
                                 data = attr.toString();
                                 break;
                                
                                 case "fill":
                                 fillColor = attr.toString();
                                 break;
                                
                                 case "fill-opacity":
                                 fillAlpha = Number(attr.toString());
                                 break;
                                
                                 case "stroke":
                                 strokeColor = attr.toString();
                                 break;
                                
                                 case "stroke-opacity":
                                 strokeAlpha = Number(attr.toString());
                                 break;
                                
                                 case "stroke-width":
                                 strokeWidth = Number(attr.toString());
                                 break;
                                
                                 case "transform":
                                 transformStr = attr.toString();
                                 break;
             
                                 case "style":
                                 style = attr.toString();
                                 break;
                                
                                 default:
                                 break;
                          }
                     }
                    
                     if(id == null)
                            id = "Path_" + (Math.random()*1000000).toString();
 
                     if(style != null) //style on high priority
                            setByStyle();
              }
 
然后在显示时创建相应的degrafa对象, 并应用这些属性
              public function show():void
              {
                     try
                     {
                            //Create new group for transform
                            group = new GeometryGroup();
                            group.target = surface;
                            group.id = "Group_" + id;
                            surface.graphicsCollection.addItem(group);
                           
                            //Create new objects
                            dgfObject = new Path(null);
                            dgfObject.id = id;
                            dgfObject.data = data;
             
                            dgfObject.fill = getFillObject();
                            dgfObject.stroke = getStrokeObject();
                           
                            //add to geometrygroup
                            group.geometryCollection.addItem(dgfObject);
                           
                            //Transform
                            var matrix:Matrix = getTransformMatrix();
                                  
                            if(matrix != null)
                                   group.transform.matrix = matrix;
                     }
                     catch(error:Error)
                     {
                            Alert.show(error.message);
                     }
                           
                     //show update
                     //group.draw(null,null);
              }
 
其它普通的图形对象也类似实现, 目前可以支持Rect, Line, Path, Circle, Ellipse, PolyLine, Polygon, Image, Text和Use。
对Stroke和Fill对象,在degrafa的实现必须添加到特殊的位置进行使用, 因此对每个SVG对象使用Fill和Stroke属性转换对象,添加到全局的笔画或填充组中,然后对图形进行设置。目前可以支持普通,线性,圆形和图形笔画和填充。
 
protected function getStrokeObject():IGraphicsStroke
              {
                     if(strokeColor == null)
                            return addNewSolidStroke();
                     else if(strokeColor.substr(0,3) == "url")
                            return getStrokeFromCollection();
                     else
                            return addNewSolidStroke();
              }
             
              protected function addNewSolidStroke():IGraphicsStroke
              {
                     var newSolidStroke:SolidStroke = new SolidStroke();
                     newSolidStroke.id = "SolidStroke_" + id;
                     newSolidStroke.alpha = strokeAlpha;
                     newSolidStroke.weight = strokeWidth;
                    
                     if(strokeColor == null)
                            newSolidStroke.color = null;
                     else
                            newSolidStroke.color = Number("0x" + strokeColor.substr(1));
                           
                     surface.strokeCollection.addItem(newSolidStroke);
                           
                     return newSolidStroke;
              }
 
SVG中的变换种类很多, 包括平移,旋转,歪斜(SKEW)和矩阵, 所有的变换都可以用矩阵变换表示, 矩阵的变换可以转换为Degrafa矩阵对象,然后应用到图形上
 
protected function getTransformMatrix():Matrix
              {
                     if(transformStr == null)
                            return null;
                                  
                     if(transformStr.substr(0, 6)!="matrix")
                            return null;
                           
                     var startIndex:int = transformStr.indexOf("(");
                     var endIndex:int = transformStr.indexOf(")");
                           
                     var str:String = transformStr.substr(startIndex + 1, endIndex - startIndex - 1);
                           
                     var matrixData:Array = str.split(",");
                     var matrix:Matrix = new Matrix();      
                                  
                     matrix.a=matrixData[0];
                     matrix.b=matrixData[1];
                     matrix.c=matrixData[2];
                     matrix.d=matrixData[3];
                     matrix.tx=matrixData[4];
                     matrix.ty=matrixData[5];
                           
                     return matrix;
              }
 
通过这些转换, 可以将简单的SVG图形动态显示在FLEX中,与其它SVG显示程序(例如INKSCAPE或ASV,,FIREFOX)中的效果基本保持一致。但由于SVG标准本身比较复杂,需要相当大的工作量才能覆盖全部的SVG标准。其中包括:
l         SVG脚本
l         SVG Group
l         SVG动画
l         复杂的多层次坐标变换等
 
另外由于degrafa在文本显示中的局限性(目前degrafa利用TEXTBOX显示文本),基本无法实现文本的高级操作,例如旋转等。

抱歉!评论已关闭.