一、什么是WebAssembly?

WebAssembly(简称WASM)是一种可以在现代Web浏览器中运行的二进制指令格式。它被设计为高性能的目标语言,可以用C++、Rust等语言编写代码,然后编译成WASM在浏览器中运行。

主要特点:

  1. 接近原生的性能

  2. 可以使用多种语言开发

  3. 与JavaScript可以互相调用

  4. 安全的沙箱执行环境

例如OCC提供的实体建模的能力就是将c++写的项目,打包成wasm包的形式,供前端调用

二、WebAssembly的加载方式

1. 基础加载方式

async function loadWasm() {
    const result = await WebAssembly.instantiateStreaming(
        fetch('module.wasm')
    );
    const instance = result.instance;
    // 使用导出的函数
    instance.exports.someFunction();

2. 传统分步加载

async function loadWasmTraditional() {
    const response = await fetch('module.wasm');
    const bytes = await response.arrayBuffer();
    const module = await WebAssembly.compile(bytes);
    const instance = await WebAssembly.instantiate(module);
    // 使用实例
}

3. ES模块方式(现代推荐方式)

import init, { someFunction } from './module.js';

async function initialize() {
    await init('./module_bg.wasm');
    someFunction();
}

三、实战案例:多边形布尔运算

以一个实际的项目为例,展示如何在Web应用中使用WebAssembly实现多边形布尔运算。

cavalier_contours是一个用于处理闭合或开放的2D轮廓,提供轮廓偏移(Offsetting),有c++和rust两个版本 这个包的github链接,下面的这个示例是rust代码打包出的wasm包

1. 简单的结构

2. WASM模块加载

  • 使用了ES模块的方式加载WASM

// 导入WASM模块和Polyline类
import init, { Polyline } from './cavalier_contours_web_ffi.js';

// 初始化函数
async function initialize() {
    try {
        await init('./cavalier_contours_web_ffi_bg.wasm');
        console.log('WASM 初始化成功');
    } catch (error) {
        console.error('WASM 初始化失败:', error);
    }
}

// 启动初始化
initialize();

3. 调用WASM例的方法

这里主要用WASM处理多边形的布尔运算。看看如何使用WASM导出的功能:

Polyline

import  { Polyline } from './cavalier_contours_web_ffi.js';
async function performBoolean() {
    try {
        // 准备数据:将JavaScript数组转换为WASM可用的格式
        const vertices1 = points1.flatMap(p => [p[0], p[1], 0]);
        const vertices2 = points2.flatMap(p => [p[0], p[1], 0]);
        
        // 创建WASM对象
        const poly1 = new Polyline(new Float64Array(vertices1), true);
        const poly2 = new Polyline(new Float64Array(vertices2), true);
        
        // 执行布尔运算
        const operation = parseInt(document.getElementById('operation').value);
        const result = poly1.boolean(poly2, operation);

        // 处理结果
        if (result && (result.posPlines || result.negPlines)) {
            // 绘制结果...
        }

        // 清理WASM资源
        poly1.free();
        poly2.free();
    } catch (error) {
        console.error('布尔运算执行失败:', error);
    }
}

示例:

交集运算