SkiaSharp跨平台繪圖研究5-Blazor WebAssembly網頁繪圖


SkiaSharp跨平台繪圖研究5-Blazor WebAssembly網頁繪圖

20211012日,.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正式版都已經發布,SkiaSharpBlazor WebAssembly的支持仍然處於預覽狀態。

 

創建Blazor WebAssembly項目

選擇項目類型Blazor WebAssemblyNET 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三板斧,基於三板斧不斷封裝也發展出了ReactVueAngular等集成框架,但是前后端數據交互通常要做很多變換處理,畢竟前后端語言的數據類型不一樣。Blazor框架把C#強類型語言推進到前端網頁開發,打通了前后端統一框架和語言的技術路線,這是非常了不起的突破。Blazor開發常規的表單、導航網頁功能都已經非常好用了,但是一旦涉及繪圖,仍然要借助JavaScript語言去實現,實在是一個遺憾。

不過從現在開始,C#也可以在Html網頁SkiaSharp畫布上繪圖了,消除了C#前端開發最后一個屏障。但是,僅有繪圖功能是遠遠不夠的,Html生態圈中有海量高質量、開源的圖形插件,例如ECharts,把模板選好,再放入數據,就能出來光鮮亮麗的圖表,並且擁有非常豐富的滾動,縮放,懸停,選取等交互能力。SkiaSharp畫布要走的路還很長,希望將來能構建起一個新的生態圈。

 

 

DEMO源代碼參見:https://gitee.com/woodsun/skia-sharp-demo

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM