代码之家  ›  专栏  ›  技术社区  ›  Jauzsika

围绕图形对象移动符号

  •  3
  • Jauzsika  · 技术社区  · 15 年前

    我已经从adobeillustrator文档导入了很多路径到flash文件中。路径作为场景中的图形对象存在。使用纯actionscript,如何在每条线之后移动符号,而不使用预定义的运动指南。

    编辑:我附加了一个Flash文件,里面全是图形对象。

    http://rapidshare.com/files/406497264/pather.fla.html

    谢谢!

    3 回复  |  直到 15 年前
        1
  •  9
  •   Adaline Simonian    8 年前

    好问题+1

    我在工作中见过佛罗里达州,家里没有cs5,但我理解你想要达到的目标。

    1. :

    由于flashcs4,你可以复制一条路径,并将其粘贴到一个运动中间层。这将类似于经典的Tween的运动指南功能。这其中有不少问题:

    • 您可能需要手动执行剪切/粘贴操作
    • 并非所有路径都可以粘贴到运动上
    • 您可以使用AnimationFactory类并添加一个目标,但问题是 目标正在设置动画,您无法对其进行actionscript控制。你可以设置一个计时器 在AnimationFactory运动的持续时间内,但会变得很麻烦。

    显然这是不可能的。

    1. :

      我偶然发现这个很方便 jsfl script by ericlin 它遍历舞台上选定的所有形状。如果选择路径并运行脚本(只需双击jsfl文件),就会得到解析后的坐标。

    我做了一个简单的测试 TweenLite

    import com.greensock.*;
    import com.greensock.easing.*;
    import com.greensock.plugins.*;
    
    TweenPlugin.activate([BezierPlugin]);
    
    graphics.lineStyle(0.05);
    var index:int = 0;
    var ball:Sprite = new Sprite();
    ball.graphics.beginFill(0x009900,.75);ball.graphics.drawCircle(-2,-2,4);ball.graphics.endFill();
    addChild(ball);
    
    drawLines();
    
    function drawLines():void{
        var t:Number = .01;
        var timeline:TimelineLite = new TimelineLite();
        var i:int = index;
        for(index; index <= ptArray.length; index += 12){
            timeline.append( new TweenLite(ball, t, {x:ptArray[i],y:ptArray[i+1]}) );
            timeline.append( new TweenLite(ball, t, {bezier:[{x:ptArray[i+2], y:ptArray[i+3]}, {x:ptArray[i+4], y:ptArray[i+5]}]}) );
            this.graphics.moveTo(ptArray[i], ptArray[i+1]);
            this.graphics.curveTo(ptArray[i+2], ptArray[i+3], ptArray[i+4], ptArray[i+5]);
            i += 6;
            timeline.append( new TweenLite(ball, t, {x:ptArray[i],y:ptArray[i+1]}) );
            timeline.append( new TweenLite(ball, t, {bezier:[{x:ptArray[i+2], y:ptArray[i+3]}, {x:ptArray[i+4], y:ptArray[i+5]}]}) );
            this.graphics.moveTo(ptArray[i], ptArray[i+1]);
            this.graphics.curveTo(ptArray[i+2], ptArray[i+3], ptArray[i+4], ptArray[i+5]);
        }
    }
    

    *注意:*此处不显示ptArray,因为它会浪费太多空间。 这个 result 那不是很好吗。你可以看看这个房间 fla 明白我的意思。 jsfl脚本可以修改,但是我看到你强调了actionscript的用法,所以这也是一个禁忌。

    1. 使用AS3SWF在运行时反编译swf并访问形状 :

    Claus Wahlers 开发了一个惊人的as3库,名为 as3swf 它允许flash/flex开发人员在运行时反编译swfs。这是一个 awesome article 解释 exporters 已经写好了。

    AS3ShapeExporter 并将as3 draw命令更改为TweenLite代码。基本上我用一个快速的tween-to-position,lineTo,来代替moveTo,用一个bezier tween来代替常规tween和curveTo。Tween-Lite的bezier插件幸运地使用了二次bezier,就像curveTo一样。

    import com.codeazur.as3swf.*;
    import com.codeazur.as3swf.tags.*;
    import com.codeazur.as3swf.exporters.*;
    
    this.loaderInfo.addEventListener(Event.COMPLETE, completeHandler);
    
    function completeHandler(e:Event):void {
        var swf:SWF = new SWF(this.loaderInfo.bytes);//new SWF(URLLoader(e.target).data as ByteArray);
        var doc:AS3ShapeTweenLiteExporter = new AS3ShapeTweenLiteExporter(swf,"ball",.01);
        // Loop over all tags
        for (var i:uint = 0; i < swf.tags.length; i++) {
            var tag:ITag = swf.tags[i];
            // Check if tag is a DefineShape
            if (tag is TagDefineShape) {
              // Export shape tween
              TagDefineShape(tag).export(doc);
    
            }
        }
        trace(doc.actionScript);
    }
    

    基本上,我加载swf,一旦它准备好了,我就把它的字节传递给as3swf,并使用as3shapeetweenliteexporter来解析形状标记和输出actionscript。 我传递给构造函数的3个参数是:swf实例、tween目标的名称和每个tween的时间。

    下面是我的黑客课程的样子:

    package com.codeazur.as3swf.exporters
    {
        import com.codeazur.as3swf.SWF;
        import com.codeazur.utils.StringUtils;
    
        import flash.display.CapsStyle;
        import flash.display.InterpolationMethod;
        import flash.display.JointStyle;
        import flash.display.LineScaleMode;
        import flash.display.SpreadMethod;
        import flash.geom.Matrix;
        import com.codeazur.as3swf.exporters.core.DefaultShapeExporter;
    
        public class AS3ShapeTweenLiteExporter extends DefaultShapeExporter
        {
            protected var _actionScript:String;
            protected var _target:String;
            protected var _time:Number;
    
            public function AS3ShapeTweenLiteExporter(swf:SWF,target:String,time:Number) {
                super(swf);
                _target = target;
                _time = time;
            }
    
            public function get actionScript():String { return _actionScript; }
    
            override public function beginShape():void {
                _actionScript = "import com.greensock.*;\rimport com.greensock.plugins.*;\r\rTweenPlugin.activate([BezierPlugin]);\r\rvar shapeTimeline:TimelineLite = new TimelineLite()\r";
            }
    
            override public function beginFills():void {
                //_actionScript += "// Fills:\rgraphics.lineStyle();\r";
            }
    
            override public function beginLines():void {
                //_actionScript += "// Lines:\r";
            }
    
            override public function beginFill(color:uint, alpha:Number = 1.0):void {
                if (alpha != 1.0) {
                    _actionScript += StringUtils.printf("graphics.beginFill(0x%06x, %f);\r", color, alpha);
                } else {
                    _actionScript += StringUtils.printf("graphics.beginFill(0x%06x);\r", color);
                }
            }
    
            override public function beginGradientFill(type:String, colors:Array, alphas:Array, ratios:Array, matrix:Matrix = null, spreadMethod:String = SpreadMethod.PAD, interpolationMethod:String = InterpolationMethod.RGB, focalPointRatio:Number = 0):void {
                var asMatrix:String = "null";
                if (matrix != null) {
                    asMatrix = "new Matrix(" +
                        matrix.a + "," +
                        matrix.b + "," +
                        matrix.c + "," +
                        matrix.d + "," +
                        matrix.tx + "," +
                        matrix.ty + ")";
                }
                var asColors:String = "";
                for (var i:uint = 0; i < colors.length; i++) {
                    asColors += StringUtils.printf("0x%06x", colors[i]);
                    if (i < colors.length - 1) { asColors += ","; }
                }
                if (focalPointRatio != 0.0) {
                    _actionScript += StringUtils.printf("graphics.beginGradientFill('%s', [%s], [%s], [%s], %s, '%s', '%s', %s);\r",
                        type,
                        asColors,
                        alphas.join(","),
                        ratios.join(","),
                        asMatrix,
                        spreadMethod,
                        interpolationMethod,
                        focalPointRatio.toString());
                } else if (interpolationMethod != InterpolationMethod.RGB) {
                    _actionScript += StringUtils.printf("graphics.beginGradientFill('%s', [%s], [%s], [%s], %s, '%s', '%s'\r);",
                        type,
                        asColors,
                        alphas.join(","),
                        ratios.join(","),
                        asMatrix,
                        spreadMethod,
                        interpolationMethod);
                } else if (spreadMethod != SpreadMethod.PAD) {
                    _actionScript += StringUtils.printf("graphics.beginGradientFill('%s', [%s], [%s], [%s], %s, '%s');\r",
                        type,
                        asColors,
                        alphas.join(","),
                        ratios.join(","),
                        asMatrix,
                        spreadMethod);
                } else if (matrix != null) {
                    _actionScript += StringUtils.printf("graphics.beginGradientFill('%s', [%s], [%s], [%s], %s);\r",
                        type,
                        asColors,
                        alphas.join(","),
                        ratios.join(","),
                        asMatrix);
                } else {
                    _actionScript += StringUtils.printf("graphics.beginGradientFill('%s', [%s], [%s], [%s]);\r",
                        type,
                        asColors,
                        alphas.join(","),
                        ratios.join(","));
                }
            }
    
            override public function beginBitmapFill(bitmapId:uint, matrix:Matrix = null, repeat:Boolean = true, smooth:Boolean = false):void {
                var asMatrix:String = "null";
                if (matrix != null) {
                    asMatrix = "new Matrix(" +
                        matrix.a + "," +
                        matrix.b + "," +
                        matrix.c + "," +
                        matrix.d + "," +
                        matrix.tx + "," +
                        matrix.ty + ")";
                }
                if (smooth) {
                    _actionScript += StringUtils.printf("// graphics.beginBitmapFill(%d, %s, %s, %s);\r", bitmapId, asMatrix, repeat, smooth);
                } else if (!repeat) {
                    _actionScript += StringUtils.printf("// graphics.beginBitmapFill(%d, %s, %s, %s);\r", bitmapId, asMatrix, repeat);
                } else {
                    _actionScript += StringUtils.printf("// graphics.beginBitmapFill(%d, %s, %s, %s);\r", bitmapId, asMatrix);
                }
            }
    
            override public function endFill():void {
                _actionScript += "graphics.endFill();\r";
            }
    
            override public function lineStyle(thickness:Number = NaN, color:uint = 0, alpha:Number = 1.0, pixelHinting:Boolean = false, scaleMode:String = LineScaleMode.NORMAL, startCaps:String = null, endCaps:String = null, joints:String = null, miterLimit:Number = 3):void {
                /*
                if (miterLimit != 3) {
                    _actionScript += StringUtils.printf("graphics.lineStyle(%f, 0x%06x, %f, %s, %s, %s, %s, %f);\r",
                        thickness, color, alpha, pixelHinting.toString(),
                        (scaleMode == null ? "null" : "'" + scaleMode + "'"),
                        (startCaps == null ? "null" : "'" + startCaps + "'"),
                        (joints == null ? "null" : "'" + joints + "'"),
                        miterLimit);
                } else if (joints != null && joints != JointStyle.ROUND) {
                    _actionScript += StringUtils.printf("graphics.lineStyle(%f, 0x%06x, %f, %s, %s, %s, %s);\r",
                        thickness, color, alpha, pixelHinting.toString(),
                        (scaleMode == null ? "null" : "'" + scaleMode + "'"),
                        (startCaps == null ? "null" : "'" + startCaps + "'"),
                        "'" + joints + "'");
                } else if(startCaps != null && startCaps != CapsStyle.ROUND) {
                    _actionScript += StringUtils.printf("graphics.lineStyle(%f, 0x%06x, %f, %s, %s, %s);\r",
                        thickness, color, alpha, pixelHinting.toString(),
                        (scaleMode == null ? "null" : "'" + scaleMode + "'"),
                        "'" + startCaps + "'");
                } else if(scaleMode != LineScaleMode.NORMAL) {
                    _actionScript += StringUtils.printf("graphics.lineStyle(%f, 0x%06x, %f, %s, %s);\r",
                        thickness, color, alpha, pixelHinting.toString(),
                        (scaleMode == null ? "null" : "'" + scaleMode + "'"));
                } else if(pixelHinting) {
                    _actionScript += StringUtils.printf("graphics.lineStyle(%f, 0x%06x, %f, %s);\r",
                        thickness, color, alpha, pixelHinting.toString());
                } else if(alpha != 1.0) {
                    _actionScript += StringUtils.printf("graphics.lineStyle(%f, 0x%06x, %f);\r", thickness, color, alpha);
                } else if(color != 0) {
                    _actionScript += StringUtils.printf("graphics.lineStyle(%f, 0x%06x);\r", thickness, color);
                } else if(!isNaN(thickness)) {
                    _actionScript += StringUtils.printf("graphics.lineStyle(%f);\r", thickness);
                } else {
                    _actionScript += "graphics.lineStyle();\r";
                }
                */
            }
    
            override public function moveTo(x:Number, y:Number):void {
                //_actionScript += StringUtils.printf("graphics.moveTo(%f, %f);\r", x, y);
                //_actionScript += StringUtils.printf(_target+".x = %f;\r"+_target+".y = %f;\r", x, y);
                _actionScript += StringUtils.printf("shapeTimeline.append(new TweenLite("+_target+",0.001,{x:%f,y: %f}));\r", x, y);
            }
    
            override public function lineTo(x:Number, y:Number):void {
                //_actionScript += StringUtils.printf("graphics.lineTo(%f, %f);\r", x, y);
                _actionScript += StringUtils.printf("shapeTimeline.append(new TweenLite("+_target+","+_time+",{x:%f,y: %f}));\r", x, y);
            }
    
            override public function curveTo(controlX:Number, controlY:Number, anchorX:Number, anchorY:Number):void {
                //_actionScript += StringUtils.printf("graphics.curveTo(%f, %f, %f, %f);\r", controlX, controlY, anchorX, anchorY);
                _actionScript += StringUtils.printf("shapeTimeline.append(new TweenLite("+_target+","+_time+",{bezier:[{x:%f,y: %f},{x:%f,y: %f}]}));\r", controlX, controlY, anchorX, anchorY);
            }
        }
    }
    

    result . 你可以下载它的 fla fla 为此生成了代码。

    这是一个纯actionscript版本,结果不错。

    也可以根据需要随意修改这个类(比如说你想改用计时器等等)

    我有时间再把这件事修改一下。 用来计算距离,然后除以最大行驶距离。这反过来又被用来衡量时间上的每一个吐温。另外,我还将松弛设置为线性,因为默认值(Quad.easeOut)增加了抖动。时间不太准确,但看起来 a bit better . 更新佛罗里达州 here here

    更新的时间线代码:

    import com.codeazur.as3swf.*;
    import com.codeazur.as3swf.tags.*;
    import com.codeazur.as3swf.exporters.*;
    
    this.loaderInfo.addEventListener(Event.COMPLETE, completeHandler);
    
    function completeHandler(e:Event):void {
        var swf:SWF = new SWF(this.loaderInfo.bytes);//new SWF(URLLoader(e.target).data as ByteArray);
        var doc:AS3ShapeTweenLiteExporter = new AS3ShapeTweenLiteExporter(swf,"ball",1,300);
        // Loop over all tags
        for (var i:uint = 0; i < swf.tags.length; i++) {
            var tag:ITag = swf.tags[i];
            // Check if tag is a DefineShape
            if (tag is TagDefineShape) {
              // Export shape tween
              TagDefineShape(tag).export(doc);
    
            }
        }
        trace(doc.actionScript);
        System.setClipboard(doc.actionScript);
    } 
    

    这个 updated exporter

    再一次,请随意修补。

    1. 使用AS3解析直接从Illustrator导出的FXG

    由于Illustrator CS4,您可以通过 文件>保存副本>选择FXG文件类型 这是你的答案 fxg file 我用过。

    令人惊叹的Lib Spark包含 FXG Parser . 还有一个SVGParser,但现在我只玩了fxg。

    因此,第一步是下载库:

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

    您可以使用这个示例,因为您使用的是flashcs5。解析器使用 TLF 用于文本。我没有费心下载整个flex4sdk来获得swc和设置。我刚刚注释掉了文本解析器,因为我们关心的是路径。注释掉的类位于底部。

    该库包含一个 Path PathTween.as 您可能会识别as3swf类中的一些变量。 以下是我添加的一些变量的一些解释:

    • 代码-静态,包含每个路径实例的导入代码+时间线精简代码,这是代码:)
    • 时间-一个通用的时间为每个吐温,方便设置从课堂外
    • 目标-将为每个路径递增并用作中间目标的名称。
    • _代码、\u距离、\u x、\u y、\u时间刻度-与as3swf方法相同
    • _timeRel—每次的相对时间(例如,调整后)

    另外,我做了一个快速修复,添加了一个默认绕组,因为有时 .fxg文件中可能缺少属性,这会中断解析器。

    为了使用,您需要对 FxgFactory.as文件 因此它使用PathTween解析器而不是默认的Path类。

    private static const PARSERS:Array = [  Graphic , Group , Library, 
                                                    Path , Ellipse, Rect, Line, 
                                                    BitmapGraphic, BitmapImage, 
                                                    TextGraphic, RichText ];
    

    变成:

    private static const PARSERS:Array = [  Graphic , Group , Library, 
                                                    PathTweenTracer , Ellipse, Rect, Line, 
                                                    BitmapGraphic, BitmapImage, 
                                                    TextGraphic, RichText ];
    

    import fxgparser.*
    import fxgparser.parser.*;
    
    var fxgurl:String = "fingerprint.fxg";
    var fxgSprite:FxgDisplay;
    
    var loader:URLLoader = new URLLoader( new URLRequest( fxgurl ) );
        loader.addEventListener( Event.COMPLETE , displayData );
    
    //some setup
    PathTween.MAX_DISTANCE = 360;//change this to fit your shape's largest dimension(width || height)
    PathTween.TIME = 2;//change this to your needs
    PathTween.TARGET = "ball";//a name of a target clip that will be incremented for each move,line,curve
    
    
    function displayData( e:Event ):void {
        var fxgxml:XML = XML( e.currentTarget.data );
    
        fxgSprite = new FxgDisplay( fxgxml );   //parse SVG
        System.setClipboard(PathTween.CODE);
        //make some clips for the tester
        trace(getClips());
    
        addChild( fxgSprite );  
    }
    
    function getClips():String {
        var result:String = 'this.filters = [new GlowFilter(0x00ff99)]\r';
        var clipsNum:int = PathTween.ID;
        var target:String = PathTween.TARGET;
        for(var i:int = 0 ; i < clipsNum ; i++)
            result += 'var '+(target+i)+':Sprite = new Sprite();\r'+(target+i)+'.graphics.beginFill(0x00ff00);\r'+(target+i)+'.graphics.drawCircle(-2,-2,4);\r'+(target+i)+'.graphics.endFill();\raddChild('+(target+i)+');\r';
        return result;
    }
    

    这相当简单:

    • 在PathTween中设置常量
    • 加载fxg
    • 一旦装好了,就画出来。绘图时,代码在后台生成
    • 一旦画好了,就把代码放到剪贴板上。对于我的路径,我有大约11K条生成的线,所以在这里跟踪不是一个好主意
    • 在PathTween中只保留tweening代码,我会生成一些代码( )在这里制作目标影片。您可以根据需要在PathTween中随意添加这种功能。

    你可以看到 result fla .

    到目前为止,as3swf是很酷的,一旦你已经准备好了fla与粘贴插画路径, 我喜欢FXG方法的地方:

    • 你跳过了粘贴 复制为FXG。你可以用一个fla 生成所有需要的代码,只需
    • 每个路径都是单独解析的,所以这更灵活一些。
    • 虽然它生成的代码比as3swf版本多,但是立方贝塞尔曲线、圆弧

    这真的很有趣,有个人的时间表,所以我做了另一个副本,画了一些 奇斯跟踪到位图数据。

    Here 的PathTweenTracer类,与前面一样,将其放入解析器包中。 再说一次 分析器

    路径中心,椭圆,矩形,直线,
    位图,位图,
    TextGraphic,RichText];
    

    这个 timeline 这个 result source )

    以下是生成的动画的一些屏幕截图:

    fxg anim 1

    fxg anim 2

    fxg anim 3

    注释掉 TextGraphic.as

    至于嵌套问题('这些图形对象是否可以通过AS3访问,或者我应该将它们转换为符号/任何必要的格式?'):

    Tink something 比flashplayer10早很多,但我不知道这方面有什么进展。

        2
  •  2
  •   gMale    15 年前

    1. 在屏幕上移动符号
    2. 确定运动路径


    在屏幕上移动符号

    stage.addEventListener(Event.ENTER_FRAME, doMotion);
    
    ...
    
    public function doMotion(event:Event):void {
       //animate along the path
       targetSymbol.x = someNewValue;
       targetSymbol.y = someNewValue;
    }    
    

    另一种方法(我承认经常使用的方法)是使用计时器触发动画调用,在本例中是“domation”函数。例如:

    var FPS:Integer = 30; //frames per second (approx)
    
    var animationTimer:Timer = new Timer(1/FPS * 1000); //converted from SEC to MS
    animationTimer.addEventListener(TimerEvent.TIMER, doMotion);
    animationTimer.start();
    


    确定运动路径

    棘手的部分是确定运动路径。从你的描述中没有办法知道最好的方法。但是,试一试,似乎所有的路都是直线。

    - -
    如果是这样,则可以使用 y , 宽度 , 高度 旋转

    . 然后把这些小数字加到 y 每次迭代中的值。你也可以通过调整你的运动的“速度”来增加像“放松”这样的效果,使它开始和停止的“柔和”

    由于这些行被导入到flash中,因此可以为它们指定实例名称,以简化编码。或者,如果有太多的行,您可以遍历存储某种类型集合中所有行的所有显示对象。

    - 另一种方法 -

    我希望这些都能有所帮助,

        3
  •  1
  •   Casey    15 年前

    问题是:这些图形对象是否可以通过AS3访问,或者我应该将它们转换为符号/任何必要的格式。请举例说明。

    我不知道有什么方法可以直接访问AS3中的符号。据我所知,他们是他们的父母MovieClip的图形属性的元素。例如,您可以编写如下代码:

    var drawOnMe:Sprite = new Sprite();
    
    drawOnMe.graphics.beginFill(0xCC0000);
    drawOnMe.graphics.drawRect(0,0,100,100);
    drawOnMe.graphics.endFill();
    

    但是,一旦在drawinme.graphics对象上绘制了此形状,就不能再访问它了,因为它没有标识符。你的进口艺术品基本上是在同一条船上。

    由于无法访问艺术品,因此无法从导入的轮廓中获取点并沿路径设置符号动画。简言之,我真的不认为这是可以做到的。

    有关图形属性的详细信息:

    http://help.adobe.com/en_US/AS3LCR/Flash_10.0/