c# 编写 WebAssembly

创建一个.net 7.0类库工程,引用下面的nuget包:

    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.5" />
    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.5" />
    <PackageReference Include="SkiaSharp.Views.Blazor" Version="2.88.3" />  如果用到SkiaSharp就引入这个

然后把Project sdk改成这样:

<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

然后c#代码可以这样写:

using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.JSInterop;

namespace WebAssemblyTest
{
    public class Program
    {
        private static IJSRuntime js;
        private static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            var host = builder.Build();
            js = host.Services.GetRequiredService<IJSRuntime>();
            RunInSeconds();
            await host.RunAsync();
        }

        static async void RunInSeconds()
        {
            while (true)
            {
                await Task.Delay(2000);
                //调用javascript里面的test方法
                await js.InvokeVoidAsync("test", new byte[] { 0x1, 0x2 });
            }
        }

        /// <summary>
        /// 给js调用的函数
        /// </summary>
        /// <param name="i"></param>
        /// <param name="j"></param>
        /// <returns></returns>
        [JSInvokable]
        public static byte[] Add(int i, int j)
        {
            return new byte[] { (byte)i,(byte)j};
        }
    }
}

js代码这样写:

<html lang="en">
<head>
    <meta charset="UTF-8" />
</head>
<body>
</body>
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script>
    function test(r) {
        console.log(r);
        alert(r);
    }
    window.onload = async function () {
        await Blazor.start();
        const r = await DotNet.invokeMethodAsync(
            'WebAssemblyTest',//程序集的名字
            'Add',//要调用的标注了[JSInvokable]方法的名字
            666,//若干参数
            333
        );
        console.log(r);
    };
</script>
</html>

注意编译生成的_framework文件夹必须放在web服务器,并且设置mimeType以便前端可以顺利下载

var provider = new FileExtensionContentTypeProvider();
provider.Mappings[".dll"] = "application/octet-stream";//配置添加新的映射关系
provider.Mappings[".gz"] = "application/octet-stream";
provider.Mappings[".dat"] = "application/octet-stream";
provider.Mappings[".blat"] = "application/octet-stream";
provider.Mappings[".pdb"] = "application/octet-stream";
provider.Mappings[".wasm"] = "application/octet-stream";
app.UseStaticFiles(new StaticFileOptions
{
    ContentTypeProvider = provider,//应用新的映射关系
});

一个SkiaSharp显示图片到canvas的例子

using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.JSInterop;
using SkiaSharp;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;

namespace WebAssemblyTest
{
    public class Program
    {
        private static IJSRuntime js;
        private static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            var host = builder.Build();
            js = host.Services.GetRequiredService<IJSRuntime>();
            RunInSeconds();
            await host.RunAsync();
        }

        static async void RunInSeconds()
        {
            try
            {

                HttpClient client = new HttpClient();
                using var ret = await client.GetStreamAsync("https://img0.baidu.com/it/u=189915953,3148055061&fm=253&fmt=auto&app=120&f=JPEG?w=1422&h=800");
                var bs = new byte[ret.Length];
                ret.Read(bs , 0 , bs.Length);
                ret.Dispose();
                while (true)
                {
                    using (var ms = new MemoryStream(bs))
                    {
                        ms.Position = 0;
                        using (var skiaBitmap = SKBitmap.Decode(ms))
                        {   
                            // 获取图片的宽度和高度
                            var width = skiaBitmap.Width;
                            var height = skiaBitmap.Height;
                            using (var canvas = new SKCanvas(skiaBitmap))
                            {
                                // 添加文本
                                var paint = new SKPaint
                                {
                                    IsAntialias = true,
                                    Color = SKColors.Blue,
                                    TextAlign = SKTextAlign.Center,
                                    TextSize = 64
                                };
                                canvas.DrawText(DateTime.Now.ToString("测试 HH:mm:ss"), width / 2f, height / 2f, paint);
                            }

                         

                            // 创建一个用于存储像素数据的数组
                            var pixelData = new byte[width * height * 4];

                            // 将像素数据序列化到数组中
                            for (var y = 0; y < height; ++y)
                            {
                                for (var x = 0; x < width; ++x)
                                {
                                    var index = (y * width + x) * 4;
                                    var color = skiaBitmap.GetPixel(x, y);
                                    pixelData[index] = color.Red;
                                    pixelData[index + 1] = color.Green;
                                    pixelData[index + 2] = color.Blue;
                                    pixelData[index + 3] = color.Alpha;
                                }
                            }

                            //调用javascript里面的test方法
                            await js.InvokeVoidAsync("test", pixelData, width, height);
                        }
                    }
                    await Task.Delay(25);
                }
            }
            catch (Exception ex)
            {
                await js.InvokeVoidAsync("showErr", ex.ToString());
            }
            
        }

        /// <summary>
        /// 给js调用的函数
        /// </summary>
        /// <param name="i"></param>
        /// <param name="j"></param>
        /// <returns></returns>
        [JSInvokable]
        public static byte[] Add(int i, int j)
        {
            return new byte[] { (byte)i,(byte)j};
        }
    }
}
<html lang="en">
<head>
    <meta charset="UTF-8" />
</head>
<body>
    <canvas id="myCanvas" style="width:800px;height:800px;"></canvas>
</body>
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script>
    function test(data, width, height) {
        const canvas = document.getElementById('myCanvas');
        canvas.style.width = width + "px";
        canvas.style.height = height + "px";
        canvas.width = width;
        canvas.height = height;
        const context = canvas.getContext('2d');
        context.width = width;
        context.height = height;

        const imageData = context.createImageData(width, height);

        for (let i = 0; i < data.length; i += 4) {
            imageData.data[i] = data[i]; // 红色通道
            imageData.data[i + 1] = data[i + 1]; // 绿色通道
            imageData.data[i + 2] = data[i + 2]; // 蓝色通道
            imageData.data[i + 3] = data[i + 3]; // alpha 通道
        }

        context.putImageData(imageData, 0, 0);
    }
    function showErr(err) {
        console.error(err);
    }
    window.onload = async function () {
        await Blazor.start();
    };
</script>
</html>
posted @ 2023-06-12 15:25  IWing  阅读(660)  评论(0编辑  收藏  举报