用SVG和CSS繪製逼真的雲
SVG和CSS打造逼真雲朵效果
希臘神話中,宙斯創造了雲仙女涅菲勒。和其它希臘神話一樣,這個故事相當離奇。這裡是一個簡短且合適的版本:
傳說中,涅菲勒是宙斯以自己美麗妻子的形象創造的。一位凡人邂逅涅菲勒,愛上了她,他們一起……最終,不可思議的是,這朵雲誕下了半人半馬的半人馬嬰兒。
很奇怪,對吧?我個人也無法理解。幸運的是,在瀏覽器中創建雲朵的過程要簡單得多,也正經得多。
最近,我發現開發者Yuan Chuan實現了代碼生成的、逼真的雲朵效果。對我來說,這種在瀏覽器中實現的效果曾經是神話故事。
只需瀏覽一下這個示例代碼,我們就能想像到,通過使用帶有<filter></filter>
元素(包含兩個SVG濾鏡)的CSS box-shadow
,可以實現令人信服的單個雲朵效果。
我們想要的逼真效果是通過feTurbulence
和feDisplacementMap
的巧妙結合實現的。這些SVG濾鏡功能強大、複雜且提供了非常令人興奮的功能(包括一個奧斯卡獲獎算法!)。然而,其底層複雜性可能會讓人望而生畏。
雖然SVG濾鏡的物理原理超出了本文的範圍,但在MDN和w3.org上提供了大量的文檔。關於feTurbulence
和feDisplacementMap
的非常有益的頁面是免費提供的(並且作為這本精彩書籍的一個章節)。
在本文中,我們將專注於學習如何使用這些SVG濾鏡來獲得驚人的效果。我們不需要深入了解幕後算法的運作方式,就像藝術家不需要了解顏料的分子結構就能渲染出令人驚嘆的風景一樣。
相反,讓我們密切關注幾個對在瀏覽器中繪製令人信服的雲朵至關重要的SVG屬性。使用這些屬性,我們可以將這些強大的濾鏡運用自如,並學習如何在自己的項目中精確地自定義它們。
從基礎開始
CSS box-shadow
屬性有五個值得關注的值:
<code>box-shadow:<offsetx><offsety><blurradius><spreadradius><color> ;</color></spreadradius></blurradius></offsety></offsetx></code>
讓我們將這些值調高(可能高於任何理智的開發者會使用的值),這樣陰影本身就會成為舞台上的一個角色。
<code>#cloud-square { background: turquoise; box-shadow: 200px 200px 50px 0px #000; width: 180px; height: 180px; } #cloud-circle { background: coral; border-radius: 50%; box-shadow: 200px 200px 50px 0px #000; width: 180px; height: 180px; }</code>
你玩過或者見過影子戲嗎?
就像用手改變形狀來改變陰影一樣,我們HTML中的“源形狀”可以移動和變形來移動和改變在瀏覽器中渲染的陰影的形狀。 box-shadow
複製了原始大小和border-radius
上的“變形”功能。 SVG濾鏡同時應用於元素及其陰影。
<code><svg height="0" width="0"><filter><feturbulence basefrequency=".01" numoctaves="10" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="10"></fedisplacementmap></filter></svg></code>
這是我們目前SVG的標記。它不會渲染,因為我們還沒有定義任何視覺效果(更不用說零寬度和高度了)。它的唯一目的是保存一個濾鏡,我們將這個濾鏡提供給我們的SourceGraphic
(也就是我們的<div>)。我們的源<code><div>及其陰影都由濾鏡獨立扭曲。我們將添加必要的CSS規則,使用其ID將HTML元素( <code>#cloud-circle
)鏈接到SVG濾鏡:
<code>#cloud-circle { filter: url(#filter); box-shadow: 200px 200px 50px 0px #fff; }</code>
瞧!
好吧,承認吧,添加SVG濾鏡相當不起眼。
別擔心!我們只是觸及了表面,還有很多好東西要看。
實驗feDisplacementMap
的scale
屬性
對這個屬性進行一些非科學的實驗可以產生戲劇性的效果。目前,讓我們保持feTurbulence
中的所有值不變,只需調整DisplacementMap
的scale
屬性。
隨著scale
值的增加(以30為增量),我們的源<div>會發生扭曲,並投射出陰影來反映雲朵在天空中的隨機形態。<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code><fedisplacementmap in="SourceGraphic" scale="180"></fedisplacementmap></code></pre><div class="contentsignin">登入後複製</div></div>
<p>好了,我們有所進展!讓我們稍微改變一下顏色,以產生更令人信服的雲朵效果,並增強效果。</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> <code>body { background: linear-gradient(165deg, #527785 0%, #7FB4C7 100%); } #cloud-circle { width: 180px; height: 180px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 200px 200px 50px 0px #fff; }</code></pre><div class="contentsignin">登入後複製</div></div>
<p>現在我們更接近逼真的雲朵效果了!</p>
<h3 id="修改-code-box-shadow-code-的-code-blur-code-值">修改<code>box-shadow
的blur
值
下面的圖像系列顯示了blur
值對box-shadow
的影響。在這裡, blur
值以10像素為增量增加。
為了使我們的雲朵具有一些積雲般的效果,我們可以稍微加寬我們的源<div>。<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> <code>#cloud-circle { width: 500px; height: 275px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 200px 200px 60px 0px #fff; }</code></pre><div class="contentsignin">登入後複製</div></div>
<p>等等!我們加寬了源元素,現在它擋住了我們稱之為雲朵的白色陰影。讓我們將陰影“重新投射”到更遠的距離,這樣我們的雲朵就不會被源圖像遮擋。 (可以想像一下,將你的手從牆上移開,這樣就不會擋住影子戲的視線。)</p>
<p>這可以通過一些CSS定位輕鬆實現。<code><div>是雲朵的父元素,默認情況下是靜態定位的。讓我們用一些絕對定位將我們的源<code><div>“塞”起來並移出文檔流。最初,這也會重新定位我們的陰影,因此我們還需要增加陰影與元素的距離,並稍微調整元素的位置。<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> <code>#cloud-circle { width: 500px; height: 275px; background: #000; border-radius: 50%; filter: url(#filter); box-shadow: 400px 400px 60px 0px #fff; /* 增加阴影偏移量*/ position: absolute; /* 将父元素移出文档流*/ top: -320px; /* 向下移动*/ left: -320px; /* 向右移动*/ }</code></pre><div class="contentsignin">登入後複製</div></div>
<p>是的!我們已經得到了一個相當令人信服的雲朵。</p>
<p>渲染到瀏覽器中的圖像對雲朵的描繪相當不錯——但是,我不確定……這朵雲真的能體現雲仙女涅菲勒嗎?我相信我們可以做得更好!</p>
<h3 id="使用圖層表達深度">使用圖層表達深度</h3>
<p>這就是我們想要的:</p>
<p>從這張照片中云朵的深度、紋理和豐富性來看,有一點很清楚:宙斯上過美術學校。至少,他一定讀過《設計的普遍原則》,其中闡述了一個強大而看似普通的概念:</p>
<blockquote><p> […] 照明偏差在深度和自然感的解釋中起著重要作用,並且可以通過設計師以各種方式進行操作……使用光暗區域之間的對比度來改變深度的外觀。</p></blockquote>
<p>這段話為我們提供了一個線索,說明我們如何才能大大改進我們自己生成的雲朵代碼。我們可以通過將不同形狀、大小和顏色的圖層堆疊在一起,來渲染出與參考圖像中的雲朵高度相似的雲朵。這只需要根據需要多次調用我們的濾鏡即可。 </p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><code><svg height="0" width="0"><filter><feturbulence basefrequency="0.012" numoctaves="4" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="170"></fedisplacementmap></filter><filter><feturbulence basefrequency="0.012" numoctaves="2" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="150"></fedisplacementmap></filter><filter><feturbulence basefrequency="0.012" numoctaves="2" type="fractalNoise"></feturbulence><fedisplacementmap in="SourceGraphic" scale="100"></fedisplacementmap></filter></svg></code></pre><div class="contentsignin">登入後複製</div></div>
<p>應用我們的圖層將使我們有機會探索<code>feTurbulence
並實現其多功能性。我們將選擇可用的更平滑的類型: fractalNoise
,並將numOctaves
調高到6。
<code><feturbulence basefrequency="n" numoctaves="6" type="fractalNoise"></feturbulence></code>
這意味著什麼?現在,讓我們重點關注baseFrequency
屬性。以下是我們增加n的值時得到的結果:
諸如湍流、噪聲、頻率和倍頻程之類的詞語可能顯得奇怪甚至令人困惑。但是別擔心!將這個濾鏡的效果比作聲波實際上是完全準確的。我們可以將低頻( baseFrequency=0.001
)與低沉的噪聲聯繫起來,並將高頻( baseFrequency=0.1
)與更高、更清晰的音調聯繫起來。
我們可以看到,對於積雲般的效果, baseFrequency
的值可能舒適地位於~0.005和~0.01範圍內。
使用numOctaves
添加細節
遞增numOctaves
允許我們以極其精細的細節來渲染圖像。這需要大量的計算,因此請注意:高值會嚴重影響性能。除非你的瀏覽器戴著頭盔和護膝,否則盡量避免提高這個值。
好消息是,我們不需要將這個值調得太高就能產生細節和精細度。如上圖所示,我們可以將numOctaves
值設置為4或5。
結果如下
使用seed
屬性實現無限變化
關於seed
屬性有很多內容需要說明,因為它暗示了幕後發生的魔法。但是,就我們的目的而言, seed
的效用可以用四個字概括:“不同的值,不同的形狀”。
Perlin噪聲函數(前面提到過)使用此值作為其隨機數生成器的起點。選擇不包含此屬性將默認seed
為零。但是,如果包含此屬性,無論我們賦予seed
什麼值,都不需要擔心性能問題。
上面的GIF代表了seed
提供的一些功能。請記住,每一朵雲都是一個分層的複合雲。 (雖然我已經調整了每個圖層的屬性,但我保持了它們各自的seed
值一致。)
在這裡,仔細觀察參考圖像,我已經將3個雲<div>(不透明度不同)疊加到一個基礎<code><div>上。通過反複試驗和輸入任意<code>seed
值,我最終得到了一個類似於照片中云朵形狀的形狀。
天馬行空
當然,認為我們繪製到瀏覽器上的<div>會優於宙斯的涅菲勒,那將是狂妄自大。然而,我們能夠從CSS和SVG濾鏡中挖掘出越多的奧秘,我們就越有能力創造出視覺上令人驚嘆的東西,並且與雷神最初的創造高度相似。然後,我們可以繼續進行進一步的實驗!<p>反射霧氣</p>
<p>高層卷雲</p>
<p>在本文中,我們只是涉足了一個充滿力量和復雜性的海洋。 SVG濾鏡通常看起來令人不知所措且難以接近。</p>
<p>然而,就像A Single Div項目中的示例或Diana Smith的繪畫技巧一樣,一種輕鬆愉快的實驗方法總是會帶來驚人的結果!</p>
<h4 id="成就解鎖-涅菲勒雲朵生成器">成就解鎖!涅菲勒雲朵生成器</h4>
<p>我相信你們很多人很樂意深入了解製作雲朵所需的所有技術細節,但可能更喜歡一些更方便在項目中使用雲朵的方法。我開發了一個小工具來幫助生成雲朵並實驗形狀和變化。</p>
<p>生成雲朵!</p>
<p>有任何問題、建議或意見?請在Twitter上聯繫我,或在此帖中發表評論。</p>
<p><small>非常感謝Amelia Bellamy-Royds對本文提出的寶貴建議。</small></p>
</div>
以上是用SVG和CSS繪製逼真的雲的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

關於Flex佈局中紫色斜線區域的疑問在使用Flex佈局時,你可能會遇到一些令人困惑的現象,比如在開發者工具(d...
