flash - 在图形对象周围移动符号

标签 flash actionscript-3

我已经将Adobe Illustrator文档中的许多路径直接导入到Flash文件中。路径在场景中作为“图形对象”存在。使用纯动作脚本,如何在不使用预定义的运动指南的情况下沿每行移动符号。

编辑:我已经附加了Flash文件,其中充满了图形对象。

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

问题是:这些图形对象是否可以通过AS3访问,还是应该将它们转换为符号/任何必要的格式?并请举一些AS示例。

谢谢!

最佳答案

好问题+1

我见过Fla在工作,没有CS5在家,但我了解您要达到的目标。

我的方法是:

  • 运动路径:

  • 从Flash CS4开始,您可以复制路径并将其粘贴到Motion Tween中。这将与“经典补间”的“运动指南”功能相似。这有很多问题:
  • 您可能需要手动执行剪切/粘贴
  • 并非所有路径都可以粘贴到运动
  • 您可以使用AnimationFactory类并添加目标,但是问题是
    目标是动画,您无法对其进行动作控制。您可以设置一个计时器
    在AnimationFactory动作期间,但变得麻烦。

  • 显然,这是一个禁忌。
  • 使用JSFL遍历IDE内内的路径:

    我偶然发现了这个非常方便的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脚本可以更改,但是我看到您强调了动作脚本的用法,所以这也不是不行。
  • 使用AS3SWF在运行时反编译swf并访问形状:

  • Claus Wahlers开发了一个惊人的as3库as3swf,它允许Flash / Flex开发人员在运行时反编译swfs。这是awesome article的解释
    swfs内部形状的来龙去脉。已经写了很多exporters

    我只是复制了AS3ShapeExporter并将as3绘制命令更改为TweenLite代码。基本上,我将moveTo替换为快速补间,以将lineTo替换为常规补间,将curveTo替换为bezier补间。 Tween Lite的BezierPlugin幸运地使用了二次贝塞尔曲线,就像curveTo一样。

    这是您需要粘贴到包含形状的fla中的代码:
    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,然后使用AS3ShapeTweenLiteExporter解析形状标签并吐出动作脚本。
    我传递给构造函数的3个参数是:swf实例,补间目标的名称和每个补间的时间。

    这是我被黑在一起的课程的样子:
    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);
            }
        }
    }
    

    下载as3swf之后,您需要将此类保存在导出程序包中。
    这是result。您可以下载其fla,也可以下载生成该代码的fla

    这是一个纯ActionScript版本,效果不错。

    动画看起来很生涩,因为它为每个线段使用了相同的时间进行补间。有些较短,而另一些较长。您可以存储先前的位置,并将其与当前位置一起使用以计算距离,并基于此为每个TweenLite实例生成一个体面的图像。
    也可以根据需要随意修改该类(例如您想使用Timer等等)。

    更新

    我有时间再修改一点。
    我稍微更改了导出器,现在它也期望目标对象可以移动最大距离。这将是所选内容的宽度或高度(所有行),具体取决于哪一个较大(宽度与高度)。先前的x和y值被存储
    并用于计算距离,然后将该距离除以行进的最大距离。依次使用它来缩放每个补间上的时间。另外,我将缓动设置为线性,因为默认值(Quad.easeOut)已添加到抖动中。计时不是很准确,但是看起来是a bit better。更新了fla的herehere

    更新的时间轴代码:
    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:

    同样,请随意修改。

    更新2:

    好的,这是另一种方法...
  • 使用AS3解析从Illustrator直接导出的FXG :

  • 从Illustrator CS4开始,您可以通过文件>保存副本>选择FXG文件类型将图形另存为FXG。
    这是我使用的fxg file

    日本再做一次:)
    惊人的Lib Spark包含FXG Parser。还有一个SVGParser,但目前我只玩过fxg。

    因此,第一步是下载该库:
    svn export http://www.libspark.org/svn/as3/FxgParser
    

    由于使用Flash CS5,因此使用示例可能会很好。解析器将TLF用于文本。我没有费心下载整个flex4 sdk来获取swc和设置。我只是注释掉了文本解析器,因为我们关心路径。注释掉的类在底部。

    该库包含一个Path解析器,可对其进行克隆和修改以获取一些动画代码:PathTween.as
    您可能会认识到as3swf类中的某些变量。
    这是我添加的一些变量的一些说明:
  • ID-是静态的,并且是解析的Path数量的计数器,这意味着我们可以为每个路径单独设置动画
  • CODE-静态,包含每个路径实例的导入代码+时间轴精简版代码,这是THE CODE :)
  • MAX_DISTANCE-与as3swf方法类似,此方法用于根据
  • 行驶的距离来更改每个补间的时间
  • TIME-每个补间的通用时间,方便从类
  • 外部设置
  • TARGET-每个路径的名称将递增,并用作补间目标。
  • _code,_distance,_x,_y,_timeScale-与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中,我生成一些代码( getClips())以在此处制作目标影片。随时根据需要在PathTween中添加此类功能。

  • 然后,我打开了一个新的fla文件,并:
  • 粘贴剪贴板中已经存在的剪辑(几千行代码)
  • 从“输出面板”复制了代码,并将其粘贴到“TweenPlugin.activate([BezierPlugin]);”之后

  • 您可以看到result并获取fla

    到目前为止,一旦您准备好带有粘贴的插图画家路径的fla,as3swf就会很酷,
    可能更快,因为as3swf使用字节。
    我喜欢FXG方法:
  • ,您将跳过粘贴
    图形成fla,您只需保存一个
    复制为FXG。你可以用一个fla来
    生成您需要的所有代码
    将路径更改为您的fxg文件
    想要动画。
  • 每个路径都是单独解析的,因此这有点灵活。
  • ,尽管它生成的代码比as3swf版本,立方贝塞尔曲线,弧形更多
    和其他曲线分成lineTo命令,使动画稍微平整。

  • 这实际上很有趣,而且有各自的时间表,所以我又制作了一个副本,画了一些
    俗气的痕迹进入位图数据。

    Here的PathTweenTracer类与之前的类一样,将其放在解析器包中。
    同样,需要在FxgFactory中更新 PARSERS 常量:
    private static const PARSERS:Array = [  Graphic , Group , Library, 
                                                    PathTweenTracer , Ellipse, Rect, Line, 
                                                    BitmapGraphic, BitmapImage, 
                                                    TextGraphic, RichText ];
    

    timeline代码几乎相同。
    result看起来不错(source)

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

    fxg anim 1

    fxg anim 2

    fxg anim 3

    注释掉TextGraphic.as

    FXG方法将更适合该问题(“使用纯动作脚本,如何在不使用预定义的运动向导的情况下沿每行移动符号?”)

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

    正如@Casey所提到的,设置完图形后就无法访问它们。使用更新的Graphics API,您可以将图形从一个Graphics实例复制到另一个Graphics实例,但这不会公开命令。我记得Tink在Flash Player 10之前就有了something,但是我不知道它的进展如何。

    高温超导

    关于flash - 在图形对象周围移动符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3170824/

    相关文章:

    flash - 对ActionScript 2实现Google Analytics(分析)跟踪的最佳方法是什么?

    sql - 使用 Like 选择的 ActionScript 和 SQLite 参数

    flash - 由于影片剪辑重叠导致的 AS3 MOUSE_OVER 问题

    javascript - 快速需要 Flash/Lightwindow 帮助

    flash - 有没有办法让Flash强制静态类型?

    javascript - 在客户端调整/裁剪图像大小的最佳方法是什么?

    javascript - 使用inner.html

    flash - 在 Adob​​e AIR/Actionscript 3.0 中录制 WAV - **问题**

    actionscript-3 - (简单的)Flex 3 应用程序需要什么版本的 Flash 播放器?

    android - 从 ActionScript3 中的 If 语句中跳出?