惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
V2EX
WordPress大学
WordPress大学
U
Unit 42
I
InfoQ
A
About on SuperTechFans
宝玉的分享
宝玉的分享
J
Java Code Geeks
博客园 - 司徒正美
爱范儿
爱范儿
Engineering at Meta
Engineering at Meta
G
Google Developers Blog
人人都是产品经理
人人都是产品经理
小众软件
小众软件
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
aimingoo的专栏
aimingoo的专栏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Last Week in AI
Last Week in AI
腾讯CDC
Recent Announcements
Recent Announcements

博客园 - 梦想CAD控件

网页CAD如何在web端实现AutoCAD的绘圆弧功能 网页CAD控件中对象捕捉的运用和二次开发方法(网页端编辑DWG) 网页端CAD的图形选择、编辑与夹点操作教程(CAD in WEB) 云原生CAD后台处理DWG(MxServiceCode) 网页CAD图纸保存与数据持久化(BS架构CAD插件) 网页CAD中命令行驱动与参数化绘图的使用教程 在线CAD视图控制与图层管理二开实战 开源网页实时协同设计平台-在线编辑CAD图纸 在线CAD SDK开发包图纸转换功能使用教程(在线CAD API) 统信麒麟鸿蒙系统软件集成CAD功能(国产系统CAD控件) 网页CAD开发包结构与功能说明(网页CAD实时协同编辑) 网页CAD结合AI实现自然语言设计CAD图纸 (JS实现预览)在线CAD中的“组”功能开发 (在线CAD)html在线预览cad图纸SDK集成方法 (JS编辑DWG文件)在线CAD二开实现图纸表格提取到excel 网页版CAD与gis结合实现在线地图和CAD编辑 (html在线预览cad图纸插件)在线CAD实现形位公差标注 (WEB CAD API )网页CAD插件如何开发焊接符号 (HTML VUE在线编辑DWG)网页CAD利用AI实现多行文本功能的开发 (web cad sdk)在线CAD中配置属性的使用教程 (WEB CAD二次开发)在线CAD SDK调用内部弹框的方法 在线CAD插件通过上下文对象MxPluginContext修改UI界面的方法 国产操作系统中好用的CAD软件(统信,麒麟,信创环境安装CAD) (pdm集成CAD SDK)在线CAD绘制条形码、二维码的教程 在线CAD绘制门和窗(WEB CAD二次开发家装设计软件) 在线CAD绘制墙体(WEB端开发室内设计软件) (在线三维参数化建模)网页三维CAD中加载和保存STEP模型 (H5在线CAD SDK)在线CAD中线型表的使用方法 (web查看三维CAD图纸)在三维网页CAD中绘制一个窗户模型
Web CAD图形引擎实现DWG图纸网页批注和查看
梦想CAD控件 · 2026-05-27 · via 博客园 - 梦想CAD控件

前言

在之前的文档中,我们已对 MxCAD 产品进行了宏观介绍,并完成了开发环境的初步搭建与 Demo 运行。然而,从运行官方示例构建自有业务系统之间,仍存在概念理解与工程落地的鸿沟。本篇文档的核心目标在于填补这一空白,重点解决以下两个关键问题:

概念理清:深入解析 MxCAD  MxDraw 的技术定位与职能边界。明确 MxCAD 作为编辑内核负责原图数据的深度操作,而 MxDraw 作为渲染引擎专注于图纸浏览与非侵入式批注。

工程落地:指导开发者在自己的项目中,从零构建一个具备图纸加载、视图浏览、独立批注功能的最小可行性产品(MVP),下面以vue项目为讲解示例。

通过本文的学习,您将掌握如何根据业务需求(是仅需审阅批注,还是需要修改原图)选择合适的技术组件,并能够独立搭建起一个可运行的 Web CAD 基础框架,为后续开发复杂的在线设计平台奠定坚实基础。

1

. 核心架构解析:MxCAD 与 MxDraw 的功能界定

在梦想云图(DreamCloud CAD)的技术体系中,MxCAD  MxDraw 是两个核心组件。尽管二者在底层紧密耦合,但在业务逻辑与应用场景上存在明确的职能划分。理解二者的区别是进行二次开发的前提。

1.1 MxDraw:轻量级前端渲染与批注引擎

  • 定义MxDraw 是一个基于 HTML5 Canvas WebGL 技术的前端图形渲染引擎。
  • 核心职能:图纸浏览与非侵入式批注。
    • 渲染展示:负责将 CAD 矢量数据高效地绘制于浏览器端,支持平移、缩放、旋转等视图操作。
    • 批注处理:提供独立的批注图层管理功能。用户可在图纸上层添加云线、文字注释、测量标记等信息。
    • 数据隔离MxDraw 的批注操作不修改原始 DWG/DXF 文件的几何数据与数据库结构。批注信息通常以独立文件(如 JSON 或专用批注格式)存储,或与原图分离保存,确保原图的完整性与安全性。
  • 适用场景:图纸在线审阅、协同设计标注、移动端轻量化查看、无需修改原图的设计评审。

1.2 MxCAD:全功能 CAD 业务内核

定义MxCAD 是基于 C++ 核心通过 WebAssembly (Wasm) 移植至 Web 端的专业 CAD 开发框架。

核心职能:图纸数据编辑与深度业务逻辑。

  • 数据解析:完整解析 AutoCAD 原生格式(DWG/DXF),支持所有版本及复杂实体。
  • 实体编辑:提供对图纸底层数据库的直接读写能力。支持实体的创建、修改、删除、属性变更等操作,这些操作会直接改变原图纸的数据结构。

适用场景Web 端在线绘图、图纸深化设计、自动化生成报表、基于图纸数据的业务系统集成。

1.3 协作机制与版本演进

在实际的技术架构中,MxCAD  MxDraw 并非孤立存在,而是呈现出紧密的层级协作与演进关系:

2

基础与升级的关系

MxDraw 是梦想云图技术体系的基础层。它提供了核心的 HTML5 Canvas 渲染能力、基础的图形交互逻辑以及轻量级的批注功能。其设计初衷是解决在网页上快速、高效地展示和标注 CAD 图纸这一核心痛点。

MxCAD 则是基于 MxDraw 的全功能升级版本。它在保留并复用 MxDraw 所有渲染与交互优势的基础上,通过引入 C++ 内核(编译为 WebAssembly)和 TypeScript 业务框架,扩展了完整的 CAD 数据解析、实体编辑、几何计算及复杂命令处理能力。

简而言之MxCAD = MxDraw (渲染与交互) + CAD 专业内核 (数据与逻辑)

协作模式

默认集成:在大多数应用场景下,开发者引入 MxCAD 开发包时,实际上已经包含了 MxDraw 的功能模块。MxCAD 内部会自动调用 MxDraw 进行图形绘制和用户交互监听。

按需调用: 

  • 若业务场景仅需查看与批注(如图纸审阅、移动端巡查),可直接利用 MxCAD 中集成的 MxDraw 接口模式。此时系统表现为轻量级引擎,不加载重型编辑内核(或仅使用其渲染部分),确保启动速度与运行性能。
  • 若业务场景涉及原图修改、参数化设计或数据提取,则激活 MxCAD 的完整内核功能,对底层数据库进行读写操作。

无缝切换:由于二者同源,开发者可以在同一个项目中根据权限或功能模块,动态切换只读/批注模式编辑模式,无需更换底层引擎,保证了用户体验的一致性与技术架构的统一性。

这种架构设计既保证了轻量级应用的极致性能,又为专业级应用提供了无限扩展的可能。

. 构建基础 CAD 项目:图纸预览与批注实战

2.1 环境准备与项目初始化

环境要求

Node.js: ≥ v16

包管理器: npm / pnpm

构建工具:

Vite (推荐,配置简单,开发速度快)

Webpack (支持,需配置 worker-loader 或相关 WASM 处理规则)

其他:Rollup, Parcel 等支持自定义 Loader/Plugin 的构建工具均可。

后端服务: 需运行云图开发包提供的图纸转换服务,用于处理 DWG/DXF MXWEB

可直接开启云图开发包 3000 端口下的服务。

也可自行根据图纸转换文档规则设置新的转换接口。

创建或集成项目

您可新建项目或在现有项目中添加 CAD 模块:

# 新建 Vue3 + TypeScript 项目
npm create vite@latest cad-viewer -- --template vue-ts
cd cad-viewer
npm install

安装核心依赖

# 安装 mxcad 核心包
npm install mxcad
# 若使用 pnpm,请额外安装 mxdraw (通常 mxcad 已包含,视具体版本策略而定)
# pnpm add mxdraw

配置构建工具支持多线程

MxCAD 的高性能渲染依赖 SharedArrayBuffer,这要求服务器响应头必须包含 Cross-Origin-Opener-Policy: same-origin  Cross-Origin-Embedder-Policy: require-corp无论使用何种打包工具(WebpackRollup 等),都必须进行此配置,否则引擎将无法启动或自动降级。

下面以 Vite 为例演示配置方法,修改 vite.config.ts,在 server.headers 中添加响应头:

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  server: {
    // 开发环境:直接在此处配置响应头
    headers: {
      "Cross-Origin-Opener-Policy": "same-origin",
      "Cross-Origin-Embedder-Policy": "require-corp",
    }
  },
  build: {
    target: 'esnext' // 确保编译目标支持最新特性
  }
})

2.2 创建 Canvas 容器与初始化 MxCAD 引擎

模板结构:Canvas 与文件上传控件

在组件模板中定义渲染容器和文件选择器,并添加控制按钮。

<template>
  <!-- CAD 渲染区域 -->
  <div style="width: 100vw; height: 95vh; overflow: hidden;">
    <canvas id="myCanvas"></canvas>
  </div>

  <!-- 控制栏 -->
  <div style="margin-top: 10px; padding: 10px; background: #f5f5f5;">
    <!-- 隐藏的文件输入框 -->
    <input
      type="file"
      ref="fileInput"
      accept=".dwg,.dxf,.mxweb"
      @change="openDwgFile"
      style="display:none"
    />
    
    <!-- 功能按钮 -->
    <button @click="$refs.fileInput.click()" :disabled="!mxcadReady">打开图纸</button>
    <button @click="startCloudMark" :disabled="!mxcadReady">绘制云线批注</button>
    <button @click="saveMarkup" :disabled="!mxcadReady">保存批注</button>
    <button @click="loadMarkup" :disabled="!mxcadReady">加载批注</button>
  </div>
</template>

初始化 MxCAD 实例

Vue 组件的 onMounted 生命周期中调用 createMxCad,完成 Canvas 绑定、WASM 核心文件路径定位、字体库路径设置以及初始化完成的回调处理。

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { createMxCad, MxCpp } from 'mxcad';

const mxcadReady = ref(false);
const fileInput = ref<HTMLInputElement | null>(null);

onMounted(() => {
  // 自动检测浏览器环境:支持 SharedArrayBuffer 则启用多线程 (2d),否则降级为单线程 (2d-st)
  const mode = "SharedArrayBuffer" in window ? "2d" : "2d-st";

  createMxCad({
    canvas: "#myCanvas",
    // 动态定位 WASM 文件路径,兼容 Vite/Webpack 等构建工具
    locateFile: (fileName: string) => {
      return new URL(
        `../../node_modules/mxcad/dist/wasm/${mode}/${fileName}`,
        import.meta.url
      ).href;
    },
    fileUrl: "", // 初始不加载文件,等待用户通过 UI 选择
    fontspath: new URL(
      "../../node_modules/mxcad/dist/fonts",
      import.meta.url
    ).href,
    // 初始化完成回调
    onInit: () => {
      console.log("MxCAD 引擎初始化完成");
      mxcadReady.value = true;
    }
  });
});
</script>

 更多配置项 createMxCad 支持丰富的自定义配置(如背景色、多选配置、视区移动方式等)。如需了解完整的配置参数列表及详细说明,请访问官方文档:[MxCadConfig 配置接口文档。

2.3 打开图纸并预览(关键格式说明)

重要说明:MxCAD 文件格式限制

MxCAD 引擎内核仅能直接解析和打开特定的 .mxweb 格式文件。它无法直接在浏览器端读取原生的 AutoCAD 格式(如 .dwg  .dxf)。

因此,在实现“打开图纸”功能时,必须遵循以下逻辑:

判断格式:检查用户选择的文件后缀。

格式转换:如果文件是 .dwg  .dxf,必须先将其上传至后端转换服务,由服务端将其转换为 .mxweb 格式。

加载渲染:只有获取到 .mxweb 格式的文件流或 URL 后,才能调用 mxcad.openWebFile() 进行加载和渲染。

若跳过转换步骤直接尝试加载 DWG 文件,MxCAD 将报错或无法显示任何内容。

3

文件选择与处理流程

基于上述限制,我们的代码逻辑分为两条路径:

  • 路径 A (.mxweb):浏览器原生支持,直接生成临时 URL 加载。
  • 路径 B (.dwg/.dxf):调用本地转换服务 localhost:3000/uploadfile 上传 -> 服务端自动转换 -> 返回/生成 .mxweb 路径 -> 加载。

跨域处理配置

由于前端开发服务器(默认 localhost:5173)与图纸转换服务(localhost:3000)端口不同,直接请求会触发浏览器的跨域限制 (CORS)

无论使用何种打包工具(WebpackRollup 等),在开发环境下都必须配置代理(Proxy)或将请求转发至同源,以解决跨域问题。生产环境通常通过 Nginx 反向代理统一入口来解决。

以下以 Vite 为例演示开发环境的代理配置:

修改 vite.config.ts,添加 server.proxy 配置,将 /api 或特定路径的请求转发至转换服务:

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  server: {
    // ....其他配置 
    // 开发环境跨域代理配置
    proxy: {
      // 匹配所有以 /api 开头的请求(建议前端请求时加上 /api 前缀)
      '/api': {
        target: 'http://localhost:3000', // 图纸转换服务地址
        changeOrigin: true,              // 修改 Host 头为 target
        rewrite: (path) => path.replace(/^\/api/, ''), // 去掉 /api 前缀再转发
      },
      // 或者直接代理特定的转换接口路径
      //'/uploadfile': {
      //  target: 'http://localhost:3000',
      //  changeOrigin: true,
      // },
      // '/demo': {
      //  target: 'http://localhost:3000',
      //  changeOrigin: true,
      // }
    }
  }
})

 前端代码适配示例: 配置代理后,前端请求地址需调整为相对路径或带前缀的路径:

// 原地址:http://localhost:3000/uploadfile
// 代理后地址:/api/uploadfile (需在 proxy 中配置 rewrite) 或直接 /uploadfile
const res = await fetch("/api/uploadfile", { // Vite 会自动拦截并转发到 localhost:3000/uploadfile
  method: "POST",
  body: formData,
});

 代码实现:打开网络图纸

图纸的加载与渲染核心依赖于 MxCAD 提供的 openWebFile API。该接口支持从网络 URL 直接加载 .mxweb 或转换后的图纸数据,并提供了丰富的参数控制(如是否使用多线程、加载策略等)。

<script setup lang="ts">
// ... 上述初始化代码 ...

// 打开图纸处理函数
const openDwgFile = async (event: Event) => {
  const target = event.target as HTMLInputElement;
  const file = target.files?.[0];
  if (!file) return; 
  const fileName = file.name;
  // 获取文件后缀并转为小写
  const fileExt = fileName.slice(fileName.lastIndexOf(".")).toLowerCase();
  const mxcad = MxCpp.getCurrentMxCAD();

  if (fileExt === ".dwg" || fileExt === ".dxf") {
    // DWG/DXF 需要后端转换
    const formData = new FormData();
    formData.append("file", file);
    
    try {
      // 调用代理后的上传接口
      const res = await fetch("/upfile/mxcad", {
        method: "POST",
        body: formData,
      });
      
      if (!res.ok) throw new Error(`请求失败:${res.status}`);
      
      // 约定:转换后的文件位于 /demo/ 目录下,文件名不变,后缀变为 .mxweb
      const mxwebFullUrl = `/demo/${fileName}.mxweb`;
      mxcad.openWebFile(mxwebFullUrl);
      
    } catch (err) {
      console.error(err);
      alert("上传或转换失败,请检查后端服务是否启动");
    }
  } else if (fileExt === ".mxweb") {
    // MXWEB 直接读取
    const tempUrl = URL.createObjectURL(file);
    mxcad.openWebFile(tempUrl);
  } else {
    alert("不支持该文件格式,请上传 .dwg, .dxf 或 .mxweb");
  }
  // 重置 input value,允许重复选择同一文件
  target.value = "";
};
</script>

 关键点说明:

  • 转换接口: //localhost:3000/uploadfile 是云图开发包自带的演示服务,实际生产环境请替换为您的后端地址。
  • 路径约定: 代码假设转换服务会将结果固定在 /demo/ 目录下,且文件名保持原名仅后缀变为 .mxweb
  • API 调用: 无论源文件是什么,最终都统一调用 mxcad.openWebFile(url) 进行渲染。openWebFile 支持更多高级参数,例如控制是否使用工作线程 (isWorkThread)、指定数据加载到内存还是 IndexedDB (fetchAttributes) 等。如需了解完整的参数定义及详细说明,请访问官方文档: McObject.openWebFile API 文档

2.4 批注功能实现(创建、保存、回显)

创建批注(以审图云线为例)

此功能通过 MxDraw 提供的交互接口,让用户在图上绘制云线并添加文字说明。

import {
  MxFun,
  MrxDbgUiPrPoint,
  McEdGetPointWorldDrawObject,
  MrxDbgUiPrBaseReturn,
  MxDbRectBoxLeadComment,
} from "mxdraw";
// 绘制云线批注函数
function startCloudMark() {
  const point = new MrxDbgUiPrPoint(); // 获取点交互对象
  const mxDraw = MxFun.getCurrentDraw(); // 获取当前绘图对象
  const worldDrawComment = new McEdGetPointWorldDrawObject(); // 动态绘制辅助对象
  const mxCheckDraw = new MxDbRectBoxLeadComment(); // 云线批注实体对象
  // 设置云线半径(屏幕坐标转文档坐标)
  mxCheckDraw.radius = MxFun.screenCoordLong2Doc(5);
  mxCheckDraw.setLineWidth(3);
  mxCheckDraw.setLineWidthByPixels(true);
  // 第一步:获取起始点
  point.setMessage("\n云线框起始点: ");
  point.go((status) => {
    if (status != MrxDbgUiPrBaseReturn.kOk) return;    
    mxCheckDraw.point1 = point.value();    
    // 动态预览:移动鼠标时绘制矩形
    worldDrawComment.setDraw((currentPoint) => {
      mxCheckDraw.point2 = currentPoint;
      worldDrawComment.drawCustomEntity(mxCheckDraw);
    });
    point.setUserDraw(worldDrawComment);
    point.setMessage("\n云线框结束点: ");
    // 第二步:获取结束点
    point.go((status) => {
      if (status != MrxDbgUiPrBaseReturn.kOk) return;     
      mxCheckDraw.point2 = point.value();      
      // 动态预览:确定文本位置
      worldDrawComment.setDraw((currentPoint) => {
        mxCheckDraw.point3 = currentPoint;
        worldDrawComment.drawCustomEntity(mxCheckDraw);
      });
      // 设置批注文本属性
      mxCheckDraw.text = "审图批注";
      mxCheckDraw.textWidth = MxFun.screenCoordLong2Doc(100);
      mxCheckDraw.textHeight = MxFun.screenCoordLong2Doc(50);
      mxCheckDraw.fixedSize = true;
      if (mxCheckDraw.fixedSize) {
        mxCheckDraw.textHeight = 20;
        mxCheckDraw.textWidth = 130;
      }
      point.setMessage("\n审图标注点: ");
      // 第三步:获取文本引出点
      point.go((status) => {
        if (status != MrxDbgUiPrBaseReturn.kOk) return;
        mxCheckDraw.point3 = point.value();
        // 将实体添加到图纸数据库
        mxDraw.addMxEntity(mxCheckDraw);
      });
    });
  });
}

 绘制效果如下所示:

4

保存批注数据

使用官方推荐的 saveMxEntityToJson() 方法,将当前图纸上的所有非原生实体(即批注)序列化为 JSON 字符串。本示例暂存至 localStorage 模拟数据库存储。

import { MxFun } from "mxdraw";
// 保存图纸批注
const saveMarkup = () => {
  const draw = MxFun.getCurrentDraw();
  if (!draw) return;  
  // 序列化批注数据
  const jsonData = draw.saveMxEntityToJson();
  localStorage.setItem("mx-markup-data", jsonData);
  alert("批注已保存至本地存储");
};

 回显批注数据

当用户再次打开图纸时,从存储中读取 JSON 数据,并调用 loadMxEntityFromJson() 还原批注。

import { MxFun } from "mxdraw";

// 恢复图纸批注
const loadMarkup = () => {
  const draw = MxFun.getCurrentDraw();
  if (!draw) return;

  const jsonData = localStorage.getItem("mx-markup-data");
  if (jsonData) {
    draw.loadMxEntityFromJson(jsonData);
    alert("批注已加载");
  } else {
    alert("未找到保存的批注数据");
  }
};

 最佳实践提示:在实际业务中,应将 saveMarkup 生成的 JSON 数据通过 AJAX/Fetch 发送给后端,与图纸 ID 关联存储;loadMarkup 应在图纸加载完成后(监听 onOpenFileComplete 回调)自动从后端拉取数据并执行加载。

2.5 运行验证

启动服务:

  • 确保云图转换服务已在 localhost:3000 运行。
  • 启动前端项目:npm run dev

测试流程:

  • 预览 MXWEB:点击打开图纸,选择 .mxweb 文件 图纸秒开。
  • 预览 DWG:点击打开图纸,选择 .dwg 文件 自动上传转换 加载转换后的图纸。
  • 绘制批注:点击绘制云线批注,在图上依次点击起始点、结束点、文字引出点 云线绘制成功。
  • 保存:点击保存批注” → 检查浏览器 LocalStorage 是否有 mx-markup-data 键值。
  • 回显:刷新页面(清空内存),重新打开同一张图纸 点击加载批注” → 确认云线准确还原。

. 常见问题与注意事项

路径配置敏感性

Wasm 文件和字体文件的路径配置必须精确。若控制台出现 404 错误或 Wasm 编译失败,请首先检查 public 目录结构及初始化参数中的 locateFile  fontspath 路径字符串是否正确。

跨域隔离策略 (COOP/COEP)

较新版本的 MxCAD 利用 SharedArrayBuffer 进行多线程优化以提升性能。若在 Chrome/Edge 中遇到 SharedArrayBuffer is not defined 相关报错,必须在 Web 服务器(或 Vite 配置)的响应头中严格配置:

Cross-Origin-Opener-Policy: same-origin

Cross-Origin-Embedder-Policy: require-corp

字体缺失处理

若图纸文字显示为问号或乱码,通常是因为缺少对应的 SHX 字体文件。请确保开发包中的 fonts 目录已完整部署到项目中,或在后端转换服务中配置字体映射。

大文件性能

对于超过 50MB 的超大图纸,建议在加载前进行前端提示。可考虑启用 SDK 中的按需加载功能或简化显示模式(如关闭抗锯齿、隐藏填充图案)以优化渲染帧率。

批注数据管理

批注数据是独立于原图存在的。务必在前端或后端建立图纸 ID - 批注 JSON”的映射关系,避免不同图纸间的批注混淆。