好问题+1
我在工作中见过佛罗里达州,家里没有cs5,但我理解你想要达到的目标。
-
:
由于flashcs4,你可以复制一条路径,并将其粘贴到一个运动中间层。这将类似于经典的Tween的运动指南功能。这其中有不少问题:
-
您可能需要手动执行剪切/粘贴操作
-
并非所有路径都可以粘贴到运动上
-
您可以使用AnimationFactory类并添加一个目标,但问题是
目标正在设置动画,您无法对其进行actionscript控制。你可以设置一个计时器
在AnimationFactory运动的持续时间内,但会变得很麻烦。
显然这是不可能的。
-
:
我偶然发现这个很方便
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的用法,所以这也是一个禁忌。
-
使用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
再一次,请随意修补。
-
使用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
)
以下是生成的动画的一些屏幕截图:
注释掉
TextGraphic.as
至于嵌套问题('这些图形对象是否可以通过AS3访问,或者我应该将它们转换为符号/任何必要的格式?'):
Tink
有
something
比flashplayer10早很多,但我不知道这方面有什么进展。