本文參考文章:In Pixels we trust, Scalable UIs In QML part 2.,感謝原文作者的貢獻(xiàn)。
上一篇,我們談到了擴(kuò)展的難度在于擴(kuò)展當(dāng)前我們已經(jīng)應(yīng)用于移動(dòng)和嵌入式設(shè)備的 PPI 范圍。我們還提到了避免這個(gè)問(wèn)題的最常見(jiàn)的方法是通過(guò)提供幾種不同分辨率下的圖像資源來(lái)幫助緩解這個(gè)問(wèn)題。
它是如何工作的?我們又如何在 QML 中進(jìn)行實(shí)現(xiàn)呢?更重要的是它是否存在問(wèn)題?這是最好的解決方案么?它權(quán)衡了哪些利弊?
圖標(biāo)
圖標(biāo)是一個(gè)比較容易入手的點(diǎn),圖標(biāo)在移動(dòng)設(shè)備誕生之前就被我們進(jìn)行縮放,這與我們現(xiàn)在在移動(dòng)設(shè)備上進(jìn)行的縮放非常類似。平臺(tái)的圖標(biāo)尺寸通常是2的倍數(shù),它一般是像16x16, 24×24, 32×32, 48×48, 64×64, 96×96, 128×128,172×172, 256×256, 512×152… 這樣類似。所有這些尺寸的原因有很多,包括營(yíng)銷、具體使用、類型、可點(diǎn)擊區(qū)域和可見(jiàn)性等。但你可能會(huì)問(wèn),如何會(huì)這么多,我們?cè)趺床恢皇鞘褂靡粋€(gè)大?。?/p>
為了回答這個(gè)問(wèn)題,我們首先需要了解像素和縮放效果。
什么是像素?
英文為Pixel,又叫Picture element。數(shù)字圖象是由按一定間隔排列的亮度不同的像點(diǎn)構(gòu)成的,形成像點(diǎn)的單位稱“像素”,也就是說(shuō),組成圖象的最小單位是像素,像素是圖象的最小因素。從計(jì)算機(jī)技術(shù)的角度來(lái)解釋,像素是硬件和軟件所能控制的最小單位。它指顯示屏的畫(huà)面上表示出來(lái)的最小單位,不是圖畫(huà)上的最小單位。像素是在影像感應(yīng)器上將光信號(hào)轉(zhuǎn)變成電信號(hào)的基本工作單位,以 CMOS 感應(yīng)器的像素為例,它包含了一個(gè)光電二極管,用來(lái)產(chǎn)生與入射光成比例的電荷,同時(shí)它也包含了其他一些電子元件,以提供緩存轉(zhuǎn)換和復(fù)位功能。當(dāng)每個(gè)像素上的電容所積累的電荷達(dá)到一定數(shù)量并被傳送給信號(hào)放大器再通過(guò)數(shù)模轉(zhuǎn)換之后,所拍攝影像的原始信號(hào)才得以真正顯現(xiàn),而具有這些全部功能的器件才能稱為是一個(gè)真正的影像感應(yīng)器。比如,一臺(tái)數(shù)碼相機(jī)的最高分辨率為3264×2448,意味著它擁有的影像感應(yīng)器會(huì)有7990272個(gè)像素點(diǎn)。該段文字參考什么是像素。
縮放是如何實(shí)現(xiàn)的?
縮放可以通過(guò)多個(gè)智能或非智能算法完成,但通常是新渲染網(wǎng)格中像素插值的結(jié)果。 結(jié)果是當(dāng)像素被拉伸時(shí),它被分布在新的像素網(wǎng)格上。
關(guān)于圖標(biāo)的一些事項(xiàng)
圖標(biāo)是使用像素網(wǎng)格充分發(fā)揮其潛力的特殊圖像。我們?nèi)匀灰韵袼乩L制圖標(biāo),即使它們實(shí)際是在矢量繪圖應(yīng)用程序中完成的。我們?nèi)匀粚⑽覀兊氖噶颗c虛擬渲染網(wǎng)格對(duì)齊,我們這樣做可以最大限度地提高對(duì)比度和銳度,因此圖標(biāo)往往會(huì)大量的使用垂直和水平的對(duì)比度。
縮放圖標(biāo)會(huì)導(dǎo)致模糊圖像,因?yàn)檫@些像素對(duì)比度在內(nèi)插過(guò)程中會(huì)變得模糊,如果對(duì)比線在主要的16×16網(wǎng)格線上完成,則只能處理多個(gè)值。即使在那里我們失去了有意義的數(shù)據(jù),作為1像素寬的對(duì)比度成為0.5或0.25的子像素。
因此,當(dāng)我們進(jìn)行圖像處理時(shí),每個(gè)圖標(biāo)都會(huì)針對(duì)每個(gè)尺寸進(jìn)行重做,我們絕對(duì)不會(huì)將圖標(biāo)從一個(gè)大小縮放到另一個(gè)尺寸...

您可以在圖像中看到,將圖標(biāo)縮放1像素可能會(huì)導(dǎo)致非常模糊的結(jié)果。 我的建議是,如果您需要不同尺寸的圖標(biāo),每英寸不同的像素看起來(lái)相同,那么您應(yīng)該提供多個(gè)圖像,使用2x和1之間的縮放因子,并重新繪制圖標(biāo),以利用額外的像素。
Android 期望的圖標(biāo)
再以 Android 平臺(tái)為例:
為了創(chuàng)建不同密度的圖標(biāo),您應(yīng)該遵循五個(gè)主要密度(分別為: medium, high, x-high, xx-high, and xxx-high)之間的2:3:4:6:8縮放比例。例如,考慮將啟動(dòng)器圖標(biāo)的大小指定為48×48 dp。 這意味著基準(zhǔn)線(MDPI)的 asset 為 48×48 像素,high 密度(HDPI)asset 應(yīng)為基準(zhǔn)線的1.5倍即 72×72 像素,x-high 密度(XHDPI)asset 應(yīng)為基準(zhǔn)線的兩倍即 96×96 像素,等等。

按鈕和其他 X/Y 獨(dú)立的可擴(kuò)展元素
應(yīng)該以獨(dú)立于 X/Y 的方式擴(kuò)展的 UI 元素,如Buttons、GroupBoxes和其他自定義的基于圖像的元素。他們?nèi)绾喂ぷ鳎?br> 在QML中,我們有一個(gè)由這些元素構(gòu)成的組件,例如 BorderImage,它可以將圖像分割成 9 部分,所以它可以適當(dāng)?shù)姆绞娇s放/平鋪每一個(gè)圖像。
BorderImage {
id: scalableElement
source: "./image/Imagebase.png"
width: 100; height: 100
border.left: 25; border.top: 25
border.right: 25; border.bottom: 25
}
上面的代碼,通過(guò)對(duì) Imagebase.png 的圖像指定 25 像素的四個(gè)邊距,從而達(dá)到不縮放圖片的四個(gè)角,僅僅拉伸這 25 像素邊距之外的區(qū)域來(lái)創(chuàng)建了一個(gè) 100X100 像素的元素。

現(xiàn)在的主要問(wèn)題是什么? 應(yīng)該有多大? 用什么度量?
如果它在觸摸屏上使用,那么它應(yīng)該足夠大,您可以觸摸它,而不會(huì)導(dǎo)致誤觸,足夠大應(yīng)該是是7到9毫米之間,這也取決于用戶可以容忍度。這個(gè)數(shù)字粗略地說(shuō)明你的拇指與觸摸屏的接觸面的大小。
這意味著我們?cè)谶@里有兩個(gè)矛盾的指標(biāo),一方面我們有像素,在另一個(gè)物理尺寸上,我們?nèi)匀灰韵袼乇硎?QML 代碼的值,但是我們需要使這個(gè)元素大小符合我們的拇指的大小。
PPI 還是 DPI ?
PPI或DPI是屏幕一英寸的像素?cái)?shù)量,我們可以通過(guò)多種方法將 PPI 顯示給 QML,但是我們希望的是真正的 PPI 而不是邏輯的。如果你是一個(gè)“像素狂魔”,你可能需要 PPIx 和 PPIy —— 它們使得像素不再總是真的“正方形”的。

將這個(gè)理論應(yīng)用到之前的代碼上,我們可以有如下的代碼:
....
property int dpi: Screen.pixelDensity*25.4
....
BorderImage {
id: scalableElement2
source: "./image/Imagebase.png"
width: 1.5*dpi; height: 0.36*dpi
border.left: 25; border.top: 25
border.right: 25; border.bottom: 25
}
該代碼展示了我們將使用最常用的方法,ppi 或 dpi作為主要指標(biāo)。無(wú)論我們使用什么屏幕,它都將創(chuàng)建一個(gè)1.5英寸長(zhǎng)的0.36英寸高的按鈕。然而,在多個(gè)屏幕上它看起來(lái)仍然會(huì)不一樣,拐角處的曲率可能會(huì)隨著 PPI 的增長(zhǎng)而下降,同時(shí)陰影也將變得越來(lái)越不可見(jiàn)。所以我們需要引入一個(gè)我們?yōu)閳D標(biāo)準(zhǔn)備的類似的解決方案,我們可以使用多個(gè) BaseImage 為多個(gè)可能的 PPI 范圍。在我的下一篇博客文章中,我將嘗試展示如何以不是太丑陋的方式來(lái)完成這一目標(biāo)。我們還將討論這種方法的局限性……QML 中的縮放(3):BorderImage