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>