您的位置:首页 > 其它

Flash文本引擎, 第二部分: 交互

2013-08-09 09:32 399 查看
[原文链接: http://guyinthechair.com/2010/06/the-flash-text-engine-part-2-interaction/ ]

[原文作者:
Paul Taylor 原文时间: Jun. 28, 2010 ]

[原创翻译: http://www.smithfox.com/?e=183 ,转载请保留此声明, 谢谢]

这是介绍Flash文本引擎系列文章的第二部分: 第一部分, 第二部分, 第三部分.

[b]首先需要澄清[/b], 这些系列文章不是写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 型的光标 :) , 总之, 希望你也喜欢! 祝你好运!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: