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

     最近有客户提到如何让Network上网元的标签垂直显示,首先想到的就是每个字符之间插入一个回车。这个用Network#labelFunction就能达到目的:

network.labelFunction = function (element:IElement):String {
	var name:String = element.name;
	if(element.getClient('vertical')) {
		var result:String = '';
		for(var i:int=0,n:int=name.length; i<n; i++) {
			result += name.charAt(i) + '\n';
		}
		result = result.substr(0, result.length-1);
		return result;
	} else {
		return name;
	}
};

    来段代码测试看看:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
				xmlns:twaver="http://www.servasoftware.com/2009/twaver/flex"
				layout="absolute" width="100%" height="100%"
				creationComplete="init()" backgroundColor="#FFFFFF" >
	<mx:Script>
		<![CDATA[
			import twaver.Consts;
			import twaver.ElementBox;
			import twaver.IElement;
			import twaver.Node;
			import twaver.Styles;

			private var box:ElementBox = new ElementBox();

			private function init():void {
				network.labelFunction = function (element:IElement):String {
					var name:String = element.name;
					if(element.getClient('vertical')) {
						var result:String = '';
						for(var i:int=0,n:int=name.length; i<n; i++) {
							result += name.charAt(i) + '\n';
						}
						result = result.substr(0, result.length-1);
						return result;
					} else {
						return name;
					}
				};

				var node1:Node = new Node();
				node1.location = new Point(100, 100);
				node1.setStyle(Styles.LABEL_POSITION, Consts.POSITION_LEFT_LEFT);
				node1.setClient('vertical', true);
				node1.name = '竖向文字Vertical Text';
				box.add(node1);

				network.elementBox = box;
			}
		]]>
	</mx:Script>
	<twaver:Network id="network" width="100%" height="100%" />
</mx:Application>

 

      运行效果如下:


     上面的方法很容易让文字垂直显示,但效果不是很理想,中英文混合时,英文也被一个字母一个字母地分开了。有没有更好的方案?答案是肯定的,借助于Flex的Flash Text Engine (FTE)和Text Layout Framework (TLF),可以很容易的让文字从上到下显示。
      先来看看一个小例子,设置TextLayoutFormat的blockProgression属性为BlockProgression.RL即可:

package {
	import flash.display.Sprite;

	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.conversion.TextConverter;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.formats.TextLayoutFormat;

	public class StaticHelloWorld extends Sprite {
		public function StaticHelloWorld() {
			var textLayoutFormat:TextLayoutFormat = new TextLayoutFormat();
			textLayoutFormat.lineHeight = 30;
			textLayoutFormat.locale = 'zh';
			textLayoutFormat.blockProgression = BlockProgression.RL;

			var text:String = "测试竖向文字,再看看English如何?";
			var textFlow:TextFlow = TextConverter.importToFlow(text, TextConverter.PLAIN_TEXT_FORMAT);
			textFlow.hostFormat = textLayoutFormat;
			textFlow.flowComposer.addController(new ContainerController(this, 25, 200));
			textFlow.flowComposer.updateAllControllers();
		}
	}
}

 

运行效果如下:


       的确这样效果就好多了,英文不会被一个字母一个字母地打断,然后我们自定义一个Attachment:

package {
	import flash.display.Sprite;
	import flash.text.engine.FontPosture;
	import flash.text.engine.FontWeight;

	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.elements.ParagraphElement;
	import flashx.textLayout.elements.SpanElement;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.formats.BlockProgression;
	import flashx.textLayout.formats.TextDecoration;
	import flashx.textLayout.formats.TextLayoutFormat;

	import twaver.Styles;
	import twaver.network.ui.BasicAttachment;
	import twaver.network.ui.ElementUI;

	public class FTELabelAttachment extends BasicAttachment {

		private var textLayoutFormat:TextLayoutFormat = new TextLayoutFormat();

		public function FTELabelAttachment(elementUI:ElementUI, showInAttachmentCanvas:Boolean=false) {
			super(elementUI, showInAttachmentCanvas);

			this.textLayoutFormat.locale = 'zh';
			this.textLayoutFormat.blockProgression = BlockProgression.RL;
		}

		override public function updateProperties():void {
			super.updateProperties();

			this.textLayoutFormat.fontFamily = element.getStyle(Styles.LABEL_FONT);
			this.textLayoutFormat.color = element.getStyle(Styles.LABEL_COLOR);
			this.textLayoutFormat.fontSize = element.getStyle(Styles.LABEL_SIZE);
			this.textLayoutFormat.fontStyle = element.getStyle(Styles.LABEL_ITALIC) ? FontPosture.ITALIC : FontPosture.NORMAL;
			this.textLayoutFormat.fontWeight = element.getStyle(Styles.LABEL_BOLD) ? FontWeight.BOLD : FontWeight.NORMAL;
			this.textLayoutFormat.textDecoration = element.getStyle(Styles.LABEL_UNDERLINE ? TextDecoration.UNDERLINE : TextDecoration.NONE);

			var textFlow:TextFlow = new TextFlow();
			textFlow.hostFormat = this.textLayoutFormat;
			var p:ParagraphElement = new ParagraphElement();
			textFlow.addChild(p);
			var span:SpanElement = new SpanElement();
			span.text = network.getLabel(element);
			p.addChild(span);

			var fteLabel:Sprite = new Sprite();
			this.content = fteLabel;
			var containerController:ContainerController = new ContainerController(fteLabel, this.textLayoutFormat.fontSize, 1000);
			textFlow.flowComposer.addController(containerController);
			textFlow.flowComposer.updateAllControllers();
		}

		override public function get position():String {
			return element.getStyle(Styles.LABEL_POSITION);
		}

		override public function get xOffset():Number {
			return element.getStyle(Styles.LABEL_XOFFSET);
		}

		override public function get yOffset():Number {
			return element.getStyle(Styles.LABEL_YOFFSET);
		}

		override public function get padding():Number {
			return element.getStyle(Styles.LABEL_PADDING);
		}

		override public function get paddingLeft():Number {
			return element.getStyle(Styles.LABEL_PADDING_LEFT);
		}

		override public function get paddingRight():Number {
			return element.getStyle(Styles.LABEL_PADDING_RIGHT);
		}

		override public function get paddingTop():Number {
			return element.getStyle(Styles.LABEL_PADDING_TOP);
		}

		override public function get paddingBottom():Number {
			return element.getStyle(Styles.LABEL_PADDING_BOTTOM);
		}

		override public function get cornerRadius():Number {
			return element.getStyle(Styles.LABEL_CORNER_RADIUS);
		}

		override public function get pointerLength():Number {
			return element.getStyle(Styles.LABEL_POINTER_LENGTH);
		}

		override public function get pointerWidth():Number {
			return element.getStyle(Styles.LABEL_POINTER_WIDTH);
		}

		override public function get direction():String {
			return element.getStyle(Styles.LABEL_DIRECTION);
		}

		override public function get fill():Boolean {
			return element.getStyle(Styles.LABEL_FILL);
		}

		override public function get fillColor():Number {
			return element.getStyle(Styles.LABEL_FILL_COLOR);
		}

		override public function get fillAlpha():Number {
			return element.getStyle(Styles.LABEL_FILL_ALPHA);
		}

		override public function get gradient():String {
			return element.getStyle(Styles.LABEL_GRADIENT);
		}

		override public function get gradientColor():Number {
			return element.getStyle(Styles.LABEL_GRADIENT_COLOR);
		}

		override public function get gradientAlpha():Number {
			return element.getStyle(Styles.LABEL_GRADIENT_ALPHA);
		}

		override public function get contentXScale():Number {
			return element.getStyle(Styles.LABEL_CONTENT_XSCALE);
		}

		override public function get contentYScale():Number {
			return element.getStyle(Styles.LABEL_CONTENT_YSCALE);
		}

		override public function get outlineWidth():Number {
			return element.getStyle(Styles.LABEL_OUTLINE_WIDTH);
		}

		override public function get outlineColor():Number {
			return element.getStyle(Styles.LABEL_OUTLINE_COLOR);
		}

		override public function get outlineAlpha():Number {
			return element.getStyle(Styles.LABEL_OUTLINE_ALPHA);
		}
	}
}

 

      再自定义Node和NodeUI,使用这个Attachment代替TWaver自带的LabelAttachment:

自定义Node:

package {
	import twaver.Node;

	public class FTELabelNode extends Node {
		public function FTELabelNode(id:Object=null) {
			super(id);
		}

		public override function get elementUIClass():Class {
			return FTELabelNodeUI;
		}
	}
}

     自定义NodeUI:

package {
	import twaver.Node;
	import twaver.network.Network;
	import twaver.network.ui.NodeUI;

	public class FTELabelNodeUI extends NodeUI {

		private var _labelAttachment:FTELabelAttachment = null;

		public function FTELabelNodeUI(network:Network, node:Node) {
			super(network, node);
		}

		override protected function checkLabelAttachment():void{
			var label:String = this.network.getLabel(element);
			if(label != null && label != ""){
				if(this._labelAttachment == null){
					this._labelAttachment = new FTELabelAttachment(this, false);
					this.addAttachment(this._labelAttachment);
				}
			}else{
				if(this._labelAttachment != null){
					this.removeAttachment(this._labelAttachment);
					this._labelAttachment = null;
				}
			}
		}
	}
}

 

最后,写个例子看看效果:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
				xmlns:twaver="http://www.servasoftware.com/2009/twaver/flex"
				layout="absolute" width="100%" height="100%"
				creationComplete="init()" backgroundColor="#FFFFFF" >
	<mx:Script>
		<![CDATA[
			import twaver.Consts;
			import twaver.ElementBox;
			import twaver.IElement;
			import twaver.Node;
			import twaver.Styles;

			private var box:ElementBox = new ElementBox();

			private function init():void {
				network.labelFunction = function (element:IElement):String {
					var name:String = element.name;
					if(element.getClient('vertical')) {
						var result:String = '';
						for(var i:int=0,n:int=name.length; i<n; i++) {
							result += name.charAt(i) + '\n';
						}
						result = result.substr(0, result.length-1);
						return result;
					} else {
						return name;
					}
				};

				var node1:Node = new Node();
				node1.location = new Point(100, 100);
				node1.setStyle(Styles.LABEL_POSITION, Consts.POSITION_LEFT_LEFT);
				node1.setClient('vertical', true);
				node1.name = '竖向文字Vertical Text';
				box.add(node1);

				var node2:Node = new FTELabelNode();
				node2.location = new Point(300, 100);
				node2.setStyle(Styles.LABEL_POSITION, Consts.POSITION_LEFT_LEFT);
				node2.name = '竖向文字Vertical Text';
				box.add(node2);

				network.elementBox = box;
			}

			private function changeFontSize():void {
				box.forEach(function (element:IElement):void {
					element.setStyle(Styles.LABEL_SIZE, element.getStyle(Styles.LABEL_SIZE) + 2);
				});
			}
		]]>
	</mx:Script>
	<mx:VBox width="100%" height="100%">
		<mx:HBox width="100%" height="20">
			<mx:Button label="Change Font Size" click="changeFontSize()"/>
		</mx:HBox>
		<twaver:Network id="network" width="100%" height="100%" />
	</mx:VBox>
</mx:Application>

 

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

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

手把手教你配置MAX96712解串器:从I2C地址分配到PWM帧同步 本文详细解析了MAX96712解串器在自动驾驶视觉链路中的核心配置流程。从I2C地址分配、GMSL2数据流映射到实现多摄像头精准同步的PWM帧同步触发,手把手指导工程师构建高可靠性的图像传输系统,并提供了实用的Linux调试技巧与问题排查思路。 阅读详情

相关推荐

深入了解神经网络:构建人工智能的基石

这篇博客将为您解释神经网络的构造,让您能够理解这个令人着迷的领域的基本工作原理。神经网络是人工智能领域的关键技术,它们的构造基于神经元的灵感,并结合了数学、统计和机器学习的原理。输入可以类比为神经元的树突,而输出可以类比为神经元的轴突,计算则可以类比为细胞核。较好的方法就是预先设定几个可选值,通过切换这几个值来看整个模型的预测效果,选择效果最好的值作为最终选择。:这是神经网络的核心部分,包含多个层次的神经元。、神经网络结构图中的拓扑与箭头代表着预测过程时数据的流向,跟训练时的数据流有一定的区别;

AI_dataloads的博客 2万+

Twaver-HTML5基础学习(31)Tree基本使用

Twaver-HTML5基础学习(31)Tree基本使用

见贤思齐焉,见不贤内自省 907

STM32实现任意角度移相全桥PWM

STM32实现任意角度移相全桥PWM,最小分辨率0.5度,频率占空比课任意调节 本文重点在于如何产生任意角度的移相, 两个定时器工作于主从模式,从模式为Gate mode,用第一个定时器触发第二个来实现延时移相

Wind blog 3万+

Twaver 中link流动效果,tooltip显示/隐藏

1.设置link的流动效果有时发现单纯设置link.setStyle('link.flow', true);并没有起作用,这时需要检查之前是否设置://流动线条network.setLinkFlowEnabled(true);2.设置toolTip的显示与隐藏    network.setToolTipEnabled(true);    network.setToolTipEnabled(fals...

Keep moving on. 1656

Arxml文件可视化:当汽车软件架构遇见交互式设计工具

本文探讨了Arxml文件在汽车电子系统开发中的可视化技术,结合AUTOSAR架构标准,介绍了如何利用现代Web技术构建交互式设计工具。通过三维组件关系图、动态数据流展示和版本对比等功能,显著提升开发效率和架构评审质量,适用于MBD和ASPICE开发流程。

weixin_29050271的博客 427

游戏封包抓取实战:雷电模拟器+ProxyDroid+查尔斯3.93+WPE全流程解析

本文详细解析了使用雷电模拟器、ProxyDroid、查尔斯3.93和WPE进行游戏封包抓取的全流程实战。通过环境搭建、代理配置与工具协同,手把手教你抓取HTTP/HTTPS及原始Socket数据,涵盖从流量转向、证书安装到数据分析和常见问题排查,是学习游戏网络协议分析与安全测试的实用指南。

u8v9w0x1y的博客 441

TextInput双向绑定ContainerController出错

TextInput控件除了输入数据,如果文本和一个数据双向绑定(一般是需要通过按钮改变文本,比如微调数字控件),在输入、选择文本、点击按钮改变文本等操作之后会出现错误。 断在flashx.textLayout.container::ContainerController文件

~。~||| 1459

中兴问天 BE7200MAX SFP 光口用华为猫棒替代光猫完整配置教程

PPPoE 账号密码:若原光猫为 Route 模式,在宽带设置页可见用户名,密码需按 F12 打开浏览器开发者模式,点击密码输入框,查看代码中 “value=” 后的内容即为明文密码。若仍失败,核对 PON 类型是否与运营商网络匹配。PON 认证信息:LOID(逻辑 ID,部分地区含密码)、设备 SN 码(标签或设备信息页)、PON 类型(GPON/EPON,运营商网络类型)。电脑保持与路由器连接,访问路由器管理地址(默认通常为 192.168.5.1,可参考路由器说明书),登录后台。

Gulper_Eel的博客 3329

Twaver-HTML5基础学习(33)自动布局

Twaver-HTML5基础学习(33)自动布局

见贤思齐焉,见不贤内自省 1068

解析 RABAX during SAPGUI Logon 错误及其解决方案

登录用户关联了初始启动程序,该程序由于未处理的异常导致运行时错误。在 ST22 查看错误的程序名和错误行。修复初始程序代码中的逻辑问题。重新部署修复后的代码。示例代码:防止未处理的异常TRY." 模拟逻辑处理ENDTRY.此代码通过 TRY-CATCH 块捕获潜在错误,避免程序崩溃。是 SAP 系统中常见的运行时错误,其根源可能涉及多个方面,包括用户配置、系统状态、数据库连接和自定义开发等。通过结合 ST22、SM21 等诊断工具,以及完善的代码实践和系统监控,可以有效预防和解决此类问题。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1780

基于matlab的阈值分割的车牌定位识别系统

车牌自动识别模块是现代社会智能交通系统(ITS)的重要组成部分,是图像处理和模式识别技术研究的热点,具有非常广泛的应用。车牌识别主要包括以下三个主要步骤:车牌区域定位、车牌字符分割、车牌字符识别。本案例通过对采集的车牌图像进行灰度变换、边缘检测、腐蚀及平滑等过程进行车牌图像预处理,并由此得到一种基于车牌颜色纹理特征的车牌定位方法,最终实现了车牌区域定位。车牌字符分割是为了方便后续对车牌字符进行匹配,从而对车牌进行识别。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 967

Twaver-HTML5基础学习(32)Network样式andTree样式

Twaver-HTML5基础学习(32)Network样式andTree样式

见贤思齐焉,见不贤内自省 1068

高级用法:LangChain 安全防护(Guardrails)

在调用开始时校验请求,可做关键词过滤、身份校验、限流等。= "human":return {}],# 使用],= "human":return {}],

Long_像风一样自由 316

Twaver-HTML5基础学习(14)连线(Link)连线类型(直线、延伸直线、正交直线)

Twaver-HTML5基础学习(14)连线(Link)连线类型(直线、延伸直线、正交直线)

见贤思齐焉,见不贤内自省 2108

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Twaver-HTML5基础学习(26)背景

Twaver-HTML5基础学习(26)背景

见贤思齐焉,见不贤内自省 648

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

TWaver初学实战——基于HTML5的交互式地铁图

每天坐地铁,经常看地铁图,有一天突然想到,地铁图不也是一种拓扑结果吗?TWaver到底能与地铁图擦出怎样的火花呢? 想到就干,先到网上找幅参考图。各种风格的地铁图还挺多,甚至有大学生自主设计制作,受到地铁相关人士的认可和赞扬。不过看到他花了3周时间,我就比较同情他了,如果学会了TWaver,我保他连3天都不用就可以完成,而且还是纯矢量、可交互、有动态效果、无失真缩放的拓扑图。 ...

weixin_30736301的博客 641

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

html 组织结构 图表,HTML5实现的矢量卡片式组织结构图

组织结构图(Organization chart)是企业的流程运转、部门设置及职能规划等最基本的结构依据。和客户交流时,不少人都提到需要一个灵活的工具来绘制呈现企业的组织架构,今天就给大家带来一款用TWaver实现的组织结构图,提供多种布局方式,为了清晰呈现组织里每个人的职能,我们定制了名片样式来展示网元。首先来看下整体效果。先来一个经典的上下层级布局:再来一个圆形布局:这些布局用twaver来实...

weixin_35457696的博客 1163

Text Layout Framework 概述系列(三)核心组件

<br />Core component(核心组件)包括 Text Layout Framework的模型层和视图层。在这个部分我们首先分析模型层的内部数据结构以及文本和文本属性是如何存储的。接下来,我们详细地介绍框架的视图层 以及将文本组合进容器对象来呈现文本的 flow composer。1. 文本流的层次体系<br />模型层用一个分层的树来表示文本。树中的每个节点都是elements包中某一个类的实例。例如,树的根节点肯定是TextFlow类的一个实例。 TextFlow类代表一个完整的文本

larntin 2758

TWaver图形界面之道(六)TWaver设计模式

继续上一章的TWaver图形界面之道(五)Hello TWaver TWaver设计模式         让我们详细探讨TWaver的设计模式,本章包括三个方面:MVC的设计模式,数据元素与数据容器,以及事件驱动机制。 什么是设计模式?         为了解决一些反复出现的问题,而提出的一种通用的解决方案,我们称为“设计模式”,设计模式是一种广泛的概念,软件开发有设计模式,UI设计有设计

TWaver可视化 1806

在3D场景中显示汉字

TWaver 3D for Flex本身支持3D文字的显示,但是用户必须嵌入一套字库才可以。使用传统的方式,显示3D文字。 [Embed("extrusionfonts.swf", mimeType="application/octet-stream")] private var font:Class; ..... twaver.threed.util.Util3D.checkTextFont...

web开发自学 341

twaver(html版)使用过程中的小知识

使用twaver已有一段时间,偶尔碰到忽略到的配置,一直没记录,今天把使用时碰到的问题记录下来,方便以后查阅 1.背景色 box.setStyle('background.type', 'vector'); box.setStyle('background.vector.fill', true); box.setStyle('background.vector.fill.color', 're...

liwenxia626的专栏 1668

TWaver局部自动布局及嵌套Group处理

TWaver提供了一些布局算法帮助我们快速为网元设置位置,很多情况下已经够用了,但是对于一些复杂的布局还需要我们自己做一些处理,看下面这个例子: 运行截图: 这个时候直接使用TNetwork#doLayout就不好使了,因为doLayout会对network中所有网元使用同一种布局算法,但是截图中Group下多个子Group各有自己的布局方式,我的解决办法是,先对最外层的Group整个布局

TWaver可视化 1984

TWaver HTML5之树形布局

今天是春节后上班的第三天,给大家分享一下我们前段时间的一个需求,需求是这样的:界面中的网元分为不同的域,比如一级域,二级域,三级域,….N级域,而且不同域之间会有连线。对于这个需求,按照常规的想法,使用group岂不是很简单,一级域是一个group,二级域也是一个group,二级域的group是一级域的父亲,以此类推。但是这样有个问题,如果域比较多,会造成group的过度嵌套,界面中group多了之后,不仅用户体验下降,而且会严重影响性能,所以倒不如直接用树,可以很直观的体现各个域之间的层级关系。

TWaver可视化 4567
上一篇: 自定义告警染色
下一篇: 打造模块化的TWaver Flex应用
subnetwork
博客等级 码龄17年 17粉丝 84原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值