鼠标悬停在Flash上​​的事件 [英] Flash events on mouse over

查看:185
本文介绍了鼠标悬停在Flash上​​的事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么方法可以在鼠标移动到Flash项目中的某个对象上时找出调用什么方法?

>到目前为止,@ rvmook的部分解决方案离我的观点最近。这将有助于如果你使用DisplayObjectContainer的的 getObjectsUnderPoint()方法来获取您翻转的显示对象的列表,然后遍历它们并检查哪个具有翻转/鼠标悬停事件处理程序,然后继续下钻。所以一个简短的解决方案是:
$ b $ ol
  • 加载你想要的swf找出滚动/鼠标悬停处理程序的名称*

  • 添加滚动处理程序(将气泡设置为true)
  • 在滚动处理程序循环通过具有滚动/鼠标悬停处理程序的鼠标下的对象,并获取它们的详细信息。

    注意! getObjectsUnderPoint()工作,如果加载瑞士法郎有托管加载瑞士法郎的域的权限。找到一个方法 areInaccessibleObjectsUnderPoint ()方法。如果你拥有加载的瑞士法郎应该没有任何问题。否则,您需要在承载加载的swf的域上使用crossdomain.xml来授予加载器swf的域访问权限(并且加载器swf应该传递 new LoaderContext(true)作为第二个参数对于Loader intance的load()方法),或者使用你选择的语言的服务器端脚本来首先代理/复制加载的swf。

    这里有一个基本的我的意思是例子:

    $ p $ package {
    import flash.display。*;
    导入flash.events。*;
    导入flash.geom.Point;
    import flash.net.URLRequest;
    import flash.sampler.getMemberNames;

    public class BasicInfoTest extends Sprite {

    private var cursor:Point = new Point();

    public function BasicInfoTest(){
    init();

    私有函数init():void {
    var loader:Loader = addChild(new Loader)as Loader;
    loader.load(new URLRequest('B.swf'));
    addEventListener(MouseEvent.ROLL_OVER,onOver);

    private function onOver(event:MouseEvent):void {
    cursor.x = mouseX; cursor.y = mouseY;
    var obj:Array = getObjectsUnderPoint(cursor);
    var numObj:int = obj.length;
    for(var i:int = 0; i< numObj; i ++){//在光标处查找具有滚动/鼠标悬停事件处理程序的对象
    if(obj [i] .hasEventListener(MouseEvent。 ROLL_OVER)|| OBJ [I] .hasEventListener(的MouseEvent.MOUSE_OVER)){
    变种成员:对象= getMemberNames(OBJ [1]); //使用@ rvmook的方法来获得听众
    为每个( var name:QName in members){
    if(name.localName ==listeners){
    for(var j:int = 0; j< obj [i] [name] .length; j ++){
    var func:Function = obj [i] [name] [j];
    尝试{
    func.call(); ('。')[0]。
    trace(' ); //解析错误信息,你可能需要修改这个
    trace('StackTrace',error.getStackTrace());
    }
    }
    }
    }
    }
    }
    }
    }
    }

    如果您只需要找出方法的名称,就应该这样做。
    如果您需要更多信息,您可以访问加载的swf的bytearray并解析actionscript字节码以获取信息。我必须承认二进制和汇编有点不在我的范围,但幸运的是有一些伟大的库在那里反编译SWF文件在运行时在AS3。 AS3SWF 是一个很好的例子,但是与actionscript标签没有多大关系,而 as3commons 是专门研究代码方面的大型库集合。



    这是使用as3-commons库(字节码的前一个示例的改编, lang logging and

      package {} =nofollow>反射)显示方法签名和正文(如AVM2指令) 
    import flash.display。*;
    导入flash.events。*;
    导入flash.geom.Point;
    import flash.net。*;
    import flash.sampler.getMemberNames;
    import flash.utils.ByteArray;

    导入org.as3commons.bytecode.swf.SWFFile;
    import org.as3commons.bytecode.swf.SWFFileIO;
    import org.as3commons.bytecode.tags.DoABCTag;

    public class AdvancedInfo extends Sprite {

    private var cursor:Point = new Point();
    private var methodInfo:Array;

    public function AdvancedInfo(){
    init();

    private function init():void {
    var byteLoader:URLLoader = new URLLoader(new URLRequest('B.swf'));
    byteLoader.dataFormat = URLLoaderDataFormat.BINARY;
    byteLoader.addEventListener(Event.COMPLETE,bytesLoaded);

    私有函数bytesLoaded(event:Event):void {
    var ba:ByteArray = event.target.data as ByteArray; //获得swf字节
    var swfFile:SWFFile = new SWFFileIO()。read(ba); //使用as3-commons读取字节
    var abcTags:Array = swfFile.getTagsByType(DoABCTag); //获取动作字节码(ABC)标签
    for each(var tag:abcTags中的DoABCTag)methodInfo = tag.abcFile.methodInfo; //循环标签并获取方法信息
    //显示和滚动
    var d:Loader = addChild(new Loader() )作为Loader;
    d.loadBytes(ba);
    addEventListener(MouseEvent.ROLL_OVER,rolledOver,true,0,true);

    private function getMethodDetails(methodName:String):String {
    var result:String ='';
    for(var i:int = 0; i< methodInfo.length; i ++){
    if(methodInfo [i] .methodName == methodName){
    result + ='signature: \t '+ MethodInfo的[I] +' \\\
    ';
    result + ='body:\t'+ methodInfo [i] .methodBody;
    返回结果;
    }
    }
    返回结果;

    private function rolledOver(event:MouseEvent):void {
    cursor.x = mouseX; cursor.y = mouseY;
    var obj:Array = getObjectsUnderPoint(cursor);
    var numObj:int = obj.length;
    为(VAR我:= 0; I< numObj;我++){
    如果(OBJ [I] .hasEventListener(MouseEvent.ROLL_OVER)|| OBJ [I] .hasEventListener(的MouseEvent.MOUSE_OVER )){
    var members:Object = getMemberNames(obj [i]); (var name:QName in members){
    if(name.localName ==listeners){
    for(var j:int = 0; j< obj [i ] [name] .length; j ++){
    var func:Function = obj [i] [name] [j];
    尝试{
    func.call();
    } catch(error:Error){
    var methodName:String = error.message.split('on')[1] .split('。')[0] .split('/' )[1] .split( '()')[0];
    trace(getMethodDetails(methodName));
    }
    }
    }
    }
    }
    }
    }

    }
    }

    以下是加载的SWF代码的文档:

      package {
    import flash.events。*;
    import flash.display。*;

    public class B extends Sprite {
    public function B(){
    addEventListener(Event.ADDED_TO_STAGE,init)
    }
    private function init (新的Sprite())作为Sprite;(void Sprite()):void {
    (var i:int = 0; i< 1000; i ++){
    var b:Sprite = addChild
    b.graphics.lineStyle(Math.random()* 3);
    b.graphics.drawCircle(-3,-3,3);
    b.x = 3 + Math.random()* stage.stageWidth - 6;
    b.y = 3 + Math.random()* stage.stageHeight - 6;
    b.buttonMode = true;
    b.addEventListener(MouseEvent.ROLL_OVER,onRollOver);

    $ b private function onRollOver(event:MouseEvent):void {
    event.currentTarget.scaleX = event.currentTarget.scaleY = .1 + Math.random()* 2.1;



    code $
    $ p $这里是一个样本在我的AdvancedInfo例子中使用getMethodDetails方法详细跟踪:

     签名:private function QName [Namespace [private :: B]: onRollOver](QName [Namespace [public :: flash.events]:MouseEvent]):QName [Namespace [public]:void] 
    body:
    private function QName [Namespace [private :: B]: QName [Namespace [public :: flash.events]:MouseEvent]):QName [Namespace [public]:void]
    {
    // maxStack = 5,localCount = 3,initScopeDepth = 9 ,maxScopeDepth = 10
    0:debugfile [/ Users / george / Documents / Flex Builder 3 / Del / src ;; B.as]:2
    2:debugline [28]:4
    4:getlocal_0:5
    5:pushscope:6
    6:debug [1,18,0,28]:11
    11:debugline [29]:13
    13: getlocal_1:14
    14:getproperty [QName [Namespace [public]:currentTarget]]:16
    16:getlocal_1:17
    17:getproperty [QName [Namespace [public]:currentTarget]]:19
    19:pushdouble [0.1]:21
    21:getlex [QName [ ]:23
    23:callproperty [QName [Namespace [public]:random],0]:26
    26:pushdouble [2.1]:28
    28:multiply:29
    29:add:30
    30:dup:31
    31:setlocal_2:32
    32:setproperty [Multiname [name = scaleY,nsset = [Namespace [private :: B Namespace [public],Namespace [private :: B.as $ 25],Namespace [packageInternalNamespace],Namespace [namespace :: http://adobe.com/AS3/2006/builtin],Namespace [protectedNamespace :: B] ,命名空间[staticProtectedNamespace :: B],命名空间[staticProtectedNamespace :: flash.display使用:雪碧],命名空间[staticProtectedNamespace :: flash.display使用:级DisplayObjectContainer],命名空间[staticProtectedNamespace :: flash.display使用:InteractiveObject],命名空间[staticProtectedNamespace :: FLAS h.display:的DisplayObject],命名空间[staticProtectedNamespace :: flash.events:此事件],命名空间[staticProtectedNamespace:对象]]]]:34
    34:getlocal_2:35
    35:杀[2] :37
    37:setproperty [Multiname [name = scaleX,nsset = [Namespace [private :: B],Namespace [public],Namespace [private :: B.as $ 25],Namespace [packageInternalNamespace] namespace :: http://adobe.com/AS3/2006/builtin],Namespace [protectedNamespace :: B],Namespace [staticProtectedNamespace :: B],Namespace [staticProtectedNamespace :: flash.display:Sprite],Namespace [staticProtectedNamespace:命名空间[staticProtectedNamespace :: flash.display:InteractiveObject],命名空间[staticProtectedNamespace :: flash.display:DisplayObject],命名空间[staticProtectedNamespace :: flash.events:EventDispatcher] ]]]]:39
    39:debugline [30]:41
    41:returnvoid:42
    }
    trai ts =(no traits)

    有关AVM2指令的更多信息,请访问 documentation SWF文件格式规范(PDF链接)。

    <其他涉及第三方软件的选项,我还没有完全探究:


    1. 使用 FlashFirebug - 就我个人而言,我还没有设法让它运行
      ,也许我没有正确设置。 li>
    2. 使用getObjectsUnderPoint跟踪对象(实例名/ etc)的信息,并使用滚动/鼠标悬停处理程序,然后使用商业反编译器使用获得的信息查找处理程序。 $ b

    HTH


    Is there any way to find out what methods get called when moving the mouse over an object in a Flash project?

    解决方案

    So far @rvmook's partial solution is the closest from my point of view. It would help if you use DisplayObjectContainer's getObjectsUnderPoint() method to get a list of display objects you roll over, then loop through them and check which one has rollover/mouseover event handlers, then continue drilling down.

    So one short solution would be:

    1. Load the swf you want to find out the name of that rollover/mouseover handler.*
    2. Add a rollover handler(with bubbles set to true)
    3. In the rollover handler loop through the objects under the mouse that have rollover/mouseover handlers and get their details.

    Note! getObjectsUnderPoint() works if the loading swf has permissions from the domain hosting the loaded swf. One way to find areInaccessibleObjectsUnderPoint() method. If you own the loaded swf there shouldn't be any problems. Otherwise you either need a crossdomain.xml on the domain hosting the loaded swf granting the loader swf's domain access (and the loader swf should pass new LoaderContext(true) as the second parameter for load() method of the Loader intance) or use a server side script in the language of your choice to proxy/copy over the loaded swf first.

    Here's a basic example of what I mean:

    package{
        import flash.display.*;
        import flash.events.*;
        import flash.geom.Point;
        import flash.net.URLRequest;
        import flash.sampler.getMemberNames;
    
        public class BasicInfoTest extends Sprite{
    
            private var cursor:Point = new Point();
    
            public function BasicInfoTest(){
                init();
            }
            private function init():void{
                var loader:Loader = addChild(new Loader) as Loader;
                loader.load(new URLRequest('B.swf'));
                addEventListener(MouseEvent.ROLL_OVER,onOver);
            }
            private function onOver(event:MouseEvent):void{
                cursor.x = mouseX;cursor.y = mouseY;
                var obj:Array = getObjectsUnderPoint(cursor);
                var numObj:int = obj.length; 
                for(var i:int = 0 ; i < numObj ; i++){//look for objects under cursor that have rollover/mouseover event handlers
                    if(obj[i].hasEventListener(MouseEvent.ROLL_OVER) || obj[i].hasEventListener(MouseEvent.MOUSE_OVER)){
                        var members:Object = getMemberNames(obj[i]);//use @rvmook's method to get listeners
                        for each (var name:QName in members){
                            if (name.localName == "listeners"){
                                for (var j : int = 0; j < obj[i][name].length; j++){
                                    var func:Function = obj[i][name][j];
                                    try{
                                        func.call();
                                    }catch(error:Error){
                                        trace('Methods called on mouse over:',error.message.split('on ')[1].split('.')[0]);//parse error message, you might need to adapt this
                                        trace('StackTrace',error.getStackTrace()); 
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    

    This should do if you only need to find out the name of the method. If you need further information, you could access the loaded swf's bytearray and parse the actionscript bytecode to get information. I must admit binary and assembly are a bit out of my reach, but luckily there some great libraries out there to decompile swf files at runtime in as3. AS3SWF is a brilliant one, but does not deal much with actionscript tags, while as3commons is a great collection of libraries the specialize on the code aspect.

    Here is an adaptation of the previous example that uses the as3-commons libraries(bytecode,lang,logging and reflect) to display the method signature and body(as AVM2 instructions):

    package{
        import flash.display.*;
        import flash.events.*;
        import flash.geom.Point;
        import flash.net.*;
        import flash.sampler.getMemberNames;
        import flash.utils.ByteArray;
    
        import org.as3commons.bytecode.swf.SWFFile;
        import org.as3commons.bytecode.swf.SWFFileIO;
        import org.as3commons.bytecode.tags.DoABCTag;
    
        public class AdvancedInfo extends Sprite{
    
            private var cursor:Point = new Point();
            private var methodInfo:Array;
    
            public function AdvancedInfo(){
                init();
            }
            private function init():void{
                var byteLoader:URLLoader = new URLLoader(new URLRequest('B.swf'));
                byteLoader.dataFormat = URLLoaderDataFormat.BINARY;
                byteLoader.addEventListener(Event.COMPLETE,bytesLoaded);
            }
            private function bytesLoaded(event:Event):void{
                var ba:ByteArray = event.target.data as ByteArray;//get swf bytes
                var swfFile:SWFFile = new SWFFileIO().read(ba);//read the bytes using as3-commons
                var abcTags:Array = swfFile.getTagsByType(DoABCTag);//get actionscript bytecode (ABC) tags
                for each(var tag:DoABCTag in abcTags) methodInfo = tag.abcFile.methodInfo;//loop though tags and get method information
                //display and rollOver
                var d:Loader = addChild(new Loader()) as Loader;
                d.loadBytes(ba);
                addEventListener(MouseEvent.ROLL_OVER, rolledOver,true,0,true);
            }
            private function getMethodDetails(methodName:String):String{
                var result:String = '';
                for(var i:int = 0 ; i < methodInfo.length; i++){
                    if(methodInfo[i].methodName == methodName){
                        result += 'signature:\t'+methodInfo[i]+'\n';
                        result += 'body:\t'+methodInfo[i].methodBody;
                        return result;
                    }
                  }
                return result;
            }
            private function rolledOver(event:MouseEvent):void{
                cursor.x = mouseX;cursor.y = mouseY;
                var obj:Array = getObjectsUnderPoint(cursor);
                var numObj:int = obj.length; 
                for(var i:int = 0 ; i < numObj ; i++){
                    if(obj[i].hasEventListener(MouseEvent.ROLL_OVER) || obj[i].hasEventListener(MouseEvent.MOUSE_OVER)){
                        var members:Object = getMemberNames(obj[i]);
                        for each (var name:QName in members){
                            if (name.localName == "listeners"){
                                for (var j : int = 0; j < obj[i][name].length; j++){
                                    var func:Function = obj[i][name][j];
                                    try{
                                        func.call();
                                    }catch(error:Error){
                                        var methodName:String = error.message.split('on ')[1].split('.')[0].split('/')[1].split('()')[0]; 
                                        trace(getMethodDetails(methodName));
                                    }
                                }
                            }
                        }
                    }
                }
            }
    
        }
    }
    

    For documentation purposes here's the code for the SWF I loaded:

    package {
        import flash.events.*;
        import flash.display.*;
    
        public class B extends Sprite {
            public function B() {
                addEventListener(Event.ADDED_TO_STAGE, init)
            }
            private function init(event:Event = null) : void {
                for (var i : int = 0; i < 1000 ; i++) {
                    var b:Sprite = addChild(new Sprite()) as Sprite;
                    b.graphics.lineStyle(Math.random()*3);
                    b.graphics.drawCircle(-3, -3, 3);
                    b.x = 3+Math.random() * stage.stageWidth - 6;
                    b.y = 3+Math.random() * stage.stageHeight - 6;
                    b.buttonMode = true;
                    b.addEventListener(MouseEvent.ROLL_OVER, onRollOver);
                }
            }
            private function onRollOver(event : MouseEvent) : void {
                event.currentTarget.scaleX = event.currentTarget.scaleY = .1 + Math.random() * 2.1;
            }
        }
    }
    

    and here is a sample of the method detail trace using the getMethodDetails in my AdvancedInfo example:

    signature:  private function QName[Namespace[private::B]:onRollOver](QName[Namespace[public::flash.events]:MouseEvent]) : QName[Namespace[public]:void]
    body:   
        private function QName[Namespace[private::B]:onRollOver](QName[Namespace[public::flash.events]:MouseEvent]) : QName[Namespace[public]:void]
        {   
            //maxStack=5, localCount=3, initScopeDepth=9, maxScopeDepth=10
            0:debugfile     [/Users/george/Documents/Flex Builder 3/Del/src;;B.as]:2
            2:debugline     [28]:4
            4:getlocal_0        :5
            5:pushscope     :6
            6:debug     [1, 18, 0, 28]:11
            11:debugline        [29]:13
            13:getlocal_1       :14
            14:getproperty      [QName[Namespace[public]:currentTarget]]:16
            16:getlocal_1       :17
            17:getproperty      [QName[Namespace[public]:currentTarget]]:19
            19:pushdouble       [0.1]:21
            21:getlex       [QName[Namespace[public]:Math]]:23
            23:callproperty     [QName[Namespace[public]:random], 0]:26
            26:pushdouble       [2.1]:28
            28:multiply     :29
            29:add      :30
            30:dup      :31
            31:setlocal_2       :32
            32:setproperty      [Multiname[name=scaleY, nsset=[Namespace[private::B], Namespace[public], Namespace[private::B.as$25], Namespace[packageInternalNamespace], Namespace[namespace::http://adobe.com/AS3/2006/builtin], Namespace[protectedNamespace::B], Namespace[staticProtectedNamespace::B], Namespace[staticProtectedNamespace::flash.display:Sprite], Namespace[staticProtectedNamespace::flash.display:DisplayObjectContainer], Namespace[staticProtectedNamespace::flash.display:InteractiveObject], Namespace[staticProtectedNamespace::flash.display:DisplayObject], Namespace[staticProtectedNamespace::flash.events:EventDispatcher], Namespace[staticProtectedNamespace::Object]]]]:34
            34:getlocal_2       :35
            35:kill     [2]:37
            37:setproperty      [Multiname[name=scaleX, nsset=[Namespace[private::B], Namespace[public], Namespace[private::B.as$25], Namespace[packageInternalNamespace], Namespace[namespace::http://adobe.com/AS3/2006/builtin], Namespace[protectedNamespace::B], Namespace[staticProtectedNamespace::B], Namespace[staticProtectedNamespace::flash.display:Sprite], Namespace[staticProtectedNamespace::flash.display:DisplayObjectContainer], Namespace[staticProtectedNamespace::flash.display:InteractiveObject], Namespace[staticProtectedNamespace::flash.display:DisplayObject], Namespace[staticProtectedNamespace::flash.events:EventDispatcher], Namespace[staticProtectedNamespace::Object]]]]:39
            39:debugline        [30]:41
            41:returnvoid       :42
        }
    traits=(no traits)
    

    For more information on the AVM2 instructions visit the documentation or the SWF File format specs (PDF link).

    Other options that involve 3rd party software which I haven't fully explored would be:

    1. Using FlashFirebug - Personally I haven't managed to get it running, maybe I didn't setup correctly.
    2. Use getObjectsUnderPoint to trace information on objects(instance name/etc.) with rollover/mouseover handlers and then use a commercial decompiler to look for the handler using the information gained.

    HTH

    这篇关于鼠标悬停在Flash上​​的事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆