Эта статья описывает, как вызывать из Javascript методы Flash и наоборот.
Используя эти способы, javascript может получить доступ к буферу обмена ОС, хранимым объектам SharedObject, управлять flash-интерфейсами и многое другое.
Какой бы способ коммуникации мы не выбрали, для начала JS должен уметь находить объект Flash на странице.
Для того, чтобы все работало кроссбраузерно, Flash-ролик нужно вставить с использованием обоих тегов: object и embed, например так:
<object
id="BridgeMovie" width="400" height="200"
classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
<param name="movie" value="bridge.swf" />
<param name="allowScriptAccess" value="sameDomain" />
<embed
src="bridge.swf"
name="BridgeMovie" align="middle"
play="true" loop="false" quality="high" allowScriptAccess="sameDomain"
width="400" height="200" scale="exactfit"
type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer">
</embed>
</object>
В этом примере существенны детали:
BridgeMovie дублируется как object.id и embed.name.bridge.swf дублируется в object/embedallowScriptAccess="sameDomain"Теперь объект ролика можно получить из window["BridgeMovie"] для IE или document["BridgeMovie"] в остальных браузерах:
function getMovie() {
var M$ = navigator.appName.indexOf("Microsoft")!=-1
return (M$ ? window : document)["BridgeMovie"]
}
Далее мы разберем средства для коммуникации с этим роликом.
Самый древний, знакомый большинству флешеров способ - это вызов javascript-функции посредством getURL с протоколом javascript:
getURL('javascript:функция("параметры");');
Вызов осуществляется так:
fsCommand("функция", "параметры")
Чтобы принять этот вызов, в Javascript должна быть специальная обвязка.
Редактор Macromedia Flash может генерировать ее автоматически при публикации ролика.
Для этого нужно в Publish Settings:
Генерируемый шаблон javascript-обвязки состоит из двух частей: функция обработки и дополнительного кода для IE.
Название функции имеет вид <ИмяРолика>_DoFSCommand. В нашем случае это BridgeMovie_DoFSCommand
Первый аргумент - имя вызываемой функции, второй - строка аргументов.
Простейший вариант выглядит так:
function BridgeMovie_DoFSCommand(command, args) {
// вызвать функцию command с аргументом args
window[command].call(null, args)
}
Вызов, например, функции show из Flash приведет к цепочке вызовов:
fsCommand("show","something")BridgeMovie_DoFSCommand("show","something")show("something")Этот код нужен только для IE под Windows, в дополнение к BridgeMovie_DoFSCommand, так как в этом браузере fsCommand вызывает не Javascript, а VBScript.
if (navigator.appName && navigator.appName.indexOf("Microsoft") != -1
&& navigator.userAgent.indexOf("Windows") != -1) {
document.write('<script language=\"VBScript\"\>\n');
document.write('On Error Resume Next\n');
document.write('Sub BridgeMovie_FSCommand(ByVal command, ByVal args)\n');
document.write(' Call BridgeMovie_DoFSCommand(command, args)\n');
document.write('End Sub\n');
document.write('</script\>\n');
}
Здесь VBScript просто передает вызов Javascript'у.
Итак, плюсы и минусы метода fscommand:
Этот способ работает, начиная с Flash 8. В отличие от всех предыдущих способов, он не только вызывает javascript, но и передает обратно возвращаемое значение, по возможности сохраняя его тип.
import flash.external.ExternalInterface;
var result = ExternalInterface.call("func", "param1", "param2", ...);
К сожалению, начиная с Flash 8, где он впервые появился, в ExternalInterface нашли большое количество разнообразных багов. Глюки сериализации, самопроизвольное изменение передаваемых данных и т.п.
Эти ошибки поправлены в новейших версиях Flash Player, но многие продолжают использовать более старые редакции Flash 8,9.
Актуальную информацию об ошибках можно получить из google, набрав "ExternalInterface bug".
Самый простой способ - установка переменной ролику:
getMovie().SetVariable("message","data")
Обратите внимание - именно SetVariable, не setVariable. Регистр здесь важен.
Чтобы Flash получил значение - можно проверять сообщения, например, на каждом кадре. Это около 12 раз в секунду.
Следующий код срабатывает на каждом кадре и ждет появления значения переменной message.
var message = null
_root.onEnterFrame = function() {
if (message!==null) {
_root.txtRecieve.text = message // получили сообщение
message = null
}
}
Применив ExternalInterface из Flash8+, можно объявить флеш-метод, который будет обрабатывать вызовы из javascript.
Формат вызова:
ExternalInterface.addCallback(функция JS, объект Flash, функция Flash);.
Например, следующий код устанавливает глобальную функцию recieveFromJS как обработчик JS-вызова sendFromJS.
import flash.external.ExternalInterface;
...
ExternalInterface.addCallback("sendFromJS", null, recieveFromJS);
function recieveFromJS(msg) {
_root.txtRecieve.text = msg;
}
В JS достаточно сделать простой вызов:
getMovie().sendFromJS(value);
Можно также использовать LocalConnection, как это сделано во Flash-Javascript Integration Kit.
Этот пример пересылает текст из верхнего JS-поля направо во Flash, из нижнего Flash-поля - налево в JS.
Вводите любой, текст и жмите кнопку для пересылки нужным методом.
|
|||||||
// Flash Storage example
import flash.external.ExternalInterface;
ExternalInterface.addCallback("sendFromJS", null, recieveFromJS);
function recieveFromJS(msg) {
_root.txtRecieve.text = msg;
}
_root.button.onRelease = function() {
fscommand("recieveFromFlash", _root.txtSend.text);
}
_root.button2.onRelease = function() {
ExternalInterface.call("recieveFromFlash", _root.txtSend.text);
}
_root.button3.onRelease = function() {
var txt = _root.txtSend.text.split('"').join('\\"')
getURL('javascript:recieveFromFlash("'+txt+'");');
}
var message = null
_root.onEnterFrame = function() {
if (message!==null) {
_root.txtRecieve.text = message
message = null
}
}
Скачать .fla - исходник флешки.
function recieveFromFlash(Txt) {
document.getElementById('txtRecieve').value = Txt;
}
function getMovie() {
var M$ = navigator.appName.indexOf("Microsoft")!=-1
return (M$ ? window : document)["BridgeMovie"]
}
function sendSetVariable() {
var value = document.getElementById('txtSend').value
var movie = getMovie()
movie.SetVariable("message", value)
}
function sendExternalInterface() {
var value = document.getElementById('txtSend').value
var movie = getMovie()
movie.sendFromJS(value);
}
/* movie name_DoFSCommand */
function BridgeMovie_DoFSCommand(command, args) {
window[command].call(null, args)
}
// Hook for Internet Explorer.
if (navigator.appName && navigator.appName.indexOf("Microsoft") != -1 &&
navigator.userAgent.indexOf("Windows") != -1) {
document.write('<script language=\"VBScript\"\>\n');
document.write('On Error Resume Next\n');
document.write('Sub BridgeMovie_FSCommand(ByVal command, ByVal args)\n');
document.write(' Call BridgeMovie_DoFSCommand(command, args)\n');
document.write('End Sub\n');
document.write('</script\>\n');
}
По просьбам читателей - примеры и исходники вынесены на отдельную страницу.
Успешной интеграции!