单击按钮时访问根阶段实例

Access root stage instance when button is clicked

我在舞台上有一个名为 myBtn 的按钮实例,还有一个名为 myContainer 的方形影片剪辑实例 - 所有这些都是从 Flash 发布的。
myContainer 中,我有一个名为 mySquare 的动画片段实例,它通过经典补间动画从舞台的一个点到另一个点。
加载舞台后,我使用 this.myBtn.on("click", startBtnOnClick) 向按钮添加事件侦听器,函数 startBtnOnClick(evt) 确实被成功调用。
我想要实现的是告诉 myContainer 在单击按钮时开始播放,为此我目前需要使用:
evt.target.parent.parent.myContainer.gotoAndPlay(0) 这行得通,但在这里似乎不是最佳做法。
哪种方法更合适?

代码是在我使用 HTML5 文档类型从 Adob​​e Flash 发布时生成的。我添加的是 startBtnOnClick() 函数定义并将事件处理程序分配给 myBtn 实例

编辑:

发布时创建了两个文件。为了播放电影,您打开 html 文件。

SquareTrial.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SquareTrial</title>

<script src="http://code.createjs.com/easeljs-0.8.1.min.js"></script>
<script src="http://code.createjs.com/tweenjs-0.6.1.min.js"></script>
<script src="http://code.createjs.com/movieclip-0.8.1.min.js"></script>
<script src="SquareTrial.js"></script>

<script>
var canvas, stage, exportRoot;

function init() {
    canvas = document.getElementById("canvas");
    exportRoot = new lib.SquareTrial();

    stage = new createjs.Stage(canvas);
    stage.addChild(exportRoot);
    stage.update();

    createjs.Ticker.setFPS(lib.properties.fps);
    createjs.Ticker.addEventListener("tick", stage);
}
</script>
</head>

<body onload="init();" style="background-color:#D4D4D4">
    <canvas id="canvas" width="550" height="400" style="background-color:#FFFFFF"></canvas>
</body>
</html>

和SquareTrial.js:

(function (lib, img, cjs, ss) {

var p; // shortcut to reference prototypes

// library properties:
lib.properties = {
    width: 550,
    height: 400,
    fps: 24,
    color: "#FFFFFF",
    manifest: []
};


// functions:

function startBtnOnClick(evt)
{
    console.log("startBtnOnClick called.");

    console.log("stage:");
    console.log(stage);

    console.log("stage.myContainer:");
    console.log(stage.myContainer);

    console.log("this.myContainer:");
    console.log(this.myContainer);
}


// symbols:


(lib.MySquare = function() {
    this.initialize();

    // Layer 1
    this.shape = new cjs.Shape();
    this.shape.graphics.f().s("#000000").ss(1,1,1).p("AoWoWIQtAAIAAQtIwtAAg");
    this.shape.setTransform(53.5,53.5);

    this.shape_1 = new cjs.Shape();
    this.shape_1.graphics.f("#6633FF").s().p("AoWIXIAAwtIQtAAIAAQtg");
    this.shape_1.setTransform(53.5,53.5);

    this.addChild(this.shape_1,this.shape);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(-1,-1,109,109);


(lib.MyBtn = function() {
    this.initialize();

    // Layer 1
    this.shape = new cjs.Shape();
    this.shape.graphics.f().s("#000000").ss(1,1,1).p("AprjWITXAAIAAGtIzXAAg");
    this.shape.setTransform(62,21.5);

    this.shape_1 = new cjs.Shape();
    this.shape_1.graphics.f("#0099FF").s().p("AprDXIAAmtITXAAIAAGtg");
    this.shape_1.setTransform(62,21.5);

    this.addChild(this.shape_1,this.shape);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(-1,-1,126,45);


(lib.MyContainer = function(mode,startPosition,loop) {
    this.initialize(mode,startPosition,loop,{});

    // Layer 1
    this.mySquare = new lib.MySquare();
    this.mySquare.setTransform(53.5,53.5,1,1,0,0,0,53.5,53.5);

    this.timeline.addTween(cjs.Tween.get(this.mySquare).to({x:397.5},47).wait(1));

}).prototype = p = new cjs.MovieClip();
p.nominalBounds = new cjs.Rectangle(-0.5,-0.5,108,108);


// stage content:
(lib.SquareTrial = function() {
    this.initialize();

    // button
    this.myContainer = new lib.MyContainer();
    this.myContainer.setTransform(102.5,99.5,1,1,0,0,0,53.5,53.5);

    this.myBtn = new lib.MyBtn();
    this.myBtn.setTransform(111,337.5,1,1,0,0,0,62,21.5);

    //this.myBtn.on("click", startBtnOnClick); //<< does not work
    this.myBtn.on("click", startBtnOnClick, this);


    this.addChild(this.myBtn,this.myContainer);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(323.5,245.5,125,314);

})(lib = lib||{}, images = images||{}, createjs = createjs||{}, ss = ss||{});
var lib, images, createjs, ss;

如果你只是在寻找舞台,你可以在任何显示对象上使用stage 属性 (getter),其中return是舞台实例继续存在。达不到舞台return null

var stage = evt.target.stage;

否则,您可能需要查看您的应用程序架构。例如,您可以通过将 this 作为 on() 方法的第三个参数传递,将您的事件处理程序绑定到当前范围。这将使您的 startBtnOnClick 方法在您的应用程序范围内触发,而不是让您查找相对于单击按钮的范围。

this.myBtn.on("click", startBtnOnClick, this);

[根据发布的内容编辑]

您的更新显示 myContainer 是您的 Flash 阶段的子级,它实际上作为库 JS(以您的 FLA 命名)中的 SquareTrial 函数导出。此 class 在 HTML.

中实例化为 exportRoot

您在库中定义函数的方式有点不正统。它基本上是一个匿名函数,但更大的问题是如果您 re-export 来自 Flash 的库,它将被覆盖。我建议要么将它移动到您包含的另一个脚本中,要么实际上将它包含在您的框架脚本中。

总之,进入实际功能。由于您使用 on() 方法在范围内调用它,因此 this 变量将引用 SquareTrial 实例(也称为 exportRoot)。您应该能够在 startBtnOnClick 方法中引用 this.myContainer

我建议的stage getter并不理想,因为EaselJS阶段只包含exportRoot。它还需要作为 this.stage 访问。您使用的 stage 引用 确实 存在,但它是在 index.html.

中创建的全局变量

因此,使用新方法,您应该能够做到这一点:

// In your frame script:
this.myBtn.on("click", startBtnOnClick, this); 

// In your function callback
console.log(this); // Should be the instance, and NOT window.
this.myContainer.gotoAndPlay(0);

如果您决定坚持使用 un-scoped 匿名函数,那么您可以通过全局 exportRoot 变量引用您的内容:

exportRoot.myContainer.gotoAndPlay(0);

希望消除任何困惑。