9RIA.com天地会 - 论坛

返回列表 发帖

天地培训

9RIA天地会官方培训机构

Adobe官方认证培训中心

[新闻资讯] [业界动态] AS3中显示对象的撤消与恢复

  • 资讯类型: 翻译
  • 来源页面: http://blog.alanklement.com/2009/09/17/as3-undo-redo-with-display-objects/
  • 资讯原标题: AS3 Undo / Redo With Display Objects
  • 资讯原作者: Alan
  • 我的评论:
    对这篇文你有啥看法,跟贴说说吧!欢迎口水和板砖,哈哈。欢迎大家和我们一同分享更多资讯。

    关于撤消&恢复操作有许多例子可寻,但我想靠自身解决。我没有看其他人的解决办法,感到很庆幸,因为我想出了一个非常不同且更简洁的解决方案。
    网上大多数撤消&恢复例子涉及到命令模式或有些过时的备忘录模式。在正常情况下这些模式是牢靠的,但是他们有大量的重复代码。这些办法的另一个缺陷是设计者必须创建一个方法以特定方式改变显示对象,因此它可以被记录下来。最后,它不可能操作对象的多个属性(一次性)或说是非常困难地。这些问题使脱颖而出的上述模式即不容易实现也不便于移值。
    我的方法是在运行时定义什么属性需要记录,直接检查显示列表,并提取一个值对象记录的值进行排序。这个对象可以排序用于稍后检索或清理和回收

    实现的代码非常简单:
    1. // Create recorder and tell what properties you want to record
    2. // add as many display object properties you want: e.g. width, height, scaleX, scaleY, alpha.....
    3. propertyRecorder = new PropertyRecorder(redSquare, ["x","y","rotation"]);

    4. //When desired, record the history
    5. propertyHistory.recordNewHistory();

    6. // Call undo() or redo() anytime you want
    7. propertyHistory.undo();
    8. propertyHistory.redo();
    复制代码
    这个例子使用2个轻量级对象,但是如果需要的话可以将它们合并成一个。历史值对象是抽象可读性。
    上面的例子可以从这里下载。如果你有FDT,可以导入到项目中。没有FDT,可以解压缩包,所有资源都在里面。
    属性记录器:
    1. public class PropertyRecorder
    2. {
    3.      private var objectToRecord : *;
    4.      private var currentHistoryIndex : uint;
    5.      private var historyStates : Array = [];
    6.      private var propertiesToWatch : Array;

    7.      public function PropertyRecorder(objectToRecord : *, propertiesToWatch : Array)
    8.      {
    9.           this.propertiesToWatch = propertiesToWatch;
    10.           this.objectToRecord = objectToRecord;
    11.           recordNewHistory();
    12.      }

    13.      public function undo() : void
    14.      {
    15.            if(currentHistoryIndex > 0)
    16.            {
    17.                 currentHistoryIndex--;
    18.                 var historyToRestore : PropertyVO = PropertyVO(historyStates[currentHistoryIndex]);
    19.                 historyToRestore.restoreProperties(objectToRecord);
    20.              }
    21.        }

    22.        public function redo() : void
    23.        {
    24.              if(currentHistoryIndex < historyStates.length - 1)
    25.              {
    26.                    currentHistoryIndex++;
    27.                    var historyToRestore : PropertyVO = PropertyVO(historyStates[currentHistoryIndex]);                               
    28.                    historyToRestore.restoreProperties(objectToRecord);
    29.              }
    30.         }

    31.         public function recordNewHistory() : void
    32.         {
    33.              checkForOldHistoryToClean();         
    34.         }

    35.         private function checkForOldHistoryToClean() : void
    36.         {
    37.                 while(currentHistoryIndex + 1 < historyStates.length)
    38.                 {
    39.                         PropertyVO(historyStates.pop()).dispose();
    40.                 }

    41.                 createNewHistoryVO();               
    42.         }

    43.         private function createNewHistoryVO() : void
    44.         {                       
    45.                 var historyVO : PropertyVO = new PropertyVO(propertiesToWatch);         
    46.                 historyVO.extractCurrentProperties(objectToRecord);

    47.                 historyStates.push(historyVO);
    48.                 currentHistoryIndex = historyStates.length - 1;
    49.         }
    复制代码
    PropertyVO:
    1. public class PropertyVO
    2. {       
    3.         private var dictionary : Dictionary = new Dictionary(true);

    4.         public function PropertyVO(propertiesToWatch : Array)
    5.         {
    6.                 for each (var item : String in propertiesToWatch)
    7.                 {
    8.                         dictionary[item] = "";
    9.                 }       
    10.         }

    11.         public function extractCurrentProperties(objectToRecord : *) : void
    12.         {
    13.                 for (var property : String in dictionary)
    14.                 {                               
    15.                         dictionary[property] = objectToRecord[property];
    16.                 }
    17.         }

    18.         public function restoreProperties(objectToRestore : *) : void
    19.         {
    20.                 for (var property : String in dictionary)
    21.                 {
    22.                         objectToRestore[property] = dictionary[property];
    23.                 }
    24.         }

    25.         public function dispose() : void
    26.         {
    27.                 for (var item : String in dictionary)
    28.                 {
    29.                         item = null;       
    30.                 }

    31.                 dictionary = null;
    32.         }
    33. }
    复制代码
    1

    评分人数

    • 达达

    达达 赐本贴 威望 + 1 银子 + 20  诏曰:

    懒得令神发指

    天地人才库
    memento模式很靠谱,特别在做一些需要撤销操作的程序中。

    TOP

    优点是简洁。
    缺点是没有办法处理稍微复杂的情况。某些对象依赖与当前被移动的呢?
    比如形变工具旁边的那些handles 。
    我觉得 undo 和 redo 就用command 好了,省的让我们没见过世面的老头花心思猜实现用意。要不然模式有啥用?

    TOP

    好兄弟,讲义气!---by eko

    踏上天地会荣耀之路!

     

    申请舵主

    加入掘金队

    加入译林军

    知识专题整理

     

    咨询(QQ):

    1442604479(小地)

     

    作者似乎认为Undo/Redo只是针对简单对象的属性而言的。
    在稍微复杂一点的情况中根本不适用。

    TOP

    我的话会考虑用堆栈来做,没想到还有这种方法。
    的确在某些简单的操作上可以非常优雅的解决问题。

    TOP

    返回列表