Animation System in Slide

语义设计

一个完整的动画由若干动画节点组成,一个动画节点以start_animate开头,以end_animate结尾,一个动画节点可以包含若干动画描述,每一个动画描述指定了在这个动画节点中,某个属性将要变成什么

指令 描述
start_animate([duration]) 开启一段动画描述(开启一个动画节点)
end_animate() 结束一段动画描述(结束一个动画节点)
<do_something>() 对某个属性进行何种修改
after(other|time) 在某个对象执行完它当前的动画后/在某个时间点后执行
duration() 获取当前对象当前动画描述的持续时间

约定

表示动画节点,当存在很多个动画节点时,第个动画节点可以被表示成

attr表示属性

表示对attr这个属性的一个动画描述

表示对attr这个属性的一个修改操作(没有动画效果,就是瞬时的事情)

不管是还是,都可以定义它们所位于的帧编号,开始时间,结束时间(对于修改操作来说,无非就是开始时间与结束时间相同)

来取开始时间,例如

来取结束时间,例如

来取帧编号,例如

来取出这个动画节点中,跟attr有关的那个动画描述,如果中不存在与attr有关的动画节点,则

讨论

Case.1 位于同一帧下的两个动画节点

Case.1.1

若存在两个动画节点,满足,$R_{attr}(N_i) R_{attr}(N_j)$

之后又添加了一个动画,那么就意味着应该不需要继续被执行了,一切以新的的描述为准,所以时间表画出来应该如下:

image-20230909192539680

Case.1.2

若存在两个动画,满足

同理,当开始时,意味着不需要被执行了,时间表如下:

image-20230909193430017

Case.2 位于不同帧下的两个动画节点

是靠前的某帧的动画节点,是靠后的某帧的动画节点

此时无法把画在同一个时间轴上,我们知道这么一件事:如果,那么一定可以覆盖对这个attr的效果,所以开始执行的时候直接把给删了就行了

Case.3 代码实现层

假设正打算对元素的attr属性进行修改

Case.3.1 Basic类

  • 如果is_animating为真,那么该元素一定存在一个动画节点,新建一个,需要使得:
    • 只需要在处保留这三个属性,然后把挂到上即可
  • 如果is_animating为假,设该元素的上一个动画节点为,新建一个
    • 恰好成立
      • 可以利用的结束回调,让在恰当的时机执行
    • 否则,若
      • 可以直接执行,无需等待
    • 否则
      • 新建一个动画节点,让
      • 利用的结束回调,让在恰当的时机执行

Case.3.2 Container类

一个container包含若干element,在container中的动画稍微复杂一点,需要做一点补充定义,在container中的动画可以被分成两类

  • 对某一个集合中的element的attr进行单步操作
  • 对某一个集合中的element的attr进行连续多步操作

设计如下

  • 当开始录制动画时,设动画可以被描述为,为自己新建一个动画节点,为内部的部分元素建立动画节点,假设第个元素建立的动画节点被描述成
    • 对于那些不涉及动画操作的元素来说,理论上来说是没有必要的
    • 对于那些涉及到动画操作的元素来说
      • 如果对的操作最终是单步操作,则:
      • 如果对的操作最终是多步操作,假设是步,则理论上需要对建立个动画节点:
  • 当普通修改时,设修改可以被描述为
    • 对内部元素进行操作时,显然需要让内部元素的修改开始时间与保持一致

Case3.3

Case3.3.1

container开启动画,内部element有并行的不同的动画步

Array a(Box b1, Box b2, Box b3);
D: animate duration
S: animate start stamp
a.after(S);
a.start_animate(D);
    // 动画1: [S, S+D/2]
    b1.after(a);
    b1.start_animate(D/2);
    b1.<prop>();
    b1.end_animate();
    
    // 动画2: [S+D/2, S+D]
    b1.after(a + D/2);
    b1.start_animate(D/2);
    b1.<prop>();
    b1.end_animate();
    
    // 动画3: [S, S+D]
    b1.after(a);
    b1.start_animate(D);
    b1.<prop>();
    b1.end_animate();
a.end_animate();

Case3.3.2

container开启延时

Array a(Box b1, Box b2, Box b3);
D: animate duration
S: animate start stamp
a.after(S);
    // 行动1: S
    b1.after(a);
    b1.<prop>();
    
    // 行动2: S(行动1之后)
    b1.after(a);
    b1.<prop>();
    
    // 行动3: S(行动2之后)
    b1.after(a);
    b1.<prop>();

Case3.3.3

container没有发生动画,仅仅是container内部的element进行了动画

Array a(Box b1, Box b2, Box b3);
D: animate duration
S: animate start stamp
b1.after(S)
// 动画1: [S, S+D/2]
b1.start_animate(D);
b1.<prop>();
b1.end_animate(D);
    
// 动画2: [S+D/2, S+D]
b1.start_animate(D);
b1.<prop>();
b1.end_animate(D);
    
// 动画3: [S, S+D]
b1.after(S)
  .start_animate(D);
b1.<prop>();
b1.end_animate();

我们把element叫做,container叫做,把对的一次涉及到属性修改的函数调用叫做

可以对定义出函数,分别表示的动画开始时间,的动画持续时间,是否处于录制动画的状态

可以对定义出函数,满足,分别表示的相对开始时间点,和相对持续时间

观察发现,应有如下关系成立: