ActionScript 3与JavaScript双向通信实战指南
概述
在Web开发中,有时需要实现Flash动画与HTML页面之间的数据交互。本文详细介绍如何在HTML页面中通过JavaScript控制SWF文件的内容,同时让SWF文件能够调用JavaScript函数实现双向通信。
第一步:创建Flash应用程序
使用Flash CC创建一个新的FLA文件,关联一个主类ColorPanel。Flash会自动生成对应的AS3源文件。以下是完整的AS3代码实现:
package {
import flash.display.MovieClip;
import flash.text.TextField;
import flash.events.MouseEvent;
import flash.external.ExternalInterface;
import fl.controls.Button;
import flash.system.System;
public class ColorPanel extends MovieClip {
private var config:Object;
private var displayText:TextField;
private var actionButton:Button;
private var clickCount:int = 0;
public function ColorPanel() {
//获取外部传入的参数
config = LoaderInfo(this.root.loaderInfo).parameters;
//初始化交互按钮
actionButton = new Button();
actionButton.label = "点击计数";
actionButton.width = 120;
actionButton.height = 25;
actionButton.x = 10;
actionButton.y = 10;
this.addChild(actionButton);
//按钮点击事件
this.actionButton.addEventListener(MouseEvent.CLICK, handleButtonClick);
//初始化文本显示区域
displayText = new TextField();
displayText.border = true;
displayText.borderColor = 0xCCCCCC;
displayText.x = 10;
displayText.y = this.actionButton.y + this.actionButton.height + 10;
displayText.width = this.stage.stageWidth - 20;
displayText.height = this.stage.stageHeight - this.actionButton.height - 40;
this.addChild(displayText);
//读取初始参数
var initialContent:String = config["content"];
if (initialContent != null && initialContent.length > 0) {
displayText.text = initialContent;
} else {
displayText.text = "请通过content参数传入初始内容";
}
//注册JavaScript回调函数
ExternalInterface.addCallback("updateDisplayText", updateTextContent);
ExternalInterface.addCallback("getClickCount", retrieveClickCount);
}
/**
* 更新文本内容
*/
private function updateTextContent(newContent:String):void {
this.displayText.text = newContent;
//通知JavaScript内容已更新
if (ExternalInterface.available) {
ExternalInterface.call("onContentUpdated", "内容更新成功");
}
}
/**
* 获取点击次数
*/
private function retrieveClickCount():int {
return this.clickCount;
}
/**
* 按钮点击处理
*/
private function handleButtonClick(event:MouseEvent):void {
clickCount++;
var message:String = "当前点击次数: " + clickCount;
this.displayText.text = message;
//调用外部JavaScript函数
if (ExternalInterface.available) {
ExternalInterface.call("onButtonClicked", clickCount);
}
}
}
}
完成代码后,在Flash中按Ctrl+Enter生成SWF文件,命名为ColorPanel.swf。
第二步:创建HTML嵌入页面
使用swfobject库将SWF文件嵌入到HTML页面中。swfobject是一个成熟的解决方案,能够自动处理各浏览器的兼容性问题。
<!DOCTYPE html>
<html>
<head>
<title>AS3与JavaScript通信演示</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript">
var flashId = "flashContainer";
swfobject.registerObject(flashId, "11.0.0", "expressInstall.swf");
</script>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.control-panel { margin: 10px 0; }
input { padding: 5px; width: 200px; }
button { padding: 5px 15px; cursor: pointer; }
</style>
</head>
<body>
<div class="control-panel">
<input type="text" id="inputField" placeholder="输入要显示的文字" />
<button onclick="sendToFlash();">发送到SWF</button>
<button onclick="queryClickCount();">查询点击次数</button>
</div>
<div>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
width="600" height="400"
id="flashContainer">
<param name="movie" value="ColorPanel.swf">
<param name="wmode" value="transparent">
<param name="flashvars" value="content=初始显示内容">
<!--[if !IE]-->
<object type="application/x-shockwave-flash"
data="ColorPanel.swf"
width="600" height="400">
<param name="wmode" value="transparent">
<param name="flashvars" value="content=初始显示内容">
<!--[endif]-->
<a href="http://www.adobe.com/go/getflashplayer">
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif"
alt="获取Adobe Flash播放器">
</a>
<!--[if !IE]-->
</object>
<!--[endif]-->
</object>
</div>
<script language="javascript">
//获取SWF对象的跨浏览器解决方案
function getFlashObject() {
var flashObj = document.getElementById(flashId);
if (!isIE()) {
flashObj = document.getElementById(flashId).getElementsByTagName("object")[0];
}
return flashObj;
}
//浏览器检测
function isIE() {
return navigator.appName.indexOf("Microsoft") > -1;
}
//从JavaScript调用AS3函数
function sendToFlash() {
var inputValue = document.getElementById("inputField").value;
var flashObj = getFlashObject();
if (flashObj && flashObj.updateDisplayText) {
flashObj.updateDisplayText(inputValue || "未输入内容");
} else {
alert("SWF未加载完成,请稍后再试");
}
}
//查询AS3中的点击次数
function queryClickCount() {
var flashObj = getFlashObject();
if (flashObj && flashObj.getClickCount) {
var count = flashObj.getClickCount();
alert("SWF按钮被点击了 " + count + " 次");
}
}
//AS3调用JavaScript的回调函数 - 按钮点击时触发
function onButtonClicked(count) {
console.log("SWF按钮被点击,当前次数: " + count);
}
//AS3调用JavaScript的回调函数 - 内容更新时触发
function onContentUpdated(message) {
console.log("SWF内容已更新: " + message);
}
</script>
</body>
</html>
关键要点分析
1. AS3调用JavaScript函数
在AS3中使用ExternalInterface.call()方法来调用JavaScript函数。第一个参数是JavaScript函数名,后续参数将传递给该JavaScript函数。例如:
//调用JavaScript函数,传递单个参数
ExternalInterface.call("onButtonClicked", clickCount);
//调用JavaScript函数,传递多个参数
ExternalInterface.call("someFunction", "参数1", "参数2", "参数3");
2. JavaScript调用AS3函数
需要在AS3端注册回调函数,使JavaScript能够调用AS3中的方法。关键步骤包括:
- AS3端注册:使用
ExternalInterface.addCallback()方法注册AS3函数,指定JavaScript中调用的别名 - 获取正确的SWF对象:由于各浏览器获取DOM对象的方式不同,需要编写兼容性代码
浏览器兼容性的处理代码:
function getFlashObject() {
var flashObj = document.getElementById(flashId);
//非IE浏览器需要获取嵌套的object元素
if (!isIE()) {
flashObj = document.getElementById(flashId).getElementsByTagName("object")[0];
}
return flashObj;
}
这是因为在非IE浏览器中,SWF的object元素是嵌套在另一个object元素内部的。
3. 注意事项
- 确保SWF文件已完全加载后再进行通信
- 使用
ExternalInterface.available检查当前环境是否支持外部接口 - 通过FlashVars传递初始参数时,使用
LoaderInfo(this.root.loaderInfo).parameters读取 - 如果页面使用了jQuery等库,检测对象是否为空的语法可能有所不同
总结
通过ExternalInterface类,AS3与JavaScript之间可以很方便地进行双向通信。实现过程中需要特别注意浏览器兼容性问题,特别是获取SWF对象的方式。掌握这些要点后,就能在Web项目中灵活实现Flash与HTML的交互功能。