操作實例:閱讀器應(yīng)用(JavaScript和HTML)
隨著平板電腦變得越來越普及,融合了閱讀體驗的應(yīng)用很快就會變得流行起來。 下面我們重點介紹了可用來創(chuàng)建優(yōu)秀閱讀器應(yīng)用的新 CSS 和 HTML5 功能。 閱讀本文后,你將對在這些應(yīng)用中使用的主要布局功能有一個全面的了解,而且還可以獲得一個基本的閱讀器應(yīng)用引導(dǎo)你入門。現(xiàn)在,我們了解一下在 Windows 中營造卓越閱讀器體驗的詳細信息。
簡介
Windows 8 為開發(fā)人員和設(shè)計者提供了一系列最新的 HTML5 和 CSS3 功能,用于創(chuàng)建新穎獨特的閱讀體驗。具體而言,由于諸如 CSS 區(qū)域和 CSS 網(wǎng)格等新技術(shù),你可以創(chuàng)建數(shù)字出版物,讓這些出版物結(jié)合 HTML 的優(yōu)勢—流體布局、基于標記的樣式、可訪問的內(nèi)容、交互性—與到目前為止僅在印刷領(lǐng)域中可用的創(chuàng)新布局。
傳統(tǒng)網(wǎng)頁內(nèi)容的呈現(xiàn)形式為單列豎排。段落堆放在段落和其他圖像之上,偶爾插入的浮動元素可呈現(xiàn)出一些視覺多樣化。“頁面”僅通過將內(nèi)容分段為不同的 HTML 文檔來創(chuàng)建;不存在任何基于標記的方式來獲取一連串的內(nèi)容并將內(nèi)容分段為單個的文本屏幕。缺少用于創(chuàng)建列和適應(yīng)屏幕大小的強大控件表示許多頁面僅針對特定 分辨率(如 1024 × 768)進行優(yōu)化。在高分辨率、寬屏幕監(jiān)視器上呈現(xiàn)為小分辨率優(yōu)化的文本時,你會看到糟糕體驗的一個好示例。 以下圖像顯示了縱橫比為 4:3 的監(jiān)視器上的單列布局。
以下圖像顯示了寬屏幕監(jiān)視器上具有空白區(qū)域的相同布局。
相比之下,設(shè)計用于充分利用頁面可用空間的頁面可能會以多列文本為特征,從而在填充屏幕的同時確保文本的各行不會太長,易于閱讀。 通過一些小的優(yōu)化措施,標題可以增加其大小以更加搶眼,并且當文本環(huán)繞在圖像周圍時可以為圖像提供更加顯眼的位置。
以下圖像顯示了用于寬屏幕監(jiān)視器的改進閱讀器布局。
印刷設(shè)計者長久以來都可以輕松設(shè)計這樣的布局,因為他們只需要應(yīng)付預(yù)先已知的固定頁面大小。適應(yīng)性布局的設(shè)計者必須使用諸如 CSS 網(wǎng)格和媒體查詢等工具來創(chuàng)建頁面,這些頁面智能地適應(yīng)不同的屏幕大小。
本文章與動態(tài) CSS 區(qū)域模板示例一起介紹如何創(chuàng)建適應(yīng)各種屏幕大小的美觀布局來進行閱讀。在查看新的 CSS 閱讀功能中,我們仔細查看了幾個新功能,你可以使用這些功能以創(chuàng)新性的新方式呈現(xiàn)文本和圖像。在匯聚多個功能以創(chuàng)建良好的閱讀體驗中,我們通過說明如何組合這些功能來構(gòu)建適應(yīng)性閱讀體驗來繼續(xù),該體驗結(jié)合了優(yōu)秀設(shè)計與流體和美觀布局。
查看新 CSS 閱讀功能
我們了解一下你可能會在閱讀器應(yīng)用中使用的新 CSS 功能:多列、斷字、網(wǎng)格、區(qū)域以及排除項。
多列
通過 CSS 多列,設(shè)計人員可以將元素 — 例如,div 元素或頁面的 body— 的內(nèi)聯(lián)內(nèi)容(如文本)設(shè)置為尺寸相同且相鄰的多個連續(xù)列格式。例如,只需將 CSS 屬性 column-count: 2; 添加到 div,即可生成如下圖所示的布局。
但是,多列也確實有一些限制。所有列必須具有相同的尺寸,而且相互之間相鄰放置。而且,多列元素的內(nèi)容遵守 CSSoverflow 屬性;即它剪切、添加滾動條,或通過在原始元素旁邊創(chuàng)建其他列來溢出。 由于這些原因,CSS 區(qū)域在以下這些情形下可能是更好的文本布局選項:需要更多變的頁面布局,或元素的內(nèi)聯(lián)內(nèi)容可能溢出元素。下圖顯示了通過溢出多列元素創(chuàng)建的新列。
Note CSS 多列有一個“平衡”選項,可以確保所有列的長度相同,而且最后一列不會顯著短于其他列。此功能不能確保這些列具有相同的行數(shù),也不能確保這些行在各列中都是對齊的。應(yīng)當為多列元素中的內(nèi)容設(shè)置格式,以使所有元素都是單行高度的倍數(shù),包括段落和圖像的補白。
下圖顯示了經(jīng)過平衡的多列布局(淡藍色外框)與未經(jīng)平衡的布局(紅色外框)相比較,如何設(shè)置內(nèi)容的格式。
#p#
Note 此示例經(jīng)過了適當?shù)钠胶?,因為列?nèi)的元素根據(jù)列尺寸和間距進行了匹配。
下列代碼顯示了這兩種布局的創(chuàng)建方法。
- <!DOCTYPEHTML>
- <html>
- <head>
- <style>
- #div1{
- width: 180px;
- height: 300px;
- column-fill: balance;
- column-count: 2;
- float: left;
- border: solid 2px lightblue;
- margin-right: 8px;
- }
- #div2{
- width: 180px;
- height: 300px;
- column-fill: auto;
- column-count: 2;
- float: left;
- border: solid 2px red;
- margin-right: 8px;
- }
- </style>
- </head>
- <body>
- <div id="div1" class="div1">
- Hi friend! Hi friend! Hi friend! Hi friend!
- Hi friend! Hi friend! Hi friend! Hi friend!
- Hi friend! Hi friend! Hi friend! Hi friend!
- Hi friend! Hi friend! Hi friend! Hi friend!
- Hi friend! Hi friend! Hi friend! Hi friend!
- </div>
- <div id="div2">
- Hi friend! Hi friend! Hi friend! Hi friend!
- Hi friend! Hi friend! Hi friend! Hi friend!
- Hi friend! Hi friend! Hi friend! Hi friend!
- Hi friend! Hi friend! Hi friend! Hi friend!
- Hi friend! Hi friend! Hi friend! Hi friend!
- </div>
- </body>
- </html>
斷字
多列使我們可以將內(nèi)聯(lián)內(nèi)容(如文本)布置在相對較窄的列中。但是這些列的內(nèi)容看起來可能會參差不齊,特別是在平均單詞長度占列寬度的較大比例時。尤其是,當列與 text-align: justify 屬性結(jié)合使用時,單詞之間可能會出現(xiàn)較大的空白間隙,從而使內(nèi)容的外觀不規(guī)則且不美觀,如下所示。
相應(yīng)地,我們現(xiàn)在提供自動斷字功能,這樣多行的排列更緊密,同時還提供強大的閱讀體驗,如下所示。
斷字在 W3C CSS 文本級別 3 規(guī)范的部分中定義。CSS 斷字提供了以下能力:
- 指定斷字分隔符前后的最小字詞片段長度。
- 指定連續(xù)斷字行的最大數(shù)量。
- 避免段落和列中最后的字詞被斷字。
- 指定自定義斷字字符。
大量語言支持在 Windows 8 和 Internet Explorer 10 中進行斷字,且建議將斷字用于 CSS 多列和區(qū)域。
網(wǎng)格
CSS 網(wǎng)格布局的核心理念是,將頁面劃分成定義好的一組行和列,然后根據(jù)這些行和列使用 CSS 設(shè)置元素的位置和尺寸。因為行和列的尺寸可以定義為固定、靈活或按內(nèi)容調(diào)整大小,所以很容易構(gòu)建一個完全填滿整個屏幕的布局,無論屏幕尺寸如何。
例如,下圖顯示了一個閱讀器示例,它劃分為帶有多個元素的兩列和三行。在瀏覽器窗口的尺寸更改時,某些元素必須保持不變,而其他元素會增大或縮小。
通過 CSS 網(wǎng)格布局,你可以通過以下列標記開始實現(xiàn)此設(shè)計。
- <div id="grid">
- <div id="logo">Reader Logo</div>
- <div id="page">Page</div>
- <div id="bookmarks">Bookmarks</div>
- <div id="content">Reader Content</div>
- <div id="controls">Controls</div>
- </div>
名為 grid
的 div 元素通過應(yīng)用 CSS 樣式 display: grid 設(shè)置為 grid 容器。你可以將各個行和列定義為“靈活”,它基于可用的空間增大或縮小行和列,也可以將其定義為“自動調(diào)整大小”,它調(diào)整行或列的大小以適應(yīng)放在其中的最大元素的寬度或高度。
- #grid {
- display: -ms-grid;
- -ms-grid-columns: auto 1fr;
- -ms-grid-rows: auto 1fr auto;
- }
定義網(wǎng)格后,你可以將各個元素放在特定的網(wǎng)格單元格中。顯示下列標記時,你不僅可以指定將元素放置在 CSS 中特定的行和列中,而且還可以指定讓一個元素跨多個行和列放置,并指定元素在一個單元格或一系列單元格中水平或垂直對齊。
- #logo { -ms-grid-column: 1; -ms-grid-row: 1 }
- #page { -ms-grid-column: 1; -ms-grid-row: 3 }
- #bookmarks { -ms-grid-column: 1; -ms-grid-row: 2; -ms-grid-row-align: start }
- #content { -ms-grid-column: 2; -ms-grid-row: 1; -ms-grid-row-span: 2 }
- #controls { -ms-grid-column: 2; -ms-grid-row: 3; -ms-grid-column-align: center }
可以指定元素具有固定尺寸,或填充它們所在單元格的可用寬度或高度。在前面的示例中,content
元素隨著屏幕增大,而其他元素(如 logo
元素)保持尺寸不變。
#p#
Note 因為新層疊樣式表級別 3 (CSS3) 仍為一個新興規(guī)范,所以在 Internet Explorer 10 中使用時,所有網(wǎng)格屬性都帶有前綴 "-ms-"。
通過將網(wǎng)格布局功能與 CSS3 媒體查詢相結(jié)合,你可以為不同的分辨率、縱橫比和屏幕方向指定完全不同的布局。例如,你可以針對不同的屏幕尺寸定義不同的行數(shù)或列數(shù),從而為垂直“縱向”布局指定較少的列,為水平“橫向”布局指定較多的列。你還可以指定行和列按不同方式調(diào)整大小。
此外,因為網(wǎng)格中元素的位置與指定它們的順序無關(guān) — 即它們的位置單純由 CSS 指定,而不是由 HTML 標記中的順序指定— 所以很容易在不同屏幕尺寸上為元素指定不同的排列,甚至可以完全避免在某些布局上顯示某些元素。
區(qū)域
CSS 區(qū)域支持設(shè)計人員將內(nèi)容從一個包含元素流入另一個元素,這樣可以將一個頁面或多個頁面中不同區(qū)域的內(nèi)容流連接在一起。此功能使新設(shè)計和創(chuàng)新設(shè)計成為可能。 例如,下圖顯示文本跨頁面內(nèi)兩個區(qū)域流動。請注意,與 CSS 多列不同,區(qū)域允許容器有不同的尺寸,也不需要相互直接緊密相鄰。
區(qū)域也可用于跨多個虛擬頁流動單個內(nèi)容流(例如一篇文章的文本),如下圖所示。
請注意,此上下文中的“頁面”不是通過打印過程創(chuàng)建的頁面(例如使用“@page”CSS 規(guī)則設(shè)置樣式的頁面),而是包含一個或多個區(qū)域的 div 元素。通過在可滾動區(qū)域(通常使用貼靠點來模擬翻頁)中放置這些 div 元素,我們可以創(chuàng)造一種分頁閱讀體驗,其中單個內(nèi)容流顯示在多個全屏頁面上,而不是顯示為單個內(nèi)容滾動區(qū)域。此外,區(qū)域可以與 CSS 網(wǎng)格和媒體查詢結(jié)合使用,以創(chuàng)建準確符合特定屏幕尺寸的頁面,并生成顯示特定內(nèi)容流所需的準確頁數(shù)。
下圖顯示了區(qū)域工作原理的高級概述。來自源文檔 (Content.html) 的內(nèi)容流入主模板文檔 (Master.html) 的多個區(qū)域。
需要注意,區(qū)域不參與文檔的 CSS 樣式層疊,因此在特定區(qū)域上放置的樣式規(guī)則(如 text-color: red)不影響區(qū)域中的內(nèi)容。但是對內(nèi)容文檔本身放置的樣式規(guī)則一定會影響內(nèi)容,盡管這些規(guī)則不影響主模板文檔中的任何元素。
同樣,主模板中區(qū)域顯示的內(nèi)容不存在于主模板的文檔對象模型 (DOM) 中;通過 Microsoft Visual Studio 中的 DOM 資源管理器查看 Master.html,例如,將顯示每個區(qū)域為空。相反,區(qū)域顯示的內(nèi)容存在于 Master.html 中的隱藏 iframe 元素中,并指向 Content.html。
排除項
CSS 排除項提供了一種使內(nèi)聯(lián)內(nèi)容環(huán)繞元素(如圖像、標題或文本標注)的方法。排除項與 CSS 浮動類似,但是排除項不是被推到包含塊的一側(cè)或另一側(cè),而是可以放置在包含塊的中間,并且使內(nèi)容圍繞兩側(cè)流動,如下所示。
排除項一次可以與多個環(huán)繞元素交互。例如,排除項可以由多個區(qū)域環(huán)繞,并且使每個區(qū)域中的內(nèi)容都圍繞它。有關(guān)如何執(zhí)行此操作的詳細信息,請參閱結(jié)合使用多個功能以營造完美閱讀體驗。
請注意,在 Internet Explorer 10 中,區(qū)域只能是矩形塊。但是,多個區(qū)域可以放置為排列在一起,以創(chuàng)建非矩形的區(qū)域。
結(jié)合使用多個功能以營造完美閱讀體驗
現(xiàn)在,我們已經(jīng)了解可用來在 Windows 8 中營造完美閱讀體驗的各項技術(shù),讓我們來討論一下如何結(jié)合使用這些技術(shù)。我們通過查看動態(tài) CSS 區(qū)域模板示例來 完成這些操作。首先,我們介紹如何結(jié)合使用網(wǎng)格、媒體查詢、區(qū)域及排除項來創(chuàng)建各個頁面模板。接著,我們查看實例化這些頁面模板,直到已顯示源文檔中的所 有內(nèi)容的 JavaScript 代碼。最后,我們查看可以基于屏幕尺寸或字體大小更改來調(diào)整頁數(shù)的附加 JavaScript 代碼。
布置頁面模板
以下圖像顯示示例的第 1 頁,其中包括:
- 一個標題(“動態(tài)區(qū)域模板示例”)。
- 作為兩個并行列布置的兩個區(qū)域。
- 位于頁面中間的一個排除集(土星的圖片),這會導(dǎo)致兩個區(qū)域中周圍的內(nèi)容環(huán)繞該排除集。
#p#
下圖顯示了頁面 1 的網(wǎng)格結(jié)構(gòu)。
尤其是,頁面 1 包含單個 div 元素,此元素通過使用 display: -ms-grid 屬性變?yōu)橐粋€網(wǎng)格。其他元素(如區(qū)域和排除項)放在此單個 div 上。為此網(wǎng)格指定應(yīng)用程序區(qū)域的整個寬度和高度,如果應(yīng)用處于填充或貼靠模式,則該區(qū)域可能是整個屏幕或屏幕的一部分。
頁面 1 劃分為 4 列 5 行。每一列的大小是 1 個分數(shù)單位 (1FR),它表示在布置固定尺寸和自動調(diào)整尺寸的軌跡(行或列)后,可用于網(wǎng)格的所有空間的其中一份。在此例中,因為沒有固定尺寸或自動調(diào)整尺寸的軌跡,所以每一列占有應(yīng)用程序區(qū)域的 25% 寬度。
與之相比,頁面 1 上 5 行中的第一行是自動調(diào)整尺寸行,而其余的行只有微小的尺寸調(diào)整。頁面標題在第 1 行,它將占用顯示“Dynamic region Templates Sample”標題所需的空間。應(yīng)用程序區(qū)域的其余高度被其余行占用,其中每行只有不到應(yīng)用程序區(qū)域的 25%。
網(wǎng)格內(nèi)包含兩個區(qū)域。每個區(qū)域跨兩列四行:第一個區(qū)域位于第 2 行,第 1 列(CSS 網(wǎng)格 1 索引),第二個區(qū)域位于第 2 行,第 3 列。每個區(qū)域只是一個設(shè)置了 -ms-flow-from: content 屬性的 div 元素。因為每個區(qū)域共用同一個流名稱,所以內(nèi)容流從第一個區(qū)域開始,繼續(xù)到下一個,然后前進到不同頁面的后續(xù)區(qū)域。
網(wǎng)格還用于將排除項放置在頁面的中間。在此例中,排除項是一個 div 元素,通過 CSSflexbox 顯示屬性將一張土星圖像放置在中間。此排除項通過設(shè)置 -ms-wrap-flow: both 屬性創(chuàng)建。當排除項放置在網(wǎng)格中間(第 3 行,第 2 列,跨兩行兩列)后,與排除項相交的任何內(nèi)聯(lián)內(nèi)容將環(huán)繞它分布。此行為與傳統(tǒng)的浮動元素不同,后者必須放置在頁面的一側(cè)。
請注意,區(qū)域和排除項的放置都是跨行和列延伸的。出現(xiàn)這種情況,是因為應(yīng)用運行的設(shè)備具有不同的屏幕分辨率,或者因為應(yīng)用已經(jīng)在全屏幕和填充模式之 間進行切換。隨著應(yīng)用分辨率更改尺寸,屏幕上的元素也相應(yīng)增大和縮小。這明顯是區(qū)域的最優(yōu)行為,因為我們希望文本區(qū)域填滿應(yīng)用程序區(qū)域,但是不要溢出。沒 有填入?yún)^(qū)域的任何文本僅簡單移入到下一個區(qū)域。根據(jù)內(nèi)容,設(shè)計人員可能不希望圖像隨著屏幕尺寸進行拉伸,而希望保留圖像的縱橫比或絕對尺寸。這可以通過更 改 –ms-grid-row-align 和 –ms-grid-column-align 屬性的 stretch 默認值來輕松實現(xiàn)。
接下來的兩個圖像顯示了 Dynamic Region Templates Sample 的頁面 2 和頁面 3 的網(wǎng)格劃分。這兩個頁面布局都是 4 × 4 的網(wǎng)格,其中每一行和每一列都等于可用空間的相等分數(shù)尺寸。這兩個頁面的唯一實質(zhì)性差別(除了背景圖像的明顯不同)是頁面 2 具有單一區(qū)域跨越頁面中間的兩行兩列,而頁面 3 具有多個區(qū)域,在整個頁面上交錯分布。總體而言,所有這些頁面演示了單個內(nèi)容流通過 CSS 區(qū)域分布到多個頁面。
下面是頁面 2。
下面是頁面 3。
Note 上面所有三個頁面中顯示的內(nèi)容都完全對齊而且應(yīng)用了斷字。這些樣式屬性是在內(nèi)容(來自 content.html 文件)上設(shè)置的,而不是在任何區(qū)域本身上設(shè)置的。如前面所提到的,這是因為樣式層疊不會滲透進入?yún)^(qū)域。
實例化頁面模板
我們已經(jīng)討論了如何使用區(qū)域、網(wǎng)格和排除項來創(chuàng)建頁面。你可以在動態(tài) CSS 區(qū)域模板示例項 目中看到這些頁面,分別為 page1.html、page2.html 和 page3.html。但是,我們還沒有檢查在激活應(yīng)用時,這些頁面是如何動態(tài)創(chuàng)建的。由于根據(jù)屏幕尺寸和字體大小,顯示內(nèi)容文檔所需的頁數(shù)會發(fā)生變化 — 較小的屏幕或較大的字體意味著每頁容納的單詞更少,因此需要更多的頁數(shù) – 必須在運行時動態(tài)實例化頁面。現(xiàn)在,我們討論如何在 Windows 應(yīng)用商店應(yīng)用中實例化預(yù)定義的模板,一次一個,直到顯示整個內(nèi)容文檔。之后,我們將討論如何根據(jù)屏幕尺寸或字體大小的運行時變化采用適合的頁數(shù)。
下面的示例顯示了 Dynamic CSS Region Templates Sample 的結(jié)構(gòu)。特別是,帶有 appContainer
的 id 屬性的 div 元素同時包含源 iframe 元素和包含各個頁面的 pageContainer
div 元素。iframe 指向 content.html 文檔,此文檔將在多個頁面中跨多個區(qū)域顯示。因為 iframe 具有 -ms-flow-into: content 屬性,所以不會顯示它。appContainer
div 和各個頁面將占用分配給應(yīng)用的所有可用屏幕空間,因為它們的寬度和高度都設(shè)置為 100% 的應(yīng)用程序區(qū)域。
#p#
通過使用 display: -ms-box 屬性,已經(jīng)將 pageContainer
div 配置為 flexbox,并且已經(jīng)將 body 元素設(shè)置為 overflow: scroll。因為 flexbox 的默認行為是將其中的所有元素相鄰放置,從而達到按需要水平增長,所以用戶可以通過鼠標或觸控輸入水平平移來滾動瀏覽頁面。
Note 設(shè)計人員通過設(shè)置 -ms-box-orient: vertical 屬性,可以輕松切換到垂直分頁模式。同時,為了使觸控滾動能正確工作,iframe 元素必須與正在滾動的頁面位于同一個父元素中。如果滾動元素是 body 元素本身,這顯然不是問題,但是在 iframe 和頁面的其他配置中,這可能會出現(xiàn)問題。
現(xiàn)在我們已了解閱讀應(yīng)用最終將如何構(gòu)建,接下來我們討論頁面在應(yīng)用中是如何放置的。下面的示例代碼來自 regionTemplatePage.js,顯示了 pageTemplates
陣列。
- var pageTemplates = [
- '/html/page1.html',
- '/html/page2.html',
- '/html/page3.html',
- '/html/pageDefault.html'
- ];
pageTemplates
陣列指向應(yīng)用包中與將要實例化的頁面對應(yīng)的各個文件及 createPages
函數(shù)使用的引用文件。createPages
函數(shù)被源 iframe 的 load 事件觸發(fā)的事件偵聽器函數(shù)調(diào)用。
下列代碼顯示了 createPages
,從 pageTemplates
陣列選擇和實例化頁面模板的函數(shù)。
- unction createPages() {
- var targetPage;
- if (currentPage > (pageTemplates.length - 1)) {
- targetPage = pageTemplates[pageTemplates.length - 1];
- } else {
- targetPage = pageTemplates[currentPage];
- }
- var flexboxElement = document.getElementById('pageContainer');
- WinJS.UI.Fragments.render(targetPage, flexboxElement).then(function () {
- msSetImmediate(function () {
- currentPage += 1;
- var flexboxElement = document.getElementById('pageContainer');
- var pages = flexboxElement.querySelectorAll('.page');
- var lastPage = pages[pages.length - 1];
- var regions = lastPage.querySelectorAll(searchClass);
- var lastRegion = regions[regions.length - 1];
- if (lastRegion.msRegionOverflow === 'overflow') {
- createPages();
- }
- });
- });
- }
此函數(shù)執(zhí)行三個主要步驟:選擇模板、呈現(xiàn)模板并確定是否需要其他模板。在第一步中,根據(jù)當前呈現(xiàn)的頁碼將 targetPage 變量設(shè)置為適當?shù)捻撁婺0?。通過按 createPages
遞增的計數(shù)器方法,將 SDK 示例設(shè)置為呈現(xiàn) pageTemplates
陣列中的每一頁一次,然后再呈現(xiàn)下一頁。如果示例已達到陣列末尾,則使用最后一頁模板,直到內(nèi)容呈現(xiàn)完畢。
確定頁面模板后,createPages
將從適用于 JavaScript 的 Windows 庫調(diào)用片段加載程序函數(shù),以便將所選模板呈現(xiàn)到 pageContainer
元素。片段加載程序?qū)@取目標頁面文件(此示例中的 page1.html)的 body 元素中的所有內(nèi)容,并將其插入到指定的元素(在此例中為 pageContainer
元素)中。因為片段加載程序是異步調(diào)用,所以其余的 createPages
函數(shù)必須等待,直到激活 then 函數(shù)。
激活 then 之后,createPages
導(dǎo)航 DOM 以查找最后一頁上的最后區(qū)域。createPages
測試此區(qū)域,以查看是否仍有來自內(nèi)容文檔的其他內(nèi)容要呈現(xiàn)。如果未將 msRegionOverflow 屬性設(shè)置為 "overflow",則內(nèi)容文檔已完全呈現(xiàn)在最后一個區(qū)域中或最后一頁的其他區(qū)域中。如果將 msRegionOveflow 屬性設(shè)置為 "overflow",則其他內(nèi)容將保留等待呈現(xiàn)。在這種情況下,將調(diào)用 createPages
并重新開始。
Note 由于 msSetImmediate 調(diào)用,在激活 then 函數(shù)之前存在初始 createPages
調(diào)用。這意味著 createPages
不是真正的遞歸,因為一次只有一個 createPages 實例放置在調(diào)用堆棧上。
Note 顯然,createPages 使用的模板選擇機制可供設(shè)計人員調(diào)整以滿足自己的需求。例如,不用一次又一次重復(fù)使用上次使用的模板,只要還有其他內(nèi)容需要顯示,則可以改變函數(shù)以重復(fù)循環(huán)使用模板陣列。此外,createPages
使用的簡單陣列和模板選擇機制可由任意復(fù)雜邏輯取代,復(fù)雜邏輯可能基于其他因素選擇頁面模板,例如正在呈現(xiàn)的源內(nèi)容部分或主機設(shè)備的特定分辨率或方向。
最后,createPages
函數(shù)適合每一頁都與下一頁不同的閱讀器應(yīng)用。但是,某些應(yīng)用(如電子書)可能需要更多的頁面,但完全不同的頁面類型較少。對于這些應(yīng)用,尤其是源內(nèi)容很長 (例如,長篇大作的完整文本)時,建議一次加載多個頁面模板。例如,電子書閱讀應(yīng)用不使用包含單個模板的 Page1.html 文件,而使用包含多個模板的 Pages.html 文件,每個模板是簡單的兩列或三列布局。通過將這些頁面全部一起加載到內(nèi)存中,可以顯著提升整體性能。請注意,遵循此方法可能導(dǎo)致 createPages
"超過"所需的頁數(shù),并使某些頁面沒有內(nèi)容。此問題可通過使用 resizePages
函數(shù)來修復(fù),此函數(shù)將在下一部分進行詳細介紹。
#p#
調(diào)整頁面模板大小
前面我們介紹了如何使用網(wǎng)格、區(qū)域和排除項來創(chuàng)建頁面模板,以及如何在運行時實例化應(yīng)用內(nèi)的這些頁面模板。然而,能夠響應(yīng)外部事件,在運行時更改頁 數(shù)也是很重要的。即使內(nèi)容文檔保持不變,更改應(yīng)用程序區(qū)域可能導(dǎo)致應(yīng)用的視圖狀態(tài)從全屏更改為填充或貼靠模式,從而導(dǎo)致頁面縮小或增大。更改應(yīng)用程序區(qū)域 可能導(dǎo)致每個頁面裝入不同的內(nèi)容量,并且可能要求在應(yīng)用中添加或刪除頁面。
下列代碼示例顯示了 resizePages
函數(shù),此函數(shù)支持添加或刪除頁面以響應(yīng)外部事件。在動態(tài) CSS 區(qū)域模板示例中,調(diào)用 resizePages
以響應(yīng)應(yīng)用視圖狀態(tài)更改,但是也可以調(diào)用此函數(shù)響應(yīng)諸如調(diào)整字體大小等事件。
- function resizePages() {
- var flexboxElement = document.getElementById('pageContainer');
- var pages = flexboxElement.querySelectorAll('.page');
- var lastPage = pages[pages.length-1];
- var regions = lastPage.querySelectorAll(searchClass);
- var lastRegion = regions[regions.length-1];
- if (lastRegion.msRegionOverflow === 'overflow') {
- createPages();
- }
- else {
- var firstRegion = regions[0];
- while (firstRegion.msRegionOverflow === 'empty')
- {
- flexboxElement.removeChild(lastPage);
- currentPage = currentPage - 1;
- lastPage = pages[currentPage-1];
- regions = lastPage.querySelectorAll(searchClass);
- firstRegion = regions[0];
- }
- }
- }
resizePages
函數(shù)首先定位最后一頁上最后的區(qū)域。與 createPages
函數(shù)一樣,它接著測試此區(qū)域以確定是否還有更多內(nèi)容需要更多頁面來顯示。如果有要顯示的內(nèi)容,resizePages
將調(diào)用 createPages
。此外,如果最后一個區(qū)域上沒有更多內(nèi)容,此函數(shù)將查找最后一頁上的第一個區(qū)域。如果 msRegionOverflow 屬性指示此區(qū)域不為空,我們知道內(nèi)容文檔是在最后一頁結(jié)束的;不會執(zhí)行進一步的操作,因為至少在最后一頁的第一個區(qū)域中有內(nèi)容,而且沒有內(nèi)容溢出最后一個區(qū)域。此外,如果最后一頁上的第一個區(qū)域為空,則最后一頁沒有內(nèi)容,它完全是空的。resizePages
函數(shù)刪除最后一頁,并調(diào)用它本身來測試新的最后一頁。
結(jié)合使用 resizePages
和 createPages
,便足以在應(yīng)用中添加和刪除頁面。示例頁面模板設(shè)計可以靈活伸縮以填充各種屏幕尺寸,但是設(shè)計人員可能需要頁面能夠在不同的視圖狀態(tài)、方向或屏幕分辨率下重新調(diào)整布局結(jié)構(gòu)本身,而不是簡單地調(diào)整以填充多余的空間。動態(tài) CSS 區(qū)域模板示例顯 示了如何創(chuàng)建能夠在不同視圖狀態(tài)下重新調(diào)整布局結(jié)構(gòu)本身的頁面模板。下圖顯示了示例如何將布局結(jié)構(gòu)本身調(diào)整為垂直堆疊的頁面,其中每一頁都是貼靠模式下的 一個單獨區(qū)域。此方法涉及隱藏所有內(nèi)容,除了每個頁面模板僅顯示一個區(qū)域,從而在貼靠模式下僅設(shè)置一個元素作為區(qū)域,并重新設(shè)置 pageContainer
元素的方向以垂直顯示頁面。
若要了解這是如何實現(xiàn)的,請查看 Page1.html 的標記。頁面 1 中有兩個區(qū)域,每個區(qū)域都分配有一個特定的 ID 和類。兩個區(qū)域都屬于 fullregion
類,而只有第一個區(qū)域?qū)儆?snappedregion
類。fullregion
類將它的元素定義為將 –ms-flow-from 屬性設(shè)置為 content,這意味著 iframe 元素內(nèi)的材料將顯示在它們內(nèi)。snappedregion
類開始也是以相同的方式設(shè)置。
激活媒體查詢中輔屏視圖狀態(tài)的規(guī)則后,只有 snappedregion
類仍將 –ms-flow-from 屬性設(shè)置為 content;而 fullregion
類將屬性設(shè)置為 null。這樣的效果是頁面中只有一個 div 元素成為區(qū)域;內(nèi)容從該區(qū)域流到其他頁的區(qū)域中。而且,由于應(yīng)用中的其他頁面也僅在其第一個區(qū)域元素上設(shè)置 snappedregion
類,因此當應(yīng)用置于貼靠模式時,每頁只有一個區(qū)域顯示來自源文檔的內(nèi)容。下列代碼顯示頁面 1 的 HTML 和 CSS。
- <body>
- <div id="page1" class="page">
- <div id="logoContainer">
- <img id="floatLogo" src="/images/Saturn.jpg" />
- </div>
- <h1 id="title">Dynamic region Templates Sample</h1>
- <div id="page1region1" class="fullregion snappedregion"></div>
- <div id="page1region2" class="fullregion"></div>
- </div>
- </body>
- .fullregion {
- -ms-flow-from: content;
- }
- .snappedregion
- {
- -ms-flow-from: content;
- }
- /*In snapped mode the fullregion class no longer receives content from the content stream, but the snappedregion class does.*/
- @media (-ms-view-state: snapped)
- {
- .fullregion
- {
- -ms-flow-from: null;
- }
- .snappedregion
- {
- -ms-flow-from: content;
- }
- /*Change the navigation direction to vertical for RTL and LTR languages*/
- #pageContainer
- {
- -ms-box-orient: block-axis;
- }
樣式類,結(jié)合在下面的代碼中設(shè)置的樣式規(guī)則,顯示應(yīng)用在貼靠模式中如何轉(zhuǎn)換。尤其是,除了第一個區(qū)域,所有元素都設(shè)置為 display: none,而第一個區(qū)域設(shè)置為占滿整個頁面(第一行除外,此行留給文章標題使用)。在所有頁面復(fù)制此流程,并且將 pageContainer
陣列設(shè)置為按塊方向(在下面的代碼示例中為垂直方向)布置頁面時,應(yīng)用將轉(zhuǎn)換為一系列整頁區(qū)域,顯示同一內(nèi)容文檔的不同部分。應(yīng)用結(jié)合前面介紹的 resizePages
和 createPages
算法,將在貼靠模式下創(chuàng)建足夠的頁面以完全呈現(xiàn)源文檔。
- /* In snapped mode we set the first region to take up the entire page, and hide all other regions. */
- @media all and (-ms-view-state: snapped)
- {
- #page1region1
- {
- -ms-grid-row: 2;
- -ms-grid-column: 1;
- -ms-grid-row-span: 4;
- -ms-grid-column-span: 4;
- padding: 0;
- }
- #page1region2
- {
- display: none;
- }
- #logoContainer
- {
- display: none;
- }
- }
Note 前面介紹的調(diào)整頁面布局的基本機制也適用于其他設(shè)計。例如,設(shè)計人員可能需要根據(jù)頁面在 16:9 還是 4:3 模式從頁面添加或刪除區(qū)域??梢允褂?CSS 媒體查詢,根據(jù)需要修改 –ms-flow-from 和 display 屬性,從而實現(xiàn)此調(diào)整。媒體查詢還可用來更改 CSS 網(wǎng)格的結(jié)構(gòu)。例如,根據(jù)屏幕是縱向還是橫向模式,內(nèi)容布局可從 2 × 4 網(wǎng)格轉(zhuǎn)換為 4 × 2 網(wǎng)格。設(shè)計人員可能還使用 CSS 媒體查詢,根據(jù)屏幕分辨率和方向來顯示或不顯示各個圖像或其他元素。
原文鏈接:http://msdn.microsoft.com/zh-cn/library/windows/apps/hh780610.aspx