Adobe
Flashアプリケーションで何らかの機能を使おうとすると、HTMLページ内のJavaScriptのような、Flash Playerの外部にあるコードに接続しなければならないことがよくあります。このような場合、接続を行うにはActionScriptからJavaScriptを呼び出したり、あるいはその逆を行うといったことが必要です。
Flash Player 7以前のバージョンではActionScriptとJavaScript間の接続に getURL() や fscommand()を使用せざるを得ませんでしたが、JavaScriptそのものは SetVariable()や callFrame()、 callLabel()を使用してもActionScriptと接続することは可能だったのです。
それがFlash Player 8になって、いわゆる外部API(application programming interface)のExternalInterfaceクラスを使用できるようになったことで、Flashと外部プログラムとの接続を非常にシンプルに行えるようになりました。この記事では、そのExternalInterfaceクラスについて詳しく解説していきます。
このチュートリアルを完了するには、次のソフトウェアおよびファイルがインストールされている必要があります。
JavaScriptおよびドキュメントオブジェクトモデル*(DOM)に関する知識が必要です。
まずここで紹介するのは、セキュリティ関連の制限について、Flash Player 8が旧バージョンより強化されている点です。
allowScriptAccess パラメータのデフォルト値が"always"ではなく"sameDomain"になっています。 Flash Player 7以前のバージョンのSWFに対しては、これは適用されません。 この allowScriptAccess パラメータによって、SWFがHTMLページ上のJavaScriptを呼び出すかどうかが制御されます。これら4種類の制限のなかでも、 allowScriptAccess は特にJavaScriptとの接続に密接に関係しています。 こうしたセキュリティ制限の変更について詳しくは、Deneb Meketaの記事「Security Changes in Flash Player 8(Flash Player 8におけるセキュリティ変更)」をご覧ください。
この allowScriptAccess の各設定は、以下のとおりです。
allowScriptAccess が"never"の場合、外部とやり取りしようとするスクリプトは常に遮断されます。allowScriptAccess が"always"の場合、スクリプトは常に外部とやり取りできます。allowScriptAccess が"sameDomain"(Flash Player 8からSWFでこの設定がサポートされるようになっています)の場合、ホストしているWebページと同じドメインにそのSWFファイルが存在する場合に限って、スクリプトと外部のやり取りが許可されます。allowScriptAccess がHTMLページで明確に指定されていない場合、埋め込まれているSWFファイルのデフォルト値はFlash Player 8では"sameDomain"に設定され、旧バージョンでは"always"に設定されます。1つのWebページ上では同じドメインからのみJavaScript関数を呼び出すことができます。ただし、ローカルで他のドメインから呼び出しのテストを行った場合、SWFファイルの設定は allowScriptAccess = "always"となります。
FlashからHTMLにパブリッシュすると、以下のコードが生成されます。
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>allowScriptAccess</title> </head> <body bgcolor="#ffffff"> <!--url's used in the movie--> <!--text used in the movie--> <!-- saved from url=(0013)about:internet --> <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="550" height="400" id="allowScriptAccess" align="middle"> <param name="allowScriptAccess" value="sameDomain" /> <param name="movie" value="allowScriptAccess.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /><embed src="allowScriptAccess.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="allowScriptAccess" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /> </object> </body> </html>
上記のなかでハイライト表示されたコードについては、 allowScriptAccess="sameDomain" から allowScriptAccess = "always"に変更する必要があります。
注意:ローカルのFlashコンテンツをインターネットに接続させる方法については、Flash Playerテクニカルノート*を読んでください。
Flash Player 8より旧いバージョンのFlash Playerでは、Flash側からJavaScriptへの接続には getURL() と fscommand() を使用し、逆にJavaScriptからFlashに接続するには SetVariable() を使用していました。
FlashからJavaScriptを呼び出す方法として、最も簡単なのは getURL()を使用することです。Flashから callJavascript() を呼び出すには、以下のActionScriptを使用します。
var msg:String = "''Hello. ^^'";
var callJas:String = 'javascript:callJavascript('+msg+')';
getURL(callJas);
HTML上で、以下のJavaScript関数を <head> タグと <body> タグの間に入力します
。
<script language="JavaScript">
function callJavascript(str){
alert(str)
}
</script>
Flashで callJavascript() 関数を呼び出して、"Hello. ^^"というメッセージストリングをパラメータとして送ります。 すると図1のようなウィンドウが表示されるようになります。
図1.Flashから生成されたメッセージウィンドウ
注意:SWFをFlash Player 8でローカルテストしたときにセキュリティエラーが発生する場合は、 allowScriptAccess="sameDomain" を allowScriptAccess="always"に変更します。さらに、グローバルセキュリティ設定パネルでSWFファイルへのアクセスを許可する必要があります。
この fscommand() コマンドを使用すると、SWFファイルがFlash Playerと、あるいはFlash PlayerをホストしているWebブラウザのようなプログラムと接続できるようになります。 たとえば、以下のActionScriptを使うと、JavaScript関数の callJavascript()が呼び出されます。
var msg:String = "'Hello. ^^'"; var callJas:String = "callJavascript"; fscommand(callJas, msg);
まずFlashでパブリッシュ設定ダイアログボックスを開きます(ControlキーとShiftキーを押しながらF12キーを押します)。次に、HTMLタブにある「テンプレート」ポップアップメニューから「Flash(FSCommandサポート)」を選択し(図2参照)、「パブリッシュ」ボタンをクリックします。
図2.パブリッシュ設定ダイアログボックスの設定
パブリッシュされたHTMLページには、以下のJavaScriptが自動的に含まれています。
<script language="JavaScript">
<!--
var isInternetExplorer = navigator.appName.indexOf("Microsoft") != -1;
// Handle all the FSCommand messages in a Flash movie.
function fscommand_DoFSCommand(command, args) {
var fscommandObj = isInternetExplorer ? document.all.fscommand : document.fscommand;
//
// Place your code here.
//
}
// Hook for Internet Explorer.
if (navigator.appName && navigator.appName.indexOf("Microsoft") != -1 && navigator.userAgent.indexOf("Windows") != -1 && navigator.userAgent.indexOf("Windows 3.1") == -1) {
document.write('<script language=\"VBScript\"\>\n');
document.write('On Error Resume Next\n');
document.write('Sub fscommand_FSCommand(ByVal command, ByVal args)\n');
document.write(' Call fscommand_DoFSCommand(command, args)\n');
document.write('End Sub\n');
document.write('</script\>\n');
}
//-->
</script>
"Place your code here"の部分には、ユーザが作成したカスタムコードが入ります。つまり、このコードは command と args というパラメータを受け取って処理する必要があります。これらのパラメータは fscommand()を使用してFlashから送信されるものです。
たとえば、次のコードは command と argsを処理することによって、メッセージウィンドウを作成します。
function fscommand_DoFSCommand(command, args) {
var fscommandObj = isInternetExplorer ? document.all.fscommand : document.fscommand;
//
if(command=="callJavascript") {
alert(args)
}
//
}
やり取りの際には fscommand() が内部でVBScriptを使用しているので、そのページ上にある他のVBScriptとの間で干渉を起こすことがあります。また、 fscommand() によって送られるのは1つの args ストリングパラメータに限られるため、2つ以上のパラメータを送るにはJavaScriptの split() 関数を使用しなければなりません。
以下のコードは、2つの引数を渡すために fscommand() を使用した例です。 Flashで以下のコードを入力します。
var msg:String = "'Hello. ^^'#Glad to see you.*^^*"; var callJas:String = "callJavascript"; fscommand(callJas, msg);
ここで使われている # は、送信する2つの引数の間でセパレータとしての役目を果たしています。 このJavaScriptコードは以下のとおりです。
function fscommand2_DoFSCommand(command, args) {
var fscommand2Obj = isInternetExplorer ? document.all.fscommand2 : document.fscommand2;
//
if(command=="callJavascript") {
arg = args.split("#")
alert(arg[0]+'\n'+arg[1])
}
//
}
上記のコードでは、ストリングを # セパレータで分けたうえで、 \n を使用してメッセージウィンドウ内の新しい行にテキストが配置されるようにしています。すると図3のようなウィンドウが表示されるようになります。
図3.2つの引数が表示されたメッセージウィンドウ
注意:前述の例で説明したように、ローカルテストの際にFlash Player 8でセキュリティエラーが発生しないようにするために、 allowScriptAccess="sameDomain" を allowScriptAccess="always"に変更します。
JavaScriptでFlashと接続するには、いくつかある所定のメソッドのうちどれかひとつを使うという方法しかありません。 SetVariable() は、その中でも最もよく使われているメソッドです。 これを使うことで、JavaScriptからそのページに埋め込まれているSWFに対してストリングの値を送ることができます。次に、ActionScriptでは、 watch() メソッドを使用することによって、新しい値が送られてきたときに必ずcallback関数を呼び出すことができます。では、この例を見てみましょう。
Flashで以下のコードを入力します。
// An empty string variable
var testValue:String = "";
// The callback function to be executed when the variable changes
watchCallback = function (id, oldval, newval):String {
// Here you place the new value in a text field for display
result_txt.text = newval;
return newval;
};
_root.watch("testValue", watchCallback);
上記のコードによって watchCallback() が、 testValue の値が変わったとき必ず呼び出されます。 この watchCallback() が呼び出されると、新しい値が_rootの result_txt.text に割り当てられます。
HTML内の <body> セクションに、以下のコードを挿入します。
<input type=button value="Pass the variable to Flash" onClick="callJavascript()"> <form name="inputValue"> Value <input type="text" name="vars" size="10" > </form>
HTML内のテキスト入力部分に入力された値は、 vars プロパティの中に保存されます。このプロパティは inputValueという形式になっています。「Flashに値を送信」ボタンをクリックして、 callJavascript() 関数を呼び出します。
JavaScriptコードは以下のとおりです。
<script language="JavaScript">
function callJavascript(){
var sendText = inputValue.vars.value
window.document.myMovie.SetVariable("testValue", sendText);
}
</script>
上記のコードで、 window.document.FlashID にはFlashオブジェクトのリファレンスが入ります(ここでは表示していません)。このリファレンスで SetVariable(variable, value) を呼び出すと、 sendText の値が testValueという名前の変数として送信されます。
window.document.setVariable.SetVariable("testValue", sendText);
図4は、その結果を表示したものです。
図4.HTMLページからJavaScript経由で値をFlashに送信
ExternalInterfaceクラスがFlash Player 8で初めて使用可能になったことで、ActionScriptとFlash Playerコンテナ(JavaScriptを使用したHTMLページやFlash Playerが埋め込まれたデスクトップアプリケーションなど)の間の接続が非常にシンプルになりました。
ExternalInterfaceは機能的には fscommand()や CallFrame()、 CallLabel() といったメソッドと似ていますが、柔軟性と汎用性の点でこれらのメソッドよりも優れています。 Flash Player 8以降でJavaScriptとActionScript間のやり取りを行うメソッドとしては、ExternalInterfaceが最も適しています。
ActionScriptからHTMLページ上のどんなJavaScript関数でも直接呼び出すことができますし、どんなデータタイプの引数でも好きな数だけ渡すことができ、戻された値を受け取ることができます。 それと同じように、HTMLページのJavaScriptからFlash PlayerのActionScript関数を呼び出し、戻り値を得ることもできます。 次の表1は、ExternalInterfaceがサポートしているブラウザとオペレーティングシステムの組み合わせを一覧で示したものです。
| ブラウザ | オペレーティングシステム | |
|---|---|---|
| Internet Explorer 5.0以上 | Windows | |
| Netscape 8.0以上 | Windows | Mac OS |
| Mozilla 1.7.5以上 | Windows | Mac OS |
| Firefox 1.0以上 | Windows | Mac OS |
| Safari 1.3以上 | Mac OS | |
ExternalInterface.call() は、JavaScript関数を呼び出して、戻り値を処理します。 かつては、1つのメソッドを使ってJavaScript関数を呼び出し、戻り値を受け取るにはまた別のメソッドを使わなければなりませんでした。 それが今では1つの関数を呼び出すだけで、即座に戻り値を受け取ることができるのです。 ずいぶん簡単になったものですね。
この ExternalInterface.call() メソッドでは、以下の基本フォーマットが使用されます。
ExternalInterface.call(methodName:String, [parameter1:Object])
これらのパラメータは、それぞれ次の内容を意味しています。
Flashで以下のコードを入力します。
import flash.external.*; // The name of a JavaScript function to call var callJasFunction:String = "callJavascript"; //parameter var msg:String = "Hello. ^^"; // The return value after calling JavaScript var returnValue:String = ExternalInterface.call(callJasFunction, msg).toString(); return_txt.text = returnValue;
以下のJavaScriptコードを入力します。
<script language="JavaScript">
function callJavascript(str) {
alert(str)
return "ExternalInterface is a new Flash Player 8 API."
}
</script>
この callJavascript() が呼び出されると、JavaScript関数が値を受け取ったことを示すメッセージウィンドウが表示されます。 ここで「OK」をクリックすると戻り値がFlash Playerに送られ、Flash Playerはこの戻り値を受け取ってそれを return_txt.text の部分に表示します(図5参照)。
図5.JavaScriptから戻された値
注意:いつもと同じように、Flash Player 8でローカルテストを行う際には allowScriptAccess="sameDomain" を allowScriptAccess="always" に変更してください。また、ローカルのFlashコンテンツをインターネットに接続させる方法については、Flash Playerテクニカルノートを読んでください。
この ExternalInterface.addCallback() メソッドは、ActionScriptのカスタムメソッドをJavaScriptから呼び出せるように登録するためのものです。 以前はFlash Playerにビルトインされている、ごく限られた関数しか呼び出せませんでしたが、今は ExternalInterface.addCallback()を使用すれば、ユーザがSWFで定義したカスタム関数を呼び出すことができます。 さらに、データタイプがサポートされているものならパラメータを何個でも渡すことができます。
この ExternalInterface.addCallback() メソッドの基本フォーマットは、以下のようになっています。
ExternalInterface.addCallback (methodName:String, instance:Object,method:Function)
これらのパラメータは、それぞれ次の内容を意味しています。
this の対象となるオブジェクト。任意のオブジェクト(またはnull)を指定できるので、このオブジェクトは必ずしもこのメソッドを含むオブジェクトである必要はないFlashで以下のコードを入力します。
import flash.external.*;
// The name of the Flash variable to be called in JavaScript
var flashFunction:String = "callPlayBall";
var instance:Object = null;
// Callback function executed by the name of variable
var realFunction:Function = playBall;
ExternalInterface.addCallback(flashFunction, null, realFunction);
function playBall(tgX:Number, tgY:Number, spd:Number):Void {
moveMC(ball_mc, tgX, tgY, spd);
}
// Decelerating movement
function moveMC(tgMC:MovieClip, tgX:Number, tgY:Number, spd:Number):Void {
var mc:MovieClip = tgMC.createEmptyMovieClip("tp_chProp", 98765);
mc.onEnterFrame = function() {
this._parent._x += spd*(tgX-this._parent._x);
this._parent._y += spd*(tgY-this._parent._y);
var diffX:Number = Math.abs(tgX-this._parent._x);
var diffY:Number = Math.abs(tgY-this._parent._y);
if (diffX<0.5 && diffY<0.5) {
this._parent._x = tgX;
this._parent._y = tgY;
this.removeMovieClip();
}
};
}
以下のJavaScriptコードを入力します。
<script language="JavaScript">
function callExternalInterface() {
/* Call a function registered as callPlayBall in the SWF named myMovie. */
getMovieName("myMovie").callPlayBall(inputValue.x.value, inputValue.y.value, inputValue.spd.value);
}
/* This utility function resolves the string movieName to a Flash object reference based on browser type. */
function getMovieName(movieName) {
if (navigator.appName.indexOf("Microsoft") != -1) {
return window[movieName]
}
else {
return document[movieName]
}
}
</script>
以下のコードがHTMLの <body>に入ります。
<!-- Click the button to call "callExternalInterface()".-->
<input type="button" onClick="callExternalInterface()" value="Call Flash Function" />
</form>
<!-- Save the values of x, y and spd variables for each input text in inputValue.-->
<form name="inputValue">
Positon X <input type="text" name="x" size="10" >
Position Y <input type="text" name="y" size="10" >
Speed <input type="text" name="spd" size="10" >
</form>
図6は、HTMLからFlashにxとyの値を送ってボールを動かした場合の状態と、その速度を表しています。
図6.値を入力してボールを動かした例
注意:もう分かりきったことですが、Flash Player 8でローカルテストを行う際には allowScriptAccess="sameDomain" を allowScriptAccess="always" に変更してください。また、ローカルのFlashコンテンツをインターネットに接続させる方法については、Flash Playerテクニカルノート*を読んでください。
この記事で触れたトピックについてさらに詳しくは、以下のリソースをご覧ください。