【问题标题】:Isolating loaded swfs from using the parent将加载的 swf 与使用父级隔离
【发布时间】:2012-07-13 21:45:52
【问题描述】:

我有一个完整的浏览器窗口 AS3 Flash CS4 父 swf,它加载第三方子 swf,高度/宽度更小并且位置适当(即居中)。无论我尝试使用哪种加载技术,我都会在子 swf 中遇到放置和方向问题,这会破坏子进程。

在一个示例中,孩子将加载一个辅助显示对象(可能是一个影片剪辑),但会尝试将其附加到舞台上。如果我允许它在加载期间通过 SecurityDomain 访问舞台,它会将其定位在父 swf 的 0,0 而不是子 swf 的 0,0(已经适当地定位/居中)。

在另一种情况下,加载期间的子级定位是合适的,但是在子级内部放置似乎参考舞台的 X、Y 位置会被子级 swf 居中的量所抵消(即,如果子级的加载器swf 居中,使其 X 位于 200,而子 swf 内部的一个对象应该位于 100,50,它实际上位于 300,50)。

常见的线程似乎是子 swfs,无论是否允许访问舞台,都使用父级的舞台或播放器属性,而不是加载器中它们自己的属性。

如何隔离子 swf,使其仅使用其自己的子环境而不是父级的子环境进行定位和定向?

我尝试过内置的 Loader 和 UILoader、Greensock 的 SWFLoader、Flex 的 SWFLoader,甚至通过 TextField 中的文本加载它。

似乎 AIR 的 HTMLLoader 可以工作(因为 HTMLLoader 中的 SWF 对象显然使用它们自己的舞台对象),但是这个应用程序已经在浏览器中可用。

理想情况下,我仍然希望能够与孩子交流,但此时确保孩子成功运行更为重要。

这似乎是一种常见的方法,但遇到左右阻塞问题让我觉得我以错误的方式处理这个问题。

我最后的办法是用 JS 框架替换父 swf,但前提是绝对必要。

我们将不胜感激在此过程的任何部分提出解决方案的建议。

【问题讨论】:

  • 这是我关于 SE 的第一个问题,请原谅任何未能遵循 SE 协议的问题。
  • 你试过lockroot吗?
  • @The_asMan,lockroot 在 AS3 中不可用。不过谢谢你的想法。
  • 是的,我的错。您需要重新开发子 swf 以不针对阶段。任何时候你的目标阶段,你都失去了移植 swf 的能力,或者当你发现过多或范围界定会出现在你身上时。我会在子 swf 中添加一个容器,而不是舞台,它将为您保存所有内容。如果您需要孩子访问父项中的某些内容或加载 swf,那么您可以使用 parent.parent 方法进行跟踪。
  • 也看看root。加载的 swf 中的“根”似乎是指该 swf 的根。 help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/…

标签: actionscript-3 flash


【解决方案1】:

希望回答我自己的问题没有这样的“规则”......

正如 cmets 中提到的 weltraumpirat,似乎无法限制加载的 swf 访问阶段变量,例如定位/方向(mouseX 和 mouseY)。最好的解决方案是限制对舞台的访问,以便加载的 swfs 无法添加到它。这是通过在 Loader.load 调用中包含一个 LoaderContext 对象来完成的,该调用定义了一个单独的 ApplicationDomain。

var url:URLRequest = new URLRequest(/*...SWF URL...*/); 
var context:LoaderContext = new LoaderContext(false,new ApplicationDomain());
var ldr:Loader = new Loader();
ldr.load(url,context);

这将在加载的 swf 中维护一个单独的根目录。

如果 Loader 对象在父/主 swf 中的位置远离 (0,0),您可能需要与已加载的 swf 作者协调以使用 DisplayObject.globalToLocal 包装 stage.mouseX 和 stage.mouseY以反映未知的偏移量(从加载的 swf 中)。

var localMousePt:Point = this.globalToLocal(new Point(stage.mouseX,stage.mouseY));

这很糟糕,但从安全的角度来看是有道理的。我发现对于 Flash 开发人员来说,通常的做法是不考虑可能加载其 SWF 的上下文,因此认为使用舞台(而不是根)没有任何问题。最佳实践应该是始终使用根来添加和定位对象,因为您永远不知道该根可能放置在显示列表中的哪个位置以及它们与舞台之间可能有多少父级。

【讨论】:

    【解决方案2】:

    这是一个丑陋的 hack,但您总是可以在舞台上添加一个Event.ADDED 的侦听器,检查需要调整的显示对象(当然,如果它们被命名,这效果最好,但可能会有是您可以使用的其他标准),然后手动更改它们的坐标。

    private function onAdded( ev:Event ) : void {
         if ( ev.target.name == "whatever") 
             modifyCoordinates( ev.target as DisplayObject );
    }
    
    private function modifyCoordinates( target:DisplayObject ) : void {
        // displace to match parent clip
    }
    
    //...
    
    stage.addEventListener( Event.ADDED, onAdded );
    

    如果无法区分加载的剪辑生成的显示对象,您可以过滤掉您自己添加到舞台的显示对象:如果只有应用程序的根 MovieClip 在舞台上,然后一切被添加为孩子,这根本不应该是一个问题。

    我也会尝试联系作者,或反编译第三方文件 - 如果其中任何一个可行,您至少可以了解事情是如何完成的,这样您就不必猜测在哪里应用您的更改.或者您甚至可以修改并重新编译它们。

    【讨论】:

    • 这是我在等待新建议时找到的确切位置。我已经能够将添加到舞台的对象移动到子节点的孤立根目录,但是由于第三方 swf 似乎以比简单地添加到根堆栈顶部更复杂的方式处理它们,因此遇到了很大的困难。在这一点上,我唯一的办法是逐案处理单个 swf,希望找到加快兼容性开发的通用方法。不过,我仍然希望有一种方法可以将加载的 swf 阶段与父级完全隔离。
    • @kfblake 我不会浪费更多时间等待它 - 只有一个 stage。你所能做的就是联系作者并要求他们将他们所有的stage 孩子转移到root(最多三到四个搜索和替换任务)——之后你就不会再有任何问题了。
    • weltraumpirat,谢谢,这就是我得出的结论;限制对舞台的访问并与第三方作者联系,以使用 root 而不是舞台进行协调。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-02
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多