4

有没有办法在不同的帧上获取 MovieClip(确实有名称)的宽度?我尝试使用.width.getBounds(null).width,但是,它们都只会给我当前帧的宽度。我试图做gotoAndStop(frameiwant),但信息似乎不正确,直到至少下一帧

我想立即获得框架的宽度,所以我不必等到下一帧的宽度。

4

4 回答 4

4

我能想到的唯一方法是在你的项目中有一个初始阶段,它将:

  1. 遍历时间轴中的所有帧。创建一个对象,该对象将保存有关该框架中子项的信息。它可以称为Frame
  2. 遍历该框架中添加到舞台的所有子项,并添加一个描述该子项的定义对象。描述可以根据您的需要是基本的或广泛的。我们可以称这个类为ObjectDefintion.

这个过程的缺点是您需要等待FRAME_CONSTRUCTED@Larusso 在他的回答中指出的事件。这意味着帧实际上必须在您能够获取有关其子项的信息之前完成渲染,这当然意味着您必须在此阶段遍历并渲染时间轴中的每一帧。为了缓解这个问题,您真正可以做的就是将其设置frameRate为较高的值,然后在完成对所有帧的评估后将其重新设置。

我已经设置了它并且效果很好 - 我将粘贴每个类并尝试解释它们的作用。

因此,对于您的文档类(或任何包含您想要查看的帧的 MovieClip),我有这个:

public class Main extends MovieClip
{

    private var _userFrameRate:int;
    private var _frames:Vector.<Frame> = new <Frame>[];


    public function Main()
    {
        _userFrameRate = stage.frameRate;
        stage.frameRate = 120;

        addEventListener(Event.FRAME_CONSTRUCTED, _assess);
    }


    public function getFrame(index:int):Frame
    {
        return _frames[index - 1];
    }


    private function _assess(e:Event):void
    {
        var frame:Frame = new Frame(this);
        _frames.push(frame);

        if(currentFrame === totalFrames)
        {
            removeEventListener(Event.FRAME_CONSTRUCTED, _assess);
            gotoAndStop(1);
            stage.frameRate = _userFrameRate;

            ready();
        }

        else play();
    }


    public function ready():void
    {
        // Start here.

        // There is a MovieClip on frame 10 with the instance name 'test'.
        // We can get the width of it like this.
        trace( getFrame(10).define("test").property("width") );
    }

}

这基本上初始化了我们将在 MovieClip 中运行每个帧并评估其子项的阶段。该ready()方法用作代码后评估的入口点。

接下来我们有一个Frame类,它用于保存与框架相关的孩子的信息:

public class Frame
{

    private var _main:Main;
    private var _content:Object = {};


    public function Frame(main:Main)
    {
        _main = main;
        update();
    }


    public function update():void
    {
        _content = {};
        for(var i:int = 0; i < _main.numChildren; i++)
        {
            var target:DisplayObject = _main.getChildAt(i);

            // This will be explained below.
            var definition:ObjectDefinition = new ObjectDefinition(target, "x", "y", "width", "height");

            _content[target.name] = definition;
        }
    }


    public function define(name:String):ObjectDefinition
    {
        return _content[name];
    }

}

这很简单——你给它一个引用,Main这样它就可以检查每一帧中存在的孩子。

该类ObjectDefinition也非常简单,纯粹充当您要跟踪框架的每个子项的数据的存储库:

public class ObjectDefinition
{

    private var _definition:Object = {};


    public function ObjectDefinition(target:DisplayObject, ...properties)
    {
        for each(var i:String in properties)
        {
            _definition[i] = target[i];
        }
    }


    public function property(property:String):*
    {
        return _definition[property];
    }

}

您会注意到构造函数接受将要定义的目标 DisplayObject,以及您希望作为字符串跟踪的任意数量的属性(参见上文中Frame的实现)。

完成后,您可以链接方法Main.getFrame()Frame.define()ObjectDefinition.property()获取将在整个时间轴中存在的子项的属性。例如,如果您在第square15 帧上有一个实例名称为实例名称的 MovieClip,并且您想要获取它的宽度和高度,您可以.ready()像这样在其中执行此操作:

var square:ObjectDefinition = getFrame(15).define("square");
trace(square.property("width"), square.property("height"));

当然,这个过程并不理想 - 但不幸的是,这是我看到您想要实现的目标的唯一方法。

于 2013-06-04T23:22:45.557 回答
0

您可以添加一个 1 毫秒的事件侦听器并测试您存储的 previousWidth 是否不同。如果是,那你就去吧。如果不是,它可能在听同一帧。

一个 1 毫秒的计时器没什么大不了的,如果你不需要它就停止它,如果你需要它就恢复它,否则,让它不断运行。当它发生变化时,调度一个事件或任何需要发生的事情。

于 2013-06-04T07:21:55.907 回答
0

如果你知道 MovieClip 的最大尺寸,你可以试试这个:

// Create movie clip
var movie :MovieClip = new MovieClipWith3Frames();

// Move to second frame
movie.gotoAndStop(2);

// Create bitmap witch magenta background
var bd :BitmapData = new BitmapData(200, 200, false, 0xFF00FF);

// Draw second frame
bd.draw(movie);

// Found the bounds of shape
var movieBounds:Rectangle = bd.getColorBoundsRect(0xFFFFFF, 0xFF00FF, false);

trace(movieBounds); // (x=42, y=15, w=32, h=33)
于 2013-06-07T14:30:20.950 回答
0

您必须先听特定事件,然后才能询问信息。

clip.addEventListener(Event.FRAME_CONSTRUCTED, frameReadyHandler);
clip.gotoAndStop(frame);

function frameReadyHandler(event:Event):void
{
    clip.removeEventListener(Event.FRAME_CONSTRUCTED, frameReadyHandler);
    var width = clip.width;
}

Frame 构造的事件是被调度的几个事件中的第一个。它在框架脚本执行之前就被调度了。您也可以等待 on enter frame 事件。

于 2013-05-27T18:00:03.367 回答