開源跨平臺(tái)移動(dòng)項(xiàng)目Ngui【視圖與布局系統(tǒng)】

2018-12-09 12:51 更新

Ngui簡(jiǎn)介

這是一個(gè)GUI的排版顯示引擎和跨平臺(tái)的GUI應(yīng)用程序開發(fā)框架,基于NodeJS/OpenGL,這也是第一個(gè)在移動(dòng)端Android/iOS融合NodeJS的前端GUI項(xiàng)目,至此JavaScript成為了真正意義上前后端通吃的語(yǔ)言。

Ngui的目標(biāo):在此基礎(chǔ)上開發(fā)GUI應(yīng)用程序可擁有開發(fā)WEB應(yīng)用般簡(jiǎn)單與速度同時(shí)兼顧Native應(yīng)用程序的性能與體驗(yàn)。

視圖View

在上一篇中我已經(jīng)為大家講了Ngui入門,今天我就來介紹ngui的核心部分(視圖與布局)。

Viewgui核心部件派生為Notification。 用它來描述屏幕上所有可見的元素,它是所有視圖的基礎(chǔ)類型它也是事件的響應(yīng)者,這些事件由硬件以及操作系統(tǒng)觸發(fā)。詳細(xì)的API文檔講大家去這里查閱。

下面是ngui現(xiàn)在提供的所有View繼承關(guān)系圖: 注:帶*號(hào)的為抽象類型或協(xié)議沒有構(gòu)造函數(shù)

看到這個(gè)繼承關(guān)系大家是不是覺得有點(diǎn)復(fù)雜了,其實(shí)這要與瀏覽器比那真是小巫見大巫,當(dāng)然那并不是我想要的,這一切都是為了效率。當(dāng)然為了效率在功能上肯定是要做裁剪的,魚和熊掌不可兼得。

有這么多視圖它到底能為我們做什么呢?

視圖在廣義功能上劃分有兩類:

非布局視圖

顧名思義非布局視圖就是那種不帶布局功能的視圖,就是你把它的位置固定后,它是不會(huì)再受到任何其它視圖元素有影響,除非你再次更改它的位置translate屬性。這種是最快的,因?yàn)椴恍枰M(jìn)行布局計(jì)算。

現(xiàn)在ngui提供的非布局視圖有兩個(gè):

關(guān)于這兩個(gè)視圖的具體API接口說明請(qǐng)大家查閱文檔,但在這里特別要說明的是transform,也就是矩陣變換。

矩陣變換是GUI繪圖系統(tǒng)里的一個(gè)重要概念,transform用一個(gè)Matrix來描述繪圖元素點(diǎn)線或面在屏幕上的實(shí)際位置與形狀,這個(gè)矩陣通常由一組3x34x4向量組成,3x3為2d矩陣4x4為3d矩陣,在View上使用的是一個(gè)裁剪過的3x2的2d矩陣所它暫時(shí)不支持3d中的z軸,以后的版本中可以會(huì)所變化。

View中的transform屬性并沒有直接暴露而是換成了一組屬性:

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

你可以通過matrix屬性得到這個(gè)矩陣但它是只讀的,只能通過xy這個(gè)方式對(duì)它進(jìn)行設(shè)置。

調(diào)用final_matrix()函數(shù)得到的是父視圖的final_matrix與當(dāng)前視圖的matrix乘積。對(duì)這就是這個(gè)視圖在屏幕是的真實(shí)位置,確切的講是這個(gè)View.origin在屏幕上的確切位置,因?yàn)閲?yán)謹(jǐn)?shù)恼f一張圖片或一個(gè)矩形在屏幕上是由4個(gè)點(diǎn)組成的一個(gè)面。

注意: 頻繁的交替設(shè)置transform與調(diào)用matrix/finalMatrix會(huì)帶來不必要的性能消耗,ngui的渲染邏輯是在渲染畫面前不對(duì)任何視圖屬性設(shè)置做額外的計(jì)算只做存儲(chǔ)并該標(biāo)記屬性的改變,等待準(zhǔn)備渲染前才做統(tǒng)一的計(jì)算。當(dāng)一個(gè)視圖的transform改變時(shí)如果這時(shí)你要獲取matrixfinalMatrix那么直接返回matrixfinalMatrix那一定是不正確的,幸好系統(tǒng)會(huì)做檢測(cè)當(dāng)發(fā)生了改變你要強(qiáng)取些值會(huì)提前對(duì)這些值做運(yùn)算,返回一個(gè)正確的值給你,但如果你頻繁的設(shè)置與獲取,那就會(huì)頻繁的做些運(yùn)算。并且這只僅限于非布局視圖,在布局視圖上這樣做并不會(huì)返回正確的值參見Trap in Layout

布局視圖

布局視圖按可放置內(nèi)容劃分有三類:

Div

從API文檔上看見Div只有一個(gè)屬性contentAlign, 那么這里重點(diǎn)講述就是這個(gè)屬性,因?yàn)樗桥c瀏覽器完全不相同有的地方,至于基礎(chǔ)類型Box大家可以參與API文檔會(huì)有詳細(xì)說明,注意padding這個(gè)屬性在ngui里是沒有的,因?yàn)檫@個(gè)導(dǎo)致系統(tǒng)復(fù)雜性上升,但以后要不要加待定。

nguiDiv并沒有自己?jiǎn)为?dú)的浮動(dòng)方式這個(gè)屬性。但Div能設(shè)置它的contentAlign對(duì)它的內(nèi)容對(duì)齊方式做出更改,這個(gè)屬性可選的值有4個(gè),默認(rèn)為left左對(duì)齊

  • left
  • right
  • top
  • bottom

這其實(shí)很好理解 :

  • leftright為水平布局,內(nèi)容對(duì)齊方式從左到右或從右到左排列,溢出往下?lián)Q行。
  • topbottom為垂直布局,內(nèi)容對(duì)齊方式從上到下或從下到上排列,溢出往右換列。

需要注意的是它的內(nèi)容必須為Box類型否則這個(gè)屬性并不會(huì)對(duì)它產(chǎn)生任何的效果,如果它內(nèi)部出現(xiàn)了SpanTextNode那么SpanTextNode的出現(xiàn)不會(huì)對(duì)Div的內(nèi)容布局造成任何影響,因?yàn)?a rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" >Div會(huì)忽略非Box內(nèi)容的排版處理,同理一個(gè)BoxDiv出現(xiàn)在非排版布局視圖內(nèi)部那它的位置與使用非布局視圖沒有區(qū)別。

Hybrid

Div一樣它也只有一個(gè)屬性textAlign但它可以對(duì)任何Layout內(nèi)容做排版處理這當(dāng)然也包括SpanTextNode。

Div的區(qū)別Hybrid的內(nèi)容方式的不同,Hybrid把它的所有內(nèi)容都當(dāng)成文本進(jìn)行處理。它的可選有6個(gè),默認(rèn)為left

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

left right center 很好理解 left_reverse right_reverse center_reverse 是在對(duì)齊的基礎(chǔ)上將內(nèi)容顛倒排列,

如:對(duì)Ngui進(jìn)行顛倒排版會(huì)變成這樣

left_reverse center_reverse right_reverse
SJodacovA SJodacovA SJodacovA

Span,TextNode,Text

  • Span并沒有顯示實(shí)體,也就是說它并不會(huì)在屏幕上顯示任何可見的東西,它的存在只為是為了設(shè)置嵌套的TextNode視圖屬性,因?yàn)橐?a rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" >TextLayout上的屬性都能被它的子TextLayout所繼承,這也是ngui中唯具有繼承性質(zhì)屬性的視圖。

  • TextNodeSpan的子類型,但它有實(shí)體它也是個(gè)葉子視圖,也就是它不能再存在子視圖。

Indep

獨(dú)立的Div,相當(dāng)于html-css中的絕對(duì)定位,它存在于DivHybrid內(nèi)部時(shí),會(huì)進(jìn)行獨(dú)立排版,不會(huì)影響其它兄弟視圖的排版位置。

Limit,IndepLimit

限制的盒子,minWidth, maxWidth,minHeight,maxHeight,這些屬性能限制盒子的尺寸,這與html中的限制很相似。

Root

Root一個(gè)應(yīng)用程序只能是唯一的也是必須的

Examples

最后為大家寫一段代碼實(shí)際運(yùn)行一下

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的運(yùn)行效果:

下面是`iphone6`的運(yùn)行效果

下面是Google nexus6的運(yùn)行效果:

下面是`Google nexus6`的運(yùn)行效果

就說到這里吧,已經(jīng)累的不行了,下一篇為大家講動(dòng)作系統(tǒng)。

謝謝大家,未完待續(xù)~

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)