Flash文本引擎, 第二部分: 交互
[原文链接: http://guyinthechair.com/2010/06/the-flash-text-engine-part-2-interaction/? ?] 这是介绍Flash文本引擎系列文章的第二部分:?第一部分,?第二部分,?第三部分.? 首先需要澄清,这些系列文章不是写Adobe的文本布局框架(Text Layout Framework,以下简称TLF)的,TLF是一个高级的排版和文字布局框架,TLF是建立在FTE(Flash Text Engine)之上的,FTE是一个低层的Player native API,它在flash.text.engine?package内.? FTE交互在前一篇文章中,我介绍了如何渲染TextLine,本文将介绍如何和已经创建的TextLine交互. TextLine是一个InteractiveObjects?对象,你可以直接增加event listener以侦听哪些交互事件。 FTE也能让你为每一个ContentElement指定EventDispatcher. 当用户和ContentElement的数据交互时,会clone到用户指定的EventDispatcher. 我在下面的讨论中,你会发现每种方法都有其长处和短处. 方法一: 将TextLine看作InteractiveObject因为TextLine是InteractiveObject,你可以监听每个TextLine实例的键盘和鼠标事件. 这种方式,你能知道是在和哪个TextLine在交互,但主要缺点是对其所正在渲染的ContextElement却一无所知. 一个TextLine可以渲染多个ContentElement,多个TextLine又可以渲染同一个ContentElement. 看下面的Demo: Source 实际上,有的情况,你也没有必要知道是哪些ContentElement,比如,?你不关心TextLine的修饰: 下划线,删除线,是否被选中. 下面的Demo是可以选择文字的: Source 方法二: 用TextLineMirrorRegions??(以面简写成TLMRs)FTE交互的首选方式还是用 TextLineMirrorRegions?,上篇文章说过: 你必须用??TextElement,?GraphicElement,or?GroupElement? 之一来创建文本实例. 创建后你可以设置ContentElement.eventMirror属性为你所指定的EventDispatcher. 这种方式能让你和特定的ContentElement交互.? 在下面的demo代码中,我创建了一个EventDispather对象,并且设置给TextElement.eventMirror属性,然后监听这个EventDispather对象的 mouseMove 事件,每当Mouse over这个TextElement时,就会trace下来. var dispatcher:EventDispatcher = new EventDispatcher(); new TextElement('Inspiring quote here.',new ElementFormat( new FontDescription()),dispatcher); var onMouseMove:Function = function(e:MouseEvent):void{ trace('Mouse move on ' + e.target.toString()); } dispatcher.addEventListener(MouseEvent.MOUSE_MOVE,onMouseMove); 下面Demo中的两行文字是同一个TextElement的两个不同的部分: Source 和之前的Demo有什么不同之处? TextLine有一个mirrorRegions? 属性,保存了TextLineMirrorRegion数组(Vector). 由于多个ContentElement能被同一个TextLine所渲染,TextLine会为每个ContentElement创建TLMR实例,并且分别赋给各个ContentElement.eventMirror?属性. TextLine会监听自己的交互事件,当事件和任何一个TLMR的事件重叠时,TextLine会通知相应的TLMR. 在所有TextLine的正常事件处理结束后. 每个TLMR会用其eventMirror属性所指的EventDispather实例再次dispatch事件一次. 这个例子中,我为TextLine和其ContentElement的eventMirror都监听了 "MouseDown" 事件. 注意eventMirror的事件触发的时间: Source 下面的Demo,我用TextLineMirrorRegion为每个Element设置了不同的样式 Source 注意事项:如果没有<注意事项>,那就不是flash player的功能了 :) TLMR只是模拟了事件,它不会re-dispatch它从TextLine所接受到的实例,因为TLMR不是一个InteractiveObject. 如果你用eventMirror来监听 MouseEvent,你要意识到那是一个伪造的事件 -- 就算是target是TextLine,也是这样, 这些事件不是源?自TextLine,这点和player原生的事件不一样. Rollover/rollout事件这种模拟机制,也意味着我们受到Adobe选择这样做的摆布(或是限制),他们觉得?没有必要模拟rollover/rollout事件. 你会发现eventMirror并没有roll相关的事件. 由于ContentElement并没有display-list children,roll event的行为就和mouSEOver,mouSEOut的行为完全一样,相必Adobe是基于这一点认为没有必要实现roll事件的. 然而,Roll事件还是非常有必要的, 尽管 ContentElement没有 display-list children,然而它还是有 ContentElement children的,相当于 ContentElement的层次结构代替了 disply 的层次结构,所以 roll 事件还是必须的. 举个例子,看下面的xml model的渲染: <p> Outside the group. <group> <text color="#44AA00"> First group child. </text> <text color="#AA0044"> Second group child. </text> </group> Outside the group.? </p>? 上面这种case,你可能想让group这个node作为一个整体来看待,(就像一个带children的DisplayObjectContainer 那样). 下面就上这个xml model的例子,你将鼠标在 First group child和 Second group child之间划动时,你会发现你紧接着会看到来自group的 "mouSEOut","mouSEOver"两个事件,如果是roll 事件,应该只会收到从child来的mouSEOver和mouSEOut,应该没有group的相关mouSEOver和mouSEOut事件. ?下面的这个demo,按Mouse,会清空 trace. Source 比较:那,怎么搭配这两种方法呢? 简而言之,就是: 看情况. 如果你只是需要基本的交互功能,而并不关心上下文(比如 selection你就需要关心上下文),那就直接在TextLine上加listener. 如果你需要关心上下文,需要知道是在和哪个ContentElement交互,那你只能选择 event mirroring 的方式. P.S. ?也许我有点强迫症,每次悬停在FTE文字上时,我非常希望能看到 I 型的光标,我最喜欢的Demo,还是第二个,因为我实现了 I 型的光标? :) ?,总之,希望你也喜欢! 祝你好运! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |