使用AS3动画bezier曲线的方法?

时间:2013-08-11 12:16:00

标签: actionscript-3 actionscript

我一直在努力寻找使用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秒,渲染滞后,你可以看到前一行,有没有办法摆脱它?

1 个答案:

答案 0 :(得分:1)

嗯。也许您应该发布使用过的TweenMax版本来正确调试问题。似乎有几个,一些使用异步调度的“更新”事件,一些使用一个enterframe监听器,从而确保每个帧都调用每个更新例程。因此,图形抖动可能发生在异步场景中。

关于其他问题:

  1. 是的,您必须重新绘制有问题的图形对象,这涉及调用graphics.clear()。看,Graphics对象是一个黑盒子实体,你不能直接到达曲线的控制点来以某种方式补间它。因此,为了更改曲线上的点,您必须重绘它。

  2. 一种更有效的方法是直接在Sprite上模拟补间,通过一个enterframe监听器和一个类似于Strong.easeOut的函数,用于补间以插入坐标。然后,您将摆脱TweenMax库中包含的所有额外框架,并将完全控制事件和代码流。然而,这是模拟yoyo行为,时间设置行为,帧率行为(你可以切换到“time = frame”方法,消除其中一个问题)和缓和行为的一些工作。 tweenNumbers将如下所示:


  3. 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(看到上一行),因此目标设备的视频子系统无法一次绘制多帧。