编辑:我附加了Flash文件,充满了绘图对象.
http://rapidshare.com/files/406497264/pather.fla.html
问题是:这些绘图对象是否可以通过AS3访问,或者我应该将它们转换为符号/任何必要的格式.请举几个AS示例.
谢谢!
解决方法
我已经看到了工作中的fla,没有cs5回家,但我明白你想要实现的目标.
我的方法是:
>运动路径:
从Flash CS4开始,您可以复制路径,并将其粘贴到Motion Tween上.这将类似于Classic 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,{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,ptArray[i+5]); } }
*注意:*此处未显示ptArray,因为它会浪费太多空间.
result并不是那么好.你可以看看fla,看看我的意思.
jsfl脚本可能会被更改,但我看到你强调了actionscript的用法,所以这也是不行的.
>使用AS3SWF在运行时反编译swf并访问形状:
Claus Wahlers开发了一个令人惊叹的as3库,名为as3swf,它允许flash / flex开发人员在运行时反编译swfs.这是一个awesome article解释
swfs内部形状的来龙去脉.已经写了很多exporters.
我刚刚复制了AS3ShapeExporter并将as3 draw命令更改为TweenLite代码.基本上我用快速补间将moveTo替换为使用bezier补间的常规补间和curveTo定位lineTo. 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来解析形状标签并吐出actionscript.
我传递给构造函数的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);\r",type,asColors,alphas.join(","),ratios.join(",asMatrix,spreadMethod,interpolationMethod,focalPointRatio.toString()); } else if (interpolationMethod != InterpolationMethod.RGB) { _actionScript += StringUtils.printf("graphics.beginGradientFill('%s','%s'\r);",interpolationMethod); } else if (spreadMethod != SpreadMethod.PAD) { _actionScript += StringUtils.printf("graphics.beginGradientFill('%s','%s');\r",spreadMethod); } else if (matrix != null) { _actionScript += StringUtils.printf("graphics.beginGradientFill('%s',asMatrix); } else { _actionScript += StringUtils.printf("graphics.beginGradientFill('%s',[%s]);\r",")); } } override public function beginBitmapFill(bitmapId:uint,repeat:Boolean = true,smooth:Boolean = false):void { var asMatrix:String = "null"; if (matrix != null) { asMatrix = "new Matrix(" + matrix.a + "," + matrix.ty + ")"; } if (smooth) { _actionScript += StringUtils.printf("// graphics.beginBitmapFill(%d,bitmapId,repeat,smooth); } else if (!repeat) { _actionScript += StringUtils.printf("// graphics.beginBitmapFill(%d,repeat); } else { _actionScript += StringUtils.printf("// graphics.beginBitmapFill(%d,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,thickness,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,"'" + joints + "'"); } else if(startCaps != null && startCaps != CapsStyle.ROUND) { _actionScript += StringUtils.printf("graphics.lineStyle(%f,"'" + startCaps + "'"); } else if(scaleMode != LineScaleMode.NORMAL) { _actionScript += StringUtils.printf("graphics.lineStyle(%f,(scaleMode == null ? "null" : "'" + scaleMode + "'")); } else if(pixelHinting) { _actionScript += StringUtils.printf("graphics.lineStyle(%f,pixelHinting.toString()); } else if(alpha != 1.0) { _actionScript += StringUtils.printf("graphics.lineStyle(%f,alpha); } else if(color != 0) { _actionScript += StringUtils.printf("graphics.lineStyle(%f,0x%06x);\r",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,x,y); //_actionScript += StringUtils.printf(_target+".x = %f;\r"+_target+".y = %f;\r",y); _actionScript += StringUtils.printf("shapeTimeline.append(new TweenLite("+_target+",0.001,{x:%f,y: %f}));\r",y); } override public function lineTo(x:Number,y:Number):void { //_actionScript += StringUtils.printf("graphics.lineTo(%f,"+_time+",y); } override public function curveTo(controlX:Number,controlY:Number,anchorX:Number,anchorY:Number):void { //_actionScript += StringUtils.printf("graphics.curveTo(%f,controlX,controlY,anchorX,anchorY); _actionScript += StringUtils.printf("shapeTimeline.append(new TweenLite("+_target+",{bezier:[{x:%f,y: %f},y: %f}]}));\r",anchorY); } } }
下载as3swf后,需要将此类保存在导出程序包中.
这是result.你可以下载它的fla以及生成代码的fla.
这是一个纯粹的动作版本,并且结果不错.
动画看起来很生涩,因为它使用相同的时间量来补间每个线段.有些较短,有些较长.您可以存储先前的位置并将其与当前位置一起使用来计算距离,并根据该位置为每个TweenLite实例生成一个体面.
也可以随心所欲地修改该类(比如你想使用Timer等)
更新
我有时间再修补一下.
我稍微更改了导出器,现在它还期望目标对象的最大距离.这将是选择的宽度或高度(所有线条),具体取决于哪一个更大(宽度与高度).存储先前的x和y值
并用于计算距离,然后该距离除以最大行程距离.这反过来用于缩放每个补间的时间.此外,我已将缓动设置为线性,因为默认(Quad.eaSEOut)添加到抖动中.时间不是很准确,但看起来是a bit better.更新了fla的here和here
更新的时间线代码:
import com.codeazur.as3swf.*; import com.codeazur.as3swf.tags.*; import com.codeazur.as3swf.exporters.*; this.loaderInfo.addEventListener(Event.COMPLETE,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); }
再次,随时修补.
更新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和设置.我刚刚注释了Text解析器,因为我们关注路径.注释掉的课程位于底部.
该库包含一个Path解析器,它被克隆并修改以获得一些动画代码:PathTween.as
您可能会认识到as3swf类中的一些变量.
以下是我添加的一些变量的一些解释:
> ID – 是静态的,是解析的Path数量的计数器,这意味着我们可以单独为每个路径设置动画
> CODE – static,包含每个路径实例的时间轴lite代码的导入代码,这是代码:)
> MAX_DISTANCE – 类似于as3swf方法,用于根据行进距离改变每个补间的时间
> TIME – 每个补间的通用时间,方便从课外设置
> TARGET – 将为每个路径递增的名称,并用作补间目标.
> _code,_distance,_x,_y,_timeScale – 与as3swf方法相同
> _timeRel – 每次的相对时间(例如,在调整之后)
此外,我已经做了一个quickfix,添加了一个默认的绕组,因为有时,.fxg文件中可能缺少winding属性并且会破坏解析器.
为了使用,您需要对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,PathTweenTracer,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,4);\r'+(target+i)+'.graphics.endFill();\raddChild('+(target+i)+');\r'; return result; }
这很简单:
>在PathTween中设置常量
>加载fxg
>一旦装好,就画出来.在绘图时,代码在后台生成
>一旦绘制完毕,将代码放入剪贴板.对于我的路径,我有大约11K的生成线,因此跟踪在这里不是一个好主意
>也只保留PathTween中的补间代码,我生成一些代码(getClips())来制作目标影片剪辑.您可以根据需要随意在PathTween中添加此类功能.
然后我打开了一个新的fla文件:
>粘贴已经在剪贴板中的剪辑(几千行代码)
>从“输出面板”复制代码并在“TweenPlugin.activate([BezierPlugin]);”之后粘贴它
到目前为止,as3swf很酷,一旦你准备好粘贴插画路径,
可能会更快,因为as3swf使用字节.
我喜欢FXG方法:
>您跳过粘贴的步骤
图形成fla,你只需保存一个
复制为FXG.你可以用一个fla来
只需生成所需的所有代码
更改fxg文件的路径
想要动画.
>每个路径都是单独解析的,因此更灵活一些.
>虽然它产生的代码比as3swf版本,立方贝塞尔曲线,弧线更多
和其他曲线分解为lineTo命令,这些命令使动画均匀一点.
这实际上很有趣,有个别的时间表,所以我制作了另一个副本,吸引了一些
俗气的痕迹成为位图数据.
Here是PathTweenTracer类,与前一个类一样,将它放在解析器包中.
同样,需要在FxgFactory中更新PARSERS常量:
private static const PARSERS:Array = [ Graphic,RichText ];
timeline代码几乎相同.
result看起来不错(source)
以下是生成的动画的一些屏幕截图:
FXG方法更适合这个问题(‘使用纯动作脚本,如何在不使用预定义的运动参考线的情况下在每条线后移动符号?’)
至于嵌套问题(‘这些绘图对象是否可以通过AS3访问,或者我应该将它们转换为符号/任何必要的格式?’):
正如@Casey所提到的,一旦设置完就无法访问图形.使用更新的Graphics API,您可以将图形从一个Graphics实例复制到另一个,但不会公开命令.我记得Tink在Flash Player 10之前有something方式,但我不知道它的进展是什么.
HTH