zoukankan      html  css  js  c++  java
  • SWF运行时判断两个DisplayObject是否同个类型,属于flash professional库中的同一个元件

    一般我们判断两个实例对象是否同样的类型,可以用typeof得到对象类型,然后用==号比较。

    typeof适用于原生类型。

    而对于自定义类型,虽然typeof得到的都是Object,但还有更强的招数:getQualifiedClassName

    利用这个原生函数可以获取到两个实例的真实类型。

    然而,对于Flash professional制作出来的swf,运行时要知道其中两个MovieClip是否来自库里边的同一个元件,上述方法都无能为力了。

    本文就是探讨这个问题。

    1、首先,想到的是,如果两个实例相同类型,那么在内存中应该有类似的结构。不过flash并没有直接获取内存的接口;

    2、替代直接获取内存的方法,可以找到ByteArray。利用ByteArray.writeObject可以把对象以AMF方式序列化。

    3、但是,直接把两个MovieClip序列化,得到的ByteArray肯定不一样,因为毕竟有动态的变量值,例如x/y等。

    4、那么如果不直接对MovieClip本身writeObject,而是对它的子元件writeObject呢?一度尝试过这种方法,但最后测试的时候发现这个并没有普遍适用性,因为子元件也可能有动态的东西,例如name。运行时会被赋予各种instanceXXX名称。

    5、先抛开MovieClip,那么对最基础的Shape怎么对比相同呢?Shape无非就是画图,那么最好不过就是对比画图数据是否一致了。

         graphics.readGraphicsData()能获取到Vector,而且Vector里边的内容都是静态的。

         再结合ByteArray.writeObject就可以轻松比较到两个Shape是否一致了。

    6、利用上边Shape的思维,对MovieClip也做一样的处理。每帧获取graphics数据,writeObject到ByteArray中。最后做比较。

    详细代码:

                  /**
                   * 判断是否来自Flash Professional库里的同一个元件
                   * @param a
                   * @param b
                   */
                   private function equals(a:DisplayObject, b:DisplayObject):Boolean
                  {
                          if((a is MovieClip && b is MovieClip) || (a is Shape && b is Shape))
                         {
                                var byteArrayA:ByteArray = new ByteArray();
                                var byteArrayB:ByteArray = new ByteArray();
                                if(a is MovieClip)
                               {
                                       var mcA:MovieClip = a as MovieClip;
                                       var mcB:MovieClip = b as MovieClip;
                                       var isPlayingA:Boolean = mcA.isPlaying;
                                       var isPlayingB:Boolean = mcB.isPlaying;
                                       var currentFrameA:int = mcA.currentFrame;
                                       var currentFrameB:int = mcB.currentFrame;
                                      
                                       for (var k:int = 1; k <= mcA.totalFrames; k++)
                                      {
                                             mcA.gotoAndStop(k);
                                             byteArrayA.writeObject(mcA.graphics.readGraphicsData());
                                      }
                                       for (var i :int = 1; i <= mcB.totalFrames; i++)
                                      {
                                             mcB.gotoAndStop(i);
                                             byteArrayB.writeObject(mcB.graphics.readGraphicsData());
                                      }
                                      
                                       if(isPlayingA)
                                             mcA.gotoAndPlay(currentFrameA);
                                       else
                                             mcA.gotoAndStop(currentFrameA);
                                       if(isPlayingB)
                                             mcB.gotoAndPlay(currentFrameB);
                                       else
                                             mcB.gotoAndStop(currentFrameB);
                               }
                                else if(a is Shape)
                               {
                                       var shapeA:Shape = a as Shape;
                                       var shapeB:Shape = b as Shape;
                                      byteArrayA.writeObject(shapeA.graphics.readGraphicsData());
                                      byteArrayB.writeObject(shapeB.graphics.readGraphicsData());
                               }
                               
                                if(byteArrayA.length != byteArrayB.length)
                               {
                                       return false;
                               }
                                else
                               {
                                      byteArrayA.position = byteArrayB.position = 0;
                                       while(byteArrayA.bytesAvailable)
                                      {
                                              if(byteArrayA.readByte() != byteArrayB.readByte())
                                                     return false;
                                      }
                                       return true;
                               }
                         }
                          return false;
                  }

    验证测试:

    情况1:

    一个MovieClip,在舞台上放置两份。

    Image(30)

    运行时只有1份MovieClip数据,1份Shape数据

    Image(31)

    算法有效!

    情况2:

    基于情况1,让副本元件稍稍不同。

    Image(32)

    运行时检测得到2份Shape数据,2份MovieClip数据。

    Image(33)

    算法有效!

  • 相关阅读:
    小白的源码阅读之旅_RazorEngine_起因
    Sqlserver_小工具_Json解析
    Sqlserver_小工具_批量字段约束处理
    SqlServer_小工具_获取数据库空间信息获取
    SqlServer_小工具_系统表的使用
    Sqlserver_小工具_字符统计(区分大小写)
    SqlServer_小工具_存储空间单位自适应
    不断优化,重构我的代码-----拖拽jquery插件
    canvas绘制二次贝塞尔曲线----演示二次贝塞尔四个参数的作用
    requestAnimationFrame与setInterval,setTimeout
  • 原文地址:https://www.cnblogs.com/kenkofox/p/3833352.html
Copyright © 2011-2022 走看看