Best Practice for Transitioning From Nested State to Nested State (see diagram)

前端 未结 3 1679
你的背包
你的背包 2021-02-02 04:21

I am trying to wrap my mind around the best way to implement nested state transitions in a single threaded programming language (Actionscript). Say I have a structure like this

3条回答
  •  走了就别回头了
    2021-02-02 04:45

    either I don't fully understand you problem, or you are making it much too complicated ... try to think simple, because basically, all what you want to do, is the following:

    1. retrieve a path within a tree
    2. execute multiple animations sequentially (along that very path)

    none of these things is much to hard. for the latter task, you can probably use one of the better AS3 animation libraries. but for the sake of understanding, let me offer you a lightweight solution:

    your problem is simply carrying out asynchronous tasks sequentially. retrieving the sequence itself is not really hard. however, you should consider, that not every path passes through the root (for example from one leaf to its sibbling). in the flash world, the only way to execute asynchronous tasks sequentially are callbacks. when one task finishes, it calls back, and from there you decide what to do next.

    so here comes some code:

    first, let's define an interface for all your leafs/nodes ... the following should do the trick:

    package  {
        public interface ITransitionable {
         //implementors are to call callback when the show/hide transition is complete
         function show(callback:Function):void;
         function hide(callback:Function):void;
         function get parent():ITransitionable;
        }
    }
    

    now the following class will be able to do transitions as you specified on trees of ITransitionable:

    package  {
     public class Transition {
      ///Array of animation starting functions
      private var funcs:Array;
      ///Function to call at the end of the transition
      private var callback:Function;
      public function Transition(from:ITransitionable, to:ITransitionable, callback:Function) {
       this.callback = callback;
       this.funcs = [];
       var pFrom:Array = path(from).reverse();
       var pTo:Array = path(to).reverse();
       while ((pFrom[0] == pTo[0]) && (pTo[0] != null)) {//eliminate common path to root
        pFrom.shift();
        pTo.shift();
       }
       pFrom.reverse();//bring this one back into the right order
       //fill the function array:
       var t:ITransitionable;
       for each (t in pFrom) this.funcs.push(hider(t));
       for each (t in pFrom) this.funcs.push(shower(t));
       this.next();
      }
      ///cancels the overall transition
      public function cancel():void {
       this.funcs = [];
      }
      ///creates a function that will start a hiding transition on the given ITransitionable.
      private function hider(t:ITransitionable):Function {
       return function ():void {
        t.hide(this.next());
       }
      }
      ///@see hider
      private function shower(t:ITransitionable):Function {
       return function ():void {
        t.show(this.next());
       }
      }
      ///this function serves as simple callback to start the next animation function
      private function next(...args):void {
       if (this.funcs.length > 0) this.funcs.shift()();
       else this.callback();
      }
      ///returns the path from a node to the root
      private function path(node:ITransitionable):Array {
       var ret:Array = [];
       while (node != null) {
        ret.push(node);
        node = node.parent;
       }
       return ret;
      }
     }
    
    }
    

    it's not a perfect beauty, but it should suffice to point you into the right direction. no need for fancy state machines, what so ever ... hope this helps ...

提交回复
热议问题