开源跨平台移动项目 Ngui【视图与布局系统】

本贴最后更新于 2338 天前,其中的信息可能已经事过景迁

Ngui 简介

这是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于 NodeJS/OpenGL,这也是第一个在移动端 Android/iOS 融合 NodeJS 的前端 GUI 项目,至此 JavaScript 成为了真正意义上前后端通吃的语言。

Ngui 的目标:在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

视图 View

在上一篇中我已经为大家讲了Ngui入门,今天我就来介绍 ngui 的核心部分(视图与布局)。

Viewgui 核心部件派生为 Notification
用它来描述屏幕上所有可见的元素,它是所有视图的基础类型它也是事件的响应者,这些事件由硬件以及操作系统触发。详细的 API 文档讲大家去这里查阅。

下面是 ngui 现在提供的所有 View 继承关系图:
注:带 * 号的为抽象类型或协议没有构造函数

看到这个继承关系大家是不是觉得有点复杂了,其实这要与浏览器比那真是小巫见大巫,当然那并不是我想要的,这一切都是为了效率。当然为了效率在功能上肯定是要做裁剪的,鱼和熊掌不可兼得。

有这么多视图它到底能为我们做什么呢?

视图在广义功能上划分有两类:

非布局视图

顾名思义非布局视图就是那种不带布局功能的视图,就是你把它的位置固定后,它是不会再受到任何其它视图元素有影响,除非你再次更改它的位置 translate 属性。这种是最快的,因为不需要进行布局计算。

现在 ngui 提供的非布局视图有两个:

关于这两个视图的具体 API 接口说明请大家查阅文档,但在这里特别要说明的是 transform,也就是矩阵变换。

矩阵变换是 GUI 绘图系统里的一个重要概念,transform 用一个 Matrix 来描述绘图元素点线或面在屏幕上的实际位置与形状,这个矩阵通常由一组 3x34x4 向量组成,3x3 为 2d 矩阵 4x4 为 3d 矩阵,在 View 上使用的是一个裁剪过的 3x2 的 2d 矩阵所它暂时不支持 3d 中的 z 轴,以后的版本中可以会所变化。

View 中的 transform 属性并没有直接暴露而是换成了一组属性:

  • x
  • y
  • scaleX
  • scaleY
  • rotateZ
  • skewX
  • skewY

你可以通过 matrix 属性得到这个矩阵但它是只读的,只能通过 xy 这个方式对它进行设置。

调用 final_matrix()函数得到的是父视图的 final_matrix 与当前视图的 matrix 乘积。对这就是这个视图在屏幕是的真实位置,确切的讲是这个 View.origin 在屏幕上的确切位置,因为严谨的说一张图片或一个矩形在屏幕上是由 4 个点组成的一个面。

注意:
频繁的交替设置 transform 与调用 matrix/finalMatrix 会带来不必要的性能消耗,ngui 的渲染逻辑是在渲染画面前不对任何视图属性设置做额外的计算只做存储并该标记属性的改变,等待准备渲染前才做统一的计算。当一个视图的 transform 改变时如果这时你要获取 matrixfinalMatrix 那么直接返回 matrixfinalMatrix 那一定是不正确的,幸好系统会做检测当发生了改变你要强取些值会提前对这些值做运算,返回一个正确的值给你,但如果你频繁的设置与获取,那就会频繁的做些运算。并且这只仅限于非布局视图,在布局视图上这样做并不会返回正确的值参见 Trap in Layout

布局视图

布局视图按可放置内容划分有三类:

Div

从 API 文档上看见 Div 只有一个属性 contentAlign, 那么这里重点讲述就是这个属性,因为它是与浏览器完全不相同有的地方,至于基础类型 Box 大家可以参与 API 文档会有详细说明,注意 padding 这个属性在 ngui 里是没有的,因为这个导致系统复杂性上升,但以后要不要加待定。

nguiDiv 并没有自己单独的浮动方式这个属性。但 Div 能设置它的 contentAlign 对它的内容对齐方式做出更改,这个属性可选的值有 4 个,默认为 left 左对齐

  • left
  • right
  • top
  • bottom

这其实很好理解 :

  • leftright 为水平布局,内容对齐方式从左到右或从右到左排列,溢出往下换行。
  • topbottom 为垂直布局,内容对齐方式从上到下或从下到上排列,溢出往右换列。

需要注意的是它的内容必须为 Box 类型否则这个属性并不会对它产生任何的效果,如果它内部出现了 SpanTextNode 那么 SpanTextNode 的出现不会对 Div 的内容布局造成任何影响,因为 Div 会忽略非 Box 内容的排版处理,同理一个 BoxDiv 出现在非排版布局视图内部那它的位置与使用非布局视图没有区别。

Hybrid

Div 一样它也只有一个属性 textAlign 但它可以对任何 Layout 内容做排版处理这当然也包括 SpanTextNode

Div 的区别 Hybrid 的内容方式的不同,Hybrid 把它的所有内容都当成文本进行处理。它的可选有 6 个,默认为 left

  • left
  • right
  • center
  • left_reverse
  • right_reverse
  • center_reverse

left right center 很好理解
left_reverse right_reverse center_reverse 是在对齐的基础上将内容颠倒排列,

如:对 Ngui 进行颠倒排版会变成这样

left_reverse center_reverse right_reverse
SJodacovA SJodacovA SJodacovA

Span,TextNode,Text

  • Span 并没有显示实体,也就是说它并不会在屏幕上显示任何可见的东西,它的存在只为是为了设置嵌套的 TextNode 视图属性,因为以 TextLayout 上的属性都能被它的子 TextLayout 所继承,这也是 ngui 中唯具有继承性质属性的视图。

  • TextNodeSpan 的子类型,但它有实体它也是个叶子视图,也就是它不能再存在子视图。

  • Text 继承于 HybridTextNode 一样也是叶子视图不能存在子视图

Indep

独立的 Div,相当于 html-css 中的绝对定位,它存在于 DivHybrid 内部时,会进行独立排版,不会影响其它兄弟视图的排版位置。

Limit,IndepLimit

限制的盒子,minWidth, maxWidth,minHeight,maxHeight,这些属性能限制盒子的尺寸,这与 html 中的限制很相似。

Root

Root 一个应用程序只能是唯一的也是必须的

Examples

最后为大家写一段代码实际运行一下

import { 
	GUIApplication: App, Root,
	Div, 
	Indep,
	Hybrid, 
	Span,
	TextNode,
} from 'ngui'

new App().start(
	<Root>
		<Div margin=20 width="full" height=100
		 backgroundColor="#f00">
			<Indep width=50 height=50 
			backgroundColor="#f0f" 
			alignX="center"
			alignY="center" />
			<Div width=50 height="50" 
			backgroundColor="#00f" />
		</Div>
		<Hybrid margin=20 width="full" height=100 
		backgroundColor="#f00" textColor="#ff0" 
		textBackgroundColor="#00f6">
			Hello 
			<TextNode textColor="#000">
				Ngui!
			</TextNode>
		</Hybrid>
		<Hybrid margin=20 width="full" height=100 
		backgroundColor="#f00" 
		textAlign="center_reverse">
			Hello Ngui!
		</Hybrid>
	</Root>
)

下面是 iphone6 的运行效果:

下面是 iphone6 的运行效果

下面是 Google nexus6 的运行效果:

下面是 Google nexus6 的运行效果


就说到这里吧,已经累的不行了,下一篇为大家讲动作系统。

谢谢大家,未完待续~

  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 346 关注
  • Node.js

    Node.js 是一个基于 Chrome JavaScript 运行时建立的平台, 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动, 非阻塞 I/O 模型而得以轻量和高效。

    138 引用 • 268 回帖 • 199 关注
  • Android

    Android 是一种以 Linux 为基础的开放源码操作系统,主要使用于便携设备。2005 年由 Google 收购注资,并拉拢多家制造商组成开放手机联盟开发改良,逐渐扩展到到平板电脑及其他领域上。

    333 引用 • 323 回帖 • 70 关注
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    84 引用 • 139 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...