SkiaSharp跨平台绘图研究5-Blazor WebAssembly网页绘图
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