本文翻譯自文章 《Of vectors and scalable things.》,個人的英文水平有限,所以只是大致的翻譯,歡迎各位批評改正。同時感謝原作者的文章。

移動
為了完成我們最初的目標(biāo),今天我們將談?wù)撦d體。
SVG 是我要啟動這一系列帖子的一個主要的動機(jī)。 它是一個偉大的文件格式,它是我每天來創(chuàng)建我的所有圖像的使用最多的格式……但是經(jīng)常有關(guān)于可擴(kuò)展 UI 和向量溢出的問題。有人會說“我們應(yīng)該用向量來擴(kuò)大事物”。為此,我通常會說“可擴(kuò)展矢量圖形是可擴(kuò)展的,但你的屏幕不是”,它通常會如我希望地結(jié)束這種對話。
然而,上述聲明只是部分正確的,而不是我們應(yīng)該避免使用現(xiàn)成的矢量圖作為 UI 資源的源圖像格式的明確原因。
可擴(kuò)展定義有點(diǎn)像是一時興起
我們在過去的帖子中定義“可擴(kuò)展”UI的方式是非常奇特的,我們傾向于以最適合我們的方式使用它,忽略了概念的不同含義之間的實(shí)際差異。像是一時興起,我們的目標(biāo)是我們想要的,但卻不是真正的目標(biāo)。這往往會導(dǎo)致在這方面很常見的混淆和誤解,正是因?yàn)?SVG 中的可擴(kuò)展部分是針對某種類型的引用概念,大多數(shù)時候并不是 UI 中需要的可擴(kuò)展類型。
那么可擴(kuò)展矢量圖形的可擴(kuò)展性意味著什么?
形成SVG或任何其他主要矢量格式(主要是)關(guān)于路徑及其控制點(diǎn)(Bézier曲線)的數(shù)學(xué)信息,其視覺尺寸僅與其所在畫布的渲染大小相關(guān),因此我們可以幾乎無限放大圖像,永遠(yuǎn)不會看到像素。(對于給定的視圖區(qū)域,像素被渲染,并且相應(yīng)地改變該區(qū)域中的向量的部分)。這使它成為一種很好的格式來將圖像縮放到真正巨大的格式。縮放為40000×40000像素的圖像將看起來與原始在1000×1000中呈現(xiàn)的圖像完全相同?,F(xiàn)在我們可以看到,這往往不是我們想要的可擴(kuò)展類型:
- 首先,我們?nèi)绻胍赬和Y軸上獨(dú)立可擴(kuò)展元素(例如上一篇中的可縮放的圓角矩形),對于這種情況我們將需要像 Borderimage 組件的東西;
- 其次,當(dāng)我們縮小許多元素成為子像素,并且仍然存在難以看清。例如,在地圖中,我們可能需要根據(jù)縮放級別呈現(xiàn)不同的效果,例如使道路消失/出現(xiàn)在縮小/放大時,以及簡化路徑本身的方面;
- 第三,它忽略像素,因?yàn)槲覀兲岬降南袼厝匀环浅V匾?,在較低清晰度的屏幕中,我們可以利用像素創(chuàng)建鮮明的對比度,這使您的視覺元素溢出背景。然而,SVG 在其對路徑位置的大部分完美的數(shù)學(xué)描述中完全忽略了渲染網(wǎng)格,并且因此可以產(chǎn)生通過像素的小數(shù)離開像素網(wǎng)格的不清晰元素。(這只是在與像素網(wǎng)格配置對齊的矩形元素中是有問題的,但我們將其用作設(shè)計的優(yōu)點(diǎn))。
QML 中的 SVG
您現(xiàn)在可以在QML中使用SVG作為源格式,但是注意,除非你告訴它,否則它不會重新渲染,結(jié)果將是,如果我們縮放或者改變寬高時你將最終看到像素。您可以創(chuàng)建更大的渲染,這些渲染將提供更加可縮放的更高定義,但是花費(fèi)更多時間來渲染它并為緩存的圖像占用大量內(nèi)存。SVG也可以非常復(fù)雜,我創(chuàng)建了SVG需要花費(fèi)幾個小時來渲染我過去的KDE的許多壁紙都是以輪廓模式完成的,我只會偶爾用過濾器和顏色來看它們,我確實(shí)有一個強(qiáng)大的桌面使那些正常運(yùn)行;但是在手機(jī)上嘗試類似的東西不是一個好主意。QT中的SVG支持是有限的,許多事情將無法正常工作,過濾器大多不工作,所以如果您希望基于模糊的陰影工作,則看起來會發(fā)生巨大變化,您將不會看到這些,對于multiply濾鏡、透明度等也是如此……所以,簡而言之,不要使用SVG作為基本源圖像,除非你知道它的局限性和它的工作原理,如果你明白它的局限性和優(yōu)勢,這是一個很好的格式,有時在 QML 中也是有用的。
其他矢量格式呢? 比如說字體?
有一種我們一直使用的特殊矢量格式,也是可擴(kuò)展的,它的格式已經(jīng)在多年前解決了這個問題 —— 字體。
字體是特殊類型的單色矢量路徑,可以有特殊的提示來滿足像素可擴(kuò)展性問題。 它通過2種方法來實(shí)現(xiàn):
- 字體提示——(也稱為指示)是使用數(shù)學(xué)指令來調(diào)整字體的視覺外觀,使其與虛擬網(wǎng)格對齊。
- 字體字距——在相對x方向移動字形,以獲得更令人愉悅的視覺效果,有時可幫助網(wǎng)格對齊問題...

所有這些變化都是由您的本地字體渲染引擎完成的,這些操作的完成程度取決于您的本地字體渲染定義...
現(xiàn)在,從引入QML 2以來,字體的渲染方式已經(jīng)改變了,默認(rèn)情況下,字體提示被忽略。因此,如果您通過動畫化像素大小來縮放字體,您將獲得一個很好的平滑縮放效果,但是由于它們沒有被暗示,所以在字體周圍稍微更加模糊。 QML 允許您通過執(zhí)行本機(jī)查看的字體。
Text {
text: "Native here!"
renderType: Text.NativeRendering
}
如果你嘗試在這里做一個縮放效果,通過動畫的像素大小,你會有一個“跳躍”的文字感覺,因?yàn)殡S著大小的增加,字體提示將繼續(xù)努力將字體調(diào)整到適應(yīng)不斷變化的像素網(wǎng)格。此外,默認(rèn)方法會在更改縮放比例時通過距離字段方法執(zhí)行縮放:當(dāng)使用本機(jī)渲染屬性時,您會看到1:1比例的像素被縮放。默認(rèn)使用的距離字段方法的另一個副作用是如果縮放/字體。尺寸非常大,您開始看到方法的不準(zhǔn)確,這對您選擇的任何字體大小有效,該方法基于字體從小圖像生成距離字段字形,并且在縮放時不會更新。

此外,如果字體格式不正確(字形邊框小于字形本身),它可能會在某些邊框區(qū)域中剪切字體,具有奇怪的視覺效果。
所以,我的建議是:如果你需要可讀取的文本,你不想捏捏縮放或其他以動畫方式更改字體大小的其他效果,請使用本機(jī)渲染。如果你想要一些動態(tài)的效果,您可以嘗試一個折中的解決方案,當(dāng)運(yùn)行動畫化時,您可以選擇默認(rèn)值,動畫完成之后再將其轉(zhuǎn)換為本機(jī)屬性。在一天結(jié)束時,這主要是您認(rèn)為最重要和更精細(xì)的問題。值得注意的是,在較高的 DPI 屏幕上,暗示指令失去了很大的重要性,因?yàn)橄袼卮笮『拖鄳?yīng)的子像素抗鋸齒“灰度”變得相對于字體更小,相對不那么重要。對于非正方形像素,如許多(但不是全部)AMOLED屏幕也是如此。
下一篇文章!
下一篇文章將返回到使 X 和 Y 軸獨(dú)立縮放元素與 DPI 屬性值之間協(xié)調(diào)工作的主題……QML 中的縮放(5):縮放內(nèi)容