• 一篇清楚阐述 JAvaScript 传递数据 到 Flash 的文章


    JavaScript in love with Flash -- Control swf from JavaScript

     

    l          Control swf from JavaScript

           JavaScript controls a Flash movie via Flash Methods. A Flash Methods is a function exposed by the Flash plug-in that can be called from a hosting scripting environment. For instance, GetVariable, SetVariable and GotoFrame are all Flash Methods. Personally, I consider this nomenclature tedious and confusing. The Flash plug-in has no difference with other types of plug-ins really. Therefore a dedicated name here can only introduce troubles. There are many available Flash Methods at hand covering almost every aspect. But I strongly suggest that you use these methods mainly to send messages to Flash movies other than control over them directly. Because a Flash movie is powerful enough to manage itself but Flash Methods are relatively messy and error prone, it's a wise choice to avoid the additional complexity.

    Getting a reference

           First things first, we get a reference to the object representing the Flash movie (later referred to as Flash Object) via document.getElementById. Suppose we have the value "mosquito" for the id and name parameters.

    We write in JavaScript:

           var flashObj = document.getElementById("mosquito"); // id passed as a string

    Sometimes you see people using another equivalent way:

           var flashObj = document.mosquito; // an object path expression approach

    You can use either one as you wish. However, I prefer the first approach for its clarity and ease. Don't forget to always check if the flashObject is invalid.

           if(flashObj == null) {

                  //error handling code

           }

    An example:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

    <title>mosquito</title>

    </head>

    <body>

    <!--url's used in the movie-->

    <!--text used in the movie-->

    <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="550" height="400" id="mosquito" align="middle">

        <param name="allowScriptAccess" value="sameDomain" />

        <param name="movie" value="mosquito.swf" />

        <param name="quality" value="high" />

        <param name="bgcolor" value="#ffffff" />

        <embed src="mosquito.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="mosquito" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />

    </object>

     

    <script language="javascript">

    var flashObj = document.getElementById("mosquito");

    if(flashObj == null) {

           alert("Fail to get a reference!");

    }

    </script>

    </body>

    </html>

    Getting and Setting variables/properties

           Now that a reference to the Flash Object is acquired (flashObj), anything is possible. Let's move on!

           To get or set a variable or property inside a Flash movie, we need the help of GetVariable and SetVariable functions.

    To get a variable/property from the Flash movie:

           flashObj.GetVariable("varName");

    The return value is always a string.

    It is supposed that GetVariable returns null when the specified variable does not exist. But my test ended in an "unspecified error" with execution termination.

     

    To set a variable/property of the Flash movie:

           flashObj.SetVariable("varName", "newValue");

    This method has no return value.

    The first string parameter "varName" is the variable name that you define in the root time line or any valid target path expression. For example you can write

           var x = flashObj.GetVariable("_root.mosquito_mc._x");

    to get the _x property of a MovieClip named mosquito_mc.

            

    Type hacking!!!

           Careful readers may already have noticed that there is a problem related to type conversion between JavaScript and ActionScript. Since all parameters of the GetVariable and SetVariable are string and the return type of GetVariable is also string, getting and setting variables in this way guarantees no type safety. In fact no type information can be gained from or specified for the two methods.

           What does this mean? Suppose that we have the following ActionScript in the first frame of the root timeline.

           var age:Number = 3; // typeof(age) == "number"

    Then in JavaScript we write

           flashObj.SetVariable("age", "5");

    This will actually set age to "5" and change its type to string silently and possibly cause runtime failure in the affected swf. Caution! Savvy hackers may use this trick to break into your code!!!

           However, I found the Flash plug-in somewhat excessively clever with the type.

           flashObj.SetVariable("_root.mosquito_mc._x", "5"); // no problem at all

    This will change the position of mosquito_mc without any error! Maybe an internal conversion was done by the plug-in, but unfortunately we have no control over it!

    We know that a MovieClip has a frequently used method named addListener. Now let's hack it!

           flashObj.SetVariable("_root.addListener", "you fail! Ha-ha…");

    Inside the swf, the oringal function addListener will become a string "you fail! haha…" and any proceeding call to it will definitely FAIL!

    Seems that the Flash plug-in is not excessively clever enough!

           What happens if we pass a non-string value as the second argument to SetVariable?

    Suppose again we have the ActionScript

           var age:Number=3;

           //in the first frame of the root timeline.

     

           flashObj.SetVariable("age", 5);

           //This will still change age to a string of "5".

     

           flashObj.SetVariable("age", null);

           //This will cause a type mismatch in JavaScript.

     

           flashObj.SetVariable("age", undefined);

           //This will change age to an empty string, weird indeed!

     

           flashObj.SetVariable("age", {a:1, b:2});

           //This will change age to a string of value [object Object].

     

           flashObj.SetVariable("age", somethingUndefined);

           //Where somethingUndefined is an undefined identifier in the JavaScript.

           //This will cause an error in JavaScript saying that an undefined identifier is used.

     

           flashObj.SetVariable("someClassInstace.prop", value);

           //Where someClassInstace is an instance of a Class and prop is a getter/setter property

           //of someClassInstace.

           //This will cause an error in JavaScript saying that an undefined identifier is used.

     

     

           Whatever you specify for the second parameter, it will be firstly converted to a string and then passed to the core of the SetVariable. Make sure that you are passing a string otherwise the conversion may cause unwanted effects.

          

           It is a common case that you want to get or set a numeric variable/property. I have not yet found any elegant way. Nevertheless you can watch the variable in ActionScript and explicitly convert it to Number in time. Or in another way, you can defined a getter/setter property in your MovieClip thus your own setter function will be called when SetVariable triggers, giving a chance for any necessary type conversion. This is a tricky way indeed! :-) I'll demonstrate how to do this later in the section.

           Again I strongly suggest that you use these methods mainly to send messages to Flash movies other than control over them directly.

          

     

    Control the play back

           If your swf is mainly a sequence of frames without complex programmatic logic, it is a good idea to control the playback from JavaScript. The following Flash Methods are intended for playback control.

    flashObj.Play(); // start playing the _root timeline

     

    flashObj.StopPlay(); // stop playing the _root timeline

     

    flashObj.Rewind(); // Rewind the _root timeline to the first frame

     

    flashObj.IsPlaying(); // returns true if the movie is playing otherwise false

     

    flashObj.TGotoFrame("target", frameNumber); // moves play head of the MovieClip specified

    //by "target" to the frame specified by frameNumber.

     

    flashObj.TGotoLabel("target", "label");// moves play head of the MovieClip specified

    //by "target" to the frame specified by "label", "label" is the frame label you set in the Flash

    //authoring environment

     

    flashObj.GotoFrame(frameNumber); // set the play head to the frame specified by //frameNumber.

    Notice that the frameNumber starts at 0, unlike in Flash where the frame number begins at 1. Before calling this method, you should ensure that the target frame has already been loaded.

    if(flashObj.PercentLoaded() == 100) {

           flashObj.GotoFrame(frameNumber); // frameNumber is assigned somewhere else

    }

     

    Calling a function defined in the Flash movie

           There is no direct way to call a method defined in Flash from JavaScript because JavaScript and ActionScript functions and types are not compatible. But there are various ways to trigger code execution in a Flash movie from JavaScript.

    You can place your ActionScript code in a particular frame (latterly referred to as Frame Function). Then in JavaScript:

     

    flashObj.GotoFrame(frameNumber);

     

    flashObj.TGotoFrame("target", frameNumber);

     

    flashObj.TGotoLabel("target", "label");

     

    These functions control Flash movie playback. Jumping to the specified frame will of course trigger the code execution there.

     

    The following two functions execute ActionScript code at specified frame without moving the play head.

     

    flashObj.TCallFrame("target", frameNumber);

     

    flashObj.TCallLabel("target", "label");

     

           Frame Functions are convenient for sequential movies. However, because each Frame Function must occupy one frame. The frames holding Frame Functions become messy and unmanageable as the application complexity grow.

           ActionScript 2.0 has greatly extended the capabilities of Flash as an application platform. The fact is that sequential frames are not as useful as before in an application. Instead, OOP and design patterns become more and more active in the development of large and rich internet applications.

           Here I recommend a reasonably better approach using getter/setter properties. Getter/setter properties appear similar to other properties except that any access to them are delegated by user defined functions. More, if a SetVariable is applied to a getter/setter property, the corresponding setter function will be called.

    An example, suppose we have a Flash movie and we want to get or set the age property of it.

    In ActionScript we defined age as a getter/setter property, shown as below.

    //mosquito.fla first frame of root timeline

    import mx.utils.Delegate;

    import mx.controls.Alert;

    var name:String = "Timmy";

    var _age:Number = 3; //hold the actual value of property age

     

    //getter method for property age

    function getAge():Number {

           return _age;

    }

     

    //setter method for property age

    function setAge(val:Number) {

           var old:Number = this._age;

           _age = Number(val); //type conversion if necessary

           /* ... */

           Alert.show("age has been changed!\nold value: " + old + "\nnew value: " + _age, "setter method triggered");

    }

    this.addProperty("age", getAge, setAge); //register the age property

     

    In our HTML document:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

    <head>

    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />

    <title>mosquito</title>

    </head>

    <body>

    <!--url's used in the movie-->

    <!--text used in the movie-->

    <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="550" height="400" id="mosquito" align="middle">

        <param name="allowScriptAccess" value="sameDomain" />

        <param name="movie" value="mosquito.swf" />

        <param name="quality" value="high" />

        <param name="bgcolor" value="#ffffff" />

        <embed src="mosquito.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="mosquito" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />

    </object>

    <script language="javascript">

    var mySwf = document.getElementById("mosquito");

    mySwf.SetVariable("age", "5");

    }

    </script>

    </body>

    </html>

     

    In this way the age property will be properly set and an Alert will be displayed in the Flash movie showing the old and new value of the getter/setter property age. In this demonstration, we popup an Alert box in Flash. You can replace it with anything you need. In SetVariable("varName", "newValue"), "newValue" is a single string. What if we want to pass multiple parameters? We can put the parameters into a comma separated list and pass the list as a string. For example, SetVariable("varName", "param1, param2, param3"). Then we parse the list and extract what we need in the setter method for the varName property.

           This approach is somewhat like an event dispatching process which is generally considered suitable for large scale applications.

    Other Flash Methods

           Many more Flash Methods are available, see

    http://www.macromedia.com/support/flash/publishexport/scriptingwithflash/scriptingwithflash_03.html

    for more information.

     

  • 相关阅读:
    爬取动态html网页,requests+execjs
    pycharm2019.2一个奇怪的bugger,执行后输出内容被莫名处理
    博客园啥时候升级了,刚看到
    在浏览器的市场上,IE依然是放弃了,firefox还在继续~~
    jetbrain rider 逐渐完美了,微软要哭了么?
    div层的滑入滑出实例
    关于js的<、>、=、<=、>=的比较
    Jquery实现左右轮播效果
    Html5离线缓存详细讲解
    CANVAS画布与SVG的区别
  • 原文地址:https://www.cnblogs.com/cy163/p/1633008.html
Copyright © 2020-2023  润新知