我一直在努力寻找使用AS3制作贝塞尔曲线动画的最佳方法。到目前为止,以下是最好的解决方案:
import flash.display.*;
import flash.display.Sprite;
import flash.geom.*;
import com.greensock.TweenMax;
import com.greensock.easing.*;
public class Waves extends MovieClip
{
public var piste:Number = stage.stageHeight;
public var piste2:Number = 0;
var a:Sprite = new Sprite();
var coord:Vector.<Number> = new Vector.<Number>();
var com:Vector.<int> = new Vector.<int>();
public function Waves()
{
addChild(a);
coord.push(0, 30);
com.push(1);
coord.push(260, piste, stage.stageWidth, 30);
com.push(3);
tweenNumbers();
}
public function tweenNumbers():void {
TweenMax.to(this, 0.45, {piste:piste2, repeat:-1, yoyo:true, immediateRender:true, ease:Expo.easeOut, onUpdate:draw});
}
public function draw():void {
coord[3] = piste;
a.graphics.clear();
a.graphics.lineStyle(1,0x990000,1);
a.graphics.drawPath(com, coord);
}
}
我真的必须使用graphics.clear来设置曲线动画吗?有更有效的方法吗?如果我补间时间超过1秒,渲染滞后,你可以看到前一行,有没有办法摆脱它?
答案 0 :(得分:1)
嗯。也许您应该发布使用过的TweenMax版本来正确调试问题。似乎有几个,一些使用异步调度的“更新”事件,一些使用一个enterframe监听器,从而确保每个帧都调用每个更新例程。因此,图形抖动可能发生在异步场景中。
关于其他问题:
是的,您必须重新绘制有问题的图形对象,这涉及调用graphics.clear()
。看,Graphics对象是一个黑盒子实体,你不能直接到达曲线的控制点来以某种方式补间它。因此,为了更改曲线上的点,您必须重绘它。
一种更有效的方法是直接在Sprite上模拟补间,通过一个enterframe监听器和一个类似于Strong.easeOut
的函数,用于补间以插入坐标。然后,您将摆脱TweenMax库中包含的所有额外框架,并将完全控制事件和代码流。然而,这是模拟yoyo行为,时间设置行为,帧率行为(你可以切换到“time = frame”方法,消除其中一个问题)和缓和行为的一些工作。 tweenNumbers
将如下所示:
var isYoyo:Boolean=false;
var currentFrame:int;
var maxFrame:int;
function easingFunction(frame:int,maxframe:int,a:Number,b:Number):Number {
var x:Number=Number(frame)/maxframe;
return a+(b-a)*(x*x*(3-2*x)); // 3x^2-2x^3, a double-easing Perlin function
// recreate your needed function here!
}
var piste1:Number=0; // storing start coordinate
private function tweenNumbers():void {
maxFrame=Math.round(0.45*stage.frameRate); // from seconds to frames
currentFrame=0;
isYoyo=false;
a.addEventListener(Event.ENTER_FRAME,onUpdate);
}
private function onUpdate(e:Event):void {
if (!isYoyo) {
currentFrame++;
if (currentFrame==maxFrame) isYoyo=true;
} else {
currentFrame--;
if (currentFrame==0) isYoyo=false;
} // advance time
coords[3]=easingFunction(currentFrame,maxFrame,piste1,piste2);
// tween the coords[3] manually
a.graphics.clear();
a.graphics.lineStyle(1,0x990000,1);
a.graphics.drawPath(com, coord);
// draw updated path
}
不保证脱钩,但通常会起作用。如果你将舞台帧率设置得太高,也可能发生desynch(看到上一行),因此目标设备的视频子系统无法一次绘制多帧。