SkiaSharp跨平台繪圖研究5-Blazor WebAssembly網頁繪圖
2021年10月12日,.NET 6發布RC2候選版本(正式發布前最后一版),宣布了一個突破性的技術:支持在Web網頁上采用SkiaSharp畫布繪圖。這是.NET跨平台技術發展的一個創舉,使用C#可以直接在網頁畫布上繪圖,打破了JavaScript+canvas的長期壟斷地位。C#是強類型語言,可以無縫對接從服務端獲取的結構化數據,有效提高開發效率和質量。
ASP.NET Core updates in .NET 6 Release Candidate 2 - ASP.NET Blog (microsoft.com)
SkiaSharp is a cross-platform 2D graphics library for .NET based on the native Skia graphics library, and it now has preview support for Blazor WebAssembly. Let’s give it a try!
目前VS2022正式版和NET 6正式版都已經發布,SkiaSharp對Blazor WebAssembly的支持仍然處於預覽狀態。
創建Blazor WebAssembly項目
選擇項目類型Blazor WebAssembly,NET 6.0平台,帶托管主機,我是習慣了容器化部署方式,有個后台服務器部署起來順手一點。
修改服務端項目program.cs,綁定端口和域名證書。
using Microsoft.AspNetCore.ResponseCompression; using Microsoft.AspNetCore.Server.Kestrel.Core; using System.Net; namespace WebBlazorDemo.Server; public class Program { public static async Task Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.WebHost.ConfigureKestrel(ConfigHttps); // Add services to the container. builder.Services.AddControllersWithViews(); builder.Services.AddRazorPages(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseWebAssemblyDebugging(); } else { app.UseExceptionHandler("/Error"); } app.UseBlazorFrameworkFiles(); app.UseStaticFiles(); app.UseRouting(); app.MapRazorPages(); app.MapControllers(); app.MapFallbackToFile("index.html"); //app.Run(); await app.RunAsync(); } private static void ConfigHttps(WebHostBuilderContext context, KestrelServerOptions options) { //http服務端口 options.Listen(IPAddress.Any, 7902); //https服務端口 options.Listen(IPAddress.Any, 7903, configure); void configure(ListenOptions listenOptions) { if (context.HostingEnvironment.IsProduction()) { //填入pfx文件路徑和指定的密碼 listenOptions.UseHttps("myweb.pfx", "xxx"); } else { //本機調試必須采用默認localhost證書,否則無法建立ssl連接 listenOptions.UseHttps(); } } } }
給客戶端項目NuGet安裝SkiaSharp.Views.Blazor,現在最新版是2.88.0-preview.155。
給主頁添加繪圖代碼,跟WPF基本一樣。
@page "/" @using SkiaSharp.Views.Blazor @using SkiaSharp <PageTitle>Index</PageTitle> <h1>Hello, world!</h1> Welcome to your new app. <SurveyPrompt Title="How is Blazor working for you?" /> <button class="btn btn-primary m-1" @onclick="OnClickImg" type="button">更新繪圖</button> <br /> <SKCanvasView OnPaintSurface="OnPaintSurface" style="width:480px; height:240px" @ref="canvasView" @onclick="OnClickImg" /> @code { //private ElementReference canvasView;//這個參數無法轉換類型為SKCanvasView private SKCanvasView canvasView; private void OnClickImg() { //引發畫布更新繪圖 canvasView.Invalidate(); } void OnPaintSurface(SKPaintSurfaceEventArgs e) { var canvas = e.Surface.Canvas; canvas.Clear(SKColors.SkyBlue); using var paint = new SKPaint { Color = SKColors.Black, IsAntialias = true, Typeface = SkiaChinaFont.ChinaFont, TextSize = 24 }; string msg = $"{DateTimeOffset.Now:T}, 還有1萬行Skia繪圖代碼..."; canvas.DrawText(msg, 0, 30, paint); using var linePaint = new SKPaint() { Color = (DateTimeOffset.Now.Second % 4 <= 1) ? SKColors.Red : SKColors.Green, Style = SKPaintStyle.Stroke,//不填充 StrokeWidth = 3, }; canvas.DrawRect(10, 50, e.Info.Width - 20, e.Info.Height - 60, linePaint); msg += $", linePaint.Color={linePaint.Color}, skContainer.CanvasSize={e.Info.Size}"; Console.WriteLine(msg); } }
同樣要添加中文字體類,注意要設置字體文件為嵌入的資源。
using SkiaSharp; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace WebBlazorDemo.Client; /// <summary> /// Skia中文字體 /// </summary> public static class SkiaChinaFont { public static SKTypeface ChinaFont { get; private set; } static SkiaChinaFont() { //加載資源方案,設置字體文件屬性為嵌入的資源 var fontStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("WebBlazorDemo.Client.DroidSansFallback.ttf"); ChinaFont = SKTypeface.FromStream(fontStream); } }
我在安裝VS2022的時候沒有添加wasm-tools工作負載,所以會編譯Blazor WebAssembly報錯,在命令行運行dotnet workload install wasm-tools即可添加。然后跑起來看一下,如願以償!在網頁上用C#繪圖,終於等到了。
發布服務端項目到騰訊雲CentOS操作系統容器里測試,跟本機測試一樣結果,沒有什么依賴庫。
展望
網頁前端開發主要就是Html + Css + JavaScript三板斧,基於三板斧不斷封裝也發展出了React、Vue、Angular等集成框架,但是前后端數據交互通常要做很多變換處理,畢竟前后端語言的數據類型不一樣。Blazor框架把C#強類型語言推進到前端網頁開發,打通了前后端統一框架和語言的技術路線,這是非常了不起的突破。Blazor開發常規的表單、導航網頁功能都已經非常好用了,但是一旦涉及繪圖,仍然要借助JavaScript語言去實現,實在是一個遺憾。
不過從現在開始,C#也可以在Html網頁SkiaSharp畫布上繪圖了,消除了C#前端開發最后一個屏障。但是,僅有繪圖功能是遠遠不夠的,Html生態圈中有海量高質量、開源的圖形插件,例如ECharts,把模板選好,再放入數據,就能出來光鮮亮麗的圖表,並且擁有非常豐富的滾動,縮放,懸停,選取等交互能力。SkiaSharp畫布要走的路還很長,希望將來能構建起一個新的生態圈。
DEMO源代碼參見:https://gitee.com/woodsun/skia-sharp-demo