JavaScript 通过ExternalInterface 与Flash 对话

发布于 2024-10-27 15:53:52 字数 3520 浏览 1 评论 0原文

我一直在尝试整理 JavaScript 与 Flash 交互的概念证明。我正在使用 JQuery 和 Flash CS5、ActionScript 3。

我不是 Flash 开发人员,因此对代码表示歉意,如果我能证明这是可行的,那么 Flash 将提供给知道自己在做什么的人。

Actionscript 位于第一帧时间线中的一个层上,根电影中有几个元素:

output = new TextField();
output.y = -200;
output.x = -200;
output.width = 450;
output.height = 325;
output.multiline = true;
output.wordWrap = true;
output.border = true;
output.text = "Initializing...\n";
root.bgClip.addChild(output); 
try{
     Security.allowDomain("*");
     flash.external.ExternalInterface.marshallExceptions = true;
     output.appendText("External Interface Available? " + ExternalInterface.available + "\n");
     output.appendText("External Interface ObjectId: " + ExternalInterface.objectID + "\n");
     flash.external.ExternalInterface.addCallback("getMenuItems", returnMenuItems);
     flash.external.ExternalInterface.addCallback("changeText", changeText);
     flash.external.ExternalInterface.addCallback("changeBgColour", changeBgColour);
     flash.external.ExternalInterface.call("populateMenu", returnMenuItems());
} catch (error:SecurityError) {
    output.appendText("Security Error: " + error.message + "\n");
} catch (error:Error) {
    output.appendText("Error: " + error.message + "\n");
}
function returnMenuItems():String{
    return "[{\"menu option\": \"javascript:callFlash('changeBgColour','4CB9E4')\"}]";
}
function changeText(t:String){
    root.textClip.text = t;
}
function changeBgColour(colour:String) {
     var c:ColorTransform = root.bgClip.transform.colorTransform;
     c.color = uint(colour);
     root.bgClip.transform.colorTransform = c;
}

JavaScript 和 HTML 是:

function populateMenu(message){
    $("#options").changeType("Options", $.parseJSON(message));
    $("#options").addMenuActions();
}
function callFlash(methodToCall, param){
    alert("method: " + methodToCall + ", param: " + param);
    if(param == undefined){
        $("#AJC")[methodToCall]();
    }else{
        $("#AJC")[methodToCall](param);
    }
}
var flashvars = {};
var params = {allowScriptAccess: "always"};
var attributes = {name: "AJC"};
swfobject.embedSWF("http://192.168.184.128/ActionscriptJavascriptCommunication.swf", "AJC", "600", "400", "9", "", flashvars, params, attributes);

现在

<body>
  <div id="wrapper">
    <div id="topBar" class="top-bar"></div>
    <div id="flashContainer">
      <div id="AJC">Loading Flash...</div>
    </div>
    <ul class="dropdown" id="games"></ul>
    <ul class="dropdown" id="options"></ul>
  </div>
</body>

我知道 ActionScript 很糟糕,它看起来如此的原因是因为我有阅读很多关于从 JavaScript 联系 Flash 可能出现的问题的主题(因此允许安全域 * 并添加调试文本框等)。

我使用的 JavaScript 位于 head 的 script 标签内。 ChangeType 和 addMenuActions 只是我添加的 JQuery 方法。这些只是经过独立测试但确实有效的 JavaScript 方法。

您会注意到 ActionScript 中 try catch 的最后一行是:

flash.external.ExternalInterface.call("populateMenu", returnMenuItems());

这确实有效,它使用从 Flash 发送的文本填充我的菜单。唯一不起作用的是尝试调用使用 addCallback 函数公开的方法。

我收到警报,上面写着:

method: changeBgColour, param: 4CB9E4

但有一个错误说:

Error: $("#AJC")[methodToCall] is not a function
Source File: http://192.168.184.128/test.html#
Line: 88

我设置了一个本地虚拟机来运行 Apache,它与 192.168.184.128 相关,我想知道这是否是问题所在,我看到有几个线程提到尝试进行通信本地使用 flash 不起作用,这就是为什么我使用 apache 设置 VM 的原因?

有什么想法吗?我知道人们已经做到了这一点,这非常令人沮丧。

谢谢。

I have been trying to put together a proof of concept of JavaScript talking to Flash. I am using JQuery and Flash CS5, ActionScript 3.

I am not a Flash developer so apologies for the code, if I can prove this works the Flash will be given to someone who knows what they are doing.

The Actionscript is on a layer in the timeline in the first frame, with a couple of elements in the root movie:

output = new TextField();
output.y = -200;
output.x = -200;
output.width = 450;
output.height = 325;
output.multiline = true;
output.wordWrap = true;
output.border = true;
output.text = "Initializing...\n";
root.bgClip.addChild(output); 
try{
     Security.allowDomain("*");
     flash.external.ExternalInterface.marshallExceptions = true;
     output.appendText("External Interface Available? " + ExternalInterface.available + "\n");
     output.appendText("External Interface ObjectId: " + ExternalInterface.objectID + "\n");
     flash.external.ExternalInterface.addCallback("getMenuItems", returnMenuItems);
     flash.external.ExternalInterface.addCallback("changeText", changeText);
     flash.external.ExternalInterface.addCallback("changeBgColour", changeBgColour);
     flash.external.ExternalInterface.call("populateMenu", returnMenuItems());
} catch (error:SecurityError) {
    output.appendText("Security Error: " + error.message + "\n");
} catch (error:Error) {
    output.appendText("Error: " + error.message + "\n");
}
function returnMenuItems():String{
    return "[{\"menu option\": \"javascript:callFlash('changeBgColour','4CB9E4')\"}]";
}
function changeText(t:String){
    root.textClip.text = t;
}
function changeBgColour(colour:String) {
     var c:ColorTransform = root.bgClip.transform.colorTransform;
     c.color = uint(colour);
     root.bgClip.transform.colorTransform = c;
}

The JavaScript and HTML are:

function populateMenu(message){
    $("#options").changeType("Options", $.parseJSON(message));
    $("#options").addMenuActions();
}
function callFlash(methodToCall, param){
    alert("method: " + methodToCall + ", param: " + param);
    if(param == undefined){
        $("#AJC")[methodToCall]();
    }else{
        $("#AJC")[methodToCall](param);
    }
}
var flashvars = {};
var params = {allowScriptAccess: "always"};
var attributes = {name: "AJC"};
swfobject.embedSWF("http://192.168.184.128/ActionscriptJavascriptCommunication.swf", "AJC", "600", "400", "9", "", flashvars, params, attributes);

and

<body>
  <div id="wrapper">
    <div id="topBar" class="top-bar"></div>
    <div id="flashContainer">
      <div id="AJC">Loading Flash...</div>
    </div>
    <ul class="dropdown" id="games"></ul>
    <ul class="dropdown" id="options"></ul>
  </div>
</body>

Now I know the ActionScript is awful, the reason it looks like it does is because I have read a lot of threads about possible issues to do with contacting Flash from JavaScript (hence the allow security domain * and adding a debug text box etc).

The JavaScript I am using is within a script tag in the head. The changeType and addMenuActions are just JQuery methods I have added. These are just JavaScript methods that have been tested independently but do work.

You'll notice that the last line of my try catch in the ActionScript is:

flash.external.ExternalInterface.call("populateMenu", returnMenuItems());

This does work, it populate my menu with the text sent from Flash. The only thing that doesn't work is trying to call the methods exposed using the addCallback function.

I get the alert which says:

method: changeBgColour, param: 4CB9E4

but an error saying:

Error: $("#AJC")[methodToCall] is not a function
Source File: http://192.168.184.128/test.html#
Line: 88

I set up a local VM to run Apache, which relates to the 192.168.184.128, I wondering if this was the issue, I have seen a couple of threads mention that trying to communicate with flash locally won't work, which is why I set up the VM with apache?

Any ideas? I know people have got this working, it is very frustrating.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

鸠魁 2024-11-03 15:53:52

简单的错误:jQuery 的工厂方法生成 jQuery.init 对象,其行为与数组非常相似。您需要在实际 DOM 元素上调用该方法,该元素是“数组”中的第一个成员。

$('#AJC')[0][methodToCall]

如果遇到安全问题,您将根本无法在 Flash 和 JavaScript 之间进行通信。

Simple mistake: jQuery's factory method produces jQuery.init object, which acts very similar to an array. You need to call the method on the actual DOM element, which is the first member in the "array".

$('#AJC')[0][methodToCall]

If you had security issues, you wouldn't be able to communicate between Flash and JavaScript at all.

匿名。 2024-11-03 15:53:52

问题在于您访问 Flash 对象的方式。 SwfObject 有一个内置函数可以解决这个问题,它在所有浏览器中都能很好地工作:

function callFlash(methodToCall, param)
{
    var obj = swfobject.getObjectById("AJC");

    if(param == undefined){
        $(obj)[methodToCall]();
    }else{
        $(obj)[methodToCall](param);
    }
}

我还没有测试上面的代码,但我想它应该可以工作!

The problem is in the way you are accessing your flash object. SwfObject has a built-in function that take care of that, it works great across all browsers:

function callFlash(methodToCall, param)
{
    var obj = swfobject.getObjectById("AJC");

    if(param == undefined){
        $(obj)[methodToCall]();
    }else{
        $(obj)[methodToCall](param);
    }
}

I havent tested the code above, but I guess it should work!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文