我想在我的 SVG 設計中利用對稱性,但是大多數查看器(包括 Firefox 和 Chromium 瀏覽器)在數字清楚地告訴我不應該有的地方呈現間隙/線條。使用縮放來放大這些設計可以減少那些錯誤渲染的線條的數量和粗細。
我誤解了svg格式嗎?實作數學上正確的 svg 渲染是否太耗費資源?還是沒有人關心這種邊緣情況?
一個更好地說明我在說什么的例子:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="98" height="98" fill="red" fill-opacity="0.7">
<g id="2">
<g id="4">
<path id="p" d="m49,35c-3,0 -4.575713,0.605785 -6.9934,1.888339L31.330807,18.397364 37,15C38,7.76 38,6 39,0.7 39.7,0 44,0 49,0Z"/>
<use xlink:href="#p" transform="rotate(-60, 49, 49)"/>
<use xlink:href="#p" transform="translate(98) scale(-1, 1) rotate(60, 49, 49)"/>
</g>
<use xlink:href="#4" transform="translate(98) scale(-1, 1)"/>
</g>
<use xlink:href="#2" transform="rotate(180, 49, 49)"/>
</svg>
我在這里找到: 如果兩個部分不透明的形狀重疊,我可以在它們重疊的地方只顯示一個形狀嗎? 可以使用過濾器使重疊的形狀表現得好像它們在不透明度方面表現得好像不是一樣,但它仍然困擾著我,需要這樣的解決方法。它增加了復雜性、檔案大小并降低了與未實作這些過濾器的查看器的兼容性。
將該解決方法應用于上述示例:
<svg width="98" height="98" fill-opacity=".7" fill="red" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<filter id="f">
<feComponentTransfer>
<feFuncA type="table" tableValues="0 .7 .7" />
</feComponentTransfer>
</filter>
<g filter="url(#f)">
<g id="2">
<g id="4">
<path id="p" d="m51 35c-3-0-6 0-10 3l-15-15 11-7c2-8 1-8 2-14 0.7-0.7 7-0.7 12-0.7"/>
<use transform="rotate(-60 49 49)" xlink:href="#p"/>
<use transform="translate(98) scale(-1 1) rotate(60 49 49)" xlink:href="#p"/>
</g>
<use transform="translate(98) scale(-1 1)" xlink:href="#4"/>
</g>
<use transform="rotate(180 49 49)" xlink:href="#2"/>
</g>
</svg>
uj5u.com熱心網友回復:
想想任何型別的渲染引擎必須如何渲染您的 SVG。它逐步遍歷 SVG,一次繪制元素。
除非該形狀是精確地觸及像素邊界的直線或矩形,否則它需要平滑該形狀的邊緣。它使用一種稱為抗鋸齒的技術來做到這一點。它繪制半透明像素來逼近僅部分覆寫像素的邊緣。
例如,如果一個形狀恰好覆寫了半個像素,渲染器將使用 50% 的 alpha 將顏色繪制到該像素中。
然后它繼續前進并繪制下一個形狀。即使那個形狀有一個數學上一致的邊界,你也可能不會得到一個完美的連接。
這就是為什么。
想象三個相鄰的像素,其中一個形狀的邊緣正好穿過中心像素的一半。
-------- -------- --------
First shape drawn: | 100% | 50% | 0% |
-------- -------- --------
此處的百分比表示繪制到每個像素中的形狀顏色量。左側像素為 100%。中間像素中的 50% 顏色 (alpha)。并且沒有顏色繪制到正確的像素中。
現在想象第二個形狀與第一個形狀共享一個邊框。您可能會想象會發生以下情況。
-------- -------- --------
First shape drawn: | 100% | 50% | 0% |
-------- -------- --------
Second shape drawn: | 0% | 50% | 100% |
-------- -------- --------
Resulting image: | 100% | 100% | 100% |
-------- -------- --------
但事實并非如此。第一個形狀已經被渲染為像素。渲染器沒有關于它之前繪制的東西的形狀的記憶。它只有先前渲染的像素的顏色可以通過。
當它開始繪制中間像素時,在任一步驟中,它都會將 50% 的新顏色與已有的像素值混合。公式大致如下:
result = 0.5 * old_pixel_colour 0.5 * new_pixel_colour
因此,例如,讓我們以上面的像素百分比示例為例,假設我們在白色背景上繪制了兩個紅色形狀。
繪制第一個形狀后,像素應該看起來像這樣。
rgb(255, 0, 0) rgb(255, 128, 128) rgb(255, 255, 255)
[0 * bg 1.0 * red] [0.5 * bg 0.5 * 50%_red] [1.0 * bg zero_red]
其中bg代表像素開始的白色背景顏色。并且50%_red表示抗鋸齒用于表示半覆寫像素的 50% 透明紅色。
第二遍之后,像素將如下所示:
rgb(255, 0, 0) rgb(255, 192, 192) rgb(255, 0, 0)
[1.0 * first no_red] [0.5 * first 0.5 * 50%_red] [0 * first 1.0 * red]
wherefirst表示繪制第一個形狀后像素的顏色。我希望這是有道理的。
或以顏色(紅色)的百分比表示。
-------- -------- --------
First shape drawn: | 100% | 50% | 0% |
-------- -------- --------
Second shape drawn: | 0% | 50% | 100% |
-------- -------- --------
Resulting image: | 100% | 75% | 100% |
-------- -------- --------
所以我希望你能明白為什么這些邊界像素最終會顯示出一條微弱的白線。這是因為您正在混合兩層抗鋸齒像素。
從理論上講,渲染器可以分析一堆形狀的像素覆寫率。但這在數學上非常復雜。它會大大減慢渲染程序。
uj5u.com熱心網友回復:
Paul LeBeau 給出了抗鋸齒如何作業的一般解釋。值得注意的是,您可以在將shape-rendering演示屬性設定為的情況下關閉此演算法crispEdges。渲染器將??嘗試繪制完全不透明或完全透明的每個像素:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" width="98" height="98" fill="red" fill-opacity="0.7">
<g id="2" shape-rendering="crispEdges">
<g id="4">
<path id="p" d="m49,35c-3,0 -4.575713,0.605785 -6.9934,1.888339L31.330807,18.397364 37,15C38,7.76 38,6 39,0.7 39.7,0 44,0 49,0Z"/>
<use xlink:href="#p" transform="rotate(-60, 49, 49)"/>
<use xlink:href="#p" transform="translate(98) scale(-1, 1) rotate(60, 49, 49)"/>
</g>
<use xlink:href="#4" transform="translate(98) scale(-1, 1)"/>
</g>
<use xlink:href="#2" transform="rotate(180, 49, 49)"/>
</svg>
這可能會有所幫助,具體取決于用例或沒有。邊緣會顯得“參差不齊”,但這是可以接受的。
但這并不是問題的結束。在理想環境中,渲染器將始終決定位于“接縫”頂部的像素屬于一側還是另一側。但在離散數字的現實世界中,它可能決定像素不屬于任何一個,并使其保持透明。
特別是如果您對形狀應用了一個或多個轉換,應用程式可能會決定它必須多次舍入數字以計算最終渲染,并且舍入錯誤可能會累加。(根據我的經驗,Chrome 比其他瀏覽器更容易出現這種影響。)
最后,規范讓渲染器在他們“可能”(或不)對該屬性值做什么方面留有很大的余地:
為了獲得清晰的邊緣,用戶代理可能會關閉所有直線和曲線的抗鋸齒,或者可能只關閉接近垂直或水平的直線。此外,用戶代理可能會調整線條位置和線條寬度以將邊緣與設備像素對齊。
不幸的是,結論是每個渲染器都使用自己的優化策略,您無法保證最終結果。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/442550.html
