整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          「譯」使用.NET將WebAssembly擴展到云(

          「譯」使用.NET將WebAssembly擴展到云(一)

          1

          /

          DotNet NB 226

          原文 | Richard Lander

          翻譯 | 鄭子銘

          WebAssembly(Wasm)是一種令人興奮的新虛擬機和(匯編)指令格式。Wasm 誕生于瀏覽器,是 Blazor 項目的重要組成部分。Wasm 的第二個行動是針對應用程序和功能的云計算。WebAssembly 系統接口 (WASI) 是新的推動者,為 WebAssembly 代碼提供了一種安全地跨語言調用和實現任意 API 的方法?,F在可以使用 .NET 8 中的 wasi 實驗工作負載通過 .NET 創建 WASI 應用程序。我們正在探索這些新技術并在此環境中運行 .NET 應用程序……。真的,任何地方。

          這篇文章將幫助您了解 Wasm 的廣泛使用,并描述 .NET 已經可以實現的功能。他們說歷史不會重演,但會押韻。我們又回來進行另一輪“一次編寫,隨處運行”。WASI 應用程序是可移植的二進制文件,可以在任何硬件或操作系統上運行,并且不特定于任何編程語言。這一次,感覺不一樣了。這不僅僅是供應商的神經;一切都是中立的。

          Wasm 和 WASI

          Wasm 可能會為我們提供云計算的重啟,并承諾提供單一云原生二進制文件、更高的密度和更便宜的多租戶。出于同樣的原因,它也開啟了邊緣計算的可能性。事實上,CloudFlare 和 Fastly 已經使用 Wasm 在邊緣托管公共計算。

          Wasm 與在 Linux 容器中運行應用程序不同,后者是對現有標準和代碼的(良好且聰明的)重新打包。Wasm 更像是在沒有操作系統的環境中運行應用程序,只有匯編代碼、內存和對外部世界的標準化(和門控)訪問(通過 WASI)。

          Build 2023 上的 Hyperlight 演示(4m 視頻)深入了解了支持 Wasm 的云的外觀。它演示了在新的輕量級安全虛擬機管理程序中運行的 Blazor 應用程序。Hyperlight 激發了新托管范例的想象力。

          WebAssembly 系統接口 (WASI)、WebAssembly 接口類型 (WIT) 和 WebAssembly 組件模型是最新一輪 Wasm 創新的關鍵規范。它們基本上仍處于設計階段并正在經歷重大變化。這篇文章(以及 .NET 8 實現)以 WASI Preview 1 為中心。我們希望 .NET 9 實現使用 WASI Preview 2。

          WIT 和 wit-bindgen 使用任何源語言編寫的組件都可以與主機系統進行通信。WIT 對 C# 支持的實現由 @silesmo 領導。Wasm 和 WIT 一起定義了應用程序二進制接口(ABI)。

          我們期望 WASI 成為一組標準的 WIT 類型,提供對低級功能的訪問(例如獲取時間和讀取文件)。這些低級類型有效地形成了跨編程語言和操作系統的“Wasm 標準庫”。例如,我們從來沒有 Rust 開發人員和 .NET 開發人員可以同時使用的標準和共享功能。歷史上還沒有任何廣泛部署的本機代碼公開具有 OO 形狀(如接口)的 API,可以跨編程語言和操作系統使用。

          標準 WIT 類型以 wasi- 開頭,定義“平臺”。您可以將它們視為與 .NET 中的系統命名空間類似的方式(與 WASI 中的“S”匹配)。繼續類比,您可以在 System 命名空間之外創建自己的 .NET 命名空間,WIT 也是如此。

          這些帖子在更詳細地構建 WASI 方面做得非常出色。

          • 標準化 WASI:在 Web 之外運行 WebAssembly 的系統接口

          • 宣布字節碼聯盟:為 WebAssembly 構建一個默認安全、可組合的未來

          • WebAssembly:開發人員更新的路線圖

          即將到來的承諾是能夠采用現有的 .NET 應用程序或庫并將其編譯為 Wasm 目標。我們的設計本能是在 .NET 堆棧中實現相對較高的 WIT 接口(例如為 wasi-sql 創建 ADO.NET 數據提供程序),這將使現有代碼(包括許多現有的 NuGet 包)能夠正常工作,特別是對于沒有本機依賴項。

          Wasm 應用程序在 Wasm 運行時中運行,例如 wasmtime。與 Docker 非常相似,您可以使用特定功能配置該運行時。例如,如果您希望 Wasm 代碼能夠訪問鍵/值存儲,您可以向其公開一個鍵/值接口,該接口可以由本地數據庫或云服務支持。

          Wasm 運行時旨在可嵌入到應用程序中。事實上,有一個 wasmtime 包用于在 .NET 應用程序中托管 Wasm。.NET 代碼可以作為 Wasm 運行,但 .NET 應用程序可以托管 wasmtime????是的,這個空間開始看起來是圓形的。雖然這些場景看起來很循環,但它們最終可能非常有用,與 AppDomain 的使用方式大致相似。這也讓人想起所有“docker in docker”場景。
          我們期待更多的創新、更多的 Wasm 運行時和更多的行業參與者。事實上,Wasm 已經升級為 W3C 規范。W3C 是 Wasm 的完美家園,讓它成長為廣泛的行業規范,就像之前的 HTML 和 XML 一樣。

          wasi-實驗工作量

          .NET 8 包含一個名為 wasi-experimental 的新工作負載。它構建在 Blazor 使用的 Wasm 功能之上,將其擴展為在 wasmtime 中運行并調用 WASI 接口。它還遠未完成,但已經實現了有用的功能。

          讓我們從理論轉向演示新功能。

          安裝 .NET 8 SDK 后,您可以安裝 wasi-experimental 工作負載。

          dotnet workload install wasi-experimental

          注意:此命令可能需要管理員權限,例如在 Linux 和 macOS 上使用 sudo。

          您還需要安裝 wasmtime 來運行您即將生成的 Wasm 代碼。

          使用 wasi-console 模板嘗試一個簡單的示例。

          $ dotnet new wasiconsole -o wasiconsole
          $ cd wasiconsole
          $ cat Program.cs
          using System;

          Console.WriteLine("Hello, WASI Console!");
          $ dotnet run
          WasmAppHost --runtime-config /Users/rich/wasiconsole/bin/Debug/net8.0/wasi-wasm/AppBundle/wasiconsole.runtimeconfig.json
          Running: wasmtime run --dir . -- dotnet.wasm wasiconsole
          Using working directory: /Users/rich/wasiconsole/bin/Debug/net8.0/wasi-wasm/AppBundle
          Hello, WASI Console!

          該應用程序使用 wasmtime 運行。這里沒有 x64 或 Arm64,只有 Wasm。

          dotnet run 提供額外的信息(在控制臺輸出中)來幫助解釋發生了什么。未來這種情況可能會改變。與主機系統的所有交互均由 wasmtime 管理。

          我們可以更深入地查看 AppBundle 目錄。

          $ ls -l bin/Release/net8.0/wasi-wasm/AppBundle
          total 24872
          -rwxr--r-- 1 rich staff 11191074 Oct 31 07:53 dotnet.wasm
          -rwxr--r-- 1 rich staff 1526128 Oct 11 14:00 icudt.dat
          drwxr-xr-x 6 rich staff 192 Nov 19 19:35 managed
          -rwxr-xr-x 1 rich staff 48 Nov 19 19:35 run-wasmtime.sh
          -rw-r--r-- 1 rich staff 915 Nov 19 19:35 runtimeconfig.bin
          drwxr-xr-x 2 rich staff 64 Nov 19 19:35 tmp
          -rw-r--r-- 1 rich staff 1457 Nov 19 19:35 wasiconsole.runtimeconfig.json
          $ ls -l bin/Release/net8.0/wasi-wasm/AppBundle/managed
          total 3432
          -rw-r--r-- 1 rich staff 27136 Nov 19 19:35 System.Console.dll
          -rw-r--r-- 1 rich staff 1711616 Nov 19 19:35 System.Private.CoreLib.dll
          -rw-r--r-- 1 rich staff 5632 Nov 19 19:35 System.Runtime.dll
          -rw-r--r-- 1 rich staff 5120 Nov 19 19:35 wasiconsole.dll

          SDK 將應用程序發布到獨立部署中。.NET 運行時 — dotnet.wasm — 已經編譯為 Wasm(在我們的構建機器上)。應用程序和 dotnet.wasm 在 wasmtime 中一起加載,運行所有代碼。應用程序的實際托管代碼(位于托管目錄中)在運行時解釋,就像 Blazor WebAssembly 一樣。 @yowl 和 @SingleAccretion 社區成員一直在嘗試 Wasm 和原生 AOT。

          您可能想知道為什么我們需要將所有這些文件分開,而顯然更好的選擇是擁有一個 wasiconsole.wasm 文件。我們也可以這樣做,但稍后會在帖子中介紹它,因為我們需要在機器上安裝更多的軟件(目前 wasi 實驗工作負載不包含這些軟件)。

          RuntimeInformation 告訴我們什么?

          RuntimeInformation 是我最喜歡的類型之一。它讓我們更好地了解目標環境。

          我們可以稍微更改示例以顯示一些更有用的信息。

          using System;
          using System.Runtime.InteropServices;

          Console.WriteLine($"Hello {RuntimeInformation.OSDescription}:{RuntimeInformation.OSArchitecture}");
          Console.WriteLine($"With love from {RuntimeInformation.FrameworkDescription}");

          它產生這個輸出。

          Hello WASI:Wasm
          With love from .NET 8.0.0

          第一行很有趣。操作系統是WASI,架構是Wasm。這是有道理的,有更多的背景。文章前面提到 Wasm 可以被認為是“無操作系統”,但是我們不能簡單地稱之為 Wasm,因為現有的瀏覽器和 WASI 環境有很大不同。因此,該環境唯一一致的名稱是 WASI,而 Wasm 明確是“芯片架構”。

          Wasm 是一個 32 位計算環境,這意味著 2^32 字節是可尋址的。但是,Wasm 運行時可以配置為使用 memory64,從而可以訪問 >4GB 的內存。我們還沒有對此的支持。

          訪問主機文件系統

          Wasmtime(和其他 Wasm 運行時)提供將主機目錄映射到來賓目錄的選項。從用戶的角度來看,這與使用 Docker 進行卷掛載類似,但實現細節有所不同。

          讓我們看一個依賴目錄安裝的簡單應用程序。它使用 Markdig 包將 markdown 轉換為 HTML。公平地說,Markdig 并不是為了以 Wasm 的身份運行而編寫的。只要能夠為其創建一個舒適的管理環境,Markdig 就會很高興,這就是我們所做的。

          讓我們在 Mac M1 (Arm64) 機器上嘗試一下。

          $ pwd
          /Users/rich/git/wasm-samples/tomarkup
          $ dotnet publish
          $ cd bin/Release/net8.0/wasi-wasm/AppBundle
          $ cat run-wasmtime.sh
          wasmtime run --dir . dotnet.wasm tomarkup $*
          $ ./run-wasmtime.sh
          A valid inputfile must be provided.
          $ wasmtime run --dir . --mapdir /markdown::/Users/rich/markdown --mapdir /tmp::/Users/rich dotnet.wasm tomarkup $* /markdown/README.md /tmp/README.html
          $ ls ~/*.html
          /Users/rich/README.html
          $ cat ~/markdown/README.md | head -n 3
          # .NET Runtime

          [![Build Status](https://dev.azure.com/dnceng-public/public/_apis/build/status/dotnet/runtime/runtime?branchName=main)](https://dev.azure.com/dnceng-public/public/_build/latest?definitionId=129&branchName=main)
          $ cat ~/README.html | head -n 3
          <h1>.NET Runtime</h1>
          <p><a href="https://dev.azure.com/dnceng-public/public/_build/latest?definitionId=129&amp;branchName=main"><img src="https://dev.azure.com/dnceng-public/public/_apis/build/status/dotnet/runtime/runtime?branchName=main" alt="Build Status" /></a>
          <a href="https://github.com/dotnet/runtime/labels/help%20wanted"><img src="https://img.shields.io/github/issues/dotnet/runtime/help%20wanted?style=flat-square&amp;color=%232EA043&amp;label=help%20wanted" alt="Help Wanted" /></a>

          --mapdir 正在掛載從主機到來賓的目錄。

          如您所見,Markdown 文件已轉換為 HTML。為了簡潔起見,顯示了每個文件的前三行。

          目錄掛載所需的 CLI 手勢目前有點不方便。這是我們需要在未來版本中考慮的內容。這實際上是一個 dotnet run 和 wasmtime run 應該如何關聯的問題。

          但它能算字數嗎?

          我最近出版了《System.IO 的便利》,重點關注字數統計。我們能否獲得與 Wasm 相同的代碼來運行并看看它的運行速度有多快?

          該文章中的字數統計基準測試在 Linux x64 上運行。讓我們保持不變,但這次以 Wasm 身份運行。

          $ pwd
          /Users/rich/git/convenience/wordcount/count
          $ grep asm count.csproj
          <RuntimeIdentifier>wasi-wasm</RuntimeIdentifier>
          <WasmSingleFileBundle>true</WasmSingleFileBundle>
          $ dotnet publish
          $ cd bin/Release/net8.0/wasi-wasm/AppBundle/
          $ WASMTIME_NEW_CLI=0 wasmtime run --mapdir /text::/home/rich/git/convenience/wordcount count.wasm $* /text/Clarissa_Harlowe
          11716 110023 610515 /text/Clarissa_Harlowe/clarissa_volume1.txt
          12124 110407 610557 /text/Clarissa_Harlowe/clarissa_volume2.txt
          11961 109622 606948 /text/Clarissa_Harlowe/clarissa_volume3.txt
          12168 111908 625888 /text/Clarissa_Harlowe/clarissa_volume4.txt
          12626 108593 614062 /text/Clarissa_Harlowe/clarissa_volume5.txt
          12434 107576 607619 /text/Clarissa_Harlowe/clarissa_volume6.txt
          12818 112713 628322 /text/Clarissa_Harlowe/clarissa_volume7.txt
          12331 109785 611792 /text/Clarissa_Harlowe/clarissa_volume8.txt
          11771 104934 598265 /text/Clarissa_Harlowe/clarissa_volume9.txt
          9 153 1044 /text/Clarissa_Harlowe/summary.md
          109958 985714 5515012 total

          我更新了項目文件以包含 wasi-wasmtrue 并注釋掉 PublishAot 相關屬性。我還添加了一個runtimeconfig.template.json 文件。未對應用程序代碼進行任何更改。

          現在,我們將整個應用程序放在一個文件包中。

          $ ls -l bin/Release/net8.0/wasi-wasm/AppBundle/
          total 6684
          -rw-r--r-- 1 rich rich 1397 Nov 19 19:59 count.runtimeconfig.json
          -rwxr-xr-x 1 rich rich 6827282 Nov 19 19:59 count.wasm
          -rw-r--r-- 1 rich rich 915 Nov 19 19:59 runtimeconfig.bin
          -rwxr-xr-x 1 rich rich 27 Nov 19 19:59 run-wasmtime.sh
          drwxr-xr-x 2 rich rich 4096 Nov 19 19:59 tmp

          看起來好多了。該應用程序只有不到 7MB。我必須安裝 WASI-SDK 才能使用 WasmSingleFileBundle 屬性并設置環境變量以使 dotnetpublish 能夠找到所需的工具。

          $ echo $WASI_SDK_PATH
          /home/rich/wasi-sdk/wasi-sdk-20.0/

          wasmtime 最近發生了重大變化。我選擇使用 WASMTIME_NEW_CLI=0 來恢復運行示例的舊行為。

          讓我們回到性能。首先,作為 wasm 運行(通過解釋器執行托管代碼):

          $ time WASMTIME_NEW_CLI=0 wasmtime run --mapdir /text::/home/rich/git/convenience/wordcount count.wasm $* /text/Clarissa_Harlowe
          11716 110023 610515 /text/Clarissa_Harlowe/clarissa_volume1.txt
          12124 110407 610557 /text/Clarissa_Harlowe/clarissa_volume2.txt
          11961 109622 606948 /text/Clarissa_Harlowe/clarissa_volume3.txt
          12168 111908 625888 /text/Clarissa_Harlowe/clarissa_volume4.txt
          12626 108593 614062 /text/Clarissa_Harlowe/clarissa_volume5.txt
          12434 107576 607619 /text/Clarissa_Harlowe/clarissa_volume6.txt
          12818 112713 628322 /text/Clarissa_Harlowe/clarissa_volume7.txt
          12331 109785 611792 /text/Clarissa_Harlowe/clarissa_volume8.txt
          11771 104934 598265 /text/Clarissa_Harlowe/clarissa_volume9.txt
          9 153 1044 /text/Clarissa_Harlowe/summary.md
          109958 985714 5515012 total
          Elapsed time (ms): 821
          Elapsed time (us): 821223.8

          real 0m0.897s
          user 0m0.846s
          sys 0m0.030s

          現在有了我們對 Wasm 的(甚至更多)實驗性原生 AOT 支持。

          $ time WASMTIME_NEW_CLI=0 wasmtime run --mapdir /text::/home/rich/git/convenience/wordcount count.wasm $* /text/Clarissa_Harlowe
          11716 110023 610515 /text/Clarissa_Harlowe/clarissa_volume1.txt
          12124 110407 610557 /text/Clarissa_Harlowe/clarissa_volume2.txt
          11961 109622 606948 /text/Clarissa_Harlowe/clarissa_volume3.txt
          12168 111908 625888 /text/Clarissa_Harlowe/clarissa_volume4.txt
          12626 108593 614062 /text/Clarissa_Harlowe/clarissa_volume5.txt
          12434 107576 607619 /text/Clarissa_Harlowe/clarissa_volume6.txt
          12818 112713 628322 /text/Clarissa_Harlowe/clarissa_volume7.txt
          12331 109785 611792 /text/Clarissa_Harlowe/clarissa_volume8.txt
          11771 104934 598265 /text/Clarissa_Harlowe/clarissa_volume9.txt
          9 153 1044 /text/Clarissa_Harlowe/summary.md
          109958 985714 5515012 total
          Elapsed time (ms): 60
          Elapsed time (us): 60322.2

          real 0m0.107s
          user 0m0.064s
          sys 0m0.045s

          現在,在 Linux x64 上使用 CoreCLR 運行:

          $ time ./app/count ../Clarissa_Harlowe/
          11716 110023 610515 ../Clarissa_Harlowe/clarissa_volume1.txt
          12124 110407 610557 ../Clarissa_Harlowe/clarissa_volume2.txt
          11961 109622 606948 ../Clarissa_Harlowe/clarissa_volume3.txt
          12168 111908 625888 ../Clarissa_Harlowe/clarissa_volume4.txt
          12626 108593 614062 ../Clarissa_Harlowe/clarissa_volume5.txt
          12434 107576 607619 ../Clarissa_Harlowe/clarissa_volume6.txt
          12818 112713 628322 ../Clarissa_Harlowe/clarissa_volume7.txt
          12331 109785 611792 ../Clarissa_Harlowe/clarissa_volume8.txt
          11771 104934 598265 ../Clarissa_Harlowe/clarissa_volume9.txt
          9 153 1044 ../Clarissa_Harlowe/summary.md
          109958 985714 5515012 total
          Elapsed time (ms): 77
          Elapsed time (us): 77252.9

          real 0m0.128s
          user 0m0.096s
          sys 0m0.014s

          這些都是有趣的結果。我們有解釋、AOT 和 JIT 代碼生成方法可供比較。Wasm 解釋器能夠在不到一秒的時間內計算(略低于)一百萬個單詞,而 AOT 編譯的 Wasm 和 JIT 運行時可以在大約 100 毫秒內完成同樣的操作。

          注意:Main 方法是運行 main 的時間,由 StopWatch 測量。流程是整個流程的持續時間,以時間來衡量。

          此圖表顯示了上下文中的所有結果,包括 System.IO 的便利性帖子中的結果。

          wasmtime JIT 將 Wasm 代碼編譯到目標環境(在本例中為 Linux+x64)。例如,可以使用 wamr 對 Wasm 代碼進行 AOT。我將把它留到另一篇文章中。

          原文鏈接

          Extending WebAssembly to the Cloud with .NET

          家在做一些平面設計、文檔編輯或網站頁面的時候,經常會用到一些背景圖片,但網上下載的背景圖片有時不能滿足實際需求,自己動手制作需要較高的美術功底,相關的制作軟件也難以快速上手。其實借助一些云服務,通過簡單設置就可以生成各種紋理圖片、指定規格的站位圖、有爆炸效果的圖片以及純CSS形態的背景圖。

          一、創建指定大小的占位圖

          我們在制作網頁或者編輯文章的時候,經常都需要使用到占位圖。這樣可以在網頁或文檔制作完成后,根據實際的使用環境來替換需要的圖片。那么如何快速制作出指定大小的占位圖呢?

          首先通過瀏覽器打開placy.org這個云服務,在打開頁面的右側就可以進行參數的設置。在PLACEHOLDER的區域里面,分別設置圖片背景的寬度和高度,接下來在“Background color”參數中設置背景顏色的色號。然后可以根據自己的需要,來選擇是否在圖片中顯示需要的文字,如果需要的話那么就要勾選上下面的TEXT選項。

          首先在Caption選項里面輸入需要的文字信息,文字信息輸入完成后需要按下回車鍵,才可以在圖片中進行顯示。然后再根據提示,分別設置字體的類型、大小、形態和顏色等信息(圖1)。所有的參數設置完成以后點擊下面的“Get Placeholder”按鈕,在彈出的對話框中就可以看到PNG、JPG 和 SVG三種不同圖片格式的選項。


          用戶可以根據自己的需要進行選擇,選擇后點擊“Download placeholder”按鈕,就可以完成這個占位圖的下載(圖2)。另外,如果用戶是進行網頁設計,那么可以直接調用對話框中的代碼信息,將其插入到自己編寫的網頁代碼當中,從而可以非常方便的在網頁中直接顯示占位圖。


          二、創建波浪形的背景圖片

          現在有些手機的桌面是一種波浪效果的圖片,看上去非常的不錯。如果用戶也想生成類似的圖片,那么可以試一試“Wicked Backgrounds”這個生成器。通過它用戶只需要在其中設定幾個簡單的參數,就可以立即生成需要的背景圖片。首先通過瀏覽器打開它的官方網站wickedbackgrounds.com,點擊網頁中的“Launch Editor”按鈕后就進入到生成器的編輯頁面。該頁面分為左右兩個部分,在左側主要是幾個參數的設置區域,而右側則是生成圖片的預覽區域。

          首先點擊左側列表中的“Pick a color”選項,該服務默認使用的是深藍色的主色調,點擊該選項后在彈出的調色盤中根據自己的需要,利用鼠標點擊來選擇自己需要的主色調(圖3)。點擊“Angle”選項可以調整波浪的強度。點擊“Color mode”可以選擇圖片的顯示模式,默認選擇的是Lighten淺色模式,用戶可以根據需要選擇深色模式或變色模式。點擊“Contrast”選項可以調整波浪的不規則強度等等。


          每當用戶對一個選項進行操作后,在預覽區域就可以實時顯示出對應的效果。另外由于該服務默認是讓圖片呈橫向顯示,如果用戶想將圖片設置為手機桌面,那么可以點擊預覽區域上方的“Vertical Preview”選項,這樣就可以將圖片呈縱向顯示。除此以外,點擊“Full HD”選項還可以看到更多的尺寸參數,用戶可以根據自己的需要來進行參數的選擇(圖4)。當所有設置完成后點擊左側列表最上方的“Downlaod”按鈕,就可以完成圖片的下載操作。


          三、更加個性化的爆炸圖片

          如果用戶覺得波浪圖形的效果一般,那么還可以試試bbburst這款生成器。它可以快速生成具有爆炸效果的圖片,不僅可以給用戶一種更強烈的視覺效果,也更加適用于背景或者封面等環境。

          首先通過瀏覽器打開它的官方網站fffuel.co/bbburst/,在生成器頁面的opacity參數中,可以通過滑桿來調整圖片的透明度參數。滑桿越左透明效果越差,而滑桿越右透明效果越好。接著在amount參數中設置圖形的密度,同樣滑桿往左密度越小滑桿往右密度越大。然后在下面有一個“blur edges”的選項,通過它可以設置圖片不同區域的模糊效果。比如選擇center選項就代表圖片四周模糊而中間清晰,而選擇“top left”選項就代表左側清晰而右側模糊(圖5)。

          接下來在網頁下方可以看到“fill 1”、“fill 2”這樣的列表,其中一個選項就代表一個圖片中的圖

          案。在默認狀態下生成器已經生成了五個不同的圖案,用戶可以通過生成器上方的預覽圖來進行查看。如果覺得不滿意的話,可以點擊圖案后面的刪除按鈕,將默認的圖案進行刪除。然后再點擊下面的加號按鈕,這時生成器會自動創建一個顏色。當然用戶也可以對顏色的色號進行修改,來設定自己需要的顏色,然后在右側窗口中選擇一個對應的圖案即可(圖6)。

          所有的參數設置完成以后,點擊頁面右下角的randomize按鈕,就會隨機生成一個爆炸效果的圖片。當用戶通過預覽圖感覺滿意后,點擊右下角的Save按鈕,就可以下載一個SVG格式的圖片。當然也可以點擊copy按鈕,將其直接復制到系統的剪切板里面,這樣就可以粘貼到其他的編輯器里進行二次加工。由于生成的是SVG格式的圖片,即使是隨意的進行放大操作,也不會出現任何模糊的情況。

          關注我的頭條號@愛玩軟件的蓑草,了解最詳細的電腦技巧!

          前兩天聽歌的時候發現網易云的孤獨星球動畫挺好看,本想著在網上找找思路,誰知道直接就有,哈哈效果圖(動態的,沒找到動態工具,拿截圖湊合看吧):

          源代碼

          CSS

          #effect-music {  position: relative;  margin: auto;  width: 100%;  height: 400px;  overflow: hidden;} #effect-music > .image {  position: absolute;  left: 0;  right: 0;  top: 0;  bottom: 0;  margin: auto;  width: 150px;  height: 150px; background: url(https://tvax1.sinaimg.cn/crop.0.280.720.720.180/cf2922d4ly1g4r5m8upm6j20k00zkqt7.jpg);  background-size: cover;  background-position: center center;  border-radius: 50%;  -webkit-border-radius: 50%;  -moz-border-radius: 50%;  -ms-border-radius: 50%;  -o-border-radius: 50%;  animation: rotate 10s linear 0s infinite;  -webkit-animation: rotate 10s linear 0s infinite;} #effect-music > .wave {  position: absolute;  opacity: 0;  left: 0;  right: 0;  top: 0;  bottom: 0;  margin: auto;  width: 204px;  height: 204px;  border-radius: 50%;  border: 2px solid #eee;  animation: wave 4s linear 0s infinite;  -webkit-animation: wave 4s linear 0s infinite;} #effect-music > .wave::after {  content: "";  position: absolute;  top: -4px;  left: 50%;  width: 6px;  height: 6px;  overflow: hidden;  border-radius: 5px;  -webkit-border-radius: 5px;  -moz-border-radius: 5px;  -ms-border-radius: 5px;  -o-border-radius: 5px;  background-color: #ccc;} #effect-music > .wave:nth-child(2) {  animation-delay: 1s;} #effect-music > .wave:nth-child(3) {  animation-delay: 2s;} #effect-music > .wave:nth-child(4) {  animation-delay: 3s;} @keyframes rotate {  from {    transform: rotate(0deg);    -webkit-transform: rotate(0deg);    -moz-transform: rotate(0deg);    -ms-transform: rotate(0deg);    -o-transform: rotate(0deg);  }  to {    transform: rotate(360deg);    -webkit-transform: rotate(360deg);    -moz-transform: rotate(360deg);    -ms-transform: rotate(360deg);    -o-transform: rotate(360deg);  }} @keyframes wave {  from {    opacity: 1;    transform: rotate(0deg) scale(1);    -webkit-transform: rotate(0deg) scale(1);    -moz-transform: rotate(0deg) scale(1);    -ms-transform: rotate(0deg) scale(1);    -o-transform: rotate(0deg) scale(1);  }  to {    opacity: 0;    transform: rotate(-300deg) scale(2.2);    -webkit-transform: rotate(-300deg) scale(2.2);    -moz-transform: rotate(-300deg) scale(2.2);    -ms-transform: rotate(-300deg) scale(2.2);    -o-transform: rotate(-300deg) scale(2.2);}}

          HTML

          <div id="effect-music"><div class="image"></div><div class="wave"></div><div class="wave"></div><div class="wave"></div><div class="wave"></div></div>

          主站蜘蛛池模板: 国产主播福利精品一区二区| 3d动漫精品啪啪一区二区免费| 国产亚洲一区二区精品| 亚洲AV美女一区二区三区| 日韩一区二区三区四区不卡| 精品无码综合一区| 无码中文人妻在线一区二区三区 | 日韩人妻无码一区二区三区| 亚洲国产精品一区二区久| 激情综合一区二区三区| 国精产品一区一区三区有限公司| 亚洲国产精品乱码一区二区| 久久久不卡国产精品一区二区| 无码中文字幕一区二区三区| 久久久久99人妻一区二区三区 | 91视频国产一区| 国产精品视频一区二区三区四| 一区二区福利视频| 激情亚洲一区国产精品| 午夜福利av无码一区二区| 精品亚洲一区二区三区在线观看| 成人精品一区二区激情| 综合无码一区二区三区四区五区 | 国产精品亚洲专区一区| 极品尤物一区二区三区| 无码人妻精品一区二区| 亚洲毛片αv无线播放一区| 国产精品区AV一区二区| 亚洲一区二区三区免费| 在线观看免费视频一区| 亚洲一区AV无码少妇电影☆| 国产高清不卡一区二区| 亚洲线精品一区二区三区| 久久亚洲中文字幕精品一区| 国产熟女一区二区三区五月婷| 国产剧情一区二区| 国产一区二区三区在线观看免费| 亚洲AV日韩综合一区| 在线观看国产一区亚洲bd| 午夜视频一区二区三区| 四虎精品亚洲一区二区三区|