TWaver - 专注UI技术

http://twaver.servasoft.com/
posts - 171, comments - 191, trackbacks - 0, articles - 2
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

在TWaver Flex中实现垂直文字布局

Posted on 2012-05-04 11:30 TWaver 阅读(2249) 评论(1)  编辑  收藏
最近有客户提到如何让Network上网元的标签垂直显示,首先想到的就是每个字符之间插入一个回车。这个用Network#labelFunction就能达到目的:
 1 network.labelFunction = function (element:IElement):String {
 2     var name:String = element.name;
 3     if(element.getClient('vertical')) {
 4         var result:String = '';
 5         for(var i:int=0,n:int=name.length; i<n; i++) {
 6             result += name.charAt(i) + '\n';
 7         }
 8         result = result.substr(0, result.length-1);
 9         return result;
10     } else {
11         return name;
12     }
13 };

来段代码测试看看:
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 3                 xmlns:twaver="http://www.servasoftware.com/2009/twaver/flex"
 4                 layout="absolute" width="100%" height="100%"
 5                 creationComplete="init()" backgroundColor="#FFFFFF" >
 6     <mx:Script>
 7         <![CDATA[
 8             import twaver.Consts;
 9             import twaver.ElementBox;
10             import twaver.IElement;
11             import twaver.Node;
12             import twaver.Styles;
13 
14             private var box:ElementBox = new ElementBox();
15 
16             private function init():void {
17                 network.labelFunction = function (element:IElement):String {
18                     var name:String = element.name;
19                     if(element.getClient('vertical')) {
20                         var result:String = '';
21                         for(var i:int=0,n:int=name.length; i<n; i++) {
22                             result += name.charAt(i) + '\n';
23                         }
24                         result = result.substr(0, result.length-1);
25                         return result;
26                     } else {
27                         return name;
28                     }
29                 };
30 
31                 var node1:Node = new Node();
32                 node1.location = new Point(100, 100);
33                 node1.setStyle(Styles.LABEL_POSITION, Consts.POSITION_LEFT_LEFT);
34                 node1.setClient('vertical', true);
35                 node1.name = '竖向文字Vertical Text';
36                 box.add(node1);
37 
38                 network.elementBox = box;
39             }
40         ]]>
41     </mx:Script>
42     <twaver:Network id="network" width="100%" height="100%" />
43 </mx:Application>

运行效果如下:


上面的方法很容易让文字垂直显示,但效果不是很理想,中英文混合时,英文也被一个字母一个字母地分开了。有没有更好的方案?答案是肯定的,借助于Flex的Flash Text Engine (FTE)和Text Layout Framework (TLF),可以很容易地让文字从上到下显示。
先来看看一个小例子,设置TextLayoutFormat的blockProgression属性为BlockProgression.RL即可:
 1 package {
 2     import flash.display.Sprite;
 3 
 4     import flashx.textLayout.container.ContainerController;
 5     import flashx.textLayout.conversion.TextConverter;
 6     import flashx.textLayout.elements.TextFlow;
 7     import flashx.textLayout.formats.BlockProgression;
 8     import flashx.textLayout.formats.TextLayoutFormat;
 9 
10     public class StaticHelloWorld extends Sprite {
11         public function StaticHelloWorld() {
12             var textLayoutFormat:TextLayoutFormat = new TextLayoutFormat();
13             textLayoutFormat.lineHeight = 30;
14             textLayoutFormat.locale = 'zh';
15             textLayoutFormat.blockProgression = BlockProgression.RL;
16 
17             var text:String = "测试竖向文字,再看看English如何?";
18             var textFlow:TextFlow = TextConverter.importToFlow(text, TextConverter.PLAIN_TEXT_FORMAT);
19             textFlow.hostFormat = textLayoutFormat;
20             textFlow.flowComposer.addController(new ContainerController(this, 25, 200));
21             textFlow.flowComposer.updateAllControllers();
22         }
23     }
24 }

运行效果如下: 
的确这样效果就好多了,英文不会被一个字母一个字母地打断,然后我们自定义一个Attachment:
  1 package {
  2     import flash.display.Sprite;
  3     import flash.text.engine.FontPosture;
  4     import flash.text.engine.FontWeight;
  5 
  6     import flashx.textLayout.container.ContainerController;
  7     import flashx.textLayout.elements.ParagraphElement;
  8     import flashx.textLayout.elements.SpanElement;
  9     import flashx.textLayout.elements.TextFlow;
 10     import flashx.textLayout.formats.BlockProgression;
 11     import flashx.textLayout.formats.TextDecoration;
 12     import flashx.textLayout.formats.TextLayoutFormat;
 13 
 14     import twaver.Styles;
 15     import twaver.network.ui.BasicAttachment;
 16     import twaver.network.ui.ElementUI;
 17 
 18     public class FTELabelAttachment extends BasicAttachment {
 19 
 20         private var textLayoutFormat:TextLayoutFormat = new TextLayoutFormat();
 21 
 22         public function FTELabelAttachment(elementUI:ElementUI, showInAttachmentCanvas:Boolean=false) {
 23             super(elementUI, showInAttachmentCanvas);
 24 
 25             this.textLayoutFormat.locale = 'zh';
 26             this.textLayoutFormat.blockProgression = BlockProgression.RL;
 27         }
 28 
 29         override public function updateProperties():void {
 30             super.updateProperties();
 31 
 32             this.textLayoutFormat.fontFamily = element.getStyle(Styles.LABEL_FONT);
 33             this.textLayoutFormat.color = element.getStyle(Styles.LABEL_COLOR);
 34             this.textLayoutFormat.fontSize = element.getStyle(Styles.LABEL_SIZE);
 35             this.textLayoutFormat.fontStyle = element.getStyle(Styles.LABEL_ITALIC) ? FontPosture.ITALIC : FontPosture.NORMAL;
 36             this.textLayoutFormat.fontWeight = element.getStyle(Styles.LABEL_BOLD) ? FontWeight.BOLD : FontWeight.NORMAL;
 37             this.textLayoutFormat.textDecoration = element.getStyle(Styles.LABEL_UNDERLINE ? TextDecoration.UNDERLINE : TextDecoration.NONE);
 38 
 39             var textFlow:TextFlow = new TextFlow();
 40             textFlow.hostFormat = this.textLayoutFormat;
 41             var p:ParagraphElement = new ParagraphElement();
 42             textFlow.addChild(p);
 43             var span:SpanElement = new SpanElement();
 44             span.text = network.getLabel(element);
 45             p.addChild(span);
 46 
 47             var fteLabel:Sprite = new Sprite();
 48             this.content = fteLabel;
 49             var containerController:ContainerController = new ContainerController(fteLabel, this.textLayoutFormat.fontSize, 1000);
 50             textFlow.flowComposer.addController(containerController);
 51             textFlow.flowComposer.updateAllControllers();
 52         }
 53 
 54         override public function get position():String {
 55             return element.getStyle(Styles.LABEL_POSITION);
 56         }
 57 
 58         override public function get xOffset():Number {
 59             return element.getStyle(Styles.LABEL_XOFFSET);
 60         }
 61 
 62         override public function get yOffset():Number {
 63             return element.getStyle(Styles.LABEL_YOFFSET);
 64         }
 65 
 66         override public function get padding():Number {
 67             return element.getStyle(Styles.LABEL_PADDING);
 68         }
 69 
 70         override public function get paddingLeft():Number {
 71             return element.getStyle(Styles.LABEL_PADDING_LEFT);
 72         }
 73 
 74         override public function get paddingRight():Number {
 75             return element.getStyle(Styles.LABEL_PADDING_RIGHT);
 76         }
 77 
 78         override public function get paddingTop():Number {
 79             return element.getStyle(Styles.LABEL_PADDING_TOP);
 80         }
 81 
 82         override public function get paddingBottom():Number {
 83             return element.getStyle(Styles.LABEL_PADDING_BOTTOM);
 84         }
 85 
 86         override public function get cornerRadius():Number {
 87             return element.getStyle(Styles.LABEL_CORNER_RADIUS);
 88         }
 89 
 90         override public function get pointerLength():Number {
 91             return element.getStyle(Styles.LABEL_POINTER_LENGTH);
 92         }
 93 
 94         override public function get pointerWidth():Number {
 95             return element.getStyle(Styles.LABEL_POINTER_WIDTH);
 96         }
 97 
 98         override public function get direction():String {
 99             return element.getStyle(Styles.LABEL_DIRECTION);
100         }
101 
102         override public function get fill():Boolean {
103             return element.getStyle(Styles.LABEL_FILL);
104         }
105 
106         override public function get fillColor():Number {
107             return element.getStyle(Styles.LABEL_FILL_COLOR);
108         }
109 
110         override public function get fillAlpha():Number {
111             return element.getStyle(Styles.LABEL_FILL_ALPHA);
112         }
113 
114         override public function get gradient():String {
115             return element.getStyle(Styles.LABEL_GRADIENT);
116         }
117 
118         override public function get gradientColor():Number {
119             return element.getStyle(Styles.LABEL_GRADIENT_COLOR);
120         }
121 
122         override public function get gradientAlpha():Number {
123             return element.getStyle(Styles.LABEL_GRADIENT_ALPHA);
124         }
125 
126         override public function get contentXScale():Number {
127             return element.getStyle(Styles.LABEL_CONTENT_XSCALE);
128         }
129 
130         override public function get contentYScale():Number {
131             return element.getStyle(Styles.LABEL_CONTENT_YSCALE);
132         }
133 
134         override public function get outlineWidth():Number {
135             return element.getStyle(Styles.LABEL_OUTLINE_WIDTH);
136         }
137 
138         override public function get outlineColor():Number {
139             return element.getStyle(Styles.LABEL_OUTLINE_COLOR);
140         }
141 
142         override public function get outlineAlpha():Number {
143             return element.getStyle(Styles.LABEL_OUTLINE_ALPHA);
144         }
145     }
146 }

 再自定义Node和NodeUI,使用这个Attachment代替TWaver自带的LabelAttachment:
自定义Node:
 1 package {
 2     import twaver.Node;
 3 
 4     public class FTELabelNode extends Node {
 5         public function FTELabelNode(id:Object=null) {
 6             super(id);
 7         }
 8 
 9         public override function get elementUIClass():Class {
10             return FTELabelNodeUI;
11         }
12     }
13 }
 
自定义NodeUI:
 1 package {
 2     import twaver.Node;
 3     import twaver.network.Network;
 4     import twaver.network.ui.NodeUI;
 5 
 6     public class FTELabelNodeUI extends NodeUI {
 7 
 8         private var _labelAttachment:FTELabelAttachment = null;
 9 
10         public function FTELabelNodeUI(network:Network, node:Node) {
11             super(network, node);
12         }
13 
14         override protected function checkLabelAttachment():void{
15             var label:String = this.network.getLabel(element);
16             if(label != null && label != ""){
17                 if(this._labelAttachment == null){
18                     this._labelAttachment = new FTELabelAttachment(thisfalse);
19                     this.addAttachment(this._labelAttachment);
20                 }
21             }else{
22                 if(this._labelAttachment != null){
23                     this.removeAttachment(this._labelAttachment);
24                     this._labelAttachment = null;
25                 }
26             }
27         }
28     }
29 }
30 
 
最后,写个例子看看效果:
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
 3                 xmlns:twaver="http://www.servasoftware.com/2009/twaver/flex"
 4                 layout="absolute" width="100%" height="100%"
 5                 creationComplete="init()" backgroundColor="#FFFFFF" >
 6     <mx:Script>
 7         <![CDATA[
 8             import twaver.Consts;
 9             import twaver.ElementBox;
10             import twaver.IElement;
11             import twaver.Node;
12             import twaver.Styles;
13 
14             private var box:ElementBox = new ElementBox();
15 
16             private function init():void {
17                 network.labelFunction = function (element:IElement):String {
18                     var name:String = element.name;
19                     if(element.getClient('vertical')) {
20                         var result:String = '';
21                         for(var i:int=0,n:int=name.length; i<n; i++) {
22                             result += name.charAt(i) + '\n';
23                         }
24                         result = result.substr(0, result.length-1);
25                         return result;
26                     } else {
27                         return name;
28                     }
29                 };
30 
31                 var node1:Node = new Node();
32                 node1.location = new Point(100, 100);
33                 node1.setStyle(Styles.LABEL_POSITION, Consts.POSITION_LEFT_LEFT);
34                 node1.setClient('vertical', true);
35                 node1.name = '竖向文字Vertical Text';
36                 box.add(node1);
37 
38                 var node2:Node = new FTELabelNode();
39                 node2.location = new Point(300, 100);
40                 node2.setStyle(Styles.LABEL_POSITION, Consts.POSITION_LEFT_LEFT);
41                 node2.name = '竖向文字Vertical Text';
42                 box.add(node2);
43 
44                 network.elementBox = box;
45             }
46 
47             private function changeFontSize():void {
48                 box.forEach(function (element:IElement):void {
49                     element.setStyle(Styles.LABEL_SIZE, element.getStyle(Styles.LABEL_SIZE) + 2);
50                 });
51             }
52         ]]>
53     </mx:Script>
54     <mx:VBox width="100%" height="100%">
55         <mx:HBox width="100%" height="20">
56             <mx:Button label="Change Font Size" click="changeFontSize()"/>
57         </mx:HBox>
58         <twaver:Network id="network" width="100%" height="100%" />
59     </mx:VBox>
60 </mx:Application>

恩,这就是我想要的效果 :

 更多关于FTE和TLF的信息,请参考Adobe官方文档:
TextLayoutFormat
TextFlow
textlayout
本文完整代码见附件:FTELabelAttachment

评论

# re: 在TWaver Flex中实现垂直文字布局  回复  更多评论   

2012-05-09 12:31 by 活性炭
挺不错的好好

只有注册用户登录后才能发表评论。


网站导航: