对象同步和交互是多媒体演示中的两个核心问题。EDHM采用事件驱动的原理,使同步和交互的定义简单明了。 事件驱动是指系统的运行表现为一系列动作的执行,而只有事件才能激发动作。动作包括页间跳转和对页内对象的操作(启动、停止、移动对象等),以及暂停、继续、退出等。基本事件有定时器事件(timer event)、按钮事件(button-click event)等。动作即是对事件的响应,下面将分别介绍对各个事件如何定义响应动作,以及怎样通过定义动作来解决上面提到的核心问题──定义同步和交互。 定时器事件 定时器事件是一种周期性事件,在开始播放一页时启动定时器,设定定时器时间间隔为Dt,则每经过Dt时间,系统就会收到定时器事件。如果对定时器事件作出响应,执行动作,系统就会随时间的推移产生变化。 我们用时间轴来确定对定时器事件的响应。时间轴是一维的轴,单位是Dt 。一页中所有对象排列在轴上,如图7-16所示: 7-16 时间轴 ![]() 在实现方法上保证在时间轴上定义为先执行的操作一定会先执行,同时执行的操作一定会同时执行,从而保证了同步关系的正确性。 一些著作工具在时间轴上使用物理时间计时,难以保证同步关系的正确执行。以上图为例,预定Audio1、Text2的开始时间分别是t1、t2,如果Audio1的文件比较大或需要从网上传输,启动花费的时间多于t2-t1,则时间超过t2后Audio1才开始播放,可能造成Text2先于Audio1开始的现象,与预定顺序相反,可见用物理时间计时是不合适的。 Ark引入了虚拟时间的概念。其中的时间实际是一个计数器的值,比如Audio1的启动时间为t1,其含义是当计数器的值为t1时启动Audio1。计数器初始值为0,每隔一个固定的Dt,系统就产生一个时钟消息,在处理时钟消息的例程中,如果当前计数器的值为t,则启动所有开始时间为t的对象,停止结束时间为t的对象,这些操作都完成后把计数器的值加1。这里最关键的一点是:任何一个应该在虚拟时间t进行的操作完成之前,计数器的值不会增加,因此定于t+1或更后时刻进行的操作不可能提前进行。 这里举例说明一下。比如Audio1存在网络上,需要先传到本地一部分才能开始播放。在等待传输的过程中可能系统又响应了几次时钟消息,但由于启动过程未完,计数器的值时钟没增加,因此Text2不可能出现。只有等Audio1开始播放,下一次执行例程时才把计数器的值加1,直加到t2时才启动Text2。虚拟时间可以在等待时暂时停止,而物理时间停不下来。 上面说明了如何用虚拟时间保证先后次序,如何保证定义为同时启动的对象同时出现呢?这实际上只是一个技术性问题。比如图中Image1和Audio1开始时间相同,如果在例程中把Image1显示出来后再启动Audio1,实际看到的效果可能是Image1和Audio1出现时间相差很远。但如果把数据的显示和数据的准备分开,比如先把Image1的图像文件和Audio1的声音文件读到本地内存中准备好,再显示Image1和播放Audio1,看起来Image1和Audio1就是同时出现了。 因为虚拟时间可以暂停,因此演示实际播放时间可能会长于预想的播放时间。这其实无关紧要,因为观众重视的只是同步关系(它决定能否正确表达演示的内容),而不是一定要在几时几刻出现什么内容。 但是,仅用时间轴能定义的同步关系还是有限,有些复杂的同步关系难以在时间轴上表示出来,必须用其他方式描述。在EDHM中还定义了一种描述语言(ArkScript),帮助定义同步关系。 按钮事件 按钮或热区是和一系列动作相联系的一定形状(一般是矩形)的区域。当用户用鼠标点中按钮时系统就收到按钮点按事件,从而引发动作的执行。用户和系统交互最主要的方式就是点按按钮,以此来改变系统的运行状态,达到自由选择观看内容和顺序的目的。 为描述复杂动作设计的一种描述语言ArkScript,内嵌在系统中,用来描述超媒体演示过程中必需的动作。因此只在ArkScript中包含了标识符、表达式、分支、循环结构等语言的基本要素,又另外增添了一些函数来描述动作,比如启动对象Start()、停止对象Stop()、页跳转gotopage()、暂停pause()、继续resume()、延迟delay()等和一些基本的数学函数,页中每个对象还有left、top、width、height四个属性,修改这些属性就可以使对象的位置和大小发生变化,制造简单的动画效果。使用ArkScript就基本可以满足描述动作的需要。 EDHM用响应按钮事件的方法定义用户交互。在EDHM中,每个按钮对象都有一个字符串类型的属性"ClickScript"用来存储一段ArkScript程序,描述按下按钮后应该执行的动作。 事实上,用Script不仅可以定义交互动作,还可以定义同步关系,比如在Text1结束消息的响应函数中启动Audio1和Image1。实际上时间轴的功能完全可以用Script取代,但BHM中之所以保留了时间轴作为定义同步的工具,是因为时间轴直观简明,而用Script定义比较麻烦,缺乏直观性,给编辑和修改增加很多负担。应该把时间轴和Script结合起来使用,确定的同步关系用时间轴定义,不确定的同步关系和交互动作用Script定义,扬长避短。 其它事件 前面提到的定时器事件和按钮事件是最重要的两个事件,响应它们就基本可以满足定义同步和交互的需要,但有时还显得不够。 基于时间的数据对象播放结束事件也需要响应。基于时间的数据对象是指声音、视频等可以播放一段时间的对象,它们的播放过程往往受到各种因素,比如机器速度、同时打开设备多少、文件是否已经被调入内存,网络传输速率等的影响,结束时间是不确定的。有时需要在播放结束时立刻执行一个动作,也就是说要定义和播放结束的同步关系,这就需要响应延续性对象播放结束事件。响应动作用ArkScript描述。 实现上的基本思想就是把不确定的时间转化成确定的时间。 这种转化其实是对虚拟时间概念的发挥。给基于时间的数据加一个属性WaitEnd,让虚拟时间在基于时间的数据文件播完前暂停,播完后才继续。如图7-17所示: 7-17 时间不确定的同步关系 ![]() 希望在Audio1播放结束时停止Image1,启动Text2。只要把Audio1的WaitEnd属性设为TRUE,当时间增加到t3-1时,时钟消息处理例程看到Audio1的WaitEnd为TRUE,就检测Audio1是否播放结束,没结束就不增加计数器的值,下次执行例程时也同样检测,直到Audio1结束时才增加计数器的值到t3,这样再次执行例程时就可以停止Image1和Audio1,启动Text2了。使用WaitEnd属性后,Text2不确定的启动时间变成了确定的时间t3,这样时间轴的描述能力就大大增强了。 另外,还可以响应键盘事件等。事实上,EDHM可以响应的事件种类是不受限制的。 在EDHM中,采用直观的时间轴定义各种对象的同步关系,通过交互对象和内置的描述语言定义复杂动作,兼顾了直观性、灵活性和交互性。 |